__ Ret();
StubRuntimeCallHelper call_helper;
- char_at_generator.GenerateSlow(masm, call_helper);
+ char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
void StringCharCodeAtGenerator::GenerateSlow(
- MacroAssembler* masm,
+ MacroAssembler* masm, EmbedMode embed_mode,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
index_not_number_,
DONT_DO_SMI_CHECK);
call_helper.BeforeCall(masm);
- __ push(object_);
- __ push(index_); // Consumed by runtime conversion function.
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ Push(VectorLoadICDescriptor::VectorRegister(),
+ VectorLoadICDescriptor::SlotRegister(), object_, index_);
+ } else {
+ // index_ is consumed by runtime conversion function.
+ __ Push(object_, index_);
+ }
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
__ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
} else {
// Save the conversion result before the pop instructions below
// have a chance to overwrite it.
__ Move(index_, r0);
- __ pop(object_);
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ Pop(VectorLoadICDescriptor::VectorRegister(),
+ VectorLoadICDescriptor::SlotRegister(), object_);
+ } else {
+ __ pop(object_);
+ }
// Reload the instance type.
__ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
__ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
__ ldr(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset));
__ CompareRoot(scratch1, Heap::kWeakCellMapRootIndex);
__ b(ne, &try_array);
- __ JumpIfNotSmi(key, &miss);
HandleMonomorphicCase(masm, receiver, key, vector, slot, feedback, scratch1,
&miss);
// Is it a fixed array?
__ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex);
__ b(ne, ¬_array);
- // We have a polymorphic element handler.
- __ JumpIfNotSmi(key, &miss);
+ // We have a polymorphic element handler.
Label polymorphic, try_poly_name;
__ bind(&polymorphic);
HandleArrayCases(masm, receiver, key, vector, slot, feedback, scratch1, r8,
__ jmp(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ bind(&done);
context()->Plug(result);
__ jmp(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ bind(&done);
context()->Plug(result);
__ Ret();
StubRuntimeCallHelper call_helper;
- char_at_generator.GenerateSlow(masm, call_helper);
+ char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ Bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
void StringCharCodeAtGenerator::GenerateSlow(
- MacroAssembler* masm,
+ MacroAssembler* masm, EmbedMode embed_mode,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
// If index is a heap number, try converting it to an integer.
__ JumpIfNotHeapNumber(index_, index_not_number_);
call_helper.BeforeCall(masm);
- // Save object_ on the stack and pass index_ as argument for runtime call.
- __ Push(object_, index_);
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ Push(VectorLoadICDescriptor::VectorRegister(),
+ VectorLoadICDescriptor::SlotRegister(), object_, index_);
+ } else {
+ // Save object_ on the stack and pass index_ as argument for runtime call.
+ __ Push(object_, index_);
+ }
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
__ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
} else {
// Save the conversion result before the pop instructions below
// have a chance to overwrite it.
__ Mov(index_, x0);
- __ Pop(object_);
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ Pop(object_, VectorLoadICDescriptor::SlotRegister(),
+ VectorLoadICDescriptor::VectorRegister());
+ } else {
+ __ Pop(object_);
+ }
// Reload the instance type.
__ Ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
__ Ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
Label not_array, smi_key, key_okay, miss;
__ Ldr(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset));
__ JumpIfNotRoot(scratch1, Heap::kWeakCellMapRootIndex, &try_array);
- __ JumpIfNotSmi(key, &miss);
HandleMonomorphicCase(masm, receiver, key, vector, slot, feedback, scratch1,
&miss);
__ Bind(&try_array);
// Is it a fixed array?
__ JumpIfNotRoot(scratch1, Heap::kFixedArrayMapRootIndex, ¬_array);
- // We have a polymorphic element handler.
- __ JumpIfNotSmi(key, &miss);
+ // We have a polymorphic element handler.
Label polymorphic, try_poly_name;
__ Bind(&polymorphic);
HandleArrayCases(masm, receiver, key, vector, slot, feedback, scratch1, x6,
__ B(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ Bind(&done);
context()->Plug(result);
__ B(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ Bind(&done);
context()->Plug(result);
};
+enum EmbedMode {
+ // The code being generated is part of an IC handler, which may MISS
+ // to an IC in failure cases.
+ PART_OF_IC_HANDLER,
+
+ NOT_PART_OF_IC_HANDLER
+};
+
+
// Generates code implementing String.prototype.charCodeAt.
//
// Only supports the case when the receiver is a string and the index
// Generates the slow case code. Must not be naturally
// reachable. Expected to be put after a ret instruction (e.g., in
// deferred code). Always jumps back to the fast case.
- void GenerateSlow(MacroAssembler* masm,
+ void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
const RuntimeCallHelper& call_helper);
// Skip handling slow case and directly jump to bailout.
// Generates the slow case code. Must not be naturally
// reachable. Expected to be put after a ret instruction (e.g., in
// deferred code). Always jumps back to the fast case.
- void GenerateSlow(MacroAssembler* masm,
+ void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
const RuntimeCallHelper& call_helper) {
- char_code_at_generator_.GenerateSlow(masm, call_helper);
+ char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
char_from_code_generator_.GenerateSlow(masm, call_helper);
}
__ ret(0);
StubRuntimeCallHelper call_helper;
- char_at_generator.GenerateSlow(masm, call_helper);
+ char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
void StringCharCodeAtGenerator::GenerateSlow(
- MacroAssembler* masm,
+ MacroAssembler* masm, EmbedMode embed_mode,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
index_not_number_,
DONT_DO_SMI_CHECK);
call_helper.BeforeCall(masm);
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ push(VectorLoadICDescriptor::VectorRegister());
+ __ push(VectorLoadICDescriptor::SlotRegister());
+ }
__ push(object_);
__ push(index_); // Consumed by runtime conversion function.
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
__ mov(index_, eax);
}
__ pop(object_);
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ pop(VectorLoadICDescriptor::SlotRegister());
+ __ pop(VectorLoadICDescriptor::VectorRegister());
+ }
// Reload the instance type.
__ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
__ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
Label not_array, smi_key, key_okay, miss;
__ CompareRoot(FieldOperand(feedback, 0), Heap::kWeakCellMapRootIndex);
__ j(not_equal, &try_array);
- __ JumpIfNotSmi(key, &miss);
HandleMonomorphicCase(masm, receiver, key, vector, slot, feedback, &miss);
__ bind(&try_array);
// Is it a fixed array?
__ CompareRoot(FieldOperand(feedback, 0), Heap::kFixedArrayMapRootIndex);
__ j(not_equal, ¬_array);
- // We have a polymorphic element handler.
- __ JumpIfNotSmi(key, &miss);
+ // We have a polymorphic element handler.
Label polymorphic, try_poly_name;
__ bind(&polymorphic);
HandleArrayCases(masm, receiver, key, vector, slot, feedback, true, &miss);
__ jmp(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ bind(&done);
context()->Plug(result);
__ jmp(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ bind(&done);
context()->Plug(result);
Register result = v0;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
DCHECK(!FLAG_vector_ics ||
- (!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
- result.is(VectorLoadICDescriptor::SlotRegister())));
+ !scratch.is(VectorLoadICDescriptor::VectorRegister()));
- // StringCharAtGenerator doesn't use the result register until it's passed
- // the different miss possibilities. If it did, we would have a conflict
- // when FLAG_vector_ics is true.
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
__ Ret();
StubRuntimeCallHelper call_helper;
- char_at_generator.GenerateSlow(masm, call_helper);
+ char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
void StringCharCodeAtGenerator::GenerateSlow(
- MacroAssembler* masm,
+ MacroAssembler* masm, EmbedMode embed_mode,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
DONT_DO_SMI_CHECK);
call_helper.BeforeCall(masm);
// Consumed by runtime conversion function:
- __ Push(object_, index_);
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ Push(VectorLoadICDescriptor::VectorRegister(),
+ VectorLoadICDescriptor::SlotRegister(), object_, index_);
+ } else {
+ __ Push(object_, index_);
+ }
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
__ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
} else {
// Save the conversion result before the pop instructions below
// have a chance to overwrite it.
-
__ Move(index_, v0);
- __ pop(object_);
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ Pop(VectorLoadICDescriptor::SlotRegister(),
+ VectorLoadICDescriptor::VectorRegister(), object_);
+ } else {
+ __ pop(object_);
+ }
// Reload the instance type.
__ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
__ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
__ jmp(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ bind(&done);
context()->Plug(result);
__ jmp(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ bind(&done);
context()->Plug(result);
__ ret(0);
StubRuntimeCallHelper call_helper;
- char_at_generator.GenerateSlow(masm, call_helper);
+ char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
void StringCharCodeAtGenerator::GenerateSlow(
- MacroAssembler* masm,
+ MacroAssembler* masm, EmbedMode embed_mode,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
index_not_number_,
DONT_DO_SMI_CHECK);
call_helper.BeforeCall(masm);
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ Push(VectorLoadICDescriptor::VectorRegister());
+ __ Push(VectorLoadICDescriptor::SlotRegister());
+ }
__ Push(object_);
__ Push(index_); // Consumed by runtime conversion function.
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
__ movp(index_, rax);
}
__ Pop(object_);
+ if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
+ __ Pop(VectorLoadICDescriptor::SlotRegister());
+ __ Pop(VectorLoadICDescriptor::VectorRegister());
+ }
// Reload the instance type.
__ movp(result_, FieldOperand(object_, HeapObject::kMapOffset));
__ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
Label not_array, smi_key, key_okay, miss;
__ CompareRoot(FieldOperand(feedback, 0), Heap::kWeakCellMapRootIndex);
__ j(not_equal, &try_array);
- __ JumpIfNotSmi(key, &miss);
HandleMonomorphicCase(masm, receiver, key, vector, slot, feedback,
integer_slot, &miss);
// Is it a fixed array?
__ CompareRoot(FieldOperand(feedback, 0), Heap::kFixedArrayMapRootIndex);
__ j(not_equal, ¬_array);
- // We have a polymorphic element handler.
- __ JumpIfNotSmi(key, &miss);
+ // We have a polymorphic element handler.
Label polymorphic, try_poly_name;
__ bind(&polymorphic);
HandleArrayCases(masm, receiver, key, vector, slot, feedback, integer_slot,
__ jmp(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ bind(&done);
context()->Plug(result);
__ jmp(&done);
NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
+ generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
__ bind(&done);
context()->Plug(result);
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Flags: --allow-natives-syntax
+
/**
* @fileoverview Test indexing on strings with [].
*/
assertEquals(expected, actual);
}
+// Test out of range with a heap number case.
+var num = Math.floor(4) * 0.5;
+// TODO(mvstanton): figure out a reliable way to get a heap number every time.
+// assertFalse(!%_IsSmi(num));
+var keys = [0, num];
+var str = 'ab', arr = ['a', undefined];
+for (var i = 0; i < 100; ++i) {
+ var index = Math.floor(i / 50);
+ var key = keys[index];
+ var expected = arr[index];
+ var actual = str[key];
+ assertEquals(expected, actual);
+}
+
// Test two byte string.
var str = '\u0427', arr = ['\u0427'];
for (var i = 0; i < 50; ++i) {