KeyedLoadIC should have same register spec as LoadIC.
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. R=jkummerow@chromium.org Review URL: https://codereview.chromium.org/338963003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22103 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
846dc0f46f
commit
351ed4c8a1
@ -1856,25 +1856,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 -------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
__ cmp(r0, Operand(isolate()->factory()->prototype_string()));
|
||||
__ cmp(name, Operand(isolate()->factory()->prototype_string()));
|
||||
__ b(ne, &miss);
|
||||
receiver = r1;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -- sp[0] : receiver
|
||||
// -----------------------------------
|
||||
receiver = r0;
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss);
|
||||
|
@ -198,9 +198,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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1857,9 +1857,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());
|
||||
__ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
@ -1867,9 +1867,9 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
case KEYED_PROPERTY:
|
||||
if (expr->is_compound()) {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ ldr(r1, MemOperand(sp, 0));
|
||||
__ push(r0);
|
||||
VisitForStackValue(property->key());
|
||||
__ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
|
||||
__ ldr(LoadIC::NameRegister(), MemOperand(sp, 0));
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForStackValue(property->key());
|
||||
@ -2008,6 +2008,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
|
||||
Label l_next, l_call, l_loop;
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
|
||||
// Initial send value is undefined.
|
||||
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
||||
__ b(&l_next);
|
||||
@ -2015,9 +2018,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
|
||||
__ bind(&l_catch);
|
||||
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
|
||||
__ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw"
|
||||
__ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
|
||||
__ Push(r2, r3, r0); // "throw", iter, except
|
||||
__ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
|
||||
__ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
|
||||
__ Push(load_name, r3, r0); // "throw", iter, except
|
||||
__ jmp(&l_call);
|
||||
|
||||
// try { received = %yield result }
|
||||
@ -2051,19 +2054,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(r1));
|
||||
ASSERT(keyedload_name.is(r0));
|
||||
|
||||
__ LoadRoot(r2, Heap::knext_stringRootIndex); // "next"
|
||||
__ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
|
||||
__ Push(r2, r3, r0); // "next", iter, received
|
||||
__ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
|
||||
__ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
|
||||
__ Push(load_name, r3, r0); // "next", iter, received
|
||||
|
||||
// result = receiver[f](arg);
|
||||
__ bind(&l_call);
|
||||
__ ldr(keyedload_receiver, MemOperand(sp, kPointerSize));
|
||||
__ ldr(keyedload_name, MemOperand(sp, 2 * kPointerSize));
|
||||
__ ldr(load_receiver, MemOperand(sp, kPointerSize));
|
||||
__ ldr(load_name, MemOperand(sp, 2 * kPointerSize));
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ mov(r1, r0);
|
||||
@ -2076,10 +2075,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// if (!result.done) goto l_try;
|
||||
__ bind(&l_loop);
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
ASSERT(load_receiver.is(r0));
|
||||
ASSERT(load_name.is(r2));
|
||||
__ Move(load_receiver, r0);
|
||||
|
||||
__ push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
@ -2563,15 +2559,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForAccumulatorValue(expr->obj());
|
||||
ASSERT(r0.is(LoadIC::ReceiverRegister()));
|
||||
__ Move(LoadIC::ReceiverRegister(), r0);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
|
||||
context()->Plug(r0);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj());
|
||||
VisitForAccumulatorValue(expr->key());
|
||||
ASSERT(r0.is(KeyedLoadIC::NameRegister()));
|
||||
__ pop(KeyedLoadIC::ReceiverRegister());
|
||||
__ Move(LoadIC::NameRegister(), r0);
|
||||
__ pop(LoadIC::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
context()->Plug(r0);
|
||||
}
|
||||
@ -2626,13 +2622,13 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
|
||||
Expression* key) {
|
||||
// Load the key.
|
||||
VisitForAccumulatorValue(key);
|
||||
ASSERT(r0.is(KeyedLoadIC::NameRegister()));
|
||||
|
||||
Expression* callee = expr->expression();
|
||||
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
__ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
__ Move(LoadIC::NameRegister(), r0);
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
|
||||
@ -4045,12 +4041,12 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
|
||||
if (expr->is_jsruntime()) {
|
||||
// Push the builtins object as the receiver.
|
||||
__ ldr(r0, GlobalObjectOperand());
|
||||
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
|
||||
__ push(r0);
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
__ ldr(receiver, GlobalObjectOperand());
|
||||
__ ldr(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset));
|
||||
__ push(receiver);
|
||||
|
||||
// Load the function from the receiver.
|
||||
ASSERT(r0.is(LoadIC::ReceiverRegister()));
|
||||
__ mov(LoadIC::NameRegister(), Operand(expr->name()));
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
|
||||
@ -4228,17 +4224,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ push(ip);
|
||||
}
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
// Put the object both on the stack and in the accumulator.
|
||||
VisitForAccumulatorValue(prop->obj());
|
||||
ASSERT(r0.is(LoadIC::ReceiverRegister()));
|
||||
__ push(LoadIC::ReceiverRegister());
|
||||
// Put the object both on the stack and in the register.
|
||||
VisitForStackValue(prop->obj());
|
||||
__ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
ASSERT(r0.is(KeyedLoadIC::NameRegister()));
|
||||
__ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
__ push(KeyedLoadIC::NameRegister());
|
||||
VisitForStackValue(prop->key());
|
||||
__ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
|
||||
__ ldr(LoadIC::NameRegister(), MemOperand(sp, 0));
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
}
|
||||
|
@ -311,18 +311,16 @@ static void GenerateKeyNameCheck(MacroAssembler* masm,
|
||||
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(r0.is(ReceiverRegister()));
|
||||
ASSERT(r2.is(NameRegister()));
|
||||
// The return address is in lr.
|
||||
Register receiver = ReceiverRegister();
|
||||
Register name = NameRegister();
|
||||
ASSERT(receiver.is(r1));
|
||||
ASSERT(name.is(r2));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
|
||||
masm->isolate()->stub_cache()->GenerateProbe(
|
||||
masm, flags, r0, r2, r3, r4, r5, r6);
|
||||
masm, flags, receiver, name, r3, r4, r5, r6);
|
||||
|
||||
// Cache miss: Jump to runtime.
|
||||
GenerateMiss(masm);
|
||||
@ -333,17 +331,17 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(r0.is(ReceiverRegister()));
|
||||
ASSERT(r1.is(ReceiverRegister()));
|
||||
ASSERT(r2.is(NameRegister()));
|
||||
|
||||
Label miss, slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
|
||||
GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
|
||||
|
||||
// r1: elements
|
||||
GenerateDictionaryLoad(masm, &slow, r1, r2, r0, r3, r4);
|
||||
// r0: elements
|
||||
GenerateDictionaryLoad(masm, &slow, r0, r2, r0, r3, r4);
|
||||
__ Ret();
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
@ -361,7 +359,7 @@ static const Register LoadIC_TempRegister() { return r3; }
|
||||
|
||||
|
||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in lr.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
__ IncrementCounter(isolate->counters()->load_miss(), 1, r3, r4);
|
||||
@ -377,7 +375,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in lr.
|
||||
|
||||
__ mov(LoadIC_TempRegister(), ReceiverRegister());
|
||||
__ Push(LoadIC_TempRegister(), NameRegister());
|
||||
@ -472,27 +470,26 @@ static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(r1.is(ReceiverRegister()));
|
||||
ASSERT(r0.is(NameRegister()));
|
||||
// The return address is in lr.
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
ASSERT(receiver.is(r1));
|
||||
ASSERT(key.is(r2));
|
||||
|
||||
Label slow, notin;
|
||||
MemOperand mapped_location =
|
||||
GenerateMappedArgumentsLookup(masm, r1, r0, r2, r3, r4, ¬in, &slow);
|
||||
GenerateMappedArgumentsLookup(
|
||||
masm, receiver, key, r0, r3, r4, ¬in, &slow);
|
||||
__ ldr(r0, mapped_location);
|
||||
__ Ret();
|
||||
__ bind(¬in);
|
||||
// The unmapped lookup expects that the parameter map is in r2.
|
||||
// The unmapped lookup expects that the parameter map is in r0.
|
||||
MemOperand unmapped_location =
|
||||
GenerateUnmappedArgumentsLookup(masm, r0, r2, r3, &slow);
|
||||
__ ldr(r2, unmapped_location);
|
||||
GenerateUnmappedArgumentsLookup(masm, key, r0, r3, &slow);
|
||||
__ ldr(r0, unmapped_location);
|
||||
__ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
|
||||
__ cmp(r2, r3);
|
||||
__ cmp(r0, r3);
|
||||
__ b(eq, &slow);
|
||||
__ mov(r0, r2);
|
||||
__ Ret();
|
||||
__ bind(&slow);
|
||||
GenerateMiss(masm);
|
||||
@ -529,7 +526,7 @@ void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in lr.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4);
|
||||
@ -545,14 +542,12 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
// IC register specifications
|
||||
const Register LoadIC::ReceiverRegister() { return r0; }
|
||||
const Register LoadIC::ReceiverRegister() { return r1; }
|
||||
const Register LoadIC::NameRegister() { return r2; }
|
||||
const Register KeyedLoadIC::ReceiverRegister() { return r1; }
|
||||
const Register KeyedLoadIC::NameRegister() { return r0; }
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in lr.
|
||||
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
|
||||
@ -561,17 +556,13 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is in lr.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
|
||||
Register key = NameRegister();
|
||||
Register receiver = ReceiverRegister();
|
||||
ASSERT(key.is(r0));
|
||||
ASSERT(key.is(r2));
|
||||
ASSERT(receiver.is(r1));
|
||||
|
||||
Isolate* isolate = masm->isolate();
|
||||
@ -583,14 +574,14 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// where a numeric string is converted to a smi.
|
||||
|
||||
GenerateKeyedLoadReceiverCheck(
|
||||
masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow);
|
||||
masm, receiver, r0, r3, Map::kHasIndexedInterceptor, &slow);
|
||||
|
||||
// Check the receiver's map to see if it has fast elements.
|
||||
__ CheckFastElements(r2, r3, &check_number_dictionary);
|
||||
__ CheckFastElements(r0, r3, &check_number_dictionary);
|
||||
|
||||
GenerateFastArrayLoad(
|
||||
masm, receiver, key, r4, r3, r2, r0, NULL, &slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r2, r3);
|
||||
masm, receiver, key, r0, r3, r4, r0, NULL, &slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3);
|
||||
__ Ret();
|
||||
|
||||
__ bind(&check_number_dictionary);
|
||||
@ -598,31 +589,30 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset));
|
||||
|
||||
// Check whether the elements is a number dictionary.
|
||||
// r0: key
|
||||
// r3: elements map
|
||||
// r4: elements
|
||||
__ LoadRoot(ip, Heap::kHashTableMapRootIndex);
|
||||
__ cmp(r3, ip);
|
||||
__ b(ne, &slow);
|
||||
__ SmiUntag(r2, r0);
|
||||
__ LoadFromNumberDictionary(&slow, r4, r0, r0, r2, r3, r5);
|
||||
__ SmiUntag(r0, key);
|
||||
__ LoadFromNumberDictionary(&slow, r4, key, r0, r0, r3, r5);
|
||||
__ Ret();
|
||||
|
||||
// Slow case, key and receiver still in r0 and r1.
|
||||
// Slow case, key and receiver still in r2 and r1.
|
||||
__ bind(&slow);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_slow(),
|
||||
1, r2, r3);
|
||||
1, r4, r3);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, r2, r3, &index_name, &slow);
|
||||
GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow);
|
||||
|
||||
GenerateKeyedLoadReceiverCheck(
|
||||
masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow);
|
||||
masm, receiver, r0, r3, Map::kHasNamedInterceptor, &slow);
|
||||
|
||||
// If the receiver is a fast-case object, check the keyed lookup
|
||||
// cache. Otherwise probe the dictionary.
|
||||
__ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset));
|
||||
__ ldr(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
__ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
|
||||
__ LoadRoot(ip, Heap::kHashTableMapRootIndex);
|
||||
__ cmp(r4, ip);
|
||||
@ -630,9 +620,9 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
// Load the map of the receiver, compute the keyed lookup cache hash
|
||||
// based on 32 bits of the map pointer and the name hash.
|
||||
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
||||
__ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
|
||||
__ ldr(r4, FieldMemOperand(r0, Name::kHashFieldOffset));
|
||||
__ ldr(r0, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
__ mov(r3, Operand(r0, ASR, KeyedLookupCache::kMapHashShift));
|
||||
__ ldr(r4, FieldMemOperand(key, Name::kHashFieldOffset));
|
||||
__ eor(r3, r3, Operand(r4, ASR, Name::kHashShift));
|
||||
int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
|
||||
__ And(r3, r3, Operand(mask));
|
||||
@ -652,26 +642,24 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
Label try_next_entry;
|
||||
// Load map and move r4 to next entry.
|
||||
__ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
|
||||
__ cmp(r2, r5);
|
||||
__ cmp(r0, r5);
|
||||
__ b(ne, &try_next_entry);
|
||||
__ ldr(r5, MemOperand(r4, -kPointerSize)); // Load name
|
||||
__ cmp(r0, r5);
|
||||
__ cmp(key, r5);
|
||||
__ b(eq, &hit_on_nth_entry[i]);
|
||||
__ bind(&try_next_entry);
|
||||
}
|
||||
|
||||
// Last entry: Load map and move r4 to name.
|
||||
__ ldr(r5, MemOperand(r4, kPointerSize, PostIndex));
|
||||
__ cmp(r2, r5);
|
||||
__ cmp(r0, r5);
|
||||
__ b(ne, &slow);
|
||||
__ ldr(r5, MemOperand(r4));
|
||||
__ cmp(r0, r5);
|
||||
__ cmp(key, r5);
|
||||
__ b(ne, &slow);
|
||||
|
||||
// Get field offset.
|
||||
// r0 : key
|
||||
// r1 : receiver
|
||||
// r2 : receiver's map
|
||||
// r0 : receiver's map
|
||||
// r3 : lookup cache index
|
||||
ExternalReference cache_field_offsets =
|
||||
ExternalReference::keyed_lookup_cache_field_offsets(isolate);
|
||||
@ -684,7 +672,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ add(r3, r3, Operand(i));
|
||||
}
|
||||
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
|
||||
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
|
||||
__ ldrb(r6, FieldMemOperand(r0, Map::kInObjectPropertiesOffset));
|
||||
__ sub(r5, r5, r6, SetCC);
|
||||
__ b(ge, &property_array_property);
|
||||
if (i != 0) {
|
||||
@ -694,36 +682,34 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
// Load in-object property.
|
||||
__ bind(&load_in_object_property);
|
||||
__ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset));
|
||||
__ ldrb(r6, FieldMemOperand(r0, Map::kInstanceSizeOffset));
|
||||
__ add(r6, r6, r5); // Index from start of object.
|
||||
__ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag.
|
||||
__ ldr(r0, MemOperand(r1, r6, LSL, kPointerSizeLog2));
|
||||
__ sub(receiver, receiver, Operand(kHeapObjectTag)); // Remove the heap tag.
|
||||
__ ldr(r0, MemOperand(receiver, r6, LSL, kPointerSizeLog2));
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
|
||||
1, r2, r3);
|
||||
1, r4, r3);
|
||||
__ Ret();
|
||||
|
||||
// Load property array property.
|
||||
__ bind(&property_array_property);
|
||||
__ ldr(r1, FieldMemOperand(r1, JSObject::kPropertiesOffset));
|
||||
__ add(r1, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
||||
__ ldr(r0, MemOperand(r1, r5, LSL, kPointerSizeLog2));
|
||||
__ ldr(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
__ add(receiver, receiver, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
||||
__ ldr(r0, MemOperand(receiver, r5, LSL, kPointerSizeLog2));
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
|
||||
1, r2, r3);
|
||||
1, r4, r3);
|
||||
__ Ret();
|
||||
|
||||
// Do a quick inline probe of the receiver's dictionary, if it
|
||||
// exists.
|
||||
__ bind(&probe_dictionary);
|
||||
// r1: receiver
|
||||
// r0: key
|
||||
// r3: elements
|
||||
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
||||
__ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
|
||||
GenerateGlobalInstanceTypeCheck(masm, r2, &slow);
|
||||
__ ldr(r0, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
|
||||
GenerateGlobalInstanceTypeCheck(masm, r0, &slow);
|
||||
// Load the property to r0.
|
||||
GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4);
|
||||
GenerateDictionaryLoad(masm, &slow, r3, key, r0, r5, r4);
|
||||
__ IncrementCounter(
|
||||
isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3);
|
||||
isolate->counters()->keyed_load_generic_symbol(), 1, r4, r3);
|
||||
__ Ret();
|
||||
|
||||
__ bind(&index_name);
|
||||
@ -734,7 +720,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
// Return address is in lr.
|
||||
Label miss;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
@ -763,13 +749,13 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
// Return address is in lr.
|
||||
Label slow;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
Register scratch1 = r2;
|
||||
Register scratch2 = r3;
|
||||
Register scratch1 = r3;
|
||||
Register scratch2 = r4;
|
||||
ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
|
||||
ASSERT(!scratch2.is(receiver) && !scratch2.is(key));
|
||||
|
||||
|
@ -2199,8 +2199,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), r0);
|
||||
|
@ -3375,8 +3375,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, NEVER_INLINE_TARGET_ADDRESS);
|
||||
|
@ -1265,16 +1265,16 @@ Register* LoadStubCompiler::registers() {
|
||||
// receiver, name, scratch1, scratch2, scratch3, scratch4.
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, r3, r1, r4, r5 };
|
||||
static Register registers[] = { receiver, name, r3, r0, r4, r5 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
Register* KeyedLoadStubCompiler::registers() {
|
||||
// receiver, name, scratch1, scratch2, scratch3, scratch4.
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, r2, r3, r4, r5 };
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, r3, r0, r4, r5 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
@ -1474,21 +1474,17 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(r1.is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(r0.is(KeyedLoadIC::NameRegister()));
|
||||
// The return address is in lr.
|
||||
Label slow, miss;
|
||||
|
||||
Register key = r0;
|
||||
Register receiver = r1;
|
||||
Register key = LoadIC::NameRegister();
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
ASSERT(receiver.is(r1));
|
||||
ASSERT(key.is(r2));
|
||||
|
||||
__ UntagAndJumpIfNotSmi(r2, key, &miss);
|
||||
__ UntagAndJumpIfNotSmi(r6, key, &miss);
|
||||
__ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||
__ LoadFromNumberDictionary(&slow, r4, key, r0, r2, r3, r5);
|
||||
__ LoadFromNumberDictionary(&slow, r4, key, r0, r6, r3, r5);
|
||||
__ Ret();
|
||||
|
||||
__ bind(&slow);
|
||||
@ -1496,21 +1492,11 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
masm->isolate()->counters()->keyed_load_external_array_slow(),
|
||||
1, r2, r3);
|
||||
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
||||
|
||||
// Miss case, call the runtime.
|
||||
__ bind(&miss);
|
||||
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
|
||||
}
|
||||
|
||||
|
@ -1727,26 +1727,15 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
||||
|
||||
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
Register receiver;
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
|
||||
ASSERT(kind() == Code::LOAD_IC ||
|
||||
kind() == Code::KEYED_LOAD_IC);
|
||||
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- lr : return address
|
||||
// -- x1 : receiver
|
||||
// -- x0 : key
|
||||
// -----------------------------------
|
||||
Register key = x0;
|
||||
receiver = x1;
|
||||
__ Cmp(key, Operand(isolate()->factory()->prototype_string()));
|
||||
__ Cmp(name, Operand(isolate()->factory()->prototype_string()));
|
||||
__ B(ne, &miss);
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
// ----------- S t a t e -------------
|
||||
// -- lr : return address
|
||||
// -- x2 : name
|
||||
// -- x0 : receiver
|
||||
// -- sp[0] : receiver
|
||||
// -----------------------------------
|
||||
receiver = x0;
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, x10, x11, &miss);
|
||||
|
@ -257,9 +257,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, x10);
|
||||
GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1858,9 +1858,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());
|
||||
__ Peek(LoadIC::ReceiverRegister(), 0);
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
@ -1868,9 +1868,9 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
case KEYED_PROPERTY:
|
||||
if (expr->is_compound()) {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ Peek(x1, 0);
|
||||
__ Push(x0);
|
||||
VisitForStackValue(property->key());
|
||||
__ Peek(LoadIC::ReceiverRegister(), 1 * kPointerSize);
|
||||
__ Peek(LoadIC::NameRegister(), 0);
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForStackValue(property->key());
|
||||
@ -2260,15 +2260,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForAccumulatorValue(expr->obj());
|
||||
ASSERT(x0.is(LoadIC::ReceiverRegister()));
|
||||
__ Move(LoadIC::ReceiverRegister(), x0);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
|
||||
context()->Plug(x0);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj());
|
||||
VisitForAccumulatorValue(expr->key());
|
||||
ASSERT(x0.is(KeyedLoadIC::NameRegister()));
|
||||
__ Pop(KeyedLoadIC::ReceiverRegister());
|
||||
__ Move(LoadIC::NameRegister(), x0);
|
||||
__ Pop(LoadIC::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
context()->Plug(x0);
|
||||
}
|
||||
@ -2321,13 +2321,13 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
|
||||
Expression* key) {
|
||||
// Load the key.
|
||||
VisitForAccumulatorValue(key);
|
||||
ASSERT(x0.is(KeyedLoadIC::NameRegister()));
|
||||
|
||||
Expression* callee = expr->expression();
|
||||
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ Peek(KeyedLoadIC::ReceiverRegister(), 0);
|
||||
__ Peek(LoadIC::ReceiverRegister(), 0);
|
||||
__ Move(LoadIC::NameRegister(), x0);
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
|
||||
@ -3927,18 +3927,16 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ Push(xzr);
|
||||
}
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
// Put the object both on the stack and in the accumulator.
|
||||
VisitForAccumulatorValue(prop->obj());
|
||||
ASSERT(x0.is(LoadIC::ReceiverRegister()));
|
||||
__ Push(LoadIC::ReceiverRegister());
|
||||
// Put the object both on the stack and in the register.
|
||||
VisitForStackValue(prop->obj());
|
||||
__ Peek(LoadIC::ReceiverRegister(), 0);
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
// KEYED_PROPERTY
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
ASSERT(x0.is(KeyedLoadIC::NameRegister()));
|
||||
__ Peek(KeyedLoadIC::ReceiverRegister(), 0);
|
||||
__ Push(KeyedLoadIC::NameRegister());
|
||||
VisitForStackValue(prop->key());
|
||||
__ Peek(LoadIC::ReceiverRegister(), 1 * kPointerSize);
|
||||
__ Peek(LoadIC::NameRegister(), 0);
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
}
|
||||
@ -4389,6 +4387,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
|
||||
Label l_next, l_call, l_loop;
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
|
||||
// Initial send value is undefined.
|
||||
__ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
|
||||
__ B(&l_next);
|
||||
@ -4396,9 +4397,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
|
||||
__ Bind(&l_catch);
|
||||
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
|
||||
__ LoadRoot(x2, Heap::kthrow_stringRootIndex); // "throw"
|
||||
__ Peek(x3, 1 * kPointerSize); // iter
|
||||
__ Push(x2, x3, x0); // "throw", iter, except
|
||||
__ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
|
||||
__ Peek(x3, 1 * kPointerSize); // iter
|
||||
__ Push(load_name, x3, x0); // "throw", iter, except
|
||||
__ B(&l_call);
|
||||
|
||||
// try { received = %yield result }
|
||||
@ -4437,19 +4438,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(x1));
|
||||
ASSERT(keyedload_name.is(x0));
|
||||
|
||||
__ LoadRoot(x2, Heap::knext_stringRootIndex); // "next"
|
||||
__ Peek(x3, 1 * kPointerSize); // iter
|
||||
__ Push(x2, x3, x0); // "next", iter, received
|
||||
__ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
|
||||
__ Peek(x3, 1 * kPointerSize); // iter
|
||||
__ Push(load_name, x3, x0); // "next", iter, received
|
||||
|
||||
// result = receiver[f](arg);
|
||||
__ Bind(&l_call);
|
||||
__ Peek(keyedload_receiver, 1 * kPointerSize);
|
||||
__ Peek(keyedload_name, 2 * kPointerSize);
|
||||
__ Peek(load_receiver, 1 * kPointerSize);
|
||||
__ Peek(load_name, 2 * kPointerSize);
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ Mov(x1, x0);
|
||||
@ -4462,10 +4459,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// if (!result.done) goto l_try;
|
||||
__ Bind(&l_loop);
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
ASSERT(load_receiver.is(x0));
|
||||
ASSERT(load_name.is(x2));
|
||||
__ Move(load_receiver, x0);
|
||||
|
||||
__ Push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // x0=result.done
|
||||
|
@ -407,18 +407,16 @@ static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
|
||||
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- x2 : name
|
||||
// -- lr : return address
|
||||
// -- x0 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(x0.is(ReceiverRegister()));
|
||||
ASSERT(x2.is(NameRegister()));
|
||||
// The return address is in lr.
|
||||
Register receiver = ReceiverRegister();
|
||||
Register name = NameRegister();
|
||||
ASSERT(receiver.is(x1));
|
||||
ASSERT(name.is(x2));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
|
||||
masm->isolate()->stub_cache()->GenerateProbe(
|
||||
masm, flags, x0, x2, x3, x4, x5, x6);
|
||||
masm, flags, receiver, name, x3, x4, x5, x6);
|
||||
|
||||
// Cache miss: Jump to runtime.
|
||||
GenerateMiss(masm);
|
||||
@ -429,16 +427,16 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- x2 : name
|
||||
// -- lr : return address
|
||||
// -- x0 : receiver
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(x0.is(ReceiverRegister()));
|
||||
ASSERT(x1.is(ReceiverRegister()));
|
||||
ASSERT(x2.is(NameRegister()));
|
||||
Label miss, slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, x0, x1, x3, x4, &miss);
|
||||
GenerateNameDictionaryReceiverCheck(masm, x1, x0, x3, x4, &miss);
|
||||
|
||||
// x1 now holds the property dictionary.
|
||||
GenerateDictionaryLoad(masm, &slow, x1, x2, x0, x3, x4);
|
||||
// x0 now holds the property dictionary.
|
||||
GenerateDictionaryLoad(masm, &slow, x0, x2, x0, x3, x4);
|
||||
__ Ret();
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
@ -452,7 +450,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in lr.
|
||||
Isolate* isolate = masm->isolate();
|
||||
ASM_LOCATION("LoadIC::GenerateMiss");
|
||||
|
||||
@ -467,27 +465,23 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in lr.
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- x0 : key
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is in lr.
|
||||
Register result = x0;
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
ASSERT(receiver.is(x1));
|
||||
ASSERT(key.is(x0));
|
||||
ASSERT(key.is(x2));
|
||||
|
||||
Label miss, unmapped;
|
||||
|
||||
Register map_scratch = x2;
|
||||
Register map_scratch = x0;
|
||||
MemOperand mapped_location = GenerateMappedArgumentsLookup(
|
||||
masm, receiver, key, map_scratch, x3, x4, &unmapped, &miss);
|
||||
__ Ldr(result, mapped_location);
|
||||
@ -497,10 +491,8 @@ void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// Parameter map is left in map_scratch when a jump on unmapped is done.
|
||||
MemOperand unmapped_location =
|
||||
GenerateUnmappedArgumentsLookup(masm, key, map_scratch, x3, &miss);
|
||||
__ Ldr(x2, unmapped_location);
|
||||
__ JumpIfRoot(x2, Heap::kTheHoleValueRootIndex, &miss);
|
||||
// Move the result in x0. x0 must be preserved on miss.
|
||||
__ Mov(result, x2);
|
||||
__ Ldr(result, unmapped_location);
|
||||
__ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss);
|
||||
__ Ret();
|
||||
|
||||
__ Bind(&miss);
|
||||
@ -560,7 +552,7 @@ void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in lr.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11);
|
||||
@ -576,14 +568,12 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
// IC register specifications
|
||||
const Register LoadIC::ReceiverRegister() { return x0; }
|
||||
const Register LoadIC::ReceiverRegister() { return x1; }
|
||||
const Register LoadIC::NameRegister() { return x2; }
|
||||
const Register KeyedLoadIC::ReceiverRegister() { return x1; }
|
||||
const Register KeyedLoadIC::NameRegister() { return x0; }
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
// The return address is in lr.
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
@ -753,34 +743,30 @@ static void GenerateKeyedLoadWithNameKey(MacroAssembler* masm,
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- x0 : key
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is in lr.
|
||||
Label slow, check_name, index_smi, index_name;
|
||||
|
||||
Register key = NameRegister();
|
||||
Register receiver = ReceiverRegister();
|
||||
ASSERT(key.is(x0));
|
||||
ASSERT(key.is(x2));
|
||||
ASSERT(receiver.is(x1));
|
||||
|
||||
__ JumpIfNotSmi(key, &check_name);
|
||||
__ Bind(&index_smi);
|
||||
// Now the key is known to be a smi. This place is also jumped to from below
|
||||
// where a numeric string is converted to a smi.
|
||||
GenerateKeyedLoadWithSmiKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow);
|
||||
GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow);
|
||||
|
||||
// Slow case, key and receiver still in x0 and x1.
|
||||
// Slow case.
|
||||
__ Bind(&slow);
|
||||
__ IncrementCounter(
|
||||
masm->isolate()->counters()->keyed_load_generic_slow(), 1, x2, x3);
|
||||
masm->isolate()->counters()->keyed_load_generic_slow(), 1, x4, x3);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ Bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, key, x2, x3, &index_name, &slow);
|
||||
GenerateKeyNameCheck(masm, key, x0, x3, &index_name, &slow);
|
||||
|
||||
GenerateKeyedLoadWithNameKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow);
|
||||
GenerateKeyedLoadWithNameKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow);
|
||||
|
||||
__ Bind(&index_name);
|
||||
__ IndexFromHash(x3, key);
|
||||
@ -790,7 +776,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
// Return address is in lr.
|
||||
Label miss;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
@ -819,15 +805,14 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
// Return address is in lr.
|
||||
Label slow;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
Register scratch1 = x2;
|
||||
Register scratch2 = x3;
|
||||
ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
|
||||
ASSERT(!scratch2.is(receiver) && !scratch2.is(key));
|
||||
Register scratch1 = x3;
|
||||
Register scratch2 = x4;
|
||||
ASSERT(!AreAliased(scratch1, scratch2, receiver, key));
|
||||
|
||||
// Check that the receiver isn't a smi.
|
||||
__ JumpIfSmi(receiver, &slow);
|
||||
|
@ -1713,8 +1713,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), x0);
|
||||
|
@ -3643,8 +3643,8 @@ void LCodeGen::DoLoadKeyedFixed(LLoadKeyedFixed* instr) {
|
||||
|
||||
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);
|
||||
@ -3696,7 +3696,6 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(cp));
|
||||
// LoadIC expects name and receiver in registers.
|
||||
ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->object()).is(x0));
|
||||
__ Mov(LoadIC::NameRegister(), Operand(instr->name()));
|
||||
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
|
||||
|
@ -1247,16 +1247,16 @@ Register* LoadStubCompiler::registers() {
|
||||
// receiver, name, scratch1, scratch2, scratch3, scratch4.
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, x3, x1, x4, x5 };
|
||||
static Register registers[] = { receiver, name, x3, x0, x4, x5 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
Register* KeyedLoadStubCompiler::registers() {
|
||||
// receiver, name, scratch1, scratch2, scratch3, scratch4.
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, x2, x3, x4, x5 };
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, x3, x0, x4, x5 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
@ -1449,27 +1449,23 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
|
||||
|
||||
void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- x0 : key
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(x1.is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(x0.is(KeyedLoadIC::NameRegister()));
|
||||
// The return address is in lr.
|
||||
Label slow, miss;
|
||||
|
||||
Register result = x0;
|
||||
Register key = x0;
|
||||
Register receiver = x1;
|
||||
Register key = LoadIC::NameRegister();
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
ASSERT(receiver.is(x1));
|
||||
ASSERT(key.is(x2));
|
||||
|
||||
__ JumpIfNotSmi(key, &miss);
|
||||
__ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||
__ LoadFromNumberDictionary(&slow, x4, key, result, x2, x3, x5, x6);
|
||||
__ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6);
|
||||
__ Ret();
|
||||
|
||||
__ Bind(&slow);
|
||||
__ IncrementCounter(
|
||||
masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x2, x3);
|
||||
masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3);
|
||||
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
||||
|
||||
// Miss case, call the runtime.
|
||||
|
@ -585,9 +585,9 @@ void JSEntryStub::FinishCode(Handle<Code> code) {
|
||||
|
||||
void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { KeyedLoadIC::ReceiverRegister(),
|
||||
KeyedLoadIC::NameRegister() };
|
||||
STATIC_ASSERT(KeyedLoadIC::kRegisterArgumentCount == 2);
|
||||
Register registers[] = { LoadIC::ReceiverRegister(),
|
||||
LoadIC::NameRegister() };
|
||||
STATIC_ASSERT(LoadIC::kRegisterArgumentCount == 2);
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers,
|
||||
FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
|
||||
}
|
||||
@ -595,9 +595,9 @@ void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
|
||||
|
||||
void KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { KeyedLoadIC::ReceiverRegister(),
|
||||
KeyedLoadIC::NameRegister() };
|
||||
STATIC_ASSERT(KeyedLoadIC::kRegisterArgumentCount == 2);
|
||||
Register registers[] = { LoadIC::ReceiverRegister(),
|
||||
LoadIC::NameRegister() };
|
||||
STATIC_ASSERT(LoadIC::kRegisterArgumentCount == 2);
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers,
|
||||
FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
|
||||
}
|
||||
@ -605,9 +605,9 @@ void KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor(
|
||||
|
||||
void KeyedLoadGenericElementStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { KeyedLoadIC::ReceiverRegister(),
|
||||
KeyedLoadIC::NameRegister() };
|
||||
STATIC_ASSERT(KeyedLoadIC::kRegisterArgumentCount == 2);
|
||||
Register registers[] = { LoadIC::ReceiverRegister(),
|
||||
LoadIC::NameRegister() };
|
||||
STATIC_ASSERT(LoadIC::kRegisterArgumentCount == 2);
|
||||
descriptor->Initialize(
|
||||
ARRAY_SIZE(registers), registers,
|
||||
Runtime::FunctionForId(Runtime::kKeyedGetProperty)->entry);
|
||||
@ -623,7 +623,7 @@ void LoadFieldStub::InitializeInterfaceDescriptor(
|
||||
|
||||
void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { KeyedLoadIC::ReceiverRegister() };
|
||||
Register registers[] = { LoadIC::ReceiverRegister() };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
@ -638,8 +638,8 @@ void StringLengthStub::InitializeInterfaceDescriptor(
|
||||
|
||||
void KeyedStringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { KeyedLoadIC::ReceiverRegister(),
|
||||
KeyedLoadIC::NameRegister() };
|
||||
Register registers[] = { LoadIC::ReceiverRegister(),
|
||||
LoadIC::NameRegister() };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
@ -995,10 +995,12 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
|
||||
// Copy all arguments from the array to the stack.
|
||||
Label entry, loop;
|
||||
__ mov(ecx, Operand(ebp, kIndexOffset));
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register key = LoadIC::NameRegister();
|
||||
__ mov(key, Operand(ebp, kIndexOffset));
|
||||
__ jmp(&entry);
|
||||
__ bind(&loop);
|
||||
__ mov(edx, Operand(ebp, kArgumentsOffset)); // load arguments
|
||||
__ mov(receiver, Operand(ebp, kArgumentsOffset)); // load arguments
|
||||
|
||||
// Use inline caching to speed up access to arguments.
|
||||
Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
@ -1011,19 +1013,19 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
// Push the nth argument.
|
||||
__ push(eax);
|
||||
|
||||
// Update the index on the stack and in register eax.
|
||||
__ mov(ecx, Operand(ebp, kIndexOffset));
|
||||
__ add(ecx, Immediate(1 << kSmiTagSize));
|
||||
__ mov(Operand(ebp, kIndexOffset), ecx);
|
||||
// Update the index on the stack and in register key.
|
||||
__ mov(key, Operand(ebp, kIndexOffset));
|
||||
__ add(key, Immediate(1 << kSmiTagSize));
|
||||
__ mov(Operand(ebp, kIndexOffset), key);
|
||||
|
||||
__ bind(&entry);
|
||||
__ cmp(ecx, Operand(ebp, kLimitOffset));
|
||||
__ cmp(key, Operand(ebp, kLimitOffset));
|
||||
__ j(not_equal, &loop);
|
||||
|
||||
// Call the function.
|
||||
Label call_proxy;
|
||||
__ mov(eax, ecx);
|
||||
ParameterCount actual(eax);
|
||||
__ Move(eax, key);
|
||||
__ SmiUntag(eax);
|
||||
__ mov(edi, Operand(ebp, kFunctionOffset));
|
||||
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
|
||||
|
@ -200,9 +200,7 @@ void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for keyed IC load call (from ic-ia32.cc).
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
|
||||
GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1811,9 +1811,9 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
break;
|
||||
case NAMED_PROPERTY:
|
||||
if (expr->is_compound()) {
|
||||
// We need the receiver both on the stack and in edx.
|
||||
// We need the receiver both on the stack and in the register.
|
||||
VisitForStackValue(property->obj());
|
||||
__ mov(edx, Operand(esp, 0));
|
||||
__ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
@ -1822,8 +1822,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
if (expr->is_compound()) {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForStackValue(property->key());
|
||||
__ mov(edx, Operand(esp, kPointerSize)); // Object.
|
||||
__ mov(ecx, Operand(esp, 0)); // Key.
|
||||
__ mov(LoadIC::ReceiverRegister(), Operand(esp, kPointerSize));
|
||||
__ mov(LoadIC::NameRegister(), Operand(esp, 0));
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForStackValue(property->key());
|
||||
@ -1964,6 +1964,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
|
||||
Label l_next, l_call, l_loop;
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
|
||||
// Initial send value is undefined.
|
||||
__ mov(eax, isolate()->factory()->undefined_value());
|
||||
__ jmp(&l_next);
|
||||
@ -1971,10 +1974,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
|
||||
__ bind(&l_catch);
|
||||
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
|
||||
__ mov(ecx, isolate()->factory()->throw_string()); // "throw"
|
||||
__ push(ecx); // "throw"
|
||||
__ push(Operand(esp, 2 * kPointerSize)); // iter
|
||||
__ push(eax); // exception
|
||||
__ mov(load_name, isolate()->factory()->throw_string()); // "throw"
|
||||
__ push(load_name); // "throw"
|
||||
__ push(Operand(esp, 2 * kPointerSize)); // iter
|
||||
__ push(eax); // exception
|
||||
__ jmp(&l_call);
|
||||
|
||||
// try { received = %yield result }
|
||||
@ -2009,20 +2012,15 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// receiver = iter; f = iter.next; arg = received;
|
||||
__ bind(&l_next);
|
||||
Register keyedload_receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register keyedload_name = KeyedLoadIC::NameRegister();
|
||||
ASSERT(keyedload_receiver.is(edx));
|
||||
ASSERT(keyedload_name.is(ecx));
|
||||
|
||||
__ mov(keyedload_name,
|
||||
isolate()->factory()->next_string()); // "next"
|
||||
__ push(keyedload_name);
|
||||
__ push(Operand(esp, 2 * kPointerSize)); // iter
|
||||
__ push(eax); // received
|
||||
__ mov(load_name, isolate()->factory()->next_string());
|
||||
__ push(load_name); // "next"
|
||||
__ push(Operand(esp, 2 * kPointerSize)); // iter
|
||||
__ push(eax); // received
|
||||
|
||||
// result = receiver[f](arg);
|
||||
__ bind(&l_call);
|
||||
__ mov(keyedload_receiver, Operand(esp, kPointerSize));
|
||||
__ mov(load_receiver, Operand(esp, kPointerSize));
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ mov(edi, eax);
|
||||
@ -2036,11 +2034,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// if (!result.done) goto l_try;
|
||||
__ bind(&l_loop);
|
||||
__ push(eax); // save result
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
ASSERT(load_receiver.is(edx));
|
||||
ASSERT(load_name.is(ecx));
|
||||
__ mov(load_receiver, eax); // result
|
||||
__ Move(load_receiver, eax); // result
|
||||
__ mov(load_name,
|
||||
isolate()->factory()->done_string()); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
|
||||
@ -2510,15 +2504,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForAccumulatorValue(expr->obj());
|
||||
__ mov(LoadIC::ReceiverRegister(), result_register());
|
||||
__ Move(LoadIC::ReceiverRegister(), result_register());
|
||||
EmitNamedPropertyLoad(expr);
|
||||
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
|
||||
context()->Plug(eax);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj());
|
||||
VisitForAccumulatorValue(expr->key());
|
||||
__ pop(KeyedLoadIC::ReceiverRegister()); // Object.
|
||||
__ mov(KeyedLoadIC::NameRegister(), result_register()); // Key.
|
||||
__ pop(LoadIC::ReceiverRegister()); // Object.
|
||||
__ Move(LoadIC::NameRegister(), result_register()); // Key.
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
context()->Plug(eax);
|
||||
}
|
||||
@ -2573,9 +2567,8 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
|
||||
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ mov(KeyedLoadIC::ReceiverRegister(), Operand(esp, 0));
|
||||
// Move the key into the right register for the keyed load IC.
|
||||
__ mov(KeyedLoadIC::NameRegister(), eax);
|
||||
__ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
|
||||
__ mov(LoadIC::NameRegister(), eax);
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
|
||||
@ -4215,18 +4208,16 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ push(Immediate(Smi::FromInt(0)));
|
||||
}
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
// Put the object both on the stack and in edx.
|
||||
VisitForAccumulatorValue(prop->obj());
|
||||
ASSERT(!eax.is(LoadIC::ReceiverRegister()));
|
||||
__ push(eax);
|
||||
__ mov(LoadIC::ReceiverRegister(), eax);
|
||||
// Put the object both on the stack and in the register.
|
||||
VisitForStackValue(prop->obj());
|
||||
__ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForStackValue(prop->key());
|
||||
__ mov(KeyedLoadIC::ReceiverRegister(),
|
||||
Operand(esp, kPointerSize)); // Object.
|
||||
__ mov(KeyedLoadIC::NameRegister(), Operand(esp, 0)); // Key.
|
||||
__ mov(LoadIC::ReceiverRegister(),
|
||||
Operand(esp, kPointerSize)); // Object.
|
||||
__ mov(LoadIC::NameRegister(), Operand(esp, 0)); // Key.
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
}
|
||||
|
@ -383,43 +383,40 @@ static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(edx.is(ReceiverRegister()));
|
||||
ASSERT(ecx.is(NameRegister()));
|
||||
// The return address is on the stack.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
ASSERT(receiver.is(edx));
|
||||
ASSERT(key.is(ecx));
|
||||
|
||||
// Check that the key is a smi.
|
||||
__ JumpIfNotSmi(ecx, &check_name);
|
||||
__ JumpIfNotSmi(key, &check_name);
|
||||
__ bind(&index_smi);
|
||||
// Now the key is known to be a smi. This place is also jumped to from
|
||||
// where a numeric string is converted to a smi.
|
||||
|
||||
GenerateKeyedLoadReceiverCheck(
|
||||
masm, edx, eax, Map::kHasIndexedInterceptor, &slow);
|
||||
masm, receiver, eax, Map::kHasIndexedInterceptor, &slow);
|
||||
|
||||
// Check the receiver's map to see if it has fast elements.
|
||||
__ CheckFastElements(eax, &check_number_dictionary);
|
||||
|
||||
GenerateFastArrayLoad(masm, edx, ecx, eax, eax, NULL, &slow);
|
||||
GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow);
|
||||
Isolate* isolate = masm->isolate();
|
||||
Counters* counters = isolate->counters();
|
||||
__ IncrementCounter(counters->keyed_load_generic_smi(), 1);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&check_number_dictionary);
|
||||
__ mov(ebx, ecx);
|
||||
__ mov(ebx, key);
|
||||
__ SmiUntag(ebx);
|
||||
__ mov(eax, FieldOperand(edx, JSObject::kElementsOffset));
|
||||
__ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset));
|
||||
|
||||
// Check whether the elements is a number dictionary.
|
||||
// edx: receiver
|
||||
// ebx: untagged index
|
||||
// ecx: key
|
||||
// eax: elements
|
||||
__ CheckMap(eax,
|
||||
isolate->factory()->hash_table_map(),
|
||||
@ -428,32 +425,30 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
Label slow_pop_receiver;
|
||||
// Push receiver on the stack to free up a register for the dictionary
|
||||
// probing.
|
||||
__ push(edx);
|
||||
__ LoadFromNumberDictionary(&slow_pop_receiver, eax, ecx, ebx, edx, edi, eax);
|
||||
__ push(receiver);
|
||||
__ LoadFromNumberDictionary(&slow_pop_receiver, eax, key, ebx, edx, edi, eax);
|
||||
// Pop receiver before returning.
|
||||
__ pop(edx);
|
||||
__ pop(receiver);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&slow_pop_receiver);
|
||||
// Pop the receiver from the stack and jump to runtime.
|
||||
__ pop(edx);
|
||||
__ pop(receiver);
|
||||
|
||||
__ bind(&slow);
|
||||
// Slow case: jump to runtime.
|
||||
// edx: receiver
|
||||
// ecx: key
|
||||
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow);
|
||||
GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
|
||||
|
||||
GenerateKeyedLoadReceiverCheck(
|
||||
masm, edx, eax, Map::kHasNamedInterceptor, &slow);
|
||||
masm, receiver, eax, Map::kHasNamedInterceptor, &slow);
|
||||
|
||||
// If the receiver is a fast-case object, check the keyed lookup
|
||||
// cache. Otherwise probe the dictionary.
|
||||
__ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
|
||||
__ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset));
|
||||
__ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
|
||||
Immediate(isolate->factory()->hash_table_map()));
|
||||
__ j(equal, &probe_dictionary);
|
||||
@ -461,12 +456,12 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// The receiver's map is still in eax, compute the keyed lookup cache hash
|
||||
// based on 32 bits of the map pointer and the string hash.
|
||||
if (FLAG_debug_code) {
|
||||
__ cmp(eax, FieldOperand(edx, HeapObject::kMapOffset));
|
||||
__ cmp(eax, FieldOperand(receiver, HeapObject::kMapOffset));
|
||||
__ Check(equal, kMapIsNoLongerInEax);
|
||||
}
|
||||
__ mov(ebx, eax); // Keep the map around for later.
|
||||
__ shr(eax, KeyedLookupCache::kMapHashShift);
|
||||
__ mov(edi, FieldOperand(ecx, String::kHashFieldOffset));
|
||||
__ mov(edi, FieldOperand(key, String::kHashFieldOffset));
|
||||
__ shr(edi, String::kHashShift);
|
||||
__ xor_(eax, edi);
|
||||
__ and_(eax, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
|
||||
@ -489,7 +484,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
|
||||
__ j(not_equal, &try_next_entry);
|
||||
__ add(edi, Immediate(kPointerSize));
|
||||
__ cmp(ecx, Operand::StaticArray(edi, times_1, cache_keys));
|
||||
__ cmp(key, Operand::StaticArray(edi, times_1, cache_keys));
|
||||
__ j(equal, &hit_on_nth_entry[i]);
|
||||
__ bind(&try_next_entry);
|
||||
}
|
||||
@ -500,14 +495,12 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
|
||||
__ j(not_equal, &slow);
|
||||
__ add(edi, Immediate(kPointerSize));
|
||||
__ cmp(ecx, Operand::StaticArray(edi, times_1, cache_keys));
|
||||
__ cmp(key, Operand::StaticArray(edi, times_1, cache_keys));
|
||||
__ j(not_equal, &slow);
|
||||
|
||||
// Get field offset.
|
||||
// edx : receiver
|
||||
// ebx : receiver's map
|
||||
// ecx : key
|
||||
// eax : lookup cache index
|
||||
// ebx : receiver's map
|
||||
// eax : lookup cache index
|
||||
ExternalReference cache_field_offsets =
|
||||
ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
|
||||
|
||||
@ -531,13 +524,13 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ bind(&load_in_object_property);
|
||||
__ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset));
|
||||
__ add(eax, edi);
|
||||
__ mov(eax, FieldOperand(edx, eax, times_pointer_size, 0));
|
||||
__ mov(eax, FieldOperand(receiver, eax, times_pointer_size, 0));
|
||||
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
|
||||
__ ret(0);
|
||||
|
||||
// Load property array property.
|
||||
__ bind(&property_array_property);
|
||||
__ mov(eax, FieldOperand(edx, JSObject::kPropertiesOffset));
|
||||
__ mov(eax, FieldOperand(receiver, JSObject::kPropertiesOffset));
|
||||
__ mov(eax, FieldOperand(eax, edi, times_pointer_size,
|
||||
FixedArray::kHeaderSize));
|
||||
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
|
||||
@ -547,16 +540,16 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// exists.
|
||||
__ bind(&probe_dictionary);
|
||||
|
||||
__ mov(eax, FieldOperand(edx, JSObject::kMapOffset));
|
||||
__ mov(eax, FieldOperand(receiver, JSObject::kMapOffset));
|
||||
__ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
|
||||
GenerateGlobalInstanceTypeCheck(masm, eax, &slow);
|
||||
|
||||
GenerateDictionaryLoad(masm, &slow, ebx, ecx, eax, edi, eax);
|
||||
GenerateDictionaryLoad(masm, &slow, ebx, key, eax, edi, eax);
|
||||
__ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&index_name);
|
||||
__ IndexFromHash(ebx, ecx);
|
||||
__ IndexFromHash(ebx, key);
|
||||
// Now jump to the place where smi keys are handled.
|
||||
__ jmp(&index_smi);
|
||||
}
|
||||
@ -645,23 +638,23 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(edx.is(ReceiverRegister()));
|
||||
ASSERT(ecx.is(NameRegister()));
|
||||
// The return address is on the stack.
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
ASSERT(receiver.is(edx));
|
||||
ASSERT(key.is(ecx));
|
||||
|
||||
Label slow, notin;
|
||||
Factory* factory = masm->isolate()->factory();
|
||||
Operand mapped_location =
|
||||
GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, ¬in, &slow);
|
||||
GenerateMappedArgumentsLookup(
|
||||
masm, receiver, key, ebx, eax, ¬in, &slow);
|
||||
__ mov(eax, mapped_location);
|
||||
__ Ret();
|
||||
__ bind(¬in);
|
||||
// The unmapped lookup expects that the parameter map is in ebx.
|
||||
Operand unmapped_location =
|
||||
GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow);
|
||||
GenerateUnmappedArgumentsLookup(masm, key, ebx, eax, &slow);
|
||||
__ cmp(unmapped_location, factory->the_hole_value());
|
||||
__ j(equal, &slow);
|
||||
__ mov(eax, unmapped_location);
|
||||
@ -937,18 +930,16 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
||||
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(edx.is(ReceiverRegister()));
|
||||
ASSERT(ecx.is(NameRegister()));
|
||||
// The return address is on the stack.
|
||||
Register receiver = ReceiverRegister();
|
||||
Register name = NameRegister();
|
||||
ASSERT(receiver.is(edx));
|
||||
ASSERT(name.is(ecx));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
|
||||
masm->isolate()->stub_cache()->GenerateProbe(
|
||||
masm, flags, edx, ecx, ebx, eax);
|
||||
masm, flags, receiver, name, ebx, eax);
|
||||
|
||||
// Cache miss: Jump to runtime.
|
||||
GenerateMiss(masm);
|
||||
@ -1032,14 +1023,6 @@ const Register LoadIC::ReceiverRegister() { return edx; }
|
||||
const Register LoadIC::NameRegister() { return ecx; }
|
||||
|
||||
|
||||
const Register KeyedLoadIC::ReceiverRegister() {
|
||||
return LoadIC::ReceiverRegister();
|
||||
}
|
||||
|
||||
|
||||
const Register KeyedLoadIC::NameRegister() { return LoadIC::NameRegister(); }
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// Return address is on the stack.
|
||||
__ pop(KeyedLoadIC_TempRegister());
|
||||
|
@ -3207,8 +3207,8 @@ Operand LCodeGen::BuildFastArrayOperand(
|
||||
|
||||
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(esi));
|
||||
ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
|
||||
ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister()));
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
|
@ -2204,8 +2204,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), esi);
|
||||
LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
|
||||
LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
|
||||
LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
|
||||
LOperand* key = UseFixed(instr->key(), LoadIC::NameRegister());
|
||||
|
||||
LLoadKeyedGeneric* result =
|
||||
new(zone()) LLoadKeyedGeneric(context, object, key);
|
||||
|
@ -1292,8 +1292,8 @@ Register* LoadStubCompiler::registers() {
|
||||
|
||||
Register* KeyedLoadStubCompiler::registers() {
|
||||
// receiver, name, scratch1, scratch2, scratch3, scratch4.
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, ebx, eax, edi, no_reg };
|
||||
return registers;
|
||||
}
|
||||
@ -1454,8 +1454,8 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(edx.is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(ecx.is(KeyedLoadIC::NameRegister()));
|
||||
ASSERT(edx.is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ecx.is(LoadIC::NameRegister()));
|
||||
Label slow, miss;
|
||||
|
||||
// This stub is meant to be tail-jumped to, the receiver must already
|
||||
|
3
src/ic.h
3
src/ic.h
@ -506,9 +506,6 @@ class KeyedLoadIC: public LoadIC {
|
||||
ASSERT(target()->is_keyed_load_stub());
|
||||
}
|
||||
|
||||
static const Register ReceiverRegister();
|
||||
static const Register NameRegister();
|
||||
|
||||
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
|
||||
Handle<Object> key);
|
||||
|
||||
|
@ -1066,10 +1066,12 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
|
||||
// Copy all arguments from the array to the stack.
|
||||
Label entry, loop;
|
||||
__ movp(rax, Operand(rbp, kIndexOffset));
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register key = LoadIC::NameRegister();
|
||||
__ movp(key, Operand(rbp, kIndexOffset));
|
||||
__ jmp(&entry);
|
||||
__ bind(&loop);
|
||||
__ movp(rdx, Operand(rbp, kArgumentsOffset)); // load arguments
|
||||
__ movp(receiver, Operand(rbp, kArgumentsOffset)); // load arguments
|
||||
|
||||
// Use inline caching to speed up access to arguments.
|
||||
Handle<Code> ic =
|
||||
@ -1083,19 +1085,19 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
// Push the nth argument.
|
||||
__ Push(rax);
|
||||
|
||||
// Update the index on the stack and in register rax.
|
||||
__ movp(rax, Operand(rbp, kIndexOffset));
|
||||
__ SmiAddConstant(rax, rax, Smi::FromInt(1));
|
||||
__ movp(Operand(rbp, kIndexOffset), rax);
|
||||
// Update the index on the stack and in register key.
|
||||
__ movp(key, Operand(rbp, kIndexOffset));
|
||||
__ SmiAddConstant(key, key, Smi::FromInt(1));
|
||||
__ movp(Operand(rbp, kIndexOffset), key);
|
||||
|
||||
__ bind(&entry);
|
||||
__ cmpp(rax, Operand(rbp, kLimitOffset));
|
||||
__ cmpp(key, Operand(rbp, kLimitOffset));
|
||||
__ j(not_equal, &loop);
|
||||
|
||||
// Call the function.
|
||||
Label call_proxy;
|
||||
ParameterCount actual(rax);
|
||||
__ SmiToInteger32(rax, rax);
|
||||
__ SmiToInteger32(rax, key);
|
||||
__ movp(rdi, Operand(rbp, kFunctionOffset));
|
||||
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
|
||||
__ j(not_equal, &call_proxy);
|
||||
|
@ -780,24 +780,15 @@ void MathPowStub::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 -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
__ Cmp(rax, isolate()->factory()->prototype_string());
|
||||
__ Cmp(name, isolate()->factory()->prototype_string());
|
||||
__ j(not_equal, &miss);
|
||||
receiver = rdx;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
receiver = rax;
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss);
|
||||
|
@ -182,9 +182,7 @@ void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for keyed IC load call (from ic-x64.cc).
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
|
||||
GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1844,9 +1844,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());
|
||||
__ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
@ -1854,9 +1854,9 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
case KEYED_PROPERTY: {
|
||||
if (expr->is_compound()) {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ movp(rdx, Operand(rsp, 0));
|
||||
__ Push(rax);
|
||||
VisitForStackValue(property->key());
|
||||
__ movp(LoadIC::ReceiverRegister(), Operand(rsp, kPointerSize));
|
||||
__ movp(LoadIC::NameRegister(), Operand(rsp, 0));
|
||||
} else {
|
||||
VisitForStackValue(property->obj());
|
||||
VisitForStackValue(property->key());
|
||||
@ -1997,6 +1997,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
|
||||
Label l_next, l_call, l_loop;
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
|
||||
// Initial send value is undefined.
|
||||
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
|
||||
__ jmp(&l_next);
|
||||
@ -2004,10 +2007,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
|
||||
__ bind(&l_catch);
|
||||
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
|
||||
__ LoadRoot(rcx, Heap::kthrow_stringRootIndex); // "throw"
|
||||
__ Push(rcx);
|
||||
__ Push(Operand(rsp, 2 * kPointerSize)); // iter
|
||||
__ Push(rax); // exception
|
||||
__ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw"
|
||||
__ Push(load_name);
|
||||
__ Push(Operand(rsp, 2 * kPointerSize)); // iter
|
||||
__ Push(rax); // exception
|
||||
__ jmp(&l_call);
|
||||
|
||||
// try { received = %yield result }
|
||||
@ -2042,20 +2045,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(rdx));
|
||||
ASSERT(keyedload_name.is(rax));
|
||||
|
||||
__ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next"
|
||||
__ Push(rcx);
|
||||
__ Push(Operand(rsp, 2 * kPointerSize)); // iter
|
||||
__ Push(rax); // received
|
||||
__ LoadRoot(load_name, Heap::knext_stringRootIndex);
|
||||
__ Push(load_name); // "next"
|
||||
__ Push(Operand(rsp, 2 * kPointerSize)); // iter
|
||||
__ Push(rax); // received
|
||||
|
||||
// result = receiver[f](arg);
|
||||
__ bind(&l_call);
|
||||
__ movp(keyedload_receiver, Operand(rsp, kPointerSize));
|
||||
__ movp(keyedload_name, Operand(rsp, 2 * kPointerSize));
|
||||
__ movp(load_receiver, Operand(rsp, kPointerSize));
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ movp(rdi, rax);
|
||||
@ -2068,11 +2066,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// if (!result.done) goto l_try;
|
||||
__ bind(&l_loop);
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
ASSERT(load_receiver.is(rax));
|
||||
ASSERT(load_name.is(rcx));
|
||||
|
||||
__ Move(load_receiver, rax);
|
||||
__ Push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // rax=result.done
|
||||
@ -2503,15 +2497,16 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForAccumulatorValue(expr->obj());
|
||||
ASSERT(rax.is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(!rax.is(LoadIC::ReceiverRegister()));
|
||||
__ movp(LoadIC::ReceiverRegister(), rax);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
|
||||
context()->Plug(rax);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj());
|
||||
VisitForAccumulatorValue(expr->key());
|
||||
ASSERT(rax.is(KeyedLoadIC::NameRegister()));
|
||||
__ Pop(KeyedLoadIC::ReceiverRegister());
|
||||
__ Move(LoadIC::NameRegister(), rax);
|
||||
__ Pop(LoadIC::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
context()->Plug(rax);
|
||||
}
|
||||
@ -2561,13 +2556,13 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
|
||||
Expression* key) {
|
||||
// Load the key.
|
||||
VisitForAccumulatorValue(key);
|
||||
ASSERT(rax.is(KeyedLoadIC::NameRegister()));
|
||||
|
||||
Expression* callee = expr->expression();
|
||||
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0));
|
||||
__ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
|
||||
__ Move(LoadIC::NameRegister(), rax);
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
|
||||
@ -4224,18 +4219,16 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ Push(Smi::FromInt(0));
|
||||
}
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
VisitForAccumulatorValue(prop->obj());
|
||||
ASSERT(rax.is(LoadIC::ReceiverRegister()));
|
||||
__ Push(rax); // Copy of receiver, needed for later store.
|
||||
VisitForStackValue(prop->obj());
|
||||
__ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
ASSERT(rax.is(KeyedLoadIC::NameRegister()));
|
||||
VisitForStackValue(prop->key());
|
||||
// Leave receiver on stack
|
||||
__ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0));
|
||||
__ movp(LoadIC::ReceiverRegister(), Operand(rsp, kPointerSize));
|
||||
// Copy of key, needed for later store.
|
||||
__ Push(KeyedLoadIC::NameRegister());
|
||||
__ movp(LoadIC::NameRegister(), Operand(rsp, 0));
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
}
|
||||
|
@ -327,32 +327,31 @@ static void GenerateKeyNameCheck(MacroAssembler* masm,
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rdx.is(ReceiverRegister()));
|
||||
ASSERT(rax.is(NameRegister()));
|
||||
// The return address is on the stack.
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
ASSERT(receiver.is(rdx));
|
||||
ASSERT(key.is(rcx));
|
||||
|
||||
// Check that the key is a smi.
|
||||
__ JumpIfNotSmi(rax, &check_name);
|
||||
__ JumpIfNotSmi(key, &check_name);
|
||||
__ bind(&index_smi);
|
||||
// Now the key is known to be a smi. This place is also jumped to from below
|
||||
// where a numeric string is converted to a smi.
|
||||
|
||||
GenerateKeyedLoadReceiverCheck(
|
||||
masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow);
|
||||
masm, receiver, rax, Map::kHasIndexedInterceptor, &slow);
|
||||
|
||||
// Check the receiver's map to see if it has fast elements.
|
||||
__ CheckFastElements(rcx, &check_number_dictionary);
|
||||
__ CheckFastElements(rax, &check_number_dictionary);
|
||||
|
||||
GenerateFastArrayLoad(masm,
|
||||
rdx,
|
||||
receiver,
|
||||
key,
|
||||
rax,
|
||||
rcx,
|
||||
rbx,
|
||||
rax,
|
||||
NULL,
|
||||
@ -362,50 +361,46 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&check_number_dictionary);
|
||||
__ SmiToInteger32(rbx, rax);
|
||||
__ movp(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
|
||||
__ SmiToInteger32(rbx, key);
|
||||
__ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset));
|
||||
|
||||
// Check whether the elements is a number dictionary.
|
||||
// rdx: receiver
|
||||
// rax: key
|
||||
// rbx: key as untagged int32
|
||||
// rcx: elements
|
||||
__ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
|
||||
// rax: elements
|
||||
__ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
||||
Heap::kHashTableMapRootIndex);
|
||||
__ j(not_equal, &slow);
|
||||
__ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
|
||||
__ LoadFromNumberDictionary(&slow, rax, key, rbx, r9, rdi, rax);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&slow);
|
||||
// Slow case: Jump to runtime.
|
||||
// rdx: receiver
|
||||
// rax: key
|
||||
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
|
||||
GenerateRuntimeGetProperty(masm);
|
||||
|
||||
__ bind(&check_name);
|
||||
GenerateKeyNameCheck(masm, rax, rcx, rbx, &index_name, &slow);
|
||||
GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow);
|
||||
|
||||
GenerateKeyedLoadReceiverCheck(
|
||||
masm, rdx, rcx, Map::kHasNamedInterceptor, &slow);
|
||||
masm, receiver, rax, Map::kHasNamedInterceptor, &slow);
|
||||
|
||||
// If the receiver is a fast-case object, check the keyed lookup
|
||||
// cache. Otherwise probe the dictionary leaving result in rcx.
|
||||
__ movp(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
|
||||
// cache. Otherwise probe the dictionary leaving result in key.
|
||||
__ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset));
|
||||
__ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
|
||||
Heap::kHashTableMapRootIndex);
|
||||
__ j(equal, &probe_dictionary);
|
||||
|
||||
// Load the map of the receiver, compute the keyed lookup cache hash
|
||||
// based on 32 bits of the map pointer and the string hash.
|
||||
__ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
|
||||
__ movl(rcx, rbx);
|
||||
__ shrl(rcx, Immediate(KeyedLookupCache::kMapHashShift));
|
||||
__ movl(rdi, FieldOperand(rax, String::kHashFieldOffset));
|
||||
__ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
|
||||
__ movl(rax, rbx);
|
||||
__ shrl(rax, Immediate(KeyedLookupCache::kMapHashShift));
|
||||
__ movl(rdi, FieldOperand(key, String::kHashFieldOffset));
|
||||
__ shrl(rdi, Immediate(String::kHashShift));
|
||||
__ xorp(rcx, rdi);
|
||||
__ xorp(rax, rdi);
|
||||
int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
|
||||
__ andp(rcx, Immediate(mask));
|
||||
__ andp(rax, Immediate(mask));
|
||||
|
||||
// Load the key (consisting of map and internalized string) from the cache and
|
||||
// check for match.
|
||||
@ -417,13 +412,13 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
for (int i = 0; i < kEntriesPerBucket - 1; i++) {
|
||||
Label try_next_entry;
|
||||
__ movp(rdi, rcx);
|
||||
__ movp(rdi, rax);
|
||||
__ shlp(rdi, Immediate(kPointerSizeLog2 + 1));
|
||||
__ LoadAddress(kScratchRegister, cache_keys);
|
||||
int off = kPointerSize * i * 2;
|
||||
__ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off));
|
||||
__ j(not_equal, &try_next_entry);
|
||||
__ cmpp(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
|
||||
__ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
|
||||
__ j(equal, &hit_on_nth_entry[i]);
|
||||
__ bind(&try_next_entry);
|
||||
}
|
||||
@ -431,7 +426,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
int off = kPointerSize * (kEntriesPerBucket - 1) * 2;
|
||||
__ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off));
|
||||
__ j(not_equal, &slow);
|
||||
__ cmpp(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
|
||||
__ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
|
||||
__ j(not_equal, &slow);
|
||||
|
||||
// Get field offset, which is a 32-bit integer.
|
||||
@ -442,12 +437,12 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
|
||||
__ bind(&hit_on_nth_entry[i]);
|
||||
if (i != 0) {
|
||||
__ addl(rcx, Immediate(i));
|
||||
__ addl(rax, Immediate(i));
|
||||
}
|
||||
__ LoadAddress(kScratchRegister, cache_field_offsets);
|
||||
__ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
|
||||
__ movzxbp(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
|
||||
__ subp(rdi, rcx);
|
||||
__ movl(rdi, Operand(kScratchRegister, rax, times_4, 0));
|
||||
__ movzxbp(rax, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
|
||||
__ subp(rdi, rax);
|
||||
__ j(above_equal, &property_array_property);
|
||||
if (i != 0) {
|
||||
__ jmp(&load_in_object_property);
|
||||
@ -456,15 +451,15 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
// Load in-object property.
|
||||
__ bind(&load_in_object_property);
|
||||
__ movzxbp(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
|
||||
__ addp(rcx, rdi);
|
||||
__ movp(rax, FieldOperand(rdx, rcx, times_pointer_size, 0));
|
||||
__ movzxbp(rax, FieldOperand(rbx, Map::kInstanceSizeOffset));
|
||||
__ addp(rax, rdi);
|
||||
__ movp(rax, FieldOperand(receiver, rax, times_pointer_size, 0));
|
||||
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
|
||||
__ ret(0);
|
||||
|
||||
// Load property array property.
|
||||
__ bind(&property_array_property);
|
||||
__ movp(rax, FieldOperand(rdx, JSObject::kPropertiesOffset));
|
||||
__ movp(rax, FieldOperand(receiver, JSObject::kPropertiesOffset));
|
||||
__ movp(rax, FieldOperand(rax, rdi, times_pointer_size,
|
||||
FixedArray::kHeaderSize));
|
||||
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
|
||||
@ -473,20 +468,18 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// Do a quick inline probe of the receiver's dictionary, if it
|
||||
// exists.
|
||||
__ bind(&probe_dictionary);
|
||||
// rdx: receiver
|
||||
// rax: key
|
||||
// rbx: elements
|
||||
|
||||
__ movp(rcx, FieldOperand(rdx, JSObject::kMapOffset));
|
||||
__ movb(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset));
|
||||
GenerateGlobalInstanceTypeCheck(masm, rcx, &slow);
|
||||
__ movp(rax, FieldOperand(receiver, JSObject::kMapOffset));
|
||||
__ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset));
|
||||
GenerateGlobalInstanceTypeCheck(masm, rax, &slow);
|
||||
|
||||
GenerateDictionaryLoad(masm, &slow, rbx, rax, rcx, rdi, rax);
|
||||
GenerateDictionaryLoad(masm, &slow, rbx, key, rax, rdi, rax);
|
||||
__ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&index_name);
|
||||
__ IndexFromHash(rbx, rax);
|
||||
__ IndexFromHash(rbx, key);
|
||||
__ jmp(&index_smi);
|
||||
}
|
||||
|
||||
@ -497,7 +490,7 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register index = NameRegister();
|
||||
Register scratch = rcx;
|
||||
Register scratch = rbx;
|
||||
Register result = rax;
|
||||
ASSERT(!scratch.is(receiver) && !scratch.is(index));
|
||||
|
||||
@ -526,7 +519,7 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
Register scratch = rcx;
|
||||
Register scratch = rax;
|
||||
ASSERT(!scratch.is(receiver) && !scratch.is(key));
|
||||
|
||||
// Check that the receiver isn't a smi.
|
||||
@ -887,23 +880,22 @@ static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rdx.is(ReceiverRegister()));
|
||||
ASSERT(rax.is(NameRegister()));
|
||||
// The return address is on the stack.
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
ASSERT(receiver.is(rdx));
|
||||
ASSERT(key.is(rcx));
|
||||
|
||||
Label slow, notin;
|
||||
Operand mapped_location =
|
||||
GenerateMappedArgumentsLookup(
|
||||
masm, rdx, rax, rbx, rcx, rdi, ¬in, &slow);
|
||||
masm, receiver, key, rbx, rax, rdi, ¬in, &slow);
|
||||
__ movp(rax, mapped_location);
|
||||
__ Ret();
|
||||
__ bind(¬in);
|
||||
// The unmapped lookup expects that the parameter map is in rbx.
|
||||
Operand unmapped_location =
|
||||
GenerateUnmappedArgumentsLookup(masm, rax, rbx, rcx, &slow);
|
||||
GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow);
|
||||
__ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex);
|
||||
__ j(equal, &slow);
|
||||
__ movp(rax, unmapped_location);
|
||||
@ -953,18 +945,16 @@ void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rax.is(ReceiverRegister()));
|
||||
ASSERT(rcx.is(NameRegister()));
|
||||
// The return address is on the stack.
|
||||
Register receiver = ReceiverRegister();
|
||||
Register name = NameRegister();
|
||||
ASSERT(receiver.is(rdx));
|
||||
ASSERT(name.is(rcx));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
|
||||
masm->isolate()->stub_cache()->GenerateProbe(
|
||||
masm, flags, rax, rcx, rbx, rdx);
|
||||
masm, flags, receiver, name, rbx, rax);
|
||||
|
||||
GenerateMiss(masm);
|
||||
}
|
||||
@ -972,19 +962,19 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
|
||||
void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rdx : receiver
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rax.is(ReceiverRegister()));
|
||||
ASSERT(rdx.is(ReceiverRegister()));
|
||||
ASSERT(rcx.is(NameRegister()));
|
||||
Label miss, slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
|
||||
GenerateNameDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss);
|
||||
|
||||
// rdx: elements
|
||||
// rax: elements
|
||||
// Search the dictionary placing the result in rax.
|
||||
GenerateDictionaryLoad(masm, &slow, rdx, rcx, rbx, rdi, rax);
|
||||
GenerateDictionaryLoad(masm, &slow, rax, rcx, rbx, rdi, rax);
|
||||
__ ret(0);
|
||||
|
||||
// Dictionary load failed, go slow (but don't miss).
|
||||
@ -1055,10 +1045,8 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
// IC register specifications
|
||||
const Register LoadIC::ReceiverRegister() { return rax; }
|
||||
const Register LoadIC::ReceiverRegister() { return rdx; }
|
||||
const Register LoadIC::NameRegister() { return rcx; }
|
||||
const Register KeyedLoadIC::ReceiverRegister() { return rdx; }
|
||||
const Register KeyedLoadIC::NameRegister() { return rax; }
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
|
@ -3286,8 +3286,8 @@ Operand LCodeGen::BuildFastArrayOperand(
|
||||
|
||||
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(rsi));
|
||||
ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
|
||||
ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister()));
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
|
@ -2194,8 +2194,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), rsi);
|
||||
LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
|
||||
LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
|
||||
LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
|
||||
LOperand* key = UseFixed(instr->key(), LoadIC::NameRegister());
|
||||
|
||||
LLoadKeyedGeneric* result =
|
||||
new(zone()) LLoadKeyedGeneric(context, object, key);
|
||||
|
@ -1224,16 +1224,16 @@ Register* LoadStubCompiler::registers() {
|
||||
// receiver, name, scratch1, scratch2, scratch3, scratch4.
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, rdx, rbx, rdi, r8 };
|
||||
static Register registers[] = { receiver, name, rax, rbx, rdi, r8 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
|
||||
Register* KeyedLoadStubCompiler::registers() {
|
||||
// receiver, name, scratch1, scratch2, scratch3, scratch4.
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, rbx, rcx, rdi, r8 };
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
static Register registers[] = { receiver, name, rax, rbx, rdi, r8 };
|
||||
return registers;
|
||||
}
|
||||
|
||||
@ -1394,32 +1394,32 @@ Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
|
||||
void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rcx : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rdx.is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(rax.is(KeyedLoadIC::NameRegister()));
|
||||
ASSERT(rdx.is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(rcx.is(LoadIC::NameRegister()));
|
||||
Label slow, miss;
|
||||
|
||||
// This stub is meant to be tail-jumped to, the receiver must already
|
||||
// have been verified by the caller to not be a smi.
|
||||
|
||||
__ JumpIfNotSmi(rax, &miss);
|
||||
__ SmiToInteger32(rbx, rax);
|
||||
__ movp(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
|
||||
__ JumpIfNotSmi(rcx, &miss);
|
||||
__ SmiToInteger32(rbx, rcx);
|
||||
__ movp(rax, FieldOperand(rdx, JSObject::kElementsOffset));
|
||||
|
||||
// Check whether the elements is a number dictionary.
|
||||
// rdx: receiver
|
||||
// rax: key
|
||||
// rcx: key
|
||||
// rbx: key as untagged int32
|
||||
// rcx: elements
|
||||
__ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
|
||||
// rax: elements
|
||||
__ LoadFromNumberDictionary(&slow, rax, rcx, rbx, r9, rdi, rax);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&slow);
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rcx : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
@ -1427,7 +1427,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
|
||||
__ bind(&miss);
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rcx : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user