}
-void LoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { r0 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { r1 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void StringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { r0, r2 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedStringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { r1, r0 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
Register registers[] = { r2, r1, r0 };
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC load (from ic-arm.cc).
- // ----------- S t a t e -------------
- // -- r2 : name
- // -- lr : return address
- // -- r0 : receiver
- // -- [sp] : receiver
- // -----------------------------------
- // Registers r0 and r2 contain objects that need to be pushed on the
- // expression stack of the fake JS frame.
- Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit(), 0);
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+ Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit(), 0);
+ // 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);
}
__ bind(&fast);
}
- __ ldr(r0, GlobalObjectOperand());
- __ mov(r2, Operand(var->name()));
+ __ ldr(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadIC::NameRegister(), Operand(var->name()));
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
? NOT_CONTEXTUAL
: CONTEXTUAL;
switch (var->location()) {
case Variable::UNALLOCATED: {
Comment cmnt(masm_, "[ Global variable");
- // Use inline caching. Variable name is passed in r2 and the global
- // object (receiver) in r0.
- __ ldr(r0, GlobalObjectOperand());
- __ mov(r2, Operand(var->name()));
+ __ ldr(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadIC::NameRegister(), Operand(var->name()));
CallLoadIC(CONTEXTUAL);
context()->Plug(r0);
break;
// 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
// result = receiver[f](arg);
__ bind(&l_call);
- __ ldr(r1, MemOperand(sp, kPointerSize));
- __ ldr(r0, MemOperand(sp, 2 * kPointerSize));
+ __ ldr(keyedload_receiver, MemOperand(sp, kPointerSize));
+ __ ldr(keyedload_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);
- __ push(r0); // save result
- __ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done"
- CallLoadIC(NOT_CONTEXTUAL); // result.done in r0
+ Register load_receiver = LoadIC::ReceiverRegister();
+ Register load_name = LoadIC::NameRegister();
+ ASSERT(load_receiver.is(r0));
+ ASSERT(load_name.is(r2));
+
+ __ push(load_receiver); // save result
+ __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
+ CallLoadIC(NOT_CONTEXTUAL); // r0=result.done
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ cmp(r0, Operand(0));
__ b(eq, &l_try);
// result.value
- __ pop(r0); // result
- __ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value"
- CallLoadIC(NOT_CONTEXTUAL); // result.value in r0
- context()->DropAndPlug(2, r0); // drop iter and g
+ __ pop(load_receiver); // result
+ __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
+ CallLoadIC(NOT_CONTEXTUAL); // r0=result.value
+ context()->DropAndPlug(2, r0); // drop iter and g
break;
}
}
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
- __ mov(r2, Operand(key->value()));
- // Call load IC. It has arguments receiver and property name r0 and r2.
+ __ mov(LoadIC::NameRegister(), Operand(key->value()));
+ // Call load IC. It has register arguments receiver and property.
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
}
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
- // Call keyed load IC. It has arguments key and receiver in r0 and r1.
+ // Call keyed load IC. It has register arguments receiver and key.
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallIC(ic, prop->PropertyFeedbackId());
}
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
+ ASSERT(r0.is(LoadIC::ReceiverRegister()));
EmitNamedPropertyLoad(expr);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(r0);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- __ pop(r1);
+ ASSERT(r0.is(KeyedLoadIC::NameRegister()));
+ __ pop(KeyedLoadIC::ReceiverRegister());
EmitKeyedPropertyLoad(expr);
context()->Plug(r0);
}
} else {
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ ldr(r0, MemOperand(sp, 0));
+ __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
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(r1, MemOperand(sp, 0));
+ __ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
__ push(r0);
// Load the function from the receiver.
- __ mov(r2, Operand(expr->name()));
+ ASSERT(r0.is(LoadIC::ReceiverRegister()));
+ __ mov(LoadIC::NameRegister(), Operand(expr->name()));
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
// Push the target function under the receiver.
if (assign_type == NAMED_PROPERTY) {
// Put the object both on the stack and in the accumulator.
VisitForAccumulatorValue(prop->obj());
- __ push(r0);
+ ASSERT(r0.is(LoadIC::ReceiverRegister()));
+ __ push(LoadIC::ReceiverRegister());
EmitNamedPropertyLoad(prop);
} else {
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
- __ ldr(r1, MemOperand(sp, 0));
- __ push(r0);
+ ASSERT(r0.is(KeyedLoadIC::NameRegister()));
+ __ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
+ __ push(KeyedLoadIC::NameRegister());
EmitKeyedPropertyLoad(prop);
}
}
VariableProxy* proxy = expr->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "[ Global variable");
- __ ldr(r0, GlobalObjectOperand());
- __ mov(r2, Operand(proxy->name()));
+ __ ldr(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadIC::NameRegister(), Operand(proxy->name()));
// Use a regular load, not a contextual load, to avoid a reference
// error.
CallLoadIC(NOT_CONTEXTUAL);
// -- lr : return address
// -- r0 : receiver
// -----------------------------------
+ ASSERT(r0.is(ReceiverRegister()));
+ ASSERT(r2.is(NameRegister()));
// Probe the stub cache.
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
// -- lr : return address
// -- r0 : receiver
// -----------------------------------
+ ASSERT(r0.is(ReceiverRegister()));
+ ASSERT(r2.is(NameRegister()));
+
Label miss, slow;
GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
}
+// A register that isn't one of the parameters to the load ic.
+static const Register LoadIC_TempRegister() { return r3; }
+
+
void LoadIC::GenerateMiss(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- r2 : name
- // -- lr : return address
- // -- r0 : receiver
- // -----------------------------------
+ // The return address is on the stack.
Isolate* isolate = masm->isolate();
__ IncrementCounter(isolate->counters()->load_miss(), 1, r3, r4);
- __ mov(r3, r0);
- __ Push(r3, r2);
+ __ mov(LoadIC_TempRegister(), ReceiverRegister());
+ __ Push(LoadIC_TempRegister(), NameRegister());
// Perform tail call to the entry.
ExternalReference ref =
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- r2 : name
- // -- lr : return address
- // -- r0 : receiver
- // -----------------------------------
+ // The return address is on the stack.
- __ mov(r3, r0);
- __ Push(r3, r2);
+ __ mov(LoadIC_TempRegister(), ReceiverRegister());
+ __ Push(LoadIC_TempRegister(), NameRegister());
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
}
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
+ ASSERT(r1.is(ReceiverRegister()));
+ ASSERT(r0.is(NameRegister()));
Label slow, notin;
MemOperand mapped_location =
GenerateMappedArgumentsLookup(masm, r1, r0, r2, r3, r4, ¬in, &slow);
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
+ // The return address is on the stack.
Isolate* isolate = masm->isolate();
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4);
- __ Push(r1, r0);
+ __ Push(ReceiverRegister(), NameRegister());
// Perform tail call to the entry.
ExternalReference ref =
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
+ // The return address is on the stack.
- __ Push(r1, r0);
+ __ Push(ReceiverRegister(), NameRegister());
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
}
Label slow, check_name, index_smi, index_name, property_array_property;
Label probe_dictionary, check_number_dictionary;
- Register key = r0;
- Register receiver = r1;
+ Register key = NameRegister();
+ Register receiver = ReceiverRegister();
+ ASSERT(key.is(r0));
+ ASSERT(receiver.is(r1));
Isolate* isolate = masm->isolate();
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key (index)
- // -- r1 : receiver
- // -----------------------------------
+ // Return address is on the stack.
Label miss;
- Register receiver = r1;
- Register index = r0;
+ Register receiver = ReceiverRegister();
+ Register index = NameRegister();
Register scratch = r3;
Register result = r0;
+ ASSERT(!scratch.is(receiver) && !scratch.is(index));
StringCharAtGenerator char_at_generator(receiver,
index,
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
+ // Return address is on the stack.
Label slow;
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ Register scratch1 = r2;
+ Register scratch2 = r3;
+ ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
+ ASSERT(!scratch2.is(receiver) && !scratch2.is(key));
+
// Check that the receiver isn't a smi.
- __ JumpIfSmi(r1, &slow);
+ __ JumpIfSmi(receiver, &slow);
// Check that the key is an array index, that is Uint32.
- __ NonNegativeSmiTst(r0);
+ __ NonNegativeSmiTst(key);
__ b(ne, &slow);
// Get the map of the receiver.
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+ __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
// Check that it has indexed interceptor and access checks
// are not enabled for this object.
- __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
- __ and_(r3, r3, Operand(kSlowCaseBitFieldMask));
- __ cmp(r3, Operand(1 << Map::kHasIndexedInterceptor));
+ __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
+ __ and_(scratch2, scratch2, Operand(kSlowCaseBitFieldMask));
+ __ cmp(scratch2, Operand(1 << Map::kHasIndexedInterceptor));
__ b(ne, &slow);
// Everything is fine, call runtime.
- __ Push(r1, r0); // Receiver, key.
+ __ Push(receiver, key); // Receiver, key.
// Perform tail call to the entry.
__ TailCallExternalReference(
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* global_object = UseFixed(instr->global_object(), r0);
+ LOperand* global_object = UseFixed(instr->global_object(),
+ LoadIC::ReceiverRegister());
LLoadGlobalGeneric* result =
new(zone()) LLoadGlobalGeneric(context, global_object);
return MarkAsCall(DefineFixed(result, r0), instr);
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* object = UseFixed(instr->object(), r0);
+ LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
LInstruction* result =
DefineFixed(new(zone()) LLoadNamedGeneric(context, object), r0);
return MarkAsCall(result, instr);
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* object = UseFixed(instr->object(), r1);
- LOperand* key = UseFixed(instr->key(), r0);
+ LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
LInstruction* result =
DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), r0);
void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->global_object()).is(r0));
+ ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->result()).is(r0));
- __ mov(r2, Operand(instr->name()));
+ __ mov(LoadIC::NameRegister(), Operand(instr->name()));
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->object()).is(r0));
+ ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->result()).is(r0));
// Name is always in r2.
- __ mov(r2, Operand(instr->name()));
+ __ mov(LoadIC::NameRegister(), Operand(instr->name()));
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
}
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->object()).is(r1));
- ASSERT(ToRegister(instr->key()).is(r0));
+ ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
+ ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
+ ASSERT(r1.is(KeyedLoadIC::ReceiverRegister()));
+ ASSERT(r0.is(KeyedLoadIC::NameRegister()));
Label slow, miss;
Register key = r0;
}
-void LoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- // x0: receiver
- Register registers[] = { x0 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- // x1: receiver
- Register registers[] = { x1 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void StringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { x0, x2 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedStringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { x1, x0 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
// x2: receiver
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC load (from ic-arm.cc).
- // ----------- S t a t e -------------
- // -- x2 : name
- // -- lr : return address
- // -- x0 : receiver
- // -- [sp] : receiver
- // -----------------------------------
- // Registers x0 and x2 contain objects that need to be pushed on the
- // expression stack of the fake JS frame.
- Generate_DebugBreakCallHelper(masm, x0.Bit() | x2.Bit(), 0, x10);
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+ Generate_DebugBreakCallHelper(masm, receiver.Bit() | name.Bit(), 0, x10);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- x0 : key
- // -- x1 : receiver
- Generate_DebugBreakCallHelper(masm, x0.Bit() | x1.Bit(), 0, x10);
+ // 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);
}
__ Bind(&fast);
}
- __ Ldr(x0, GlobalObjectMemOperand());
- __ Mov(x2, Operand(var->name()));
+ __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand());
+ __ Mov(LoadIC::NameRegister(), Operand(var->name()));
ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL
: CONTEXTUAL;
CallLoadIC(mode);
switch (var->location()) {
case Variable::UNALLOCATED: {
Comment cmnt(masm_, "Global variable");
- // Use inline caching. Variable name is passed in x2 and the global
- // object (receiver) in x0.
- __ Ldr(x0, GlobalObjectMemOperand());
- __ Mov(x2, Operand(var->name()));
+ __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand());
+ __ Mov(LoadIC::NameRegister(), Operand(var->name()));
CallLoadIC(CONTEXTUAL);
context()->Plug(x0);
break;
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
- __ Mov(x2, Operand(key->value()));
+ __ Mov(LoadIC::NameRegister(), Operand(key->value()));
// Call load IC. It has arguments receiver and property name x0 and x2.
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
}
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
+ ASSERT(x0.is(LoadIC::ReceiverRegister()));
EmitNamedPropertyLoad(expr);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(x0);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- __ Pop(x1);
+ ASSERT(x0.is(KeyedLoadIC::NameRegister()));
+ __ Pop(KeyedLoadIC::ReceiverRegister());
EmitKeyedPropertyLoad(expr);
context()->Plug(x0);
}
} else {
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ Peek(x0, 0);
+ __ Peek(LoadIC::ReceiverRegister(), 0);
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
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(x1, 0);
+ __ Peek(KeyedLoadIC::ReceiverRegister(), 0);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
if (expr->is_jsruntime()) {
// Push the builtins object as the receiver.
__ Ldr(x10, GlobalObjectMemOperand());
- __ Ldr(x0, FieldMemOperand(x10, GlobalObject::kBuiltinsOffset));
- __ Push(x0);
+ __ Ldr(LoadIC::ReceiverRegister(),
+ FieldMemOperand(x10, GlobalObject::kBuiltinsOffset));
+ __ Push(LoadIC::ReceiverRegister());
// Load the function from the receiver.
Handle<String> name = expr->name();
- __ Mov(x2, Operand(name));
+ __ Mov(LoadIC::NameRegister(), Operand(name));
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
// Push the target function under the receiver.
if (assign_type == NAMED_PROPERTY) {
// Put the object both on the stack and in the accumulator.
VisitForAccumulatorValue(prop->obj());
- __ Push(x0);
+ ASSERT(x0.is(LoadIC::ReceiverRegister()));
+ __ Push(LoadIC::ReceiverRegister());
EmitNamedPropertyLoad(prop);
} else {
// KEYED_PROPERTY
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
- __ Peek(x1, 0);
- __ Push(x0);
+ ASSERT(x0.is(KeyedLoadIC::NameRegister()));
+ __ Peek(KeyedLoadIC::ReceiverRegister(), 0);
+ __ Push(KeyedLoadIC::NameRegister());
EmitKeyedPropertyLoad(prop);
}
}
VariableProxy* proxy = expr->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "Global variable");
- __ Ldr(x0, GlobalObjectMemOperand());
- __ Mov(x2, Operand(proxy->name()));
+ __ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand());
+ __ Mov(LoadIC::NameRegister(), Operand(proxy->name()));
// Use a regular load, not a contextual load, to avoid a reference
// error.
CallLoadIC(NOT_CONTEXTUAL);
// 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
// result = receiver[f](arg);
__ Bind(&l_call);
- __ Peek(x1, 1 * kPointerSize);
- __ Peek(x0, 2 * kPointerSize);
+ __ Peek(keyedload_receiver, 1 * kPointerSize);
+ __ Peek(keyedload_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);
- __ Push(x0); // save result
- __ LoadRoot(x2, Heap::kdone_stringRootIndex); // "done"
- CallLoadIC(NOT_CONTEXTUAL); // result.done in x0
+ Register load_receiver = LoadIC::ReceiverRegister();
+ Register load_name = LoadIC::NameRegister();
+ ASSERT(load_receiver.is(x0));
+ ASSERT(load_name.is(x2));
+ __ Push(load_receiver); // save result
+ __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
+ CallLoadIC(NOT_CONTEXTUAL); // x0=result.done
// The ToBooleanStub argument (result.done) is in x0.
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ Cbz(x0, &l_try);
// result.value
- __ Pop(x0); // result
- __ LoadRoot(x2, Heap::kvalue_stringRootIndex); // "value"
- CallLoadIC(NOT_CONTEXTUAL); // result.value in x0
- context()->DropAndPlug(2, x0); // drop iter and g
+ __ Pop(load_receiver); // result
+ __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
+ CallLoadIC(NOT_CONTEXTUAL); // x0=result.value
+ context()->DropAndPlug(2, x0); // drop iter and g
break;
}
}
// -- lr : return address
// -- x0 : receiver
// -----------------------------------
+ ASSERT(x0.is(ReceiverRegister()));
+ ASSERT(x2.is(NameRegister()));
// Probe the stub cache.
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
// -- lr : return address
// -- x0 : receiver
// -----------------------------------
+ ASSERT(x0.is(ReceiverRegister()));
+ ASSERT(x2.is(NameRegister()));
Label miss, slow;
GenerateNameDictionaryReceiverCheck(masm, x0, x1, x3, x4, &miss);
void LoadIC::GenerateMiss(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- x2 : name
- // -- lr : return address
- // -- x0 : receiver
- // -----------------------------------
+ // The return address is on the stack.
Isolate* isolate = masm->isolate();
ASM_LOCATION("LoadIC::GenerateMiss");
__ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4);
// Perform tail call to the entry.
- __ Push(x0, x2);
+ __ Push(ReceiverRegister(), NameRegister());
ExternalReference ref =
ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
__ TailCallExternalReference(ref, 2, 1);
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- x2 : name
- // -- lr : return address
- // -- x0 : receiver
- // -----------------------------------
-
- __ Push(x0, x2);
+ // The return address is on the stack.
+ __ Push(ReceiverRegister(), NameRegister());
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
}
// -- x1 : receiver
// -----------------------------------
Register result = x0;
- Register key = x0;
- Register receiver = x1;
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ ASSERT(receiver.is(x1));
+ ASSERT(key.is(x0));
+
Label miss, unmapped;
Register map_scratch = x2;
// -- x1 : key
// -- x2 : receiver
// -----------------------------------
-
Label slow, notin;
Register value = x0;
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- x0 : key
- // -- x1 : receiver
- // -----------------------------------
+ // The return address is on the stack.
Isolate* isolate = masm->isolate();
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11);
- __ Push(x1, x0);
+ __ Push(ReceiverRegister(), NameRegister());
// Perform tail call to the entry.
ExternalReference ref =
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- x0 : key
- // -- x1 : receiver
- // -----------------------------------
- Register key = x0;
- Register receiver = x1;
-
- __ Push(receiver, key);
+ // The return address is on the stack.
+ __ Push(ReceiverRegister(), NameRegister());
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
}
// -----------------------------------
Label slow, check_name, index_smi, index_name;
- Register key = x0;
- Register receiver = x1;
+ Register key = NameRegister();
+ Register receiver = ReceiverRegister();
+ ASSERT(key.is(x0));
+ ASSERT(receiver.is(x1));
__ JumpIfNotSmi(key, &check_name);
__ Bind(&index_smi);
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- x0 : key (index)
- // -- x1 : receiver
- // -----------------------------------
+ // Return address is on the stack.
Label miss;
- Register index = x0;
- Register receiver = x1;
+ Register receiver = ReceiverRegister();
+ Register index = NameRegister();
Register result = x0;
Register scratch = x3;
+ ASSERT(!scratch.is(receiver) && !scratch.is(index));
StringCharAtGenerator char_at_generator(receiver,
index,
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- lr : return address
- // -- x0 : key
- // -- x1 : receiver
- // -----------------------------------
+ // Return address is on the stack.
Label slow;
- Register key = x0;
- Register receiver = x1;
+
+ 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));
// Check that the receiver isn't a smi.
__ JumpIfSmi(receiver, &slow);
__ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow);
// Get the map of the receiver.
- Register map = x2;
+ Register map = scratch1;
__ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
// Check that it has indexed interceptor and access checks
// are not enabled for this object.
- __ Ldrb(x3, FieldMemOperand(map, Map::kBitFieldOffset));
+ __ Ldrb(scratch2, FieldMemOperand(map, Map::kBitFieldOffset));
ASSERT(kSlowCaseBitFieldMask ==
((1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor)));
- __ Tbnz(x3, Map::kIsAccessCheckNeeded, &slow);
- __ Tbz(x3, Map::kHasIndexedInterceptor, &slow);
+ __ Tbnz(scratch2, Map::kIsAccessCheckNeeded, &slow);
+ __ Tbz(scratch2, Map::kHasIndexedInterceptor, &slow);
// Everything is fine, call runtime.
__ Push(receiver, key);
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* global_object = UseFixed(instr->global_object(), x0);
+ LOperand* global_object = UseFixed(instr->global_object(),
+ LoadIC::ReceiverRegister());
LLoadGlobalGeneric* result =
new(zone()) LLoadGlobalGeneric(context, global_object);
return MarkAsCall(DefineFixed(result, x0), instr);
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* object = UseFixed(instr->object(), x1);
- LOperand* key = UseFixed(instr->key(), x0);
+ LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
LInstruction* result =
DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), x0);
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* object = UseFixed(instr->object(), x0);
+ LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
LInstruction* result =
DefineFixed(new(zone()) LLoadNamedGeneric(context, object), x0);
return MarkAsCall(result, instr);
void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->global_object()).Is(x0));
+ ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->result()).Is(x0));
- __ Mov(x2, Operand(instr->name()));
+ __ Mov(LoadIC::NameRegister(), Operand(instr->name()));
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->object()).Is(x1));
- ASSERT(ToRegister(instr->key()).Is(x0));
+ ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
+ ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
- // LoadIC expects x2 to hold the name, and x0 to hold the receiver.
+ // LoadIC expects name and receiver in registers.
+ ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->object()).is(x0));
- __ Mov(x2, Operand(instr->name()));
+ __ Mov(LoadIC::NameRegister(), Operand(instr->name()));
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
// -- x0 : key
// -- x1 : receiver
// -----------------------------------
+ ASSERT(x1.is(KeyedLoadIC::ReceiverRegister()));
+ ASSERT(x0.is(KeyedLoadIC::NameRegister()));
Label slow, miss;
Register result = x0;
}
+void LoadFieldStub::InitializeInterfaceDescriptor(
+ CodeStubInterfaceDescriptor* descriptor) {
+ Register registers[] = { LoadIC::ReceiverRegister() };
+ descriptor->Initialize(ARRAY_SIZE(registers), registers);
+}
+
+
+void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
+ CodeStubInterfaceDescriptor* descriptor) {
+ Register registers[] = { KeyedLoadIC::ReceiverRegister() };
+ descriptor->Initialize(ARRAY_SIZE(registers), registers);
+}
+
+
+void StringLengthStub::InitializeInterfaceDescriptor(
+ CodeStubInterfaceDescriptor* descriptor) {
+ Register registers[] = { LoadIC::ReceiverRegister(),
+ LoadIC::NameRegister() };
+ descriptor->Initialize(ARRAY_SIZE(registers), registers);
+}
+
+
+void KeyedStringLengthStub::InitializeInterfaceDescriptor(
+ CodeStubInterfaceDescriptor* descriptor) {
+ Register registers[] = { KeyedLoadIC::ReceiverRegister(),
+ KeyedLoadIC::NameRegister() };
+ descriptor->Initialize(ARRAY_SIZE(registers), registers);
+}
+
+
void KeyedLoadDictionaryElementPlatformStub::Generate(
MacroAssembler* masm) {
KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
}
-void LoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { edx };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { edx };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void StringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { edx, ecx };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedStringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { edx, ecx };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
Register registers[] = { edx, ecx, eax };
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Register state for IC load call (from ic-ia32.cc).
- // ----------- S t a t e -------------
- // -- ecx : name
- // -- edx : receiver
- // -----------------------------------
- Generate_DebugBreakCallHelper(masm, ecx.bit() | edx.bit(), 0, false);
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+ Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC load call (from ic-ia32.cc).
- // ----------- S t a t e -------------
- // -- ecx : key
- // -- edx : receiver
- // -----------------------------------
- Generate_DebugBreakCallHelper(masm, ecx.bit() | edx.bit(), 0, false);
+ Register receiver = KeyedLoadIC::ReceiverRegister();
+ Register name = KeyedLoadIC::NameRegister();
+ Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
}
// All extension objects were empty and it is safe to use a global
// load IC call.
- __ mov(edx, GlobalObjectOperand());
- __ mov(ecx, var->name());
+ __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadIC::NameRegister(), var->name());
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
? NOT_CONTEXTUAL
: CONTEXTUAL;
switch (var->location()) {
case Variable::UNALLOCATED: {
Comment cmnt(masm_, "[ Global variable");
- // Use inline caching. Variable name is passed in ecx and the global
- // object in eax.
- __ mov(edx, GlobalObjectOperand());
- __ mov(ecx, var->name());
+ __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadIC::NameRegister(), var->name());
CallLoadIC(CONTEXTUAL);
context()->Plug(eax);
break;
// receiver = iter; f = iter.next; arg = received;
__ bind(&l_next);
- __ mov(ecx, isolate()->factory()->next_string()); // "next"
- __ push(ecx);
+ 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
// result = receiver[f](arg);
__ bind(&l_call);
- __ mov(edx, Operand(esp, kPointerSize));
+ __ mov(keyedload_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
- __ mov(edx, eax); // result
- __ mov(ecx, isolate()->factory()->done_string()); // "done"
+ 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
+ __ mov(load_name,
+ isolate()->factory()->done_string()); // "done"
CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ j(zero, &l_try);
// result.value
- __ pop(edx); // result
- __ mov(ecx, isolate()->factory()->value_string()); // "value"
+ __ pop(load_receiver); // result
+ __ mov(load_name,
+ isolate()->factory()->value_string()); // "value"
CallLoadIC(NOT_CONTEXTUAL); // result.value in eax
context()->DropAndPlug(2, eax); // drop iter and g
break;
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
ASSERT(!key->value()->IsSmi());
- __ mov(ecx, Immediate(key->value()));
+ __ mov(LoadIC::NameRegister(), Immediate(key->value()));
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
}
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
- __ mov(edx, result_register());
+ __ mov(LoadIC::ReceiverRegister(), result_register());
EmitNamedPropertyLoad(expr);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(eax);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- __ pop(edx); // Object.
- __ mov(ecx, result_register()); // Key.
+ __ pop(KeyedLoadIC::ReceiverRegister()); // Object.
+ __ mov(KeyedLoadIC::NameRegister(), result_register()); // Key.
EmitKeyedPropertyLoad(expr);
context()->Plug(eax);
}
} else {
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ mov(edx, Operand(esp, 0));
+ __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ mov(edx, Operand(esp, 0));
+ __ mov(KeyedLoadIC::ReceiverRegister(), Operand(esp, 0));
// Move the key into the right register for the keyed load IC.
- __ mov(ecx, eax);
+ __ mov(KeyedLoadIC::NameRegister(), eax);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
__ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
// Load the function from the receiver.
- __ mov(edx, Operand(esp, 0));
- __ mov(ecx, Immediate(expr->name()));
+ __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
+ __ mov(LoadIC::NameRegister(), Immediate(expr->name()));
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
// Push the target function under the receiver.
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(edx, eax);
+ __ mov(LoadIC::ReceiverRegister(), eax);
EmitNamedPropertyLoad(prop);
} else {
VisitForStackValue(prop->obj());
VisitForStackValue(prop->key());
- __ mov(edx, Operand(esp, kPointerSize)); // Object.
- __ mov(ecx, Operand(esp, 0)); // Key.
+ __ mov(KeyedLoadIC::ReceiverRegister(),
+ Operand(esp, kPointerSize)); // Object.
+ __ mov(KeyedLoadIC::NameRegister(), Operand(esp, 0)); // Key.
EmitKeyedPropertyLoad(prop);
}
}
if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "[ Global variable");
- __ mov(edx, GlobalObjectOperand());
- __ mov(ecx, Immediate(proxy->name()));
+ __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadIC::NameRegister(), Immediate(proxy->name()));
// Use a regular load, not a contextual load, to avoid a reference
// error.
CallLoadIC(NOT_CONTEXTUAL);
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
+ ASSERT(edx.is(ReceiverRegister()));
+ ASSERT(ecx.is(NameRegister()));
Label slow, check_name, index_smi, index_name, property_array_property;
Label probe_dictionary, check_number_dictionary;
}
+// A register that isn't one of the parameters to the load ic.
+static const Register LoadIC_TempRegister() { return ebx; }
+
+
+// A register that isn't one of the parameters to the load ic.
+static const Register KeyedLoadIC_TempRegister() {
+ return LoadIC_TempRegister();
+}
+
+
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : key (index)
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
+ // Return address is on the stack.
Label miss;
- Register receiver = edx;
- Register index = ecx;
- Register scratch = ebx;
+ Register receiver = ReceiverRegister();
+ Register index = NameRegister();
+ Register scratch = KeyedLoadIC_TempRegister();
Register result = eax;
+ ASSERT(!result.is(scratch));
StringCharAtGenerator char_at_generator(receiver,
index,
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
+ // Return address is on the stack.
Label slow;
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ Register scratch = eax;
+ ASSERT(!scratch.is(receiver) && !scratch.is(key));
+
// Check that the receiver isn't a smi.
- __ JumpIfSmi(edx, &slow);
+ __ JumpIfSmi(receiver, &slow);
// Check that the key is an array index, that is Uint32.
- __ test(ecx, Immediate(kSmiTagMask | kSmiSignMask));
+ __ test(key, Immediate(kSmiTagMask | kSmiSignMask));
__ j(not_zero, &slow);
// Get the map of the receiver.
- __ mov(eax, FieldOperand(edx, HeapObject::kMapOffset));
+ __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
// Check that it has indexed interceptor and access checks
// are not enabled for this object.
- __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset));
- __ and_(eax, Immediate(kSlowCaseBitFieldMask));
- __ cmp(eax, Immediate(1 << Map::kHasIndexedInterceptor));
+ __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
+ __ and_(scratch, Immediate(kSlowCaseBitFieldMask));
+ __ cmp(scratch, Immediate(1 << Map::kHasIndexedInterceptor));
__ j(not_zero, &slow);
// Everything is fine, call runtime.
- __ pop(eax);
- __ push(edx); // receiver
- __ push(ecx); // key
- __ push(eax); // return address
+ __ pop(scratch);
+ __ push(receiver); // receiver
+ __ push(key); // key
+ __ push(scratch); // return address
// Perform tail call to the entry.
ExternalReference ref =
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
+ ASSERT(edx.is(ReceiverRegister()));
+ ASSERT(ecx.is(NameRegister()));
Label slow, notin;
Factory* factory = masm->isolate()->factory();
Operand mapped_location =
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
+ ASSERT(edx.is(ReceiverRegister()));
+ ASSERT(ecx.is(NameRegister()));
// Probe the stub cache.
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
+ ASSERT(edx.is(ReceiverRegister()));
+ ASSERT(ecx.is(NameRegister()));
+
Label miss, slow;
GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
void LoadIC::GenerateMiss(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : name
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
-
+ // Return address is on the stack.
__ IncrementCounter(masm->isolate()->counters()->load_miss(), 1);
- __ pop(ebx);
- __ push(edx); // receiver
- __ push(ecx); // name
- __ push(ebx); // return address
+ __ pop(LoadIC_TempRegister());
+ __ push(ReceiverRegister()); // receiver
+ __ push(NameRegister()); // name
+ __ push(LoadIC_TempRegister()); // return address
// Perform tail call to the entry.
ExternalReference ref =
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
-
- __ pop(ebx);
- __ push(edx); // receiver
- __ push(ecx); // name
- __ push(ebx); // return address
+ // Return address is on the stack.
+ __ pop(LoadIC_TempRegister());
+ __ push(ReceiverRegister()); // receiver
+ __ push(NameRegister()); // name
+ __ push(LoadIC_TempRegister()); // return address
// Perform tail call to the entry.
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
-
+ // Return address is on the stack.
__ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1);
- __ pop(ebx);
- __ push(edx); // receiver
- __ push(ecx); // name
- __ push(ebx); // return address
+ __ pop(KeyedLoadIC_TempRegister());
+ __ push(ReceiverRegister()); // receiver
+ __ push(NameRegister()); // name
+ __ push(KeyedLoadIC_TempRegister()); // return address
// Perform tail call to the entry.
ExternalReference ref =
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
-
- __ pop(ebx);
- __ push(edx); // receiver
- __ push(ecx); // name
- __ push(ebx); // return address
+ // Return address is on the stack.
+ __ pop(KeyedLoadIC_TempRegister());
+ __ push(ReceiverRegister()); // receiver
+ __ push(NameRegister()); // name
+ __ push(KeyedLoadIC_TempRegister()); // return address
// Perform tail call to the entry.
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
- ASSERT(ToRegister(instr->global_object()).is(edx));
+ ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->result()).is(eax));
- __ mov(ecx, instr->name());
+ __ mov(LoadIC::NameRegister(), instr->name());
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
- ASSERT(ToRegister(instr->object()).is(edx));
+ ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->result()).is(eax));
- __ mov(ecx, instr->name());
+ __ mov(LoadIC::NameRegister(), instr->name());
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
- ASSERT(ToRegister(instr->object()).is(edx));
- ASSERT(ToRegister(instr->key()).is(ecx));
+ ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
+ ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
- LOperand* global_object = UseFixed(instr->global_object(), edx);
+ LOperand* global_object = UseFixed(instr->global_object(),
+ LoadIC::ReceiverRegister());
LLoadGlobalGeneric* result =
new(zone()) LLoadGlobalGeneric(context, global_object);
return MarkAsCall(DefineFixed(result, eax), instr);
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
- LOperand* object = UseFixed(instr->object(), edx);
+ LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object);
return MarkAsCall(DefineFixed(result, eax), instr);
}
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
- LOperand* object = UseFixed(instr->object(), edx);
- LOperand* key = UseFixed(instr->key(), ecx);
+ LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
LLoadKeyedGeneric* result =
new(zone()) LLoadKeyedGeneric(context, object, key);
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
+ ASSERT(edx.is(KeyedLoadIC::ReceiverRegister()));
+ ASSERT(ecx.is(KeyedLoadIC::NameRegister()));
Label slow, miss;
// This stub is meant to be tail-jumped to, the receiver must already
}
-void LoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { rax };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { rdx };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void StringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { rax, rcx };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedStringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { rdx, rax };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
Register registers[] = { rdx, rcx, rax };
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Register state for IC load call (from ic-x64.cc).
- // ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
- // -----------------------------------
- Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), 0, false);
+ Register receiver = LoadIC::ReceiverRegister();
+ Register name = LoadIC::NameRegister();
+ Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC load call (from ic-x64.cc).
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -----------------------------------
- Generate_DebugBreakCallHelper(masm, rax.bit() | rdx.bit(), 0, false);
+ Register receiver = KeyedLoadIC::ReceiverRegister();
+ Register name = KeyedLoadIC::NameRegister();
+ Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
}
// All extension objects were empty and it is safe to use a global
// load IC call.
- __ movp(rax, GlobalObjectOperand());
- __ Move(rcx, var->name());
+ __ movp(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ Move(LoadIC::NameRegister(), var->name());
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
? NOT_CONTEXTUAL
: CONTEXTUAL;
switch (var->location()) {
case Variable::UNALLOCATED: {
Comment cmnt(masm_, "[ Global variable");
- // Use inline caching. Variable name is passed in rcx and the global
- // object on the stack.
- __ Move(rcx, var->name());
- __ movp(rax, GlobalObjectOperand());
+ __ Move(LoadIC::NameRegister(), var->name());
+ __ movp(LoadIC::ReceiverRegister(), GlobalObjectOperand());
CallLoadIC(CONTEXTUAL);
context()->Plug(rax);
break;
// 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
// result = receiver[f](arg);
__ bind(&l_call);
- __ movp(rdx, Operand(rsp, kPointerSize));
- __ movp(rax, Operand(rsp, 2 * kPointerSize));
+ __ movp(keyedload_receiver, Operand(rsp, kPointerSize));
+ __ movp(keyedload_name, Operand(rsp, 2 * kPointerSize));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallIC(ic, TypeFeedbackId::None());
__ movp(rdi, rax);
// if (!result.done) goto l_try;
__ bind(&l_loop);
- __ Push(rax); // save result
- __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
- CallLoadIC(NOT_CONTEXTUAL); // result.done in rax
+ Register load_receiver = LoadIC::ReceiverRegister();
+ Register load_name = LoadIC::NameRegister();
+ ASSERT(load_receiver.is(rax));
+ ASSERT(load_name.is(rcx));
+
+ __ Push(load_receiver); // save result
+ __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
+ CallLoadIC(NOT_CONTEXTUAL); // rax=result.done
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ testp(result_register(), result_register());
__ j(zero, &l_try);
// result.value
- __ Pop(rax); // result
- __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value"
+ __ Pop(load_receiver); // result
+ __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
CallLoadIC(NOT_CONTEXTUAL); // result.value in rax
context()->DropAndPlug(2, rax); // drop iter and g
break;
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
- __ Move(rcx, key->value());
+ __ Move(LoadIC::NameRegister(), key->value());
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
}
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
+ ASSERT(rax.is(LoadIC::ReceiverRegister()));
EmitNamedPropertyLoad(expr);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(rax);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- __ Pop(rdx);
+ ASSERT(rax.is(KeyedLoadIC::NameRegister()));
+ __ Pop(KeyedLoadIC::ReceiverRegister());
EmitKeyedPropertyLoad(expr);
context()->Plug(rax);
}
} else {
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ movp(rax, Operand(rsp, 0));
+ __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
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(rdx, Operand(rsp, 0));
+ __ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0));
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
__ Push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
// Load the function from the receiver.
- __ movp(rax, Operand(rsp, 0));
- __ Move(rcx, expr->name());
+ __ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
+ __ Move(LoadIC::NameRegister(), expr->name());
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
// Push the target function under the receiver.
}
if (assign_type == NAMED_PROPERTY) {
VisitForAccumulatorValue(prop->obj());
+ ASSERT(rax.is(LoadIC::ReceiverRegister()));
__ Push(rax); // Copy of receiver, needed for later store.
EmitNamedPropertyLoad(prop);
} else {
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
- __ movp(rdx, Operand(rsp, 0)); // Leave receiver on stack
- __ Push(rax); // Copy of key, needed for later store.
+ ASSERT(rax.is(KeyedLoadIC::NameRegister()));
+ // Leave receiver on stack
+ __ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0));
+ // Copy of key, needed for later store.
+ __ Push(KeyedLoadIC::NameRegister());
EmitKeyedPropertyLoad(prop);
}
}
if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "[ Global variable");
- __ Move(rcx, proxy->name());
- __ movp(rax, GlobalObjectOperand());
+ __ Move(LoadIC::NameRegister(), proxy->name());
+ __ movp(LoadIC::ReceiverRegister(), GlobalObjectOperand());
// Use a regular load, not a contextual load, to avoid a reference
// error.
CallLoadIC(NOT_CONTEXTUAL);
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
+ ASSERT(rdx.is(ReceiverRegister()));
+ ASSERT(rax.is(NameRegister()));
Label slow, check_name, index_smi, index_name, property_array_property;
Label probe_dictionary, check_number_dictionary;
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
+ // Return address is on the stack.
Label miss;
- Register receiver = rdx;
- Register index = rax;
+ Register receiver = ReceiverRegister();
+ Register index = NameRegister();
Register scratch = rcx;
Register result = rax;
+ ASSERT(!scratch.is(receiver) && !scratch.is(index));
StringCharAtGenerator char_at_generator(receiver,
index,
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
+ // Return address is on the stack.
Label slow;
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ Register scratch = rcx;
+ ASSERT(!scratch.is(receiver) && !scratch.is(key));
+
// Check that the receiver isn't a smi.
- __ JumpIfSmi(rdx, &slow);
+ __ JumpIfSmi(receiver, &slow);
// Check that the key is an array index, that is Uint32.
STATIC_ASSERT(kSmiValueSize <= 32);
- __ JumpUnlessNonNegativeSmi(rax, &slow);
+ __ JumpUnlessNonNegativeSmi(key, &slow);
// Get the map of the receiver.
- __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
+ __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
// Check that it has indexed interceptor and access checks
// are not enabled for this object.
- __ movb(rcx, FieldOperand(rcx, Map::kBitFieldOffset));
- __ andb(rcx, Immediate(kSlowCaseBitFieldMask));
- __ cmpb(rcx, Immediate(1 << Map::kHasIndexedInterceptor));
+ __ movb(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
+ __ andb(scratch, Immediate(kSlowCaseBitFieldMask));
+ __ cmpb(scratch, Immediate(1 << Map::kHasIndexedInterceptor));
__ j(not_zero, &slow);
// Everything is fine, call runtime.
- __ PopReturnAddressTo(rcx);
- __ Push(rdx); // receiver
- __ Push(rax); // key
- __ PushReturnAddressFrom(rcx);
+ __ PopReturnAddressTo(scratch);
+ __ Push(receiver); // receiver
+ __ Push(key); // key
+ __ PushReturnAddressFrom(scratch);
// Perform tail call to the entry.
__ TailCallExternalReference(
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
+ ASSERT(rdx.is(ReceiverRegister()));
+ ASSERT(rax.is(NameRegister()));
Label slow, notin;
Operand mapped_location =
GenerateMappedArgumentsLookup(
// -- rcx : name
// -- rsp[0] : return address
// -----------------------------------
+ ASSERT(rax.is(ReceiverRegister()));
+ ASSERT(rcx.is(NameRegister()));
// Probe the stub cache.
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
// -- rcx : name
// -- rsp[0] : return address
// -----------------------------------
+ ASSERT(rax.is(ReceiverRegister()));
+ ASSERT(rcx.is(NameRegister()));
Label miss, slow;
GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
}
+// A register that isn't one of the parameters to the load ic.
+static const Register LoadIC_TempRegister() { return rbx; }
+
+
+static const Register KeyedLoadIC_TempRegister() {
+ return rbx;
+}
+
+
void LoadIC::GenerateMiss(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
- // -- rsp[0] : return address
- // -----------------------------------
+ // The return address is on the stack.
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->load_miss(), 1);
- __ PopReturnAddressTo(rbx);
- __ Push(rax); // receiver
- __ Push(rcx); // name
- __ PushReturnAddressFrom(rbx);
+ __ PopReturnAddressTo(LoadIC_TempRegister());
+ __ Push(ReceiverRegister()); // receiver
+ __ Push(NameRegister()); // name
+ __ PushReturnAddressFrom(LoadIC_TempRegister());
// Perform tail call to the entry.
ExternalReference ref =
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
- // -- rsp[0] : return address
- // -----------------------------------
+ // The return address is on the stack.
- __ PopReturnAddressTo(rbx);
- __ Push(rax); // receiver
- __ Push(rcx); // name
- __ PushReturnAddressFrom(rbx);
+ __ PopReturnAddressTo(LoadIC_TempRegister());
+ __ Push(ReceiverRegister()); // receiver
+ __ Push(NameRegister()); // name
+ __ PushReturnAddressFrom(LoadIC_TempRegister());
// Perform tail call to the entry.
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
-
+ // The return address is on the stack.
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->keyed_load_miss(), 1);
- __ PopReturnAddressTo(rbx);
- __ Push(rdx); // receiver
- __ Push(rax); // name
- __ PushReturnAddressFrom(rbx);
+ __ PopReturnAddressTo(KeyedLoadIC_TempRegister());
+ __ Push(ReceiverRegister()); // receiver
+ __ Push(NameRegister()); // name
+ __ PushReturnAddressFrom(KeyedLoadIC_TempRegister());
// Perform tail call to the entry.
ExternalReference ref =
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
+ // The return address is on the stack.
- __ PopReturnAddressTo(rbx);
- __ Push(rdx); // receiver
- __ Push(rax); // name
- __ PushReturnAddressFrom(rbx);
+ __ PopReturnAddressTo(KeyedLoadIC_TempRegister());
+ __ Push(ReceiverRegister()); // receiver
+ __ Push(NameRegister()); // name
+ __ PushReturnAddressFrom(KeyedLoadIC_TempRegister());
// Perform tail call to the entry.
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(rsi));
- ASSERT(ToRegister(instr->global_object()).is(rax));
+ ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->result()).is(rax));
- __ Move(rcx, instr->name());
+ __ Move(LoadIC::NameRegister(), instr->name());
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(rsi));
- ASSERT(ToRegister(instr->object()).is(rax));
+ ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->result()).is(rax));
- __ Move(rcx, instr->name());
+ __ Move(LoadIC::NameRegister(), instr->name());
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(rsi));
- ASSERT(ToRegister(instr->object()).is(rdx));
- ASSERT(ToRegister(instr->key()).is(rax));
+ ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
+ ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LOperand* context = UseFixed(instr->context(), rsi);
- LOperand* global_object = UseFixed(instr->global_object(), rax);
+ LOperand* global_object = UseFixed(instr->global_object(),
+ LoadIC::ReceiverRegister());
LLoadGlobalGeneric* result =
new(zone()) LLoadGlobalGeneric(context, global_object);
return MarkAsCall(DefineFixed(result, rax), instr);
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), rsi);
- LOperand* object = UseFixed(instr->object(), rax);
+ LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object);
return MarkAsCall(DefineFixed(result, rax), instr);
}
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), rsi);
- LOperand* object = UseFixed(instr->object(), rdx);
- LOperand* key = UseFixed(instr->key(), rax);
+ LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
LLoadKeyedGeneric* result =
new(zone()) LLoadKeyedGeneric(context, object, key);
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
+ ASSERT(rdx.is(KeyedLoadIC::ReceiverRegister()));
+ ASSERT(rax.is(KeyedLoadIC::NameRegister()));
Label slow, miss;
// This stub is meant to be tail-jumped to, the receiver must already