}
-void LoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { a0 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { a1 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void StringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { a0, a2 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
-void KeyedStringLengthStub::InitializeInterfaceDescriptor(
- CodeStubInterfaceDescriptor* descriptor) {
- Register registers[] = { a1, a0 };
- descriptor->Initialize(ARRAY_SIZE(registers), registers);
-}
-
-
void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) {
Register registers[] = { a2, a1, a0 };
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
- // Calling convention for IC load (from ic-mips.cc).
- // ----------- S t a t e -------------
- // -- a2 : name
- // -- ra : return address
- // -- a0 : receiver
- // -- [sp] : receiver
- // -----------------------------------
- // Registers a0 and a2 contain objects that need to be pushed on the
- // expression stack of the fake JS frame.
- Generate_DebugBreakCallHelper(masm, a0.bit() | a2.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 --------------
- // -- ra : return address
- // -- a0 : key
- // -- a1 : receiver
- Generate_DebugBreakCallHelper(masm, a0.bit() | a1.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);
}
- __ lw(a0, GlobalObjectOperand());
- __ li(a2, Operand(var->name()));
+ __ lw(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ li(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 a2 and the global
- // object (receiver) in a0.
- __ lw(a0, GlobalObjectOperand());
- __ li(a2, Operand(var->name()));
+ __ lw(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ li(LoadIC::NameRegister(), Operand(var->name()));
CallLoadIC(CONTEXTUAL);
context()->Plug(v0);
break;
// [sp + 0 * kPointerSize] g
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
- Label l_next, l_call, l_loop;
+ Label l_next, l_call;
// Initial send value is undefined.
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
__ Branch(&l_next);
// receiver = iter; f = 'next'; arg = received;
__ bind(&l_next);
+ Register keyedload_receiver = KeyedLoadIC::ReceiverRegister();
+ Register keyedload_name = KeyedLoadIC::NameRegister();
+ ASSERT(keyedload_receiver.is(a1));
+ ASSERT(keyedload_name.is(a0));
+
__ LoadRoot(a2, Heap::knext_stringRootIndex); // "next"
__ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter
__ Push(a2, a3, a0); // "next", iter, received
// result = receiver[f](arg);
__ bind(&l_call);
- __ lw(a1, MemOperand(sp, kPointerSize));
- __ lw(a0, MemOperand(sp, 2 * kPointerSize));
+ __ lw(keyedload_receiver, MemOperand(sp, kPointerSize));
+ __ lw(keyedload_name, MemOperand(sp, 2 * kPointerSize));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
CallIC(ic, TypeFeedbackId::None());
__ mov(a0, v0);
__ Drop(1); // The function is still on the stack; drop it.
// if (!result.done) goto l_try;
- __ bind(&l_loop);
- __ mov(a0, v0);
- __ push(a0); // save result
- __ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done"
- CallLoadIC(NOT_CONTEXTUAL); // result.done in v0
- __ mov(a0, v0);
+ Register load_receiver = LoadIC::ReceiverRegister();
+ Register load_name = LoadIC::NameRegister();
+ ASSERT(load_receiver.is(a0));
+ ASSERT(load_name.is(a2));
+
+ __ mov(load_receiver, v0);
+ __ push(v0); // save result
+ __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
+ CallLoadIC(NOT_CONTEXTUAL); // v0=result.done
+ __ mov(load_receiver, v0);
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ Branch(&l_try, eq, v0, Operand(zero_reg));
// result.value
- __ pop(a0); // result
- __ LoadRoot(a2, Heap::kvalue_stringRootIndex); // "value"
- CallLoadIC(NOT_CONTEXTUAL); // result.value in v0
- context()->DropAndPlug(2, v0); // drop iter and g
+ __ pop(load_receiver); // result
+ __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
+ CallLoadIC(NOT_CONTEXTUAL); // v0=result.value
+ context()->DropAndPlug(2, v0); // drop iter and g
break;
}
}
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
- __ mov(a0, result_register());
- __ li(a2, Operand(key->value()));
- // Call load IC. It has arguments receiver and property name a0 and a2.
+ __ mov(LoadIC::ReceiverRegister(), result_register());
+ __ li(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());
__ mov(a0, result_register());
- // Call keyed load IC. It has arguments key and receiver in a0 and a1.
+ // 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(a0.is(LoadIC::ReceiverRegister()));
EmitNamedPropertyLoad(expr);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(v0);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- __ pop(a1);
+ ASSERT(a0.is(KeyedLoadIC::NameRegister()));
+ ASSERT(a1.is(KeyedLoadIC::ReceiverRegister()));
+ __ pop(KeyedLoadIC::ReceiverRegister());
EmitKeyedPropertyLoad(expr);
context()->Plug(v0);
}
Expression* key) {
// Load the key.
VisitForAccumulatorValue(key);
+ ASSERT(a0.is(KeyedLoadIC::NameRegister()));
Expression* callee = expr->expression();
// Load the function from the receiver.
ASSERT(callee->IsProperty());
- __ lw(a1, MemOperand(sp, 0));
+ __ lw(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
__ lw(a0, GlobalObjectOperand());
__ lw(a0, FieldMemOperand(a0, GlobalObject::kBuiltinsOffset));
__ push(a0);
+
// Load the function from the receiver.
- __ li(a2, Operand(expr->name()));
+ ASSERT(a0.is(LoadIC::ReceiverRegister()));
+ __ li(LoadIC::NameRegister(), Operand(expr->name()));
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
// Push the target function under the receiver.
} else {
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
- __ lw(a1, MemOperand(sp, 0));
+ ASSERT(a1.is(KeyedLoadIC::ReceiverRegister()));
+ __ lw(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
__ push(v0);
EmitKeyedPropertyLoad(prop);
}
VariableProxy* proxy = expr->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "[ Global variable");
- __ lw(a0, GlobalObjectOperand());
- __ li(a2, Operand(proxy->name()));
+ __ lw(LoadIC::ReceiverRegister(), GlobalObjectOperand());
+ __ li(LoadIC::NameRegister(), Operand(proxy->name()));
// Use a regular load, not a contextual load, to avoid a reference
// error.
CallLoadIC(NOT_CONTEXTUAL);
// -- ra : return address
// -- a0 : receiver
// -----------------------------------
+ ASSERT(a0.is(ReceiverRegister()));
+ ASSERT(a2.is(NameRegister()));
// Probe the stub cache.
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
// -- lr : return address
// -- a0 : receiver
// -----------------------------------
+ ASSERT(a0.is(ReceiverRegister()));
+ ASSERT(a2.is(NameRegister()));
+
Label miss, slow;
GenerateNameDictionaryReceiverCheck(masm, a0, a1, a3, t0, &miss);
}
+// A register that isn't one of the parameters to the load ic.
+static const Register LoadIC_TempRegister() { return a3; }
+
+
void LoadIC::GenerateMiss(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- a2 : name
- // -- ra : return address
- // -- a0 : receiver
- // -----------------------------------
+ // The return address is on the stack.
Isolate* isolate = masm->isolate();
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0);
- __ mov(a3, a0);
- __ Push(a3, a2);
+ __ mov(LoadIC_TempRegister(), ReceiverRegister());
+ __ Push(LoadIC_TempRegister(), NameRegister());
// Perform tail call to the entry.
ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- a2 : name
- // -- ra : return address
- // -- a0 : receiver
- // -----------------------------------
+ // The return address is on the stack.
- __ mov(a3, a0);
- __ Push(a3, a2);
+ __ mov(LoadIC_TempRegister(), ReceiverRegister());
+ __ Push(LoadIC_TempRegister(), NameRegister());
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
}
// -- a0 : key
// -- a1 : receiver
// -----------------------------------
+ ASSERT(a1.is(ReceiverRegister()));
+ ASSERT(a0.is(NameRegister()));
Label slow, notin;
MemOperand mapped_location =
GenerateMappedArgumentsLookup(masm, a1, a0, a2, a3, t0, ¬in, &slow);
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- ra : return address
- // -- a0 : key
- // -- a1 : receiver
- // -----------------------------------
+ // The return address is on the stack.
Isolate* isolate = masm->isolate();
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0);
- __ Push(a1, a0);
+ __ Push(ReceiverRegister(), NameRegister());
// Perform tail call to the entry.
ExternalReference ref =
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- ra : return address
- // -- a0 : key
- // -- a1 : receiver
- // -----------------------------------
+ // The return address is on the stack.
- __ Push(a1, a0);
+ __ 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 = a0;
- Register receiver = a1;
+ Register key = NameRegister();
+ Register receiver = ReceiverRegister();
+ ASSERT(key.is(a0));
+ ASSERT(receiver.is(a1));
Isolate* isolate = masm->isolate();
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- ra : return address
- // -- a0 : key (index)
- // -- a1 : receiver
- // -----------------------------------
+ // Return address is on the stack.
Label miss;
- Register receiver = a1;
- Register index = a0;
+ Register receiver = ReceiverRegister();
+ Register index = NameRegister();
Register scratch = a3;
Register result = v0;
+ ASSERT(!scratch.is(receiver) && !scratch.is(index));
StringCharAtGenerator char_at_generator(receiver,
index,
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // ---------- S t a t e --------------
- // -- ra : return address
- // -- a0 : key
- // -- a1 : receiver
- // -----------------------------------
+ // Return address is on the stack.
Label slow;
+ Register receiver = ReceiverRegister();
+ Register key = NameRegister();
+ Register scratch1 = a2;
+ Register scratch2 = a3;
+ ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
+ ASSERT(!scratch2.is(receiver) && !scratch2.is(key));
+
// Check that the receiver isn't a smi.
- __ JumpIfSmi(a1, &slow);
+ __ JumpIfSmi(receiver, &slow);
// Check that the key is an array index, that is Uint32.
- __ And(t0, a0, Operand(kSmiTagMask | kSmiSignMask));
+ __ And(t0, key, Operand(kSmiTagMask | kSmiSignMask));
__ Branch(&slow, ne, t0, Operand(zero_reg));
// Get the map of the receiver.
- __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
+ __ lw(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
// Check that it has indexed interceptor and access checks
// are not enabled for this object.
- __ lbu(a3, FieldMemOperand(a2, Map::kBitFieldOffset));
- __ And(a3, a3, Operand(kSlowCaseBitFieldMask));
- __ Branch(&slow, ne, a3, Operand(1 << Map::kHasIndexedInterceptor));
+ __ lbu(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
+ __ And(scratch2, scratch2, Operand(kSlowCaseBitFieldMask));
+ __ Branch(&slow, ne, scratch2, Operand(1 << Map::kHasIndexedInterceptor));
// Everything is fine, call runtime.
- __ Push(a1, a0); // Receiver, key.
+ __ Push(receiver, key); // Receiver, key.
// Perform tail call to the entry.
__ TailCallExternalReference(ExternalReference(
void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->global_object()).is(a0));
+ ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->result()).is(v0));
- __ li(a2, Operand(instr->name()));
+ __ li(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(a0));
+ ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
ASSERT(ToRegister(instr->result()).is(v0));
// Name is always in a2.
- __ li(a2, Operand(instr->name()));
+ __ li(LoadIC::NameRegister(), Operand(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(cp));
- ASSERT(ToRegister(instr->object()).is(a1));
- ASSERT(ToRegister(instr->key()).is(a0));
+ 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(), cp);
- LOperand* global_object = UseFixed(instr->global_object(), a0);
+ LOperand* global_object = UseFixed(instr->global_object(),
+ LoadIC::ReceiverRegister());
LLoadGlobalGeneric* result =
new(zone()) LLoadGlobalGeneric(context, global_object);
return MarkAsCall(DefineFixed(result, v0), instr);
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* object = UseFixed(instr->object(), a0);
+ LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
LInstruction* result =
DefineFixed(new(zone()) LLoadNamedGeneric(context, object), v0);
return MarkAsCall(result, instr);
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), cp);
- LOperand* object = UseFixed(instr->object(), a1);
- LOperand* key = UseFixed(instr->key(), a0);
+ LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
LInstruction* result =
DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), v0);
// -- a0 : key
// -- a1 : receiver
// -----------------------------------
+ ASSERT(a1.is(KeyedLoadIC::ReceiverRegister()));
+ ASSERT(a0.is(KeyedLoadIC::NameRegister()));
Label slow, miss;
Register key = a0;