void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
- Register receiver;
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+
+ ASSERT(kind() == Code::LOAD_IC ||
+ kind() == Code::KEYED_LOAD_IC);
+
if (kind() == Code::KEYED_LOAD_IC) {
- // ----------- S t a t e -------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
- __ cmp(r0, Operand(isolate()->factory()->prototype_string()));
+ __ cmp(name, Operand(isolate()->factory()->prototype_string()));
__ b(ne, &miss);
- receiver = r1;
- } else {
- ASSERT(kind() == Code::LOAD_IC);
- // ----------- S t a t e -------------
- // -- r2 : name
- // -- lr : return address
- // -- r0 : receiver
- // -- sp[0] : receiver
- // -----------------------------------
- receiver = r0;
}
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss);
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for keyed IC load (from ic-arm.cc).
- Register receiver = KeyedLoadIC::ReceiverRegister();
- Register name = KeyedLoadIC::NameRegister();
- Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0);
+ GenerateLoadICDebugBreak(masm);
}
break;
case NAMED_PROPERTY:
if (expr->is_compound()) {
- // We need the receiver both on the stack and in the accumulator.
- VisitForAccumulatorValue(property->obj());
- __ push(result_register());
+ // We need the receiver both on the stack and in the register.
+ VisitForStackValue(property->obj());
+ __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
} else {
VisitForStackValue(property->obj());
}
case KEYED_PROPERTY:
if (expr->is_compound()) {
VisitForStackValue(property->obj());
- VisitForAccumulatorValue(property->key());
- __ ldr(r1, MemOperand(sp, 0));
- __ push(r0);
+ VisitForStackValue(property->key());
+ __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
+ __ ldr(LoadIC::NameRegister(), MemOperand(sp, 0));
} else {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
+ Register load_receiver = LoadIC::ReceiverRegister();
+ Register load_name = LoadIC::NameRegister();
+
// Initial send value is undefined.
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
__ b(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
- __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw"
- __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
- __ Push(r2, r3, r0); // "throw", iter, except
+ __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
+ __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
+ __ Push(load_name, r3, r0); // "throw", iter, except
__ jmp(&l_call);
// try { received = %yield result }
// receiver = iter; f = 'next'; arg = received;
__ bind(&l_next);
- Register keyedload_receiver = KeyedLoadIC::ReceiverRegister();
- Register keyedload_name = KeyedLoadIC::NameRegister();
- ASSERT(keyedload_receiver.is(r1));
- ASSERT(keyedload_name.is(r0));
- __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next"
- __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
- __ Push(r2, r3, r0); // "next", iter, received
+ __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
+ __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
+ __ Push(load_name, r3, r0); // "next", iter, received
// result = receiver[f](arg);
__ bind(&l_call);
- __ ldr(keyedload_receiver, MemOperand(sp, kPointerSize));
- __ ldr(keyedload_name, MemOperand(sp, 2 * kPointerSize));
+ __ ldr(load_receiver, MemOperand(sp, kPointerSize));
+ __ ldr(load_name, MemOperand(sp, 2 * kPointerSize));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallIC(ic, TypeFeedbackId::None());
__ mov(r1, r0);
// if (!result.done) goto l_try;
__ bind(&l_loop);
- Register load_receiver = LoadIC::ReceiverRegister();
- Register load_name = LoadIC::NameRegister();
- ASSERT(load_receiver.is(r0));
- ASSERT(load_name.is(r2));
+ __ Move(load_receiver, r0);
__ push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
- ASSERT(r0.is(LoadIC::ReceiverRegister()));
+ __ Move(LoadIC::ReceiverRegister(), r0);
EmitNamedPropertyLoad(expr);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(r0);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- ASSERT(r0.is(KeyedLoadIC::NameRegister()));
- __ pop(KeyedLoadIC::ReceiverRegister());
+ __ Move(LoadIC::NameRegister(), r0);
+ __ pop(LoadIC::ReceiverRegister());
EmitKeyedPropertyLoad(expr);
context()->Plug(r0);
}
Expression* key) {
// Load the key.
VisitForAccumulatorValue(key);
- ASSERT(r0.is(KeyedLoadIC::NameRegister()));
Expression* callee = expr->expression();
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
+ __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
+ __ Move(LoadIC::NameRegister(), r0);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
if (expr->is_jsruntime()) {
// Push the builtins object as the receiver.
- __ ldr(r0, GlobalObjectOperand());
- __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
- __ push(r0);
+ Register receiver = LoadIC::ReceiverRegister();
+ __ ldr(receiver, GlobalObjectOperand());
+ __ ldr(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset));
+ __ push(receiver);
// Load the function from the receiver.
- ASSERT(r0.is(LoadIC::ReceiverRegister()));
__ mov(LoadIC::NameRegister(), Operand(expr->name()));
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
__ push(ip);
}
if (assign_type == NAMED_PROPERTY) {
- // Put the object both on the stack and in the accumulator.
- VisitForAccumulatorValue(prop->obj());
- ASSERT(r0.is(LoadIC::ReceiverRegister()));
- __ push(LoadIC::ReceiverRegister());
+ // Put the object both on the stack and in the register.
+ VisitForStackValue(prop->obj());
+ __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
EmitNamedPropertyLoad(prop);
} else {
VisitForStackValue(prop->obj());
- VisitForAccumulatorValue(prop->key());
- ASSERT(r0.is(KeyedLoadIC::NameRegister()));
- __ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
- __ push(KeyedLoadIC::NameRegister());
+ VisitForStackValue(prop->key());
+ __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
+ __ ldr(LoadIC::NameRegister(), MemOperand(sp, 0));
EmitKeyedPropertyLoad(prop);
}
}
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- r2 : name
- // -- lr : return address
- // -- r0 : receiver
- // -----------------------------------
- ASSERT(r0.is(ReceiverRegister()));
- ASSERT(r2.is(NameRegister()));
+ // The return address is in lr.
+ Register receiver = ReceiverRegister();
+ Register name = NameRegister();
+ ASSERT(receiver.is(r1));
+ ASSERT(name.is(r2));
// Probe the stub cache.
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
masm->isolate()->stub_cache()->GenerateProbe(
- masm, flags, r0, r2, r3, r4, r5, r6);
+ masm, flags, receiver, name, r3, r4, r5, r6);
// Cache miss: Jump to runtime.
GenerateMiss(masm);
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
- // -- r0 : receiver
+ // -- r1 : receiver
// -----------------------------------
- ASSERT(r0.is(ReceiverRegister()));
+ ASSERT(r1.is(ReceiverRegister()));
ASSERT(r2.is(NameRegister()));
Label miss, slow;
- GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
- // r1: elements
- GenerateDictionaryLoad(masm, &slow, r1, r2, r0, r3, r4);
+ // r0: elements
+ GenerateDictionaryLoad(masm, &slow, r0, r2, r0, r3, r4);
__ Ret();
// Dictionary load failed, go slow (but don't miss).
void LoadIC::GenerateMiss(MacroAssembler* masm) {
- // The return address is on the stack.
+ // The return address is in lr.
Isolate* isolate = masm->isolate();
__ IncrementCounter(isolate->counters()->load_miss(), 1, r3, r4);
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // The return address is on the stack.
+ // The return address is in lr.
__ mov(LoadIC_TempRegister(), ReceiverRegister());
__ Push(LoadIC_TempRegister(), NameRegister());
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
- ASSERT(r1.is(ReceiverRegister()));
- ASSERT(r0.is(NameRegister()));
+ // The return address is in lr.
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ ASSERT(receiver.is(r1));
+ ASSERT(key.is(r2));
+
Label slow, notin;
MemOperand mapped_location =
- GenerateMappedArgumentsLookup(masm, r1, r0, r2, r3, r4, ¬in, &slow);
+ GenerateMappedArgumentsLookup(
+ masm, receiver, key, r0, r3, r4, ¬in, &slow);
__ ldr(r0, mapped_location);
__ Ret();
__ bind(¬in);
- // The unmapped lookup expects that the parameter map is in r2.
+ // The unmapped lookup expects that the parameter map is in r0.
MemOperand unmapped_location =
- GenerateUnmappedArgumentsLookup(masm, r0, r2, r3, &slow);
- __ ldr(r2, unmapped_location);
+ GenerateUnmappedArgumentsLookup(masm, key, r0, r3, &slow);
+ __ ldr(r0, unmapped_location);
__ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
- __ cmp(r2, r3);
+ __ cmp(r0, r3);
__ b(eq, &slow);
- __ mov(r0, r2);
__ Ret();
__ bind(&slow);
GenerateMiss(masm);
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
- // The return address is on the stack.
+ // The return address is in lr.
Isolate* isolate = masm->isolate();
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4);
// IC register specifications
-const Register LoadIC::ReceiverRegister() { return r0; }
+const Register LoadIC::ReceiverRegister() { return r1; }
const Register LoadIC::NameRegister() { return r2; }
-const Register KeyedLoadIC::ReceiverRegister() { return r1; }
-const Register KeyedLoadIC::NameRegister() { return r0; }
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // The return address is on the stack.
+ // The return address is in lr.
__ Push(ReceiverRegister(), NameRegister());
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
+ // The return address is in lr.
Label slow, check_name, index_smi, index_name, property_array_property;
Label probe_dictionary, check_number_dictionary;
Register key = NameRegister();
Register receiver = ReceiverRegister();
- ASSERT(key.is(r0));
+ ASSERT(key.is(r2));
ASSERT(receiver.is(r1));
Isolate* isolate = masm->isolate();
// where a numeric string is converted to a smi.
GenerateKeyedLoadReceiverCheck(
- masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow);
+ masm, receiver, r0, r3, Map::kHasIndexedInterceptor, &slow);
// Check the receiver's map to see if it has fast elements.
- __ CheckFastElements(r2, r3, &check_number_dictionary);
+ __ CheckFastElements(r0, r3, &check_number_dictionary);
GenerateFastArrayLoad(
- masm, receiver, key, r4, r3, r2, r0, NULL, &slow);
- __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r2, r3);
+ masm, receiver, key, r0, r3, r4, r0, NULL, &slow);
+ __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3);
__ Ret();
__ bind(&check_number_dictionary);
__ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset));
// Check whether the elements is a number dictionary.
- // r0: key
// r3: elements map
// r4: elements
__ LoadRoot(ip, Heap::kHashTableMapRootIndex);
__ cmp(r3, ip);
__ b(ne, &slow);
- __ SmiUntag(r2, r0);
- __ LoadFromNumberDictionary(&slow, r4, r0, r0, r2, r3, r5);
+ __ SmiUntag(r0, key);
+ __ LoadFromNumberDictionary(&slow, r4, key, r0, r0, r3, r5);
__ Ret();
- // Slow case, key and receiver still in r0 and r1.
+ // Slow case, key and receiver still in r2 and r1.
__ bind(&slow);
__ IncrementCounter(isolate->counters()->keyed_load_generic_slow(),
- 1, r2, r3);
+ 1, r4, r3);
GenerateRuntimeGetProperty(masm);
__ bind(&check_name);
- GenerateKeyNameCheck(masm, key, r2, r3, &index_name, &slow);
+ GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow);
GenerateKeyedLoadReceiverCheck(
- masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow);
+ masm, receiver, r0, r3, Map::kHasNamedInterceptor, &slow);
// If the receiver is a fast-case object, check the keyed lookup
// cache. Otherwise probe the dictionary.
- __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset));
+ __ ldr(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
__ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHashTableMapRootIndex);
__ cmp(r4, ip);
// Load the map of the receiver, compute the keyed lookup cache hash
// based on 32 bits of the map pointer and the name hash.
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
- __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
- __ ldr(r4, FieldMemOperand(r0, Name::kHashFieldOffset));
+ __ ldr(r0, FieldMemOperand(receiver, HeapObject::kMapOffset));
+ __ mov(r3, Operand(r0, ASR, KeyedLookupCache::kMapHashShift));
+ __ ldr(r4, FieldMemOperand(key, Name::kHashFieldOffset));
__ eor(r3, r3, Operand(r4, ASR, Name::kHashShift));
int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
__ And(r3, r3, Operand(mask));
Label try_next_entry;
// Load map and move r4 to next entry.
__ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
- __ cmp(r2, r5);
+ __ cmp(r0, r5);
__ b(ne, &try_next_entry);
__ ldr(r5, MemOperand(r4, -kPointerSize)); // Load name
- __ cmp(r0, r5);
+ __ cmp(key, r5);
__ b(eq, &hit_on_nth_entry[i]);
__ bind(&try_next_entry);
}
// Last entry: Load map and move r4 to name.
__ ldr(r5, MemOperand(r4, kPointerSize, PostIndex));
- __ cmp(r2, r5);
+ __ cmp(r0, r5);
__ b(ne, &slow);
__ ldr(r5, MemOperand(r4));
- __ cmp(r0, r5);
+ __ cmp(key, r5);
__ b(ne, &slow);
// Get field offset.
- // r0 : key
- // r1 : receiver
- // r2 : receiver's map
+ // r0 : receiver's map
// r3 : lookup cache index
ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(isolate);
__ add(r3, r3, Operand(i));
}
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
- __ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
+ __ ldrb(r6, FieldMemOperand(r0, Map::kInObjectPropertiesOffset));
__ sub(r5, r5, r6, SetCC);
__ b(ge, &property_array_property);
if (i != 0) {
// Load in-object property.
__ bind(&load_in_object_property);
- __ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset));
+ __ ldrb(r6, FieldMemOperand(r0, Map::kInstanceSizeOffset));
__ add(r6, r6, r5); // Index from start of object.
- __ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag.
- __ ldr(r0, MemOperand(r1, r6, LSL, kPointerSizeLog2));
+ __ sub(receiver, receiver, Operand(kHeapObjectTag)); // Remove the heap tag.
+ __ ldr(r0, MemOperand(receiver, r6, LSL, kPointerSizeLog2));
__ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
- 1, r2, r3);
+ 1, r4, r3);
__ Ret();
// Load property array property.
__ bind(&property_array_property);
- __ ldr(r1, FieldMemOperand(r1, JSObject::kPropertiesOffset));
- __ add(r1, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
- __ ldr(r0, MemOperand(r1, r5, LSL, kPointerSizeLog2));
+ __ ldr(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+ __ add(receiver, receiver, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+ __ ldr(r0, MemOperand(receiver, r5, LSL, kPointerSizeLog2));
__ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
- 1, r2, r3);
+ 1, r4, r3);
__ Ret();
// Do a quick inline probe of the receiver's dictionary, if it
// exists.
__ bind(&probe_dictionary);
- // r1: receiver
- // r0: key
// r3: elements
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
- __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
- GenerateGlobalInstanceTypeCheck(masm, r2, &slow);
+ __ ldr(r0, FieldMemOperand(receiver, HeapObject::kMapOffset));
+ __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
+ GenerateGlobalInstanceTypeCheck(masm, r0, &slow);
// Load the property to r0.
- GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4);
+ GenerateDictionaryLoad(masm, &slow, r3, key, r0, r5, r4);
__ IncrementCounter(
- isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3);
+ isolate->counters()->keyed_load_generic_symbol(), 1, r4, r3);
__ Ret();
__ bind(&index_name);
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
- // Return address is on the stack.
+ // Return address is in lr.
Label miss;
Register receiver = ReceiverRegister();
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // Return address is on the stack.
+ // Return address is in lr.
Label slow;
Register receiver = ReceiverRegister();
Register key = NameRegister();
- Register scratch1 = r2;
- Register scratch2 = r3;
+ Register scratch1 = r3;
+ Register scratch2 = r4;
ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
ASSERT(!scratch2.is(receiver) && !scratch2.is(key));
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
- LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
+ LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), LoadIC::NameRegister());
LInstruction* result =
DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), r0);
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
- ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
+ ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
+ ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister()));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
// receiver, name, scratch1, scratch2, scratch3, scratch4.
Register receiver = LoadIC::ReceiverRegister();
Register name = LoadIC::NameRegister();
- static Register registers[] = { receiver, name, r3, r1, r4, r5 };
+ static Register registers[] = { receiver, name, r3, r0, r4, r5 };
return registers;
}
Register* KeyedLoadStubCompiler::registers() {
// receiver, name, scratch1, scratch2, scratch3, scratch4.
- Register receiver = KeyedLoadIC::ReceiverRegister();
- Register name = KeyedLoadIC::NameRegister();
- static Register registers[] = { receiver, name, r2, r3, r4, r5 };
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+ static Register registers[] = { receiver, name, r3, r0, r4, r5 };
return registers;
}
void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
- ASSERT(r1.is(KeyedLoadIC::ReceiverRegister()));
- ASSERT(r0.is(KeyedLoadIC::NameRegister()));
+ // The return address is in lr.
Label slow, miss;
- Register key = r0;
- Register receiver = r1;
+ Register key = LoadIC::NameRegister();
+ Register receiver = LoadIC::ReceiverRegister();
+ ASSERT(receiver.is(r1));
+ ASSERT(key.is(r2));
- __ UntagAndJumpIfNotSmi(r2, key, &miss);
+ __ UntagAndJumpIfNotSmi(r6, key, &miss);
__ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
- __ LoadFromNumberDictionary(&slow, r4, key, r0, r2, r3, r5);
+ __ LoadFromNumberDictionary(&slow, r4, key, r0, r6, r3, r5);
__ Ret();
__ bind(&slow);
masm->isolate()->counters()->keyed_load_external_array_slow(),
1, r2, r3);
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
// Miss case, call the runtime.
__ bind(&miss);
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
}
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
- Register receiver;
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+
+ ASSERT(kind() == Code::LOAD_IC ||
+ kind() == Code::KEYED_LOAD_IC);
+
if (kind() == Code::KEYED_LOAD_IC) {
- // ----------- S t a t e -------------
- // -- lr : return address
- // -- x1 : receiver
- // -- x0 : key
- // -----------------------------------
- Register key = x0;
- receiver = x1;
- __ Cmp(key, Operand(isolate()->factory()->prototype_string()));
+ __ Cmp(name, Operand(isolate()->factory()->prototype_string()));
__ B(ne, &miss);
- } else {
- ASSERT(kind() == Code::LOAD_IC);
- // ----------- S t a t e -------------
- // -- lr : return address
- // -- x2 : name
- // -- x0 : receiver
- // -- sp[0] : receiver
- // -----------------------------------
- receiver = x0;
}
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, x10, x11, &miss);
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for keyed IC load (from ic-arm.cc).
- Register receiver = KeyedLoadIC::ReceiverRegister();
- Register name = KeyedLoadIC::NameRegister();
- Generate_DebugBreakCallHelper(masm, receiver.Bit() | name.Bit(), 0, x10);
+ GenerateLoadICDebugBreak(masm);
}
break;
case NAMED_PROPERTY:
if (expr->is_compound()) {
- // We need the receiver both on the stack and in the accumulator.
- VisitForAccumulatorValue(property->obj());
- __ Push(result_register());
+ // We need the receiver both on the stack and in the register.
+ VisitForStackValue(property->obj());
+ __ Peek(LoadIC::ReceiverRegister(), 0);
} else {
VisitForStackValue(property->obj());
}
case KEYED_PROPERTY:
if (expr->is_compound()) {
VisitForStackValue(property->obj());
- VisitForAccumulatorValue(property->key());
- __ Peek(x1, 0);
- __ Push(x0);
+ VisitForStackValue(property->key());
+ __ Peek(LoadIC::ReceiverRegister(), 1 * kPointerSize);
+ __ Peek(LoadIC::NameRegister(), 0);
} else {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
- ASSERT(x0.is(LoadIC::ReceiverRegister()));
+ __ Move(LoadIC::ReceiverRegister(), x0);
EmitNamedPropertyLoad(expr);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(x0);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- ASSERT(x0.is(KeyedLoadIC::NameRegister()));
- __ Pop(KeyedLoadIC::ReceiverRegister());
+ __ Move(LoadIC::NameRegister(), x0);
+ __ Pop(LoadIC::ReceiverRegister());
EmitKeyedPropertyLoad(expr);
context()->Plug(x0);
}
Expression* key) {
// Load the key.
VisitForAccumulatorValue(key);
- ASSERT(x0.is(KeyedLoadIC::NameRegister()));
Expression* callee = expr->expression();
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ Peek(KeyedLoadIC::ReceiverRegister(), 0);
+ __ Peek(LoadIC::ReceiverRegister(), 0);
+ __ Move(LoadIC::NameRegister(), x0);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
__ Push(xzr);
}
if (assign_type == NAMED_PROPERTY) {
- // Put the object both on the stack and in the accumulator.
- VisitForAccumulatorValue(prop->obj());
- ASSERT(x0.is(LoadIC::ReceiverRegister()));
- __ Push(LoadIC::ReceiverRegister());
+ // Put the object both on the stack and in the register.
+ VisitForStackValue(prop->obj());
+ __ Peek(LoadIC::ReceiverRegister(), 0);
EmitNamedPropertyLoad(prop);
} else {
// KEYED_PROPERTY
VisitForStackValue(prop->obj());
- VisitForAccumulatorValue(prop->key());
- ASSERT(x0.is(KeyedLoadIC::NameRegister()));
- __ Peek(KeyedLoadIC::ReceiverRegister(), 0);
- __ Push(KeyedLoadIC::NameRegister());
+ VisitForStackValue(prop->key());
+ __ Peek(LoadIC::ReceiverRegister(), 1 * kPointerSize);
+ __ Peek(LoadIC::NameRegister(), 0);
EmitKeyedPropertyLoad(prop);
}
}
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
+ Register load_receiver = LoadIC::ReceiverRegister();
+ Register load_name = LoadIC::NameRegister();
+
// Initial send value is undefined.
__ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
__ B(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ Bind(&l_catch);
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
- __ LoadRoot(x2, Heap::kthrow_stringRootIndex); // "throw"
- __ Peek(x3, 1 * kPointerSize); // iter
- __ Push(x2, x3, x0); // "throw", iter, except
+ __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
+ __ Peek(x3, 1 * kPointerSize); // iter
+ __ Push(load_name, x3, x0); // "throw", iter, except
__ B(&l_call);
// try { received = %yield result }
// receiver = iter; f = 'next'; arg = received;
__ Bind(&l_next);
- Register keyedload_receiver = KeyedLoadIC::ReceiverRegister();
- Register keyedload_name = KeyedLoadIC::NameRegister();
- ASSERT(keyedload_receiver.is(x1));
- ASSERT(keyedload_name.is(x0));
- __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next"
- __ Peek(x3, 1 * kPointerSize); // iter
- __ Push(x2, x3, x0); // "next", iter, received
+ __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
+ __ Peek(x3, 1 * kPointerSize); // iter
+ __ Push(load_name, x3, x0); // "next", iter, received
// result = receiver[f](arg);
__ Bind(&l_call);
- __ Peek(keyedload_receiver, 1 * kPointerSize);
- __ Peek(keyedload_name, 2 * kPointerSize);
+ __ Peek(load_receiver, 1 * kPointerSize);
+ __ Peek(load_name, 2 * kPointerSize);
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallIC(ic, TypeFeedbackId::None());
__ Mov(x1, x0);
// if (!result.done) goto l_try;
__ Bind(&l_loop);
- Register load_receiver = LoadIC::ReceiverRegister();
- Register load_name = LoadIC::NameRegister();
- ASSERT(load_receiver.is(x0));
- ASSERT(load_name.is(x2));
+ __ Move(load_receiver, x0);
+
__ Push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
CallLoadIC(NOT_CONTEXTUAL); // x0=result.done
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- x2 : name
- // -- lr : return address
- // -- x0 : receiver
- // -----------------------------------
- ASSERT(x0.is(ReceiverRegister()));
- ASSERT(x2.is(NameRegister()));
+ // The return address is in lr.
+ Register receiver = ReceiverRegister();
+ Register name = NameRegister();
+ ASSERT(receiver.is(x1));
+ ASSERT(name.is(x2));
// Probe the stub cache.
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
masm->isolate()->stub_cache()->GenerateProbe(
- masm, flags, x0, x2, x3, x4, x5, x6);
+ masm, flags, receiver, name, x3, x4, x5, x6);
// Cache miss: Jump to runtime.
GenerateMiss(masm);
// ----------- S t a t e -------------
// -- x2 : name
// -- lr : return address
- // -- x0 : receiver
+ // -- x1 : receiver
// -----------------------------------
- ASSERT(x0.is(ReceiverRegister()));
+ ASSERT(x1.is(ReceiverRegister()));
ASSERT(x2.is(NameRegister()));
Label miss, slow;
- GenerateNameDictionaryReceiverCheck(masm, x0, x1, x3, x4, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, x1, x0, x3, x4, &miss);
- // x1 now holds the property dictionary.
- GenerateDictionaryLoad(masm, &slow, x1, x2, x0, x3, x4);
+ // x0 now holds the property dictionary.
+ GenerateDictionaryLoad(masm, &slow, x0, x2, x0, x3, x4);
__ Ret();
// Dictionary load failed, go slow (but don't miss).
void LoadIC::GenerateMiss(MacroAssembler* masm) {
- // The return address is on the stack.
+ // The return address is in lr.
Isolate* isolate = masm->isolate();
ASM_LOCATION("LoadIC::GenerateMiss");
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // The return address is on the stack.
+ // The return address is in lr.
__ Push(ReceiverRegister(), NameRegister());
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
}
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- x0 : key
- // -- x1 : receiver
- // -----------------------------------
+ // The return address is in lr.
Register result = x0;
Register receiver = ReceiverRegister();
Register key = NameRegister();
ASSERT(receiver.is(x1));
- ASSERT(key.is(x0));
+ ASSERT(key.is(x2));
Label miss, unmapped;
- Register map_scratch = x2;
+ Register map_scratch = x0;
MemOperand mapped_location = GenerateMappedArgumentsLookup(
masm, receiver, key, map_scratch, x3, x4, &unmapped, &miss);
__ Ldr(result, mapped_location);
// Parameter map is left in map_scratch when a jump on unmapped is done.
MemOperand unmapped_location =
GenerateUnmappedArgumentsLookup(masm, key, map_scratch, x3, &miss);
- __ Ldr(x2, unmapped_location);
- __ JumpIfRoot(x2, Heap::kTheHoleValueRootIndex, &miss);
- // Move the result in x0. x0 must be preserved on miss.
- __ Mov(result, x2);
+ __ Ldr(result, unmapped_location);
+ __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss);
__ Ret();
__ Bind(&miss);
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
- // The return address is on the stack.
+ // The return address is in lr.
Isolate* isolate = masm->isolate();
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11);
// IC register specifications
-const Register LoadIC::ReceiverRegister() { return x0; }
+const Register LoadIC::ReceiverRegister() { return x1; }
const Register LoadIC::NameRegister() { return x2; }
-const Register KeyedLoadIC::ReceiverRegister() { return x1; }
-const Register KeyedLoadIC::NameRegister() { return x0; }
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // The return address is on the stack.
+ // The return address is in lr.
__ Push(ReceiverRegister(), NameRegister());
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
}
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- x0 : key
- // -- x1 : receiver
- // -----------------------------------
+ // The return address is in lr.
Label slow, check_name, index_smi, index_name;
Register key = NameRegister();
Register receiver = ReceiverRegister();
- ASSERT(key.is(x0));
+ ASSERT(key.is(x2));
ASSERT(receiver.is(x1));
__ JumpIfNotSmi(key, &check_name);
__ Bind(&index_smi);
// Now the key is known to be a smi. This place is also jumped to from below
// where a numeric string is converted to a smi.
- GenerateKeyedLoadWithSmiKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow);
+ GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow);
- // Slow case, key and receiver still in x0 and x1.
+ // Slow case.
__ Bind(&slow);
__ IncrementCounter(
- masm->isolate()->counters()->keyed_load_generic_slow(), 1, x2, x3);
+ masm->isolate()->counters()->keyed_load_generic_slow(), 1, x4, x3);
GenerateRuntimeGetProperty(masm);
__ Bind(&check_name);
- GenerateKeyNameCheck(masm, key, x2, x3, &index_name, &slow);
+ GenerateKeyNameCheck(masm, key, x0, x3, &index_name, &slow);
- GenerateKeyedLoadWithNameKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow);
+ GenerateKeyedLoadWithNameKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow);
__ Bind(&index_name);
__ IndexFromHash(x3, key);
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
- // Return address is on the stack.
+ // Return address is in lr.
Label miss;
Register receiver = ReceiverRegister();
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // Return address is on the stack.
+ // Return address is in lr.
Label slow;
Register receiver = ReceiverRegister();
Register key = NameRegister();
- Register scratch1 = x2;
- Register scratch2 = x3;
- ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
- ASSERT(!scratch2.is(receiver) && !scratch2.is(key));
+ Register scratch1 = x3;
+ Register scratch2 = x4;
+ ASSERT(!AreAliased(scratch1, scratch2, receiver, key));
// Check that the receiver isn't a smi.
__ JumpIfSmi(receiver, &slow);
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
- LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
+ LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), LoadIC::NameRegister());
LInstruction* result =
DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), x0);
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
- ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
+ ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
+ ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister()));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
ASSERT(ToRegister(instr->context()).is(cp));
// LoadIC expects name and receiver in registers.
ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
- ASSERT(ToRegister(instr->object()).is(x0));
__ Mov(LoadIC::NameRegister(), Operand(instr->name()));
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
// receiver, name, scratch1, scratch2, scratch3, scratch4.
Register receiver = LoadIC::ReceiverRegister();
Register name = LoadIC::NameRegister();
- static Register registers[] = { receiver, name, x3, x1, x4, x5 };
+ static Register registers[] = { receiver, name, x3, x0, x4, x5 };
return registers;
}
Register* KeyedLoadStubCompiler::registers() {
// receiver, name, scratch1, scratch2, scratch3, scratch4.
- Register receiver = KeyedLoadIC::ReceiverRegister();
- Register name = KeyedLoadIC::NameRegister();
- static Register registers[] = { receiver, name, x2, x3, x4, x5 };
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+ static Register registers[] = { receiver, name, x3, x0, x4, x5 };
return registers;
}
void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- x0 : key
- // -- x1 : receiver
- // -----------------------------------
- ASSERT(x1.is(KeyedLoadIC::ReceiverRegister()));
- ASSERT(x0.is(KeyedLoadIC::NameRegister()));
+ // The return address is in lr.
Label slow, miss;
Register result = x0;
- Register key = x0;
- Register receiver = x1;
+ Register key = LoadIC::NameRegister();
+ Register receiver = LoadIC::ReceiverRegister();
+ ASSERT(receiver.is(x1));
+ ASSERT(key.is(x2));
__ JumpIfNotSmi(key, &miss);
__ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset));
- __ LoadFromNumberDictionary(&slow, x4, key, result, x2, x3, x5, x6);
+ __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6);
__ Ret();
__ Bind(&slow);
__ IncrementCounter(
- masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x2, x3);
+ masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3);
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
// Miss case, call the runtime.
void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { KeyedLoadIC::ReceiverRegister(),
- KeyedLoadIC::NameRegister() };
- STATIC_ASSERT(KeyedLoadIC::kRegisterArgumentCount == 2);
+ Register registers[] = { LoadIC::ReceiverRegister(),
+ LoadIC::NameRegister() };
+ STATIC_ASSERT(LoadIC::kRegisterArgumentCount == 2);
descriptor->Initialize(ARRAY_SIZE(registers), registers,
FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
}
void KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { KeyedLoadIC::ReceiverRegister(),
- KeyedLoadIC::NameRegister() };
- STATIC_ASSERT(KeyedLoadIC::kRegisterArgumentCount == 2);
+ Register registers[] = { LoadIC::ReceiverRegister(),
+ LoadIC::NameRegister() };
+ STATIC_ASSERT(LoadIC::kRegisterArgumentCount == 2);
descriptor->Initialize(ARRAY_SIZE(registers), registers,
FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
}
void KeyedLoadGenericElementStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { KeyedLoadIC::ReceiverRegister(),
- KeyedLoadIC::NameRegister() };
- STATIC_ASSERT(KeyedLoadIC::kRegisterArgumentCount == 2);
+ Register registers[] = { LoadIC::ReceiverRegister(),
+ LoadIC::NameRegister() };
+ STATIC_ASSERT(LoadIC::kRegisterArgumentCount == 2);
descriptor->Initialize(
ARRAY_SIZE(registers), registers,
Runtime::FunctionForId(Runtime::kKeyedGetProperty)->entry);
void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { KeyedLoadIC::ReceiverRegister() };
+ Register registers[] = { LoadIC::ReceiverRegister() };
descriptor->Initialize(ARRAY_SIZE(registers), registers);
}
void KeyedStringLengthStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { KeyedLoadIC::ReceiverRegister(),
- KeyedLoadIC::NameRegister() };
+ Register registers[] = { LoadIC::ReceiverRegister(),
+ LoadIC::NameRegister() };
descriptor->Initialize(ARRAY_SIZE(registers), registers);
}
// Copy all arguments from the array to the stack.
Label entry, loop;
- __ mov(ecx, Operand(ebp, kIndexOffset));
+ Register receiver = LoadIC::ReceiverRegister();
+ Register key = LoadIC::NameRegister();
+ __ mov(key, Operand(ebp, kIndexOffset));
__ jmp(&entry);
__ bind(&loop);
- __ mov(edx, Operand(ebp, kArgumentsOffset)); // load arguments
+ __ mov(receiver, Operand(ebp, kArgumentsOffset)); // load arguments
// Use inline caching to speed up access to arguments.
Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize();
// Push the nth argument.
__ push(eax);
- // Update the index on the stack and in register eax.
- __ mov(ecx, Operand(ebp, kIndexOffset));
- __ add(ecx, Immediate(1 << kSmiTagSize));
- __ mov(Operand(ebp, kIndexOffset), ecx);
+ // Update the index on the stack and in register key.
+ __ mov(key, Operand(ebp, kIndexOffset));
+ __ add(key, Immediate(1 << kSmiTagSize));
+ __ mov(Operand(ebp, kIndexOffset), key);
__ bind(&entry);
- __ cmp(ecx, Operand(ebp, kLimitOffset));
+ __ cmp(key, Operand(ebp, kLimitOffset));
__ j(not_equal, &loop);
// Call the function.
Label call_proxy;
- __ mov(eax, ecx);
ParameterCount actual(eax);
+ __ Move(eax, key);
__ SmiUntag(eax);
__ mov(edi, Operand(ebp, kFunctionOffset));
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC load call (from ic-ia32.cc).
- Register receiver = KeyedLoadIC::ReceiverRegister();
- Register name = KeyedLoadIC::NameRegister();
- Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
+ GenerateLoadICDebugBreak(masm);
}
break;
case NAMED_PROPERTY:
if (expr->is_compound()) {
- // We need the receiver both on the stack and in edx.
+ // We need the receiver both on the stack and in the register.
VisitForStackValue(property->obj());
- __ mov(edx, Operand(esp, 0));
+ __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
} else {
VisitForStackValue(property->obj());
}
if (expr->is_compound()) {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
- __ mov(edx, Operand(esp, kPointerSize)); // Object.
- __ mov(ecx, Operand(esp, 0)); // Key.
+ __ mov(LoadIC::ReceiverRegister(), Operand(esp, kPointerSize));
+ __ mov(LoadIC::NameRegister(), Operand(esp, 0));
} else {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
+ Register load_receiver = LoadIC::ReceiverRegister();
+ Register load_name = LoadIC::NameRegister();
+
// Initial send value is undefined.
__ mov(eax, isolate()->factory()->undefined_value());
__ jmp(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
- __ mov(ecx, isolate()->factory()->throw_string()); // "throw"
- __ push(ecx); // "throw"
- __ push(Operand(esp, 2 * kPointerSize)); // iter
- __ push(eax); // exception
+ __ mov(load_name, isolate()->factory()->throw_string()); // "throw"
+ __ push(load_name); // "throw"
+ __ push(Operand(esp, 2 * kPointerSize)); // iter
+ __ push(eax); // exception
__ jmp(&l_call);
// try { received = %yield result }
// receiver = iter; f = iter.next; arg = received;
__ bind(&l_next);
- Register keyedload_receiver = KeyedLoadIC::ReceiverRegister();
- Register keyedload_name = KeyedLoadIC::NameRegister();
- ASSERT(keyedload_receiver.is(edx));
- ASSERT(keyedload_name.is(ecx));
- __ mov(keyedload_name,
- isolate()->factory()->next_string()); // "next"
- __ push(keyedload_name);
- __ push(Operand(esp, 2 * kPointerSize)); // iter
- __ push(eax); // received
+ __ mov(load_name, isolate()->factory()->next_string());
+ __ push(load_name); // "next"
+ __ push(Operand(esp, 2 * kPointerSize)); // iter
+ __ push(eax); // received
// result = receiver[f](arg);
__ bind(&l_call);
- __ mov(keyedload_receiver, Operand(esp, kPointerSize));
+ __ mov(load_receiver, Operand(esp, kPointerSize));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallIC(ic, TypeFeedbackId::None());
__ mov(edi, eax);
// if (!result.done) goto l_try;
__ bind(&l_loop);
__ push(eax); // save result
- Register load_receiver = LoadIC::ReceiverRegister();
- Register load_name = LoadIC::NameRegister();
- ASSERT(load_receiver.is(edx));
- ASSERT(load_name.is(ecx));
- __ mov(load_receiver, eax); // result
+ __ Move(load_receiver, eax); // result
__ mov(load_name,
isolate()->factory()->done_string()); // "done"
CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
- __ mov(LoadIC::ReceiverRegister(), result_register());
+ __ Move(LoadIC::ReceiverRegister(), result_register());
EmitNamedPropertyLoad(expr);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(eax);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- __ pop(KeyedLoadIC::ReceiverRegister()); // Object.
- __ mov(KeyedLoadIC::NameRegister(), result_register()); // Key.
+ __ pop(LoadIC::ReceiverRegister()); // Object.
+ __ Move(LoadIC::NameRegister(), result_register()); // Key.
EmitKeyedPropertyLoad(expr);
context()->Plug(eax);
}
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ mov(KeyedLoadIC::ReceiverRegister(), Operand(esp, 0));
- // Move the key into the right register for the keyed load IC.
- __ mov(KeyedLoadIC::NameRegister(), eax);
+ __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
+ __ mov(LoadIC::NameRegister(), eax);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
__ push(Immediate(Smi::FromInt(0)));
}
if (assign_type == NAMED_PROPERTY) {
- // Put the object both on the stack and in edx.
- VisitForAccumulatorValue(prop->obj());
- ASSERT(!eax.is(LoadIC::ReceiverRegister()));
- __ push(eax);
- __ mov(LoadIC::ReceiverRegister(), eax);
+ // Put the object both on the stack and in the register.
+ VisitForStackValue(prop->obj());
+ __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
EmitNamedPropertyLoad(prop);
} else {
VisitForStackValue(prop->obj());
VisitForStackValue(prop->key());
- __ mov(KeyedLoadIC::ReceiverRegister(),
- Operand(esp, kPointerSize)); // Object.
- __ mov(KeyedLoadIC::NameRegister(), Operand(esp, 0)); // Key.
+ __ mov(LoadIC::ReceiverRegister(),
+ Operand(esp, kPointerSize)); // Object.
+ __ mov(LoadIC::NameRegister(), Operand(esp, 0)); // Key.
EmitKeyedPropertyLoad(prop);
}
}
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- ASSERT(edx.is(ReceiverRegister()));
- ASSERT(ecx.is(NameRegister()));
+ // The return address is on the stack.
Label slow, check_name, index_smi, index_name, property_array_property;
Label probe_dictionary, check_number_dictionary;
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ ASSERT(receiver.is(edx));
+ ASSERT(key.is(ecx));
+
// Check that the key is a smi.
- __ JumpIfNotSmi(ecx, &check_name);
+ __ JumpIfNotSmi(key, &check_name);
__ bind(&index_smi);
// Now the key is known to be a smi. This place is also jumped to from
// where a numeric string is converted to a smi.
GenerateKeyedLoadReceiverCheck(
- masm, edx, eax, Map::kHasIndexedInterceptor, &slow);
+ masm, receiver, eax, Map::kHasIndexedInterceptor, &slow);
// Check the receiver's map to see if it has fast elements.
__ CheckFastElements(eax, &check_number_dictionary);
- GenerateFastArrayLoad(masm, edx, ecx, eax, eax, NULL, &slow);
+ GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow);
Isolate* isolate = masm->isolate();
Counters* counters = isolate->counters();
__ IncrementCounter(counters->keyed_load_generic_smi(), 1);
__ ret(0);
__ bind(&check_number_dictionary);
- __ mov(ebx, ecx);
+ __ mov(ebx, key);
__ SmiUntag(ebx);
- __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset));
+ __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset));
// Check whether the elements is a number dictionary.
- // edx: receiver
// ebx: untagged index
- // ecx: key
// eax: elements
__ CheckMap(eax,
isolate->factory()->hash_table_map(),
Label slow_pop_receiver;
// Push receiver on the stack to free up a register for the dictionary
// probing.
- __ push(edx);
- __ LoadFromNumberDictionary(&slow_pop_receiver, eax, ecx, ebx, edx, edi, eax);
+ __ push(receiver);
+ __ LoadFromNumberDictionary(&slow_pop_receiver, eax, key, ebx, edx, edi, eax);
// Pop receiver before returning.
- __ pop(edx);
+ __ pop(receiver);
__ ret(0);
__ bind(&slow_pop_receiver);
// Pop the receiver from the stack and jump to runtime.
- __ pop(edx);
+ __ pop(receiver);
__ bind(&slow);
// Slow case: jump to runtime.
- // edx: receiver
- // ecx: key
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
GenerateRuntimeGetProperty(masm);
__ bind(&check_name);
- GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow);
+ GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
GenerateKeyedLoadReceiverCheck(
- masm, edx, eax, Map::kHasNamedInterceptor, &slow);
+ masm, receiver, eax, Map::kHasNamedInterceptor, &slow);
// If the receiver is a fast-case object, check the keyed lookup
// cache. Otherwise probe the dictionary.
- __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
+ __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset));
__ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
Immediate(isolate->factory()->hash_table_map()));
__ j(equal, &probe_dictionary);
// The receiver's map is still in eax, compute the keyed lookup cache hash
// based on 32 bits of the map pointer and the string hash.
if (FLAG_debug_code) {
- __ cmp(eax, FieldOperand(edx, HeapObject::kMapOffset));
+ __ cmp(eax, FieldOperand(receiver, HeapObject::kMapOffset));
__ Check(equal, kMapIsNoLongerInEax);
}
__ mov(ebx, eax); // Keep the map around for later.
__ shr(eax, KeyedLookupCache::kMapHashShift);
- __ mov(edi, FieldOperand(ecx, String::kHashFieldOffset));
+ __ mov(edi, FieldOperand(key, String::kHashFieldOffset));
__ shr(edi, String::kHashShift);
__ xor_(eax, edi);
__ and_(eax, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &try_next_entry);
__ add(edi, Immediate(kPointerSize));
- __ cmp(ecx, Operand::StaticArray(edi, times_1, cache_keys));
+ __ cmp(key, Operand::StaticArray(edi, times_1, cache_keys));
__ j(equal, &hit_on_nth_entry[i]);
__ bind(&try_next_entry);
}
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &slow);
__ add(edi, Immediate(kPointerSize));
- __ cmp(ecx, Operand::StaticArray(edi, times_1, cache_keys));
+ __ cmp(key, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &slow);
// Get field offset.
- // edx : receiver
- // ebx : receiver's map
- // ecx : key
- // eax : lookup cache index
+ // ebx : receiver's map
+ // eax : lookup cache index
ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
__ bind(&load_in_object_property);
__ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset));
__ add(eax, edi);
- __ mov(eax, FieldOperand(edx, eax, times_pointer_size, 0));
+ __ mov(eax, FieldOperand(receiver, eax, times_pointer_size, 0));
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
__ ret(0);
// Load property array property.
__ bind(&property_array_property);
- __ mov(eax, FieldOperand(edx, JSObject::kPropertiesOffset));
+ __ mov(eax, FieldOperand(receiver, JSObject::kPropertiesOffset));
__ mov(eax, FieldOperand(eax, edi, times_pointer_size,
FixedArray::kHeaderSize));
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
// exists.
__ bind(&probe_dictionary);
- __ mov(eax, FieldOperand(edx, JSObject::kMapOffset));
+ __ mov(eax, FieldOperand(receiver, JSObject::kMapOffset));
__ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
GenerateGlobalInstanceTypeCheck(masm, eax, &slow);
- GenerateDictionaryLoad(masm, &slow, ebx, ecx, eax, edi, eax);
+ GenerateDictionaryLoad(masm, &slow, ebx, key, eax, edi, eax);
__ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
__ ret(0);
__ bind(&index_name);
- __ IndexFromHash(ebx, ecx);
+ __ IndexFromHash(ebx, key);
// Now jump to the place where smi keys are handled.
__ jmp(&index_smi);
}
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- ASSERT(edx.is(ReceiverRegister()));
- ASSERT(ecx.is(NameRegister()));
+ // The return address is on the stack.
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ ASSERT(receiver.is(edx));
+ ASSERT(key.is(ecx));
+
Label slow, notin;
Factory* factory = masm->isolate()->factory();
Operand mapped_location =
- GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, ¬in, &slow);
+ GenerateMappedArgumentsLookup(
+ masm, receiver, key, ebx, eax, ¬in, &slow);
__ mov(eax, mapped_location);
__ Ret();
__ bind(¬in);
// The unmapped lookup expects that the parameter map is in ebx.
Operand unmapped_location =
- GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow);
+ GenerateUnmappedArgumentsLookup(masm, key, ebx, eax, &slow);
__ cmp(unmapped_location, factory->the_hole_value());
__ j(equal, &slow);
__ mov(eax, unmapped_location);
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : name
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- ASSERT(edx.is(ReceiverRegister()));
- ASSERT(ecx.is(NameRegister()));
+ // The return address is on the stack.
+ Register receiver = ReceiverRegister();
+ Register name = NameRegister();
+ ASSERT(receiver.is(edx));
+ ASSERT(name.is(ecx));
// Probe the stub cache.
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
masm->isolate()->stub_cache()->GenerateProbe(
- masm, flags, edx, ecx, ebx, eax);
+ masm, flags, receiver, name, ebx, eax);
// Cache miss: Jump to runtime.
GenerateMiss(masm);
const Register LoadIC::NameRegister() { return ecx; }
-const Register KeyedLoadIC::ReceiverRegister() {
- return LoadIC::ReceiverRegister();
-}
-
-
-const Register KeyedLoadIC::NameRegister() { return LoadIC::NameRegister(); }
-
-
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
// Return address is on the stack.
__ pop(KeyedLoadIC_TempRegister());
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
- ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
- ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
+ ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
+ ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister()));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
- LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
- LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
+ LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), LoadIC::NameRegister());
LLoadKeyedGeneric* result =
new(zone()) LLoadKeyedGeneric(context, object, key);
Register* KeyedLoadStubCompiler::registers() {
// receiver, name, scratch1, scratch2, scratch3, scratch4.
- Register receiver = KeyedLoadIC::ReceiverRegister();
- Register name = KeyedLoadIC::NameRegister();
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
static Register registers[] = { receiver, name, ebx, eax, edi, no_reg };
return registers;
}
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
- ASSERT(edx.is(KeyedLoadIC::ReceiverRegister()));
- ASSERT(ecx.is(KeyedLoadIC::NameRegister()));
+ ASSERT(edx.is(LoadIC::ReceiverRegister()));
+ ASSERT(ecx.is(LoadIC::NameRegister()));
Label slow, miss;
// This stub is meant to be tail-jumped to, the receiver must already
ASSERT(target()->is_keyed_load_stub());
}
- static const Register ReceiverRegister();
- static const Register NameRegister();
-
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
Handle<Object> key);
// Copy all arguments from the array to the stack.
Label entry, loop;
- __ movp(rax, Operand(rbp, kIndexOffset));
+ Register receiver = LoadIC::ReceiverRegister();
+ Register key = LoadIC::NameRegister();
+ __ movp(key, Operand(rbp, kIndexOffset));
__ jmp(&entry);
__ bind(&loop);
- __ movp(rdx, Operand(rbp, kArgumentsOffset)); // load arguments
+ __ movp(receiver, Operand(rbp, kArgumentsOffset)); // load arguments
// Use inline caching to speed up access to arguments.
Handle<Code> ic =
// Push the nth argument.
__ Push(rax);
- // Update the index on the stack and in register rax.
- __ movp(rax, Operand(rbp, kIndexOffset));
- __ SmiAddConstant(rax, rax, Smi::FromInt(1));
- __ movp(Operand(rbp, kIndexOffset), rax);
+ // Update the index on the stack and in register key.
+ __ movp(key, Operand(rbp, kIndexOffset));
+ __ SmiAddConstant(key, key, Smi::FromInt(1));
+ __ movp(Operand(rbp, kIndexOffset), key);
__ bind(&entry);
- __ cmpp(rax, Operand(rbp, kLimitOffset));
+ __ cmpp(key, Operand(rbp, kLimitOffset));
__ j(not_equal, &loop);
// Call the function.
Label call_proxy;
ParameterCount actual(rax);
- __ SmiToInteger32(rax, rax);
+ __ SmiToInteger32(rax, key);
__ movp(rdi, Operand(rbp, kFunctionOffset));
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &call_proxy);
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
- Register receiver;
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+
+ ASSERT(kind() == Code::LOAD_IC ||
+ kind() == Code::KEYED_LOAD_IC);
+
if (kind() == Code::KEYED_LOAD_IC) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- __ Cmp(rax, isolate()->factory()->prototype_string());
+ __ Cmp(name, isolate()->factory()->prototype_string());
__ j(not_equal, &miss);
- receiver = rdx;
- } else {
- ASSERT(kind() == Code::LOAD_IC);
- // ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
- // -- rsp[0] : return address
- // -----------------------------------
- receiver = rax;
}
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss);
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC load call (from ic-x64.cc).
- Register receiver = KeyedLoadIC::ReceiverRegister();
- Register name = KeyedLoadIC::NameRegister();
- Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
+ GenerateLoadICDebugBreak(masm);
}
break;
case NAMED_PROPERTY:
if (expr->is_compound()) {
- // We need the receiver both on the stack and in the accumulator.
- VisitForAccumulatorValue(property->obj());
- __ Push(result_register());
+ // We need the receiver both on the stack and in the register.
+ VisitForStackValue(property->obj());
+ __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
} else {
VisitForStackValue(property->obj());
}
case KEYED_PROPERTY: {
if (expr->is_compound()) {
VisitForStackValue(property->obj());
- VisitForAccumulatorValue(property->key());
- __ movp(rdx, Operand(rsp, 0));
- __ Push(rax);
+ VisitForStackValue(property->key());
+ __ movp(LoadIC::ReceiverRegister(), Operand(rsp, kPointerSize));
+ __ movp(LoadIC::NameRegister(), Operand(rsp, 0));
} else {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
+ Register load_receiver = LoadIC::ReceiverRegister();
+ Register load_name = LoadIC::NameRegister();
+
// Initial send value is undefined.
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
__ jmp(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
- __ LoadRoot(rcx, Heap::kthrow_stringRootIndex); // "throw"
- __ Push(rcx);
- __ Push(Operand(rsp, 2 * kPointerSize)); // iter
- __ Push(rax); // exception
+ __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
+ __ Push(load_name);
+ __ Push(Operand(rsp, 2 * kPointerSize)); // iter
+ __ Push(rax); // exception
__ jmp(&l_call);
// try { received = %yield result }
// receiver = iter; f = 'next'; arg = received;
__ bind(&l_next);
- Register keyedload_receiver = KeyedLoadIC::ReceiverRegister();
- Register keyedload_name = KeyedLoadIC::NameRegister();
- ASSERT(keyedload_receiver.is(rdx));
- ASSERT(keyedload_name.is(rax));
- __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next"
- __ Push(rcx);
- __ Push(Operand(rsp, 2 * kPointerSize)); // iter
- __ Push(rax); // received
+ __ LoadRoot(load_name, Heap::knext_stringRootIndex);
+ __ Push(load_name); // "next"
+ __ Push(Operand(rsp, 2 * kPointerSize)); // iter
+ __ Push(rax); // received
// result = receiver[f](arg);
__ bind(&l_call);
- __ movp(keyedload_receiver, Operand(rsp, kPointerSize));
- __ movp(keyedload_name, Operand(rsp, 2 * kPointerSize));
+ __ movp(load_receiver, Operand(rsp, kPointerSize));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallIC(ic, TypeFeedbackId::None());
__ movp(rdi, rax);
// if (!result.done) goto l_try;
__ bind(&l_loop);
- Register load_receiver = LoadIC::ReceiverRegister();
- Register load_name = LoadIC::NameRegister();
- ASSERT(load_receiver.is(rax));
- ASSERT(load_name.is(rcx));
-
+ __ Move(load_receiver, rax);
__ Push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
CallLoadIC(NOT_CONTEXTUAL); // rax=result.done
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
- ASSERT(rax.is(LoadIC::ReceiverRegister()));
+ ASSERT(!rax.is(LoadIC::ReceiverRegister()));
+ __ movp(LoadIC::ReceiverRegister(), rax);
EmitNamedPropertyLoad(expr);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(rax);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- ASSERT(rax.is(KeyedLoadIC::NameRegister()));
- __ Pop(KeyedLoadIC::ReceiverRegister());
+ __ Move(LoadIC::NameRegister(), rax);
+ __ Pop(LoadIC::ReceiverRegister());
EmitKeyedPropertyLoad(expr);
context()->Plug(rax);
}
Expression* key) {
// Load the key.
VisitForAccumulatorValue(key);
- ASSERT(rax.is(KeyedLoadIC::NameRegister()));
Expression* callee = expr->expression();
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0));
+ __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
+ __ Move(LoadIC::NameRegister(), rax);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
__ Push(Smi::FromInt(0));
}
if (assign_type == NAMED_PROPERTY) {
- VisitForAccumulatorValue(prop->obj());
- ASSERT(rax.is(LoadIC::ReceiverRegister()));
- __ Push(rax); // Copy of receiver, needed for later store.
+ VisitForStackValue(prop->obj());
+ __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
EmitNamedPropertyLoad(prop);
} else {
VisitForStackValue(prop->obj());
- VisitForAccumulatorValue(prop->key());
- ASSERT(rax.is(KeyedLoadIC::NameRegister()));
+ VisitForStackValue(prop->key());
// Leave receiver on stack
- __ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0));
+ __ movp(LoadIC::ReceiverRegister(), Operand(rsp, kPointerSize));
// Copy of key, needed for later store.
- __ Push(KeyedLoadIC::NameRegister());
+ __ movp(LoadIC::NameRegister(), Operand(rsp, 0));
EmitKeyedPropertyLoad(prop);
}
}
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- ASSERT(rdx.is(ReceiverRegister()));
- ASSERT(rax.is(NameRegister()));
+ // The return address is on the stack.
Label slow, check_name, index_smi, index_name, property_array_property;
Label probe_dictionary, check_number_dictionary;
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ ASSERT(receiver.is(rdx));
+ ASSERT(key.is(rcx));
+
// Check that the key is a smi.
- __ JumpIfNotSmi(rax, &check_name);
+ __ JumpIfNotSmi(key, &check_name);
__ bind(&index_smi);
// Now the key is known to be a smi. This place is also jumped to from below
// where a numeric string is converted to a smi.
GenerateKeyedLoadReceiverCheck(
- masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow);
+ masm, receiver, rax, Map::kHasIndexedInterceptor, &slow);
// Check the receiver's map to see if it has fast elements.
- __ CheckFastElements(rcx, &check_number_dictionary);
+ __ CheckFastElements(rax, &check_number_dictionary);
GenerateFastArrayLoad(masm,
- rdx,
+ receiver,
+ key,
rax,
- rcx,
rbx,
rax,
NULL,
__ ret(0);
__ bind(&check_number_dictionary);
- __ SmiToInteger32(rbx, rax);
- __ movp(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
+ __ SmiToInteger32(rbx, key);
+ __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset));
// Check whether the elements is a number dictionary.
- // rdx: receiver
- // rax: key
// rbx: key as untagged int32
- // rcx: elements
- __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
+ // rax: elements
+ __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
Heap::kHashTableMapRootIndex);
__ j(not_equal, &slow);
- __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
+ __ LoadFromNumberDictionary(&slow, rax, key, rbx, r9, rdi, rax);
__ ret(0);
__ bind(&slow);
// Slow case: Jump to runtime.
- // rdx: receiver
- // rax: key
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
GenerateRuntimeGetProperty(masm);
__ bind(&check_name);
- GenerateKeyNameCheck(masm, rax, rcx, rbx, &index_name, &slow);
+ GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow);
GenerateKeyedLoadReceiverCheck(
- masm, rdx, rcx, Map::kHasNamedInterceptor, &slow);
+ masm, receiver, rax, Map::kHasNamedInterceptor, &slow);
// If the receiver is a fast-case object, check the keyed lookup
- // cache. Otherwise probe the dictionary leaving result in rcx.
- __ movp(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
+ // cache. Otherwise probe the dictionary leaving result in key.
+ __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset));
__ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
Heap::kHashTableMapRootIndex);
__ j(equal, &probe_dictionary);
// Load the map of the receiver, compute the keyed lookup cache hash
// based on 32 bits of the map pointer and the string hash.
- __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
- __ movl(rcx, rbx);
- __ shrl(rcx, Immediate(KeyedLookupCache::kMapHashShift));
- __ movl(rdi, FieldOperand(rax, String::kHashFieldOffset));
+ __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
+ __ movl(rax, rbx);
+ __ shrl(rax, Immediate(KeyedLookupCache::kMapHashShift));
+ __ movl(rdi, FieldOperand(key, String::kHashFieldOffset));
__ shrl(rdi, Immediate(String::kHashShift));
- __ xorp(rcx, rdi);
+ __ xorp(rax, rdi);
int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
- __ andp(rcx, Immediate(mask));
+ __ andp(rax, Immediate(mask));
// Load the key (consisting of map and internalized string) from the cache and
// check for match.
for (int i = 0; i < kEntriesPerBucket - 1; i++) {
Label try_next_entry;
- __ movp(rdi, rcx);
+ __ movp(rdi, rax);
__ shlp(rdi, Immediate(kPointerSizeLog2 + 1));
__ LoadAddress(kScratchRegister, cache_keys);
int off = kPointerSize * i * 2;
__ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off));
__ j(not_equal, &try_next_entry);
- __ cmpp(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
+ __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
__ j(equal, &hit_on_nth_entry[i]);
__ bind(&try_next_entry);
}
int off = kPointerSize * (kEntriesPerBucket - 1) * 2;
__ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off));
__ j(not_equal, &slow);
- __ cmpp(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
+ __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
__ j(not_equal, &slow);
// Get field offset, which is a 32-bit integer.
for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
__ bind(&hit_on_nth_entry[i]);
if (i != 0) {
- __ addl(rcx, Immediate(i));
+ __ addl(rax, Immediate(i));
}
__ LoadAddress(kScratchRegister, cache_field_offsets);
- __ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
- __ movzxbp(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
- __ subp(rdi, rcx);
+ __ movl(rdi, Operand(kScratchRegister, rax, times_4, 0));
+ __ movzxbp(rax, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
+ __ subp(rdi, rax);
__ j(above_equal, &property_array_property);
if (i != 0) {
__ jmp(&load_in_object_property);
// Load in-object property.
__ bind(&load_in_object_property);
- __ movzxbp(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
- __ addp(rcx, rdi);
- __ movp(rax, FieldOperand(rdx, rcx, times_pointer_size, 0));
+ __ movzxbp(rax, FieldOperand(rbx, Map::kInstanceSizeOffset));
+ __ addp(rax, rdi);
+ __ movp(rax, FieldOperand(receiver, rax, times_pointer_size, 0));
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
__ ret(0);
// Load property array property.
__ bind(&property_array_property);
- __ movp(rax, FieldOperand(rdx, JSObject::kPropertiesOffset));
+ __ movp(rax, FieldOperand(receiver, JSObject::kPropertiesOffset));
__ movp(rax, FieldOperand(rax, rdi, times_pointer_size,
FixedArray::kHeaderSize));
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
// Do a quick inline probe of the receiver's dictionary, if it
// exists.
__ bind(&probe_dictionary);
- // rdx: receiver
- // rax: key
// rbx: elements
- __ movp(rcx, FieldOperand(rdx, JSObject::kMapOffset));
- __ movb(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset));
- GenerateGlobalInstanceTypeCheck(masm, rcx, &slow);
+ __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset));
+ __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset));
+ GenerateGlobalInstanceTypeCheck(masm, rax, &slow);
- GenerateDictionaryLoad(masm, &slow, rbx, rax, rcx, rdi, rax);
+ GenerateDictionaryLoad(masm, &slow, rbx, key, rax, rdi, rax);
__ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
__ ret(0);
__ bind(&index_name);
- __ IndexFromHash(rbx, rax);
+ __ IndexFromHash(rbx, key);
__ jmp(&index_smi);
}
Register receiver = ReceiverRegister();
Register index = NameRegister();
- Register scratch = rcx;
+ Register scratch = rbx;
Register result = rax;
ASSERT(!scratch.is(receiver) && !scratch.is(index));
Register receiver = ReceiverRegister();
Register key = NameRegister();
- Register scratch = rcx;
+ Register scratch = rax;
ASSERT(!scratch.is(receiver) && !scratch.is(key));
// Check that the receiver isn't a smi.
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- ASSERT(rdx.is(ReceiverRegister()));
- ASSERT(rax.is(NameRegister()));
+ // The return address is on the stack.
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ ASSERT(receiver.is(rdx));
+ ASSERT(key.is(rcx));
+
Label slow, notin;
Operand mapped_location =
GenerateMappedArgumentsLookup(
- masm, rdx, rax, rbx, rcx, rdi, ¬in, &slow);
+ masm, receiver, key, rbx, rax, rdi, ¬in, &slow);
__ movp(rax, mapped_location);
__ Ret();
__ bind(¬in);
// The unmapped lookup expects that the parameter map is in rbx.
Operand unmapped_location =
- GenerateUnmappedArgumentsLookup(masm, rax, rbx, rcx, &slow);
+ GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow);
__ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex);
__ j(equal, &slow);
__ movp(rax, unmapped_location);
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
- // -- rsp[0] : return address
- // -----------------------------------
- ASSERT(rax.is(ReceiverRegister()));
- ASSERT(rcx.is(NameRegister()));
+ // The return address is on the stack.
+ Register receiver = ReceiverRegister();
+ Register name = NameRegister();
+ ASSERT(receiver.is(rdx));
+ ASSERT(name.is(rcx));
// Probe the stub cache.
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
masm->isolate()->stub_cache()->GenerateProbe(
- masm, flags, rax, rcx, rbx, rdx);
+ masm, flags, receiver, name, rbx, rax);
GenerateMiss(masm);
}
void LoadIC::GenerateNormal(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- rax : receiver
+ // -- rdx : receiver
// -- rcx : name
// -- rsp[0] : return address
// -----------------------------------
- ASSERT(rax.is(ReceiverRegister()));
+ ASSERT(rdx.is(ReceiverRegister()));
ASSERT(rcx.is(NameRegister()));
Label miss, slow;
- GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
+ GenerateNameDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss);
- // rdx: elements
+ // rax: elements
// Search the dictionary placing the result in rax.
- GenerateDictionaryLoad(masm, &slow, rdx, rcx, rbx, rdi, rax);
+ GenerateDictionaryLoad(masm, &slow, rax, rcx, rbx, rdi, rax);
__ ret(0);
// Dictionary load failed, go slow (but don't miss).
// IC register specifications
-const Register LoadIC::ReceiverRegister() { return rax; }
+const Register LoadIC::ReceiverRegister() { return rdx; }
const Register LoadIC::NameRegister() { return rcx; }
-const Register KeyedLoadIC::ReceiverRegister() { return rdx; }
-const Register KeyedLoadIC::NameRegister() { return rax; }
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(rsi));
- ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
- ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
+ ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
+ ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister()));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), rsi);
- LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
- LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
+ LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), LoadIC::NameRegister());
LLoadKeyedGeneric* result =
new(zone()) LLoadKeyedGeneric(context, object, key);
// receiver, name, scratch1, scratch2, scratch3, scratch4.
Register receiver = LoadIC::ReceiverRegister();
Register name = LoadIC::NameRegister();
- static Register registers[] = { receiver, name, rdx, rbx, rdi, r8 };
+ static Register registers[] = { receiver, name, rax, rbx, rdi, r8 };
return registers;
}
Register* KeyedLoadStubCompiler::registers() {
// receiver, name, scratch1, scratch2, scratch3, scratch4.
- Register receiver = KeyedLoadIC::ReceiverRegister();
- Register name = KeyedLoadIC::NameRegister();
- static Register registers[] = { receiver, name, rbx, rcx, rdi, r8 };
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+ static Register registers[] = { receiver, name, rax, rbx, rdi, r8 };
return registers;
}
void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- rax : key
+ // -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
- ASSERT(rdx.is(KeyedLoadIC::ReceiverRegister()));
- ASSERT(rax.is(KeyedLoadIC::NameRegister()));
+ ASSERT(rdx.is(LoadIC::ReceiverRegister()));
+ ASSERT(rcx.is(LoadIC::NameRegister()));
Label slow, miss;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
- __ JumpIfNotSmi(rax, &miss);
- __ SmiToInteger32(rbx, rax);
- __ movp(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
+ __ JumpIfNotSmi(rcx, &miss);
+ __ SmiToInteger32(rbx, rcx);
+ __ movp(rax, FieldOperand(rdx, JSObject::kElementsOffset));
// Check whether the elements is a number dictionary.
// rdx: receiver
- // rax: key
+ // rcx: key
// rbx: key as untagged int32
- // rcx: elements
- __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
+ // rax: elements
+ __ LoadFromNumberDictionary(&slow, rax, rcx, rbx, r9, rdi, rax);
__ ret(0);
__ bind(&slow);
// ----------- S t a t e -------------
- // -- rax : key
+ // -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
__ bind(&miss);
// ----------- S t a t e -------------
- // -- rax : key
+ // -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------