MIPS: KeyedLoadIC should have same register spec as LoadIC.
Port r22103 (2c36867) Original commit message: On arm, arm64 and x64 there is a different register specification between LoadIC and KeyedLoadIC. It would be nicer if these are the same, allowing some key optimizations. BUG= R=palfia@homejinni.com Review URL: https://codereview.chromium.org/367053002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22168 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
d8aefde617
commit
7a8a44aaf6
@ -1971,25 +1971,15 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
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 -------------
|
||||
// -- ra : return address
|
||||
// -- a0 : key
|
||||
// -- a1 : receiver
|
||||
// -----------------------------------
|
||||
__ Branch(&miss, ne, a0,
|
||||
__ Branch(&miss, ne, name,
|
||||
Operand(isolate()->factory()->prototype_string()));
|
||||
receiver = a1;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
// ----------- S t a t e -------------
|
||||
// -- a2 : name
|
||||
// -- ra : return address
|
||||
// -- a0 : receiver
|
||||
// -- sp[0] : receiver
|
||||
// -----------------------------------
|
||||
receiver = a0;
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, a3, t0, &miss);
|
||||
|
@ -207,9 +207,7 @@ void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1871,9 +1871,9 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
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());
|
||||
__ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
@ -1882,9 +1882,9 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
// We need the key and receiver on both the stack and in v0 and a1.
|
||||
if (expr->is_compound()) {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ lw(a1, MemOperand(sp, 0));
|
||||
__ push(v0);
|
||||
VisitForStackValue(property->key());
|
||||
__ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
|
||||
__ lw(LoadIC::NameRegister(), MemOperand(sp, 0));
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForStackValue(property->key());
|
||||
@ -2022,6 +2022,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
|
||||
Label l_next, l_call;
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
|
||||
// Initial send value is undefined.
|
||||
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
|
||||
__ Branch(&l_next);
|
||||
@ -2030,9 +2033,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ bind(&l_catch);
|
||||
__ mov(a0, v0);
|
||||
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
|
||||
__ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw"
|
||||
__ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter
|
||||
__ Push(a2, a3, a0); // "throw", iter, except
|
||||
__ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
|
||||
__ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter
|
||||
__ Push(load_name, a3, a0); // "throw", iter, except
|
||||
__ jmp(&l_call);
|
||||
|
||||
// try { received = %yield result }
|
||||
@ -2068,19 +2071,15 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// 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
|
||||
__ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
|
||||
__ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter
|
||||
__ Push(load_name, a3, a0); // "next", iter, received
|
||||
|
||||
// result = receiver[f](arg);
|
||||
__ bind(&l_call);
|
||||
__ lw(keyedload_receiver, MemOperand(sp, kPointerSize));
|
||||
__ lw(keyedload_name, MemOperand(sp, 2 * kPointerSize));
|
||||
__ lw(load_receiver, MemOperand(sp, kPointerSize));
|
||||
__ lw(load_name, MemOperand(sp, 2 * kPointerSize));
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ mov(a0, v0);
|
||||
@ -2093,16 +2092,12 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ Drop(1); // The function is still on the stack; drop it.
|
||||
|
||||
// if (!result.done) goto l_try;
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
ASSERT(load_receiver.is(a0));
|
||||
ASSERT(load_name.is(a2));
|
||||
__ Move(load_receiver, v0);
|
||||
|
||||
__ mov(load_receiver, v0);
|
||||
__ push(v0); // save result
|
||||
__ push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // v0=result.done
|
||||
__ mov(load_receiver, v0);
|
||||
__ mov(a0, v0);
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
__ Branch(&l_try, eq, v0, Operand(zero_reg));
|
||||
@ -2272,7 +2267,6 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
__ 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());
|
||||
@ -2281,7 +2275,6 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
__ mov(a0, result_register());
|
||||
// Call keyed load IC. It has register arguments receiver and key.
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, prop->PropertyFeedbackId());
|
||||
@ -2580,16 +2573,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForAccumulatorValue(expr->obj());
|
||||
ASSERT(a0.is(LoadIC::ReceiverRegister()));
|
||||
__ Move(LoadIC::ReceiverRegister(), v0);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
|
||||
context()->Plug(v0);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj());
|
||||
VisitForAccumulatorValue(expr->key());
|
||||
ASSERT(a0.is(KeyedLoadIC::NameRegister()));
|
||||
ASSERT(a1.is(KeyedLoadIC::ReceiverRegister()));
|
||||
__ pop(KeyedLoadIC::ReceiverRegister());
|
||||
__ Move(LoadIC::NameRegister(), v0);
|
||||
__ pop(LoadIC::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
context()->Plug(v0);
|
||||
}
|
||||
@ -2623,7 +2615,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
} else {
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ lw(v0, MemOperand(sp, 0));
|
||||
__ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
EmitNamedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
// Push the target function under the receiver.
|
||||
@ -2641,13 +2633,13 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
|
||||
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(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
__ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
__ Move(LoadIC::NameRegister(), v0);
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
|
||||
@ -4093,12 +4085,12 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
|
||||
if (expr->is_jsruntime()) {
|
||||
// Push the builtins object as the receiver.
|
||||
__ lw(a0, GlobalObjectOperand());
|
||||
__ lw(a0, FieldMemOperand(a0, GlobalObject::kBuiltinsOffset));
|
||||
__ push(a0);
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
__ lw(receiver, GlobalObjectOperand());
|
||||
__ lw(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset));
|
||||
__ push(receiver);
|
||||
|
||||
// Load the function from the receiver.
|
||||
ASSERT(a0.is(LoadIC::ReceiverRegister()));
|
||||
__ li(LoadIC::NameRegister(), Operand(expr->name()));
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
|
||||
@ -4276,16 +4268,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ push(at);
|
||||
}
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
// Put the object both on the stack and in the accumulator.
|
||||
VisitForAccumulatorValue(prop->obj());
|
||||
__ push(v0);
|
||||
// Put the object both on the stack and in the register.
|
||||
VisitForStackValue(prop->obj());
|
||||
__ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
ASSERT(a1.is(KeyedLoadIC::ReceiverRegister()));
|
||||
__ lw(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
__ push(v0);
|
||||
VisitForStackValue(prop->key());
|
||||
__ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
|
||||
__ lw(LoadIC::NameRegister(), MemOperand(sp, 0));
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
}
|
||||
|
@ -317,18 +317,16 @@ static void GenerateKeyNameCheck(MacroAssembler* masm,
|
||||
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a2 : name
|
||||
// -- ra : return address
|
||||
// -- a0 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(a0.is(ReceiverRegister()));
|
||||
ASSERT(a2.is(NameRegister()));
|
||||
// The return address is in lr.
|
||||
Register receiver = ReceiverRegister();
|
||||
Register name = NameRegister();
|
||||
ASSERT(receiver.is(a1));
|
||||
ASSERT(name.is(a2));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
|
||||
masm->isolate()->stub_cache()->GenerateProbe(
|
||||
masm, flags, a0, a2, a3, t0, t1, t2);
|
||||
masm, flags, receiver, name, a3, t0, t1, t2);
|
||||
|
||||
// Cache miss: Jump to runtime.
|
||||
GenerateMiss(masm);
|
||||
@ -339,17 +337,17 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a2 : name
|
||||
// -- lr : return address
|
||||
// -- a0 : receiver
|
||||
// -- a1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(a0.is(ReceiverRegister()));
|
||||
ASSERT(a1.is(ReceiverRegister()));
|
||||
ASSERT(a2.is(NameRegister()));
|
||||
|
||||
Label miss, slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, a0, a1, a3, t0, &miss);
|
||||
GenerateNameDictionaryReceiverCheck(masm, a1, a0, a3, t0, &miss);
|
||||
|
||||
// a1: elements
|
||||
GenerateDictionaryLoad(masm, &slow, a1, a2, v0, a3, t0);
|
||||
// a0: elements
|
||||
GenerateDictionaryLoad(masm, &slow, a0, a2, v0, a3, t0);
|
||||
__ Ret();
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
@ -367,7 +365,7 @@ static const Register LoadIC_TempRegister() { return a3; }
|
||||
|
||||
|
||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in ra.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0);
|
||||
@ -382,7 +380,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in ra.
|
||||
|
||||
__ mov(LoadIC_TempRegister(), ReceiverRegister());
|
||||
__ Push(LoadIC_TempRegister(), NameRegister());
|
||||
@ -482,27 +480,27 @@ static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- a0 : key
|
||||
// -- a1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(a1.is(ReceiverRegister()));
|
||||
ASSERT(a0.is(NameRegister()));
|
||||
// The return address is in ra.
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
ASSERT(receiver.is(a1));
|
||||
ASSERT(key.is(a2));
|
||||
|
||||
Label slow, notin;
|
||||
MemOperand mapped_location =
|
||||
GenerateMappedArgumentsLookup(masm, a1, a0, a2, a3, t0, ¬in, &slow);
|
||||
GenerateMappedArgumentsLookup(
|
||||
masm, receiver, key, a0, a3, t0, ¬in, &slow);
|
||||
__ Ret(USE_DELAY_SLOT);
|
||||
__ lw(v0, mapped_location);
|
||||
__ bind(¬in);
|
||||
// The unmapped lookup expects that the parameter map is in a2.
|
||||
// The unmapped lookup expects that the parameter map is in a0.
|
||||
MemOperand unmapped_location =
|
||||
GenerateUnmappedArgumentsLookup(masm, a0, a2, a3, &slow);
|
||||
__ lw(a2, unmapped_location);
|
||||
GenerateUnmappedArgumentsLookup(masm, key, a0, a3, &slow);
|
||||
__ lw(a0, unmapped_location);
|
||||
__ LoadRoot(a3, Heap::kTheHoleValueRootIndex);
|
||||
__ Branch(&slow, eq, a2, Operand(a3));
|
||||
__ Branch(&slow, eq, a0, Operand(a3));
|
||||
__ Ret(USE_DELAY_SLOT);
|
||||
__ mov(v0, a2);
|
||||
__ mov(v0, a0);
|
||||
__ bind(&slow);
|
||||
GenerateMiss(masm);
|
||||
}
|
||||
@ -544,7 +542,7 @@ void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in ra.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0);
|
||||
@ -560,14 +558,12 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
// IC register specifications
|
||||
const Register LoadIC::ReceiverRegister() { return a0; }
|
||||
const Register LoadIC::ReceiverRegister() { return a1; }
|
||||
const Register LoadIC::NameRegister() { return a2; }
|
||||
const Register KeyedLoadIC::ReceiverRegister() { return a1; }
|
||||
const Register KeyedLoadIC::NameRegister() { return a0; }
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in ra.
|
||||
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
|
||||
@ -576,17 +572,13 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- ra : return address
|
||||
// -- a0 : key
|
||||
// -- a1 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is in ra.
|
||||
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(a0));
|
||||
ASSERT(key.is(a2));
|
||||
ASSERT(receiver.is(a1));
|
||||
|
||||
Isolate* isolate = masm->isolate();
|
||||
@ -598,15 +590,14 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// where a numeric string is converted to a smi.
|
||||
|
||||
GenerateKeyedLoadReceiverCheck(
|
||||
masm, receiver, a2, a3, Map::kHasIndexedInterceptor, &slow);
|
||||
masm, receiver, a0, a3, Map::kHasIndexedInterceptor, &slow);
|
||||
|
||||
// Check the receiver's map to see if it has fast elements.
|
||||
__ CheckFastElements(a2, a3, &check_number_dictionary);
|
||||
__ CheckFastElements(a0, a3, &check_number_dictionary);
|
||||
|
||||
GenerateFastArrayLoad(
|
||||
masm, receiver, key, t0, a3, a2, v0, NULL, &slow);
|
||||
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, a2, a3);
|
||||
masm, receiver, key, a0, a3, t0, v0, NULL, &slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, t0, a3);
|
||||
__ Ret();
|
||||
|
||||
__ bind(&check_number_dictionary);
|
||||
@ -614,42 +605,41 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ lw(a3, FieldMemOperand(t0, JSObject::kMapOffset));
|
||||
|
||||
// Check whether the elements is a number dictionary.
|
||||
// a0: key
|
||||
// a3: elements map
|
||||
// t0: elements
|
||||
__ LoadRoot(at, Heap::kHashTableMapRootIndex);
|
||||
__ Branch(&slow, ne, a3, Operand(at));
|
||||
__ sra(a2, a0, kSmiTagSize);
|
||||
__ LoadFromNumberDictionary(&slow, t0, a0, v0, a2, a3, t1);
|
||||
__ sra(a0, key, kSmiTagSize);
|
||||
__ LoadFromNumberDictionary(&slow, t0, key, v0, a0, a3, t1);
|
||||
__ Ret();
|
||||
|
||||
// Slow case, key and receiver still in a0 and a1.
|
||||
// Slow case, key and receiver still in a2 and a1.
|
||||
__ bind(&slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_slow(),
|
||||
1,
|
||||
a2,
|
||||
t0,
|
||||
a3);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, a2, a3, &index_name, &slow);
|
||||
GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow);
|
||||
|
||||
GenerateKeyedLoadReceiverCheck(
|
||||
masm, receiver, a2, a3, Map::kHasNamedInterceptor, &slow);
|
||||
masm, receiver, a0, a3, Map::kHasNamedInterceptor, &slow);
|
||||
|
||||
|
||||
// If the receiver is a fast-case object, check the keyed lookup
|
||||
// cache. Otherwise probe the dictionary.
|
||||
__ lw(a3, FieldMemOperand(a1, JSObject::kPropertiesOffset));
|
||||
__ lw(a3, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
__ lw(t0, FieldMemOperand(a3, HeapObject::kMapOffset));
|
||||
__ LoadRoot(at, Heap::kHashTableMapRootIndex);
|
||||
__ Branch(&probe_dictionary, eq, t0, Operand(at));
|
||||
|
||||
// Load the map of the receiver, compute the keyed lookup cache hash
|
||||
// based on 32 bits of the map pointer and the name hash.
|
||||
__ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
|
||||
__ sra(a3, a2, KeyedLookupCache::kMapHashShift);
|
||||
__ lw(t0, FieldMemOperand(a0, Name::kHashFieldOffset));
|
||||
__ lw(a0, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
__ sra(a3, a0, KeyedLookupCache::kMapHashShift);
|
||||
__ lw(t0, FieldMemOperand(key, Name::kHashFieldOffset));
|
||||
__ sra(at, t0, Name::kHashShift);
|
||||
__ xor_(a3, a3, at);
|
||||
int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
|
||||
@ -669,21 +659,19 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
for (int i = 0; i < kEntriesPerBucket - 1; i++) {
|
||||
Label try_next_entry;
|
||||
__ lw(t1, MemOperand(t0, kPointerSize * i * 2));
|
||||
__ Branch(&try_next_entry, ne, a2, Operand(t1));
|
||||
__ Branch(&try_next_entry, ne, a0, Operand(t1));
|
||||
__ lw(t1, MemOperand(t0, kPointerSize * (i * 2 + 1)));
|
||||
__ Branch(&hit_on_nth_entry[i], eq, a0, Operand(t1));
|
||||
__ Branch(&hit_on_nth_entry[i], eq, key, Operand(t1));
|
||||
__ bind(&try_next_entry);
|
||||
}
|
||||
|
||||
__ lw(t1, MemOperand(t0, kPointerSize * (kEntriesPerBucket - 1) * 2));
|
||||
__ Branch(&slow, ne, a2, Operand(t1));
|
||||
__ lw(t1, MemOperand(t0, kPointerSize * ((kEntriesPerBucket - 1) * 2 + 1)));
|
||||
__ Branch(&slow, ne, a0, Operand(t1));
|
||||
__ lw(t1, MemOperand(t0, kPointerSize * ((kEntriesPerBucket - 1) * 2 + 1)));
|
||||
__ Branch(&slow, ne, key, Operand(t1));
|
||||
|
||||
// Get field offset.
|
||||
// a0 : key
|
||||
// a1 : receiver
|
||||
// a2 : receiver's map
|
||||
// a0 : receiver's map
|
||||
// a3 : lookup cache index
|
||||
ExternalReference cache_field_offsets =
|
||||
ExternalReference::keyed_lookup_cache_field_offsets(isolate);
|
||||
@ -695,7 +683,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ sll(at, a3, kPointerSizeLog2);
|
||||
__ addu(at, t0, at);
|
||||
__ lw(t1, MemOperand(at, kPointerSize * i));
|
||||
__ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
|
||||
__ lbu(t2, FieldMemOperand(a0, Map::kInObjectPropertiesOffset));
|
||||
__ Subu(t1, t1, t2);
|
||||
__ Branch(&property_array_property, ge, t1, Operand(zero_reg));
|
||||
if (i != 0) {
|
||||
@ -705,28 +693,28 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
// Load in-object property.
|
||||
__ bind(&load_in_object_property);
|
||||
__ lbu(t2, FieldMemOperand(a2, Map::kInstanceSizeOffset));
|
||||
__ lbu(t2, FieldMemOperand(a0, Map::kInstanceSizeOffset));
|
||||
__ addu(t2, t2, t1); // Index from start of object.
|
||||
__ Subu(a1, a1, Operand(kHeapObjectTag)); // Remove the heap tag.
|
||||
__ Subu(receiver, receiver, Operand(kHeapObjectTag)); // Remove the heap tag.
|
||||
__ sll(at, t2, kPointerSizeLog2);
|
||||
__ addu(at, a1, at);
|
||||
__ addu(at, receiver, at);
|
||||
__ lw(v0, MemOperand(at));
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
|
||||
1,
|
||||
a2,
|
||||
t0,
|
||||
a3);
|
||||
__ Ret();
|
||||
|
||||
// Load property array property.
|
||||
__ bind(&property_array_property);
|
||||
__ lw(a1, FieldMemOperand(a1, JSObject::kPropertiesOffset));
|
||||
__ Addu(a1, a1, FixedArray::kHeaderSize - kHeapObjectTag);
|
||||
__ sll(t0, t1, kPointerSizeLog2);
|
||||
__ Addu(t0, t0, a1);
|
||||
__ lw(v0, MemOperand(t0));
|
||||
__ lw(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
__ Addu(receiver, receiver, FixedArray::kHeaderSize - kHeapObjectTag);
|
||||
__ sll(v0, t1, kPointerSizeLog2);
|
||||
__ Addu(v0, v0, receiver);
|
||||
__ lw(v0, MemOperand(v0));
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
|
||||
1,
|
||||
a2,
|
||||
t0,
|
||||
a3);
|
||||
__ Ret();
|
||||
|
||||
@ -734,17 +722,15 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// Do a quick inline probe of the receiver's dictionary, if it
|
||||
// exists.
|
||||
__ bind(&probe_dictionary);
|
||||
// a1: receiver
|
||||
// a0: key
|
||||
// a3: elements
|
||||
__ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
|
||||
__ lbu(a2, FieldMemOperand(a2, Map::kInstanceTypeOffset));
|
||||
GenerateGlobalInstanceTypeCheck(masm, a2, &slow);
|
||||
__ lw(a0, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
|
||||
GenerateGlobalInstanceTypeCheck(masm, a0, &slow);
|
||||
// Load the property to v0.
|
||||
GenerateDictionaryLoad(masm, &slow, a3, a0, v0, a2, t0);
|
||||
GenerateDictionaryLoad(masm, &slow, a3, key, v0, t1, t0);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(),
|
||||
1,
|
||||
a2,
|
||||
t0,
|
||||
a3);
|
||||
__ Ret();
|
||||
|
||||
@ -756,7 +742,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
// Return address is in ra.
|
||||
Label miss;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
@ -1071,13 +1057,13 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
// Return address is in ra.
|
||||
Label slow;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
Register scratch1 = a2;
|
||||
Register scratch2 = a3;
|
||||
Register scratch1 = a3;
|
||||
Register scratch2 = t0;
|
||||
ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
|
||||
ASSERT(!scratch2.is(receiver) && !scratch2.is(key));
|
||||
|
||||
|
@ -3327,8 +3327,8 @@ MemOperand LCodeGen::PrepareKeyedOperand(Register key,
|
||||
|
||||
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);
|
||||
|
@ -2145,8 +2145,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
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), v0);
|
||||
|
@ -1256,16 +1256,16 @@ Register* LoadStubCompiler::registers() {
|
||||
// receiver, name, scratch1, scratch2, scratch3, scratch4.
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, a3, a1, t0, t1 };
|
||||
static Register registers[] = { receiver, name, a3, a0, t0, t1 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
Register* KeyedLoadStubCompiler::registers() {
|
||||
// receiver, name, scratch1, scratch2, scratch3, scratch4.
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, a2, a3, t0, t1 };
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, a3, a0, t0, t1 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
@ -1466,45 +1466,30 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- ra : return address
|
||||
// -- a0 : key
|
||||
// -- a1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(a1.is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(a0.is(KeyedLoadIC::NameRegister()));
|
||||
// The return address is in ra.
|
||||
Label slow, miss;
|
||||
|
||||
Register key = a0;
|
||||
Register receiver = a1;
|
||||
Register key = LoadIC::NameRegister();
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
ASSERT(receiver.is(a1));
|
||||
ASSERT(key.is(a2));
|
||||
|
||||
__ JumpIfNotSmi(key, &miss);
|
||||
__ UntagAndJumpIfNotSmi(t2, key, &miss);
|
||||
__ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||
__ sra(a2, a0, kSmiTagSize);
|
||||
__ LoadFromNumberDictionary(&slow, t0, a0, v0, a2, a3, t1);
|
||||
__ LoadFromNumberDictionary(&slow, t0, key, v0, t2, a3, t1);
|
||||
__ Ret();
|
||||
|
||||
// Slow case, key and receiver still in a0 and a1.
|
||||
// Slow case, key and receiver still unmodified.
|
||||
__ bind(&slow);
|
||||
__ IncrementCounter(
|
||||
masm->isolate()->counters()->keyed_load_external_array_slow(),
|
||||
1, a2, a3);
|
||||
// Entry registers are intact.
|
||||
// ---------- S t a t e --------------
|
||||
// -- ra : return address
|
||||
// -- a0 : key
|
||||
// -- a1 : receiver
|
||||
// -----------------------------------
|
||||
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
||||
|
||||
// Miss case, call the runtime.
|
||||
__ bind(&miss);
|
||||
|
||||
// ---------- S t a t e --------------
|
||||
// -- ra : return address
|
||||
// -- a0 : key
|
||||
// -- a1 : receiver
|
||||
// -----------------------------------
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user