Use IC register definitions in platform files.
R=jkummerow@chromium.org Review URL: https://codereview.chromium.org/356713003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22035 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e26102ac24
commit
4273c7c070
@ -87,34 +87,6 @@ void RegExpConstructResultStub::InitializeInterfaceDescriptor(
|
||||
}
|
||||
|
||||
|
||||
void LoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { r0 };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { r1 };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { r0, r2 };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { r1, r0 };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { r2, r1, r0 };
|
||||
|
@ -176,15 +176,9 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC load (from ic-arm.cc).
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -- [sp] : receiver
|
||||
// -----------------------------------
|
||||
// Registers r0 and r2 contain objects that need to be pushed on the
|
||||
// expression stack of the fake JS frame.
|
||||
Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit(), 0);
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0);
|
||||
}
|
||||
|
||||
|
||||
@ -203,11 +197,10 @@ void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit(), 0);
|
||||
// Calling convention for keyed IC load (from ic-arm.cc).
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1389,8 +1389,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
|
||||
__ bind(&fast);
|
||||
}
|
||||
|
||||
__ ldr(r0, GlobalObjectOperand());
|
||||
__ mov(r2, Operand(var->name()));
|
||||
__ ldr(LoadIC::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadIC::NameRegister(), Operand(var->name()));
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
: CONTEXTUAL;
|
||||
@ -1472,10 +1472,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
switch (var->location()) {
|
||||
case Variable::UNALLOCATED: {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
// Use inline caching. Variable name is passed in r2 and the global
|
||||
// object (receiver) in r0.
|
||||
__ ldr(r0, GlobalObjectOperand());
|
||||
__ mov(r2, Operand(var->name()));
|
||||
__ ldr(LoadIC::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadIC::NameRegister(), Operand(var->name()));
|
||||
CallLoadIC(CONTEXTUAL);
|
||||
context()->Plug(r0);
|
||||
break;
|
||||
@ -2053,14 +2051,19 @@ 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
|
||||
|
||||
// result = receiver[f](arg);
|
||||
__ bind(&l_call);
|
||||
__ ldr(r1, MemOperand(sp, kPointerSize));
|
||||
__ ldr(r0, MemOperand(sp, 2 * kPointerSize));
|
||||
__ ldr(keyedload_receiver, MemOperand(sp, kPointerSize));
|
||||
__ ldr(keyedload_name, MemOperand(sp, 2 * kPointerSize));
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ mov(r1, r0);
|
||||
@ -2073,18 +2076,23 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// if (!result.done) goto l_try;
|
||||
__ bind(&l_loop);
|
||||
__ push(r0); // save result
|
||||
__ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in r0
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
ASSERT(load_receiver.is(r0));
|
||||
ASSERT(load_name.is(r2));
|
||||
|
||||
__ push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // r0=result.done
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
__ cmp(r0, Operand(0));
|
||||
__ b(eq, &l_try);
|
||||
|
||||
// result.value
|
||||
__ pop(r0); // result
|
||||
__ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in r0
|
||||
__ pop(load_receiver); // result
|
||||
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // r0=result.value
|
||||
context()->DropAndPlug(2, r0); // drop iter and g
|
||||
break;
|
||||
}
|
||||
@ -2258,15 +2266,15 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
__ mov(r2, Operand(key->value()));
|
||||
// Call load IC. It has arguments receiver and property name r0 and r2.
|
||||
__ mov(LoadIC::NameRegister(), Operand(key->value()));
|
||||
// Call load IC. It has register arguments receiver and property.
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
// Call keyed load IC. It has arguments key and receiver in r0 and r1.
|
||||
// Call keyed load IC. It has register arguments receiver and key.
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, prop->PropertyFeedbackId());
|
||||
}
|
||||
@ -2555,13 +2563,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForAccumulatorValue(expr->obj());
|
||||
ASSERT(r0.is(LoadIC::ReceiverRegister()));
|
||||
EmitNamedPropertyLoad(expr);
|
||||
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
|
||||
context()->Plug(r0);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj());
|
||||
VisitForAccumulatorValue(expr->key());
|
||||
__ pop(r1);
|
||||
ASSERT(r0.is(KeyedLoadIC::NameRegister()));
|
||||
__ pop(KeyedLoadIC::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
context()->Plug(r0);
|
||||
}
|
||||
@ -2598,7 +2608,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
} else {
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ ldr(r0, MemOperand(sp, 0));
|
||||
__ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
EmitNamedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
// Push the target function under the receiver.
|
||||
@ -2616,12 +2626,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(r1, MemOperand(sp, 0));
|
||||
__ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
|
||||
@ -4039,7 +4050,8 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
__ push(r0);
|
||||
|
||||
// Load the function from the receiver.
|
||||
__ mov(r2, Operand(expr->name()));
|
||||
ASSERT(r0.is(LoadIC::ReceiverRegister()));
|
||||
__ mov(LoadIC::NameRegister(), Operand(expr->name()));
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
|
||||
// Push the target function under the receiver.
|
||||
@ -4218,13 +4230,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
// Put the object both on the stack and in the accumulator.
|
||||
VisitForAccumulatorValue(prop->obj());
|
||||
__ push(r0);
|
||||
ASSERT(r0.is(LoadIC::ReceiverRegister()));
|
||||
__ push(LoadIC::ReceiverRegister());
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
__ ldr(r1, MemOperand(sp, 0));
|
||||
__ push(r0);
|
||||
ASSERT(r0.is(KeyedLoadIC::NameRegister()));
|
||||
__ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
|
||||
__ push(KeyedLoadIC::NameRegister());
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
}
|
||||
@ -4371,8 +4385,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
VariableProxy* proxy = expr->AsVariableProxy();
|
||||
if (proxy != NULL && proxy->var()->IsUnallocated()) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ ldr(r0, GlobalObjectOperand());
|
||||
__ mov(r2, Operand(proxy->name()));
|
||||
__ ldr(LoadIC::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadIC::NameRegister(), Operand(proxy->name()));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
@ -316,6 +316,8 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(r0.is(ReceiverRegister()));
|
||||
ASSERT(r2.is(NameRegister()));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
|
||||
@ -333,6 +335,9 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(r0.is(ReceiverRegister()));
|
||||
ASSERT(r2.is(NameRegister()));
|
||||
|
||||
Label miss, slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
|
||||
@ -351,18 +356,18 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
// A register that isn't one of the parameters to the load ic.
|
||||
static const Register LoadIC_TempRegister() { return r3; }
|
||||
|
||||
|
||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is on the stack.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
__ IncrementCounter(isolate->counters()->load_miss(), 1, r3, r4);
|
||||
|
||||
__ mov(r3, r0);
|
||||
__ Push(r3, r2);
|
||||
__ mov(LoadIC_TempRegister(), ReceiverRegister());
|
||||
__ Push(LoadIC_TempRegister(), NameRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
@ -372,14 +377,10 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is on the stack.
|
||||
|
||||
__ mov(r3, r0);
|
||||
__ Push(r3, r2);
|
||||
__ mov(LoadIC_TempRegister(), ReceiverRegister());
|
||||
__ Push(LoadIC_TempRegister(), NameRegister());
|
||||
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
@ -476,6 +477,8 @@ void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(r1.is(ReceiverRegister()));
|
||||
ASSERT(r0.is(NameRegister()));
|
||||
Label slow, notin;
|
||||
MemOperand mapped_location =
|
||||
GenerateMappedArgumentsLookup(masm, r1, r0, r2, r3, r4, ¬in, &slow);
|
||||
@ -526,16 +529,12 @@ void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is on the stack.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4);
|
||||
|
||||
__ Push(r1, r0);
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
@ -553,13 +552,9 @@ const Register KeyedLoadIC::NameRegister() { return r0; }
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is on the stack.
|
||||
|
||||
__ Push(r1, r0);
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
@ -574,8 +569,10 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
|
||||
Register key = r0;
|
||||
Register receiver = r1;
|
||||
Register key = NameRegister();
|
||||
Register receiver = ReceiverRegister();
|
||||
ASSERT(key.is(r0));
|
||||
ASSERT(receiver.is(r1));
|
||||
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
@ -737,17 +734,14 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key (index)
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
// Return address is on the stack.
|
||||
Label miss;
|
||||
|
||||
Register receiver = r1;
|
||||
Register index = r0;
|
||||
Register receiver = ReceiverRegister();
|
||||
Register index = NameRegister();
|
||||
Register scratch = r3;
|
||||
Register result = r0;
|
||||
ASSERT(!scratch.is(receiver) && !scratch.is(index));
|
||||
|
||||
StringCharAtGenerator char_at_generator(receiver,
|
||||
index,
|
||||
@ -769,32 +763,35 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
// Return address is on the stack.
|
||||
Label slow;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
Register scratch1 = r2;
|
||||
Register scratch2 = r3;
|
||||
ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
|
||||
ASSERT(!scratch2.is(receiver) && !scratch2.is(key));
|
||||
|
||||
// Check that the receiver isn't a smi.
|
||||
__ JumpIfSmi(r1, &slow);
|
||||
__ JumpIfSmi(receiver, &slow);
|
||||
|
||||
// Check that the key is an array index, that is Uint32.
|
||||
__ NonNegativeSmiTst(r0);
|
||||
__ NonNegativeSmiTst(key);
|
||||
__ b(ne, &slow);
|
||||
|
||||
// Get the map of the receiver.
|
||||
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
||||
__ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
|
||||
// Check that it has indexed interceptor and access checks
|
||||
// are not enabled for this object.
|
||||
__ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
|
||||
__ and_(r3, r3, Operand(kSlowCaseBitFieldMask));
|
||||
__ cmp(r3, Operand(1 << Map::kHasIndexedInterceptor));
|
||||
__ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
|
||||
__ and_(scratch2, scratch2, Operand(kSlowCaseBitFieldMask));
|
||||
__ cmp(scratch2, Operand(1 << Map::kHasIndexedInterceptor));
|
||||
__ b(ne, &slow);
|
||||
|
||||
// Everything is fine, call runtime.
|
||||
__ Push(r1, r0); // Receiver, key.
|
||||
__ Push(receiver, key); // Receiver, key.
|
||||
|
||||
// Perform tail call to the entry.
|
||||
__ TailCallExternalReference(
|
||||
|
@ -2216,7 +2216,8 @@ LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), cp);
|
||||
LOperand* global_object = UseFixed(instr->global_object(), r0);
|
||||
LOperand* global_object = UseFixed(instr->global_object(),
|
||||
LoadIC::ReceiverRegister());
|
||||
LLoadGlobalGeneric* result =
|
||||
new(zone()) LLoadGlobalGeneric(context, global_object);
|
||||
return MarkAsCall(DefineFixed(result, r0), instr);
|
||||
@ -2270,7 +2271,7 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), cp);
|
||||
LOperand* object = UseFixed(instr->object(), r0);
|
||||
LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
|
||||
LInstruction* result =
|
||||
DefineFixed(new(zone()) LLoadNamedGeneric(context, object), r0);
|
||||
return MarkAsCall(result, instr);
|
||||
@ -2330,8 +2331,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), cp);
|
||||
LOperand* object = UseFixed(instr->object(), r1);
|
||||
LOperand* key = UseFixed(instr->key(), r0);
|
||||
LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
|
||||
LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
|
||||
|
||||
LInstruction* result =
|
||||
DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), r0);
|
||||
|
@ -2969,10 +2969,10 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
|
||||
|
||||
void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(cp));
|
||||
ASSERT(ToRegister(instr->global_object()).is(r0));
|
||||
ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->result()).is(r0));
|
||||
|
||||
__ mov(r2, Operand(instr->name()));
|
||||
__ mov(LoadIC::NameRegister(), Operand(instr->name()));
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
@ -3088,11 +3088,11 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
|
||||
|
||||
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(cp));
|
||||
ASSERT(ToRegister(instr->object()).is(r0));
|
||||
ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->result()).is(r0));
|
||||
|
||||
// Name is always in r2.
|
||||
__ mov(r2, Operand(instr->name()));
|
||||
__ mov(LoadIC::NameRegister(), Operand(instr->name()));
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
}
|
||||
@ -3394,8 +3394,8 @@ MemOperand LCodeGen::PrepareKeyedOperand(Register key,
|
||||
|
||||
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(cp));
|
||||
ASSERT(ToRegister(instr->object()).is(r1));
|
||||
ASSERT(ToRegister(instr->key()).is(r0));
|
||||
ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
|
||||
|
@ -1479,6 +1479,8 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(r1.is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(r0.is(KeyedLoadIC::NameRegister()));
|
||||
Label slow, miss;
|
||||
|
||||
Register key = r0;
|
||||
|
@ -102,36 +102,6 @@ void RegExpConstructResultStub::InitializeInterfaceDescriptor(
|
||||
}
|
||||
|
||||
|
||||
void LoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
// x0: receiver
|
||||
Register registers[] = { x0 };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
// x1: receiver
|
||||
Register registers[] = { x1 };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { x0, x2 };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { x1, x0 };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
// x2: receiver
|
||||
|
@ -235,15 +235,9 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC load (from ic-arm.cc).
|
||||
// ----------- S t a t e -------------
|
||||
// -- x2 : name
|
||||
// -- lr : return address
|
||||
// -- x0 : receiver
|
||||
// -- [sp] : receiver
|
||||
// -----------------------------------
|
||||
// Registers x0 and x2 contain objects that need to be pushed on the
|
||||
// expression stack of the fake JS frame.
|
||||
Generate_DebugBreakCallHelper(masm, x0.Bit() | x2.Bit(), 0, x10);
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.Bit() | name.Bit(), 0, x10);
|
||||
}
|
||||
|
||||
|
||||
@ -262,11 +256,10 @@ void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- x0 : key
|
||||
// -- x1 : receiver
|
||||
Generate_DebugBreakCallHelper(masm, x0.Bit() | x1.Bit(), 0, x10);
|
||||
// Calling convention for keyed IC load (from ic-arm.cc).
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.Bit() | name.Bit(), 0, x10);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1393,8 +1393,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
|
||||
__ Bind(&fast);
|
||||
}
|
||||
|
||||
__ Ldr(x0, GlobalObjectMemOperand());
|
||||
__ Mov(x2, Operand(var->name()));
|
||||
__ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand());
|
||||
__ Mov(LoadIC::NameRegister(), Operand(var->name()));
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL
|
||||
: CONTEXTUAL;
|
||||
CallLoadIC(mode);
|
||||
@ -1472,10 +1472,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
switch (var->location()) {
|
||||
case Variable::UNALLOCATED: {
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
// Use inline caching. Variable name is passed in x2 and the global
|
||||
// object (receiver) in x0.
|
||||
__ Ldr(x0, GlobalObjectMemOperand());
|
||||
__ Mov(x2, Operand(var->name()));
|
||||
__ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand());
|
||||
__ Mov(LoadIC::NameRegister(), Operand(var->name()));
|
||||
CallLoadIC(CONTEXTUAL);
|
||||
context()->Plug(x0);
|
||||
break;
|
||||
@ -1949,7 +1947,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
__ Mov(x2, Operand(key->value()));
|
||||
__ Mov(LoadIC::NameRegister(), Operand(key->value()));
|
||||
// Call load IC. It has arguments receiver and property name x0 and x2.
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
@ -2262,13 +2260,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForAccumulatorValue(expr->obj());
|
||||
ASSERT(x0.is(LoadIC::ReceiverRegister()));
|
||||
EmitNamedPropertyLoad(expr);
|
||||
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
|
||||
context()->Plug(x0);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj());
|
||||
VisitForAccumulatorValue(expr->key());
|
||||
__ Pop(x1);
|
||||
ASSERT(x0.is(KeyedLoadIC::NameRegister()));
|
||||
__ Pop(KeyedLoadIC::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
context()->Plug(x0);
|
||||
}
|
||||
@ -2304,7 +2304,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
} else {
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ Peek(x0, 0);
|
||||
__ Peek(LoadIC::ReceiverRegister(), 0);
|
||||
EmitNamedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
// Push the target function under the receiver.
|
||||
@ -2321,12 +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(x1, 0);
|
||||
__ Peek(KeyedLoadIC::ReceiverRegister(), 0);
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
|
||||
@ -3746,12 +3747,13 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
if (expr->is_jsruntime()) {
|
||||
// Push the builtins object as the receiver.
|
||||
__ Ldr(x10, GlobalObjectMemOperand());
|
||||
__ Ldr(x0, FieldMemOperand(x10, GlobalObject::kBuiltinsOffset));
|
||||
__ Push(x0);
|
||||
__ Ldr(LoadIC::ReceiverRegister(),
|
||||
FieldMemOperand(x10, GlobalObject::kBuiltinsOffset));
|
||||
__ Push(LoadIC::ReceiverRegister());
|
||||
|
||||
// Load the function from the receiver.
|
||||
Handle<String> name = expr->name();
|
||||
__ Mov(x2, Operand(name));
|
||||
__ Mov(LoadIC::NameRegister(), Operand(name));
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
|
||||
// Push the target function under the receiver.
|
||||
@ -3927,14 +3929,16 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
// Put the object both on the stack and in the accumulator.
|
||||
VisitForAccumulatorValue(prop->obj());
|
||||
__ Push(x0);
|
||||
ASSERT(x0.is(LoadIC::ReceiverRegister()));
|
||||
__ Push(LoadIC::ReceiverRegister());
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
// KEYED_PROPERTY
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
__ Peek(x1, 0);
|
||||
__ Push(x0);
|
||||
ASSERT(x0.is(KeyedLoadIC::NameRegister()));
|
||||
__ Peek(KeyedLoadIC::ReceiverRegister(), 0);
|
||||
__ Push(KeyedLoadIC::NameRegister());
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
}
|
||||
@ -4084,8 +4088,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
VariableProxy* proxy = expr->AsVariableProxy();
|
||||
if (proxy != NULL && proxy->var()->IsUnallocated()) {
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
__ Ldr(x0, GlobalObjectMemOperand());
|
||||
__ Mov(x2, Operand(proxy->name()));
|
||||
__ Ldr(LoadIC::ReceiverRegister(), GlobalObjectMemOperand());
|
||||
__ Mov(LoadIC::NameRegister(), Operand(proxy->name()));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
@ -4433,14 +4437,19 @@ 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
|
||||
|
||||
// result = receiver[f](arg);
|
||||
__ Bind(&l_call);
|
||||
__ Peek(x1, 1 * kPointerSize);
|
||||
__ Peek(x0, 2 * kPointerSize);
|
||||
__ Peek(keyedload_receiver, 1 * kPointerSize);
|
||||
__ Peek(keyedload_name, 2 * kPointerSize);
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ Mov(x1, x0);
|
||||
@ -4453,18 +4462,22 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// if (!result.done) goto l_try;
|
||||
__ Bind(&l_loop);
|
||||
__ Push(x0); // save result
|
||||
__ LoadRoot(x2, Heap::kdone_stringRootIndex); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in x0
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
ASSERT(load_receiver.is(x0));
|
||||
ASSERT(load_name.is(x2));
|
||||
__ Push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // x0=result.done
|
||||
// The ToBooleanStub argument (result.done) is in x0.
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
__ Cbz(x0, &l_try);
|
||||
|
||||
// result.value
|
||||
__ Pop(x0); // result
|
||||
__ LoadRoot(x2, Heap::kvalue_stringRootIndex); // "value"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in x0
|
||||
__ Pop(load_receiver); // result
|
||||
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // x0=result.value
|
||||
context()->DropAndPlug(2, x0); // drop iter and g
|
||||
break;
|
||||
}
|
||||
|
@ -412,6 +412,8 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// -- lr : return address
|
||||
// -- x0 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(x0.is(ReceiverRegister()));
|
||||
ASSERT(x2.is(NameRegister()));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
|
||||
@ -429,6 +431,8 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
// -- lr : return address
|
||||
// -- x0 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(x0.is(ReceiverRegister()));
|
||||
ASSERT(x2.is(NameRegister()));
|
||||
Label miss, slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, x0, x1, x3, x4, &miss);
|
||||
@ -448,18 +452,14 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- x2 : name
|
||||
// -- lr : return address
|
||||
// -- x0 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is on the stack.
|
||||
Isolate* isolate = masm->isolate();
|
||||
ASM_LOCATION("LoadIC::GenerateMiss");
|
||||
|
||||
__ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4);
|
||||
|
||||
// Perform tail call to the entry.
|
||||
__ Push(x0, x2);
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
|
||||
__ TailCallExternalReference(ref, 2, 1);
|
||||
@ -467,13 +467,8 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- x2 : name
|
||||
// -- lr : return address
|
||||
// -- x0 : receiver
|
||||
// -----------------------------------
|
||||
|
||||
__ Push(x0, x2);
|
||||
// The return address is on the stack.
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
@ -485,8 +480,11 @@ void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
Register result = x0;
|
||||
Register key = x0;
|
||||
Register receiver = x1;
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
ASSERT(receiver.is(x1));
|
||||
ASSERT(key.is(x0));
|
||||
|
||||
Label miss, unmapped;
|
||||
|
||||
Register map_scratch = x2;
|
||||
@ -518,7 +516,6 @@ void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// -- x1 : key
|
||||
// -- x2 : receiver
|
||||
// -----------------------------------
|
||||
|
||||
Label slow, notin;
|
||||
|
||||
Register value = x0;
|
||||
@ -563,16 +560,12 @@ void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- x0 : key
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
// The return address is on the stack.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11);
|
||||
|
||||
__ Push(x1, x0);
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
@ -590,15 +583,8 @@ const Register KeyedLoadIC::NameRegister() { return x0; }
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- x0 : key
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
Register key = x0;
|
||||
Register receiver = x1;
|
||||
|
||||
__ Push(receiver, key);
|
||||
// The return address is on the stack.
|
||||
__ Push(ReceiverRegister(), NameRegister());
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
}
|
||||
|
||||
@ -774,8 +760,10 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// -----------------------------------
|
||||
Label slow, check_name, index_smi, index_name;
|
||||
|
||||
Register key = x0;
|
||||
Register receiver = x1;
|
||||
Register key = NameRegister();
|
||||
Register receiver = ReceiverRegister();
|
||||
ASSERT(key.is(x0));
|
||||
ASSERT(receiver.is(x1));
|
||||
|
||||
__ JumpIfNotSmi(key, &check_name);
|
||||
__ Bind(&index_smi);
|
||||
@ -802,17 +790,14 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- x0 : key (index)
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
// Return address is on the stack.
|
||||
Label miss;
|
||||
|
||||
Register index = x0;
|
||||
Register receiver = x1;
|
||||
Register receiver = ReceiverRegister();
|
||||
Register index = NameRegister();
|
||||
Register result = x0;
|
||||
Register scratch = x3;
|
||||
ASSERT(!scratch.is(receiver) && !scratch.is(index));
|
||||
|
||||
StringCharAtGenerator char_at_generator(receiver,
|
||||
index,
|
||||
@ -834,14 +819,15 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
// ---------- S t a t e --------------
|
||||
// -- lr : return address
|
||||
// -- x0 : key
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
// Return address is on the stack.
|
||||
Label slow;
|
||||
Register key = x0;
|
||||
Register receiver = x1;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
Register scratch1 = x2;
|
||||
Register scratch2 = x3;
|
||||
ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
|
||||
ASSERT(!scratch2.is(receiver) && !scratch2.is(key));
|
||||
|
||||
// Check that the receiver isn't a smi.
|
||||
__ JumpIfSmi(receiver, &slow);
|
||||
@ -850,16 +836,16 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
__ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow);
|
||||
|
||||
// Get the map of the receiver.
|
||||
Register map = x2;
|
||||
Register map = scratch1;
|
||||
__ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
|
||||
// Check that it has indexed interceptor and access checks
|
||||
// are not enabled for this object.
|
||||
__ Ldrb(x3, FieldMemOperand(map, Map::kBitFieldOffset));
|
||||
__ Ldrb(scratch2, FieldMemOperand(map, Map::kBitFieldOffset));
|
||||
ASSERT(kSlowCaseBitFieldMask ==
|
||||
((1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor)));
|
||||
__ Tbnz(x3, Map::kIsAccessCheckNeeded, &slow);
|
||||
__ Tbz(x3, Map::kHasIndexedInterceptor, &slow);
|
||||
__ Tbnz(scratch2, Map::kIsAccessCheckNeeded, &slow);
|
||||
__ Tbz(scratch2, Map::kHasIndexedInterceptor, &slow);
|
||||
|
||||
// Everything is fine, call runtime.
|
||||
__ Push(receiver, key);
|
||||
|
@ -1658,7 +1658,8 @@ LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), cp);
|
||||
LOperand* global_object = UseFixed(instr->global_object(), x0);
|
||||
LOperand* global_object = UseFixed(instr->global_object(),
|
||||
LoadIC::ReceiverRegister());
|
||||
LLoadGlobalGeneric* result =
|
||||
new(zone()) LLoadGlobalGeneric(context, global_object);
|
||||
return MarkAsCall(DefineFixed(result, x0), instr);
|
||||
@ -1714,8 +1715,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), cp);
|
||||
LOperand* object = UseFixed(instr->object(), x1);
|
||||
LOperand* key = UseFixed(instr->key(), x0);
|
||||
LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
|
||||
LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
|
||||
|
||||
LInstruction* result =
|
||||
DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), x0);
|
||||
@ -1731,7 +1732,7 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), cp);
|
||||
LOperand* object = UseFixed(instr->object(), x0);
|
||||
LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
|
||||
LInstruction* result =
|
||||
DefineFixed(new(zone()) LLoadNamedGeneric(context, object), x0);
|
||||
return MarkAsCall(result, instr);
|
||||
|
@ -3399,9 +3399,9 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
|
||||
|
||||
void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(cp));
|
||||
ASSERT(ToRegister(instr->global_object()).Is(x0));
|
||||
ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->result()).Is(x0));
|
||||
__ Mov(x2, Operand(instr->name()));
|
||||
__ Mov(LoadIC::NameRegister(), Operand(instr->name()));
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
@ -3653,8 +3653,8 @@ void LCodeGen::DoLoadKeyedFixed(LLoadKeyedFixed* instr) {
|
||||
|
||||
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(cp));
|
||||
ASSERT(ToRegister(instr->object()).Is(x1));
|
||||
ASSERT(ToRegister(instr->key()).Is(x0));
|
||||
ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
@ -3704,9 +3704,10 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
|
||||
|
||||
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(cp));
|
||||
// LoadIC expects x2 to hold the name, and x0 to hold the receiver.
|
||||
// LoadIC expects name and receiver in registers.
|
||||
ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->object()).is(x0));
|
||||
__ Mov(x2, Operand(instr->name()));
|
||||
__ Mov(LoadIC::NameRegister(), Operand(instr->name()));
|
||||
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
|
@ -1454,6 +1454,8 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- x0 : key
|
||||
// -- x1 : receiver
|
||||
// -----------------------------------
|
||||
ASSERT(x1.is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(x0.is(KeyedLoadIC::NameRegister()));
|
||||
Label slow, miss;
|
||||
|
||||
Register result = x0;
|
||||
|
@ -614,6 +614,36 @@ void KeyedLoadGenericElementStub::InitializeInterfaceDescriptor(
|
||||
}
|
||||
|
||||
|
||||
void LoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { LoadIC::ReceiverRegister() };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { KeyedLoadIC::ReceiverRegister() };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { LoadIC::ReceiverRegister(),
|
||||
LoadIC::NameRegister() };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { KeyedLoadIC::ReceiverRegister(),
|
||||
KeyedLoadIC::NameRegister() };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadDictionaryElementPlatformStub::Generate(
|
||||
MacroAssembler* masm) {
|
||||
KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
|
||||
|
@ -93,34 +93,6 @@ void RegExpConstructResultStub::InitializeInterfaceDescriptor(
|
||||
}
|
||||
|
||||
|
||||
void LoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { edx };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { edx };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { edx, ecx };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { edx, ecx };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { edx, ecx, eax };
|
||||
|
@ -180,11 +180,9 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for IC load call (from ic-ia32.cc).
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, ecx.bit() | edx.bit(), 0, false);
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
|
||||
}
|
||||
|
||||
|
||||
@ -202,11 +200,9 @@ void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for keyed IC load call (from ic-ia32.cc).
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, ecx.bit() | edx.bit(), 0, false);
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1337,8 +1337,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
|
||||
|
||||
// All extension objects were empty and it is safe to use a global
|
||||
// load IC call.
|
||||
__ mov(edx, GlobalObjectOperand());
|
||||
__ mov(ecx, var->name());
|
||||
__ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadIC::NameRegister(), var->name());
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
: CONTEXTUAL;
|
||||
@ -1418,10 +1418,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
switch (var->location()) {
|
||||
case Variable::UNALLOCATED: {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
// Use inline caching. Variable name is passed in ecx and the global
|
||||
// object in eax.
|
||||
__ mov(edx, GlobalObjectOperand());
|
||||
__ mov(ecx, var->name());
|
||||
__ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadIC::NameRegister(), var->name());
|
||||
CallLoadIC(CONTEXTUAL);
|
||||
context()->Plug(eax);
|
||||
break;
|
||||
@ -2011,14 +2009,20 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// receiver = iter; f = iter.next; arg = received;
|
||||
__ bind(&l_next);
|
||||
__ mov(ecx, isolate()->factory()->next_string()); // "next"
|
||||
__ push(ecx);
|
||||
Register keyedload_receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register keyedload_name = KeyedLoadIC::NameRegister();
|
||||
ASSERT(keyedload_receiver.is(edx));
|
||||
ASSERT(keyedload_name.is(ecx));
|
||||
|
||||
__ mov(keyedload_name,
|
||||
isolate()->factory()->next_string()); // "next"
|
||||
__ push(keyedload_name);
|
||||
__ push(Operand(esp, 2 * kPointerSize)); // iter
|
||||
__ push(eax); // received
|
||||
|
||||
// result = receiver[f](arg);
|
||||
__ bind(&l_call);
|
||||
__ mov(edx, Operand(esp, kPointerSize));
|
||||
__ mov(keyedload_receiver, Operand(esp, kPointerSize));
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ mov(edi, eax);
|
||||
@ -2032,8 +2036,13 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// if (!result.done) goto l_try;
|
||||
__ bind(&l_loop);
|
||||
__ push(eax); // save result
|
||||
__ mov(edx, eax); // result
|
||||
__ mov(ecx, isolate()->factory()->done_string()); // "done"
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
ASSERT(load_receiver.is(edx));
|
||||
ASSERT(load_name.is(ecx));
|
||||
__ mov(load_receiver, eax); // result
|
||||
__ mov(load_name,
|
||||
isolate()->factory()->done_string()); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
@ -2041,8 +2050,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ j(zero, &l_try);
|
||||
|
||||
// result.value
|
||||
__ pop(edx); // result
|
||||
__ mov(ecx, isolate()->factory()->value_string()); // "value"
|
||||
__ pop(load_receiver); // result
|
||||
__ mov(load_name,
|
||||
isolate()->factory()->value_string()); // "value"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in eax
|
||||
context()->DropAndPlug(2, eax); // drop iter and g
|
||||
break;
|
||||
@ -2202,7 +2212,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
ASSERT(!key->value()->IsSmi());
|
||||
__ mov(ecx, Immediate(key->value()));
|
||||
__ mov(LoadIC::NameRegister(), Immediate(key->value()));
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
@ -2500,15 +2510,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForAccumulatorValue(expr->obj());
|
||||
__ mov(edx, result_register());
|
||||
__ mov(LoadIC::ReceiverRegister(), result_register());
|
||||
EmitNamedPropertyLoad(expr);
|
||||
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
|
||||
context()->Plug(eax);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj());
|
||||
VisitForAccumulatorValue(expr->key());
|
||||
__ pop(edx); // Object.
|
||||
__ mov(ecx, result_register()); // Key.
|
||||
__ pop(KeyedLoadIC::ReceiverRegister()); // Object.
|
||||
__ mov(KeyedLoadIC::NameRegister(), result_register()); // Key.
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
context()->Plug(eax);
|
||||
}
|
||||
@ -2541,7 +2551,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
} else {
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ mov(edx, Operand(esp, 0));
|
||||
__ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
|
||||
EmitNamedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
// Push the target function under the receiver.
|
||||
@ -2563,9 +2573,9 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
|
||||
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ mov(edx, Operand(esp, 0));
|
||||
__ mov(KeyedLoadIC::ReceiverRegister(), Operand(esp, 0));
|
||||
// Move the key into the right register for the keyed load IC.
|
||||
__ mov(ecx, eax);
|
||||
__ mov(KeyedLoadIC::NameRegister(), eax);
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
|
||||
@ -4023,8 +4033,8 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
__ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
|
||||
|
||||
// Load the function from the receiver.
|
||||
__ mov(edx, Operand(esp, 0));
|
||||
__ mov(ecx, Immediate(expr->name()));
|
||||
__ mov(LoadIC::ReceiverRegister(), Operand(esp, 0));
|
||||
__ mov(LoadIC::NameRegister(), Immediate(expr->name()));
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
|
||||
// Push the target function under the receiver.
|
||||
@ -4207,14 +4217,16 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
// Put the object both on the stack and in edx.
|
||||
VisitForAccumulatorValue(prop->obj());
|
||||
ASSERT(!eax.is(LoadIC::ReceiverRegister()));
|
||||
__ push(eax);
|
||||
__ mov(edx, eax);
|
||||
__ mov(LoadIC::ReceiverRegister(), eax);
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForStackValue(prop->key());
|
||||
__ mov(edx, Operand(esp, kPointerSize)); // Object.
|
||||
__ mov(ecx, Operand(esp, 0)); // Key.
|
||||
__ mov(KeyedLoadIC::ReceiverRegister(),
|
||||
Operand(esp, kPointerSize)); // Object.
|
||||
__ mov(KeyedLoadIC::NameRegister(), Operand(esp, 0)); // Key.
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
}
|
||||
@ -4371,8 +4383,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
|
||||
if (proxy != NULL && proxy->var()->IsUnallocated()) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ mov(edx, GlobalObjectOperand());
|
||||
__ mov(ecx, Immediate(proxy->name()));
|
||||
__ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadIC::NameRegister(), Immediate(proxy->name()));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
@ -388,6 +388,8 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(edx.is(ReceiverRegister()));
|
||||
ASSERT(ecx.is(NameRegister()));
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
|
||||
@ -560,18 +562,25 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
// A register that isn't one of the parameters to the load ic.
|
||||
static const Register LoadIC_TempRegister() { return ebx; }
|
||||
|
||||
|
||||
// A register that isn't one of the parameters to the load ic.
|
||||
static const Register KeyedLoadIC_TempRegister() {
|
||||
return LoadIC_TempRegister();
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key (index)
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
// Return address is on the stack.
|
||||
Label miss;
|
||||
|
||||
Register receiver = edx;
|
||||
Register index = ecx;
|
||||
Register scratch = ebx;
|
||||
Register receiver = ReceiverRegister();
|
||||
Register index = NameRegister();
|
||||
Register scratch = KeyedLoadIC_TempRegister();
|
||||
Register result = eax;
|
||||
ASSERT(!result.is(scratch));
|
||||
|
||||
StringCharAtGenerator char_at_generator(receiver,
|
||||
index,
|
||||
@ -593,35 +602,36 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
// Return address is on the stack.
|
||||
Label slow;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
Register scratch = eax;
|
||||
ASSERT(!scratch.is(receiver) && !scratch.is(key));
|
||||
|
||||
// Check that the receiver isn't a smi.
|
||||
__ JumpIfSmi(edx, &slow);
|
||||
__ JumpIfSmi(receiver, &slow);
|
||||
|
||||
// Check that the key is an array index, that is Uint32.
|
||||
__ test(ecx, Immediate(kSmiTagMask | kSmiSignMask));
|
||||
__ test(key, Immediate(kSmiTagMask | kSmiSignMask));
|
||||
__ j(not_zero, &slow);
|
||||
|
||||
// Get the map of the receiver.
|
||||
__ mov(eax, FieldOperand(edx, HeapObject::kMapOffset));
|
||||
__ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
|
||||
|
||||
// Check that it has indexed interceptor and access checks
|
||||
// are not enabled for this object.
|
||||
__ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset));
|
||||
__ and_(eax, Immediate(kSlowCaseBitFieldMask));
|
||||
__ cmp(eax, Immediate(1 << Map::kHasIndexedInterceptor));
|
||||
__ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
|
||||
__ and_(scratch, Immediate(kSlowCaseBitFieldMask));
|
||||
__ cmp(scratch, Immediate(1 << Map::kHasIndexedInterceptor));
|
||||
__ j(not_zero, &slow);
|
||||
|
||||
// Everything is fine, call runtime.
|
||||
__ pop(eax);
|
||||
__ push(edx); // receiver
|
||||
__ push(ecx); // key
|
||||
__ push(eax); // return address
|
||||
__ pop(scratch);
|
||||
__ push(receiver); // receiver
|
||||
__ push(key); // key
|
||||
__ push(scratch); // return address
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
@ -640,6 +650,8 @@ void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(edx.is(ReceiverRegister()));
|
||||
ASSERT(ecx.is(NameRegister()));
|
||||
Label slow, notin;
|
||||
Factory* factory = masm->isolate()->factory();
|
||||
Operand mapped_location =
|
||||
@ -930,6 +942,8 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(edx.is(ReceiverRegister()));
|
||||
ASSERT(ecx.is(NameRegister()));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
|
||||
@ -947,6 +961,9 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(edx.is(ReceiverRegister()));
|
||||
ASSERT(ecx.is(NameRegister()));
|
||||
|
||||
Label miss, slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
|
||||
@ -967,18 +984,13 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
// Return address is on the stack.
|
||||
__ IncrementCounter(masm->isolate()->counters()->load_miss(), 1);
|
||||
|
||||
__ pop(ebx);
|
||||
__ push(edx); // receiver
|
||||
__ push(ecx); // name
|
||||
__ push(ebx); // return address
|
||||
__ pop(LoadIC_TempRegister());
|
||||
__ push(ReceiverRegister()); // receiver
|
||||
__ push(NameRegister()); // name
|
||||
__ push(LoadIC_TempRegister()); // return address
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
@ -988,16 +1000,11 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
__ pop(ebx);
|
||||
__ push(edx); // receiver
|
||||
__ push(ecx); // name
|
||||
__ push(ebx); // return address
|
||||
// Return address is on the stack.
|
||||
__ pop(LoadIC_TempRegister());
|
||||
__ push(ReceiverRegister()); // receiver
|
||||
__ push(NameRegister()); // name
|
||||
__ push(LoadIC_TempRegister()); // return address
|
||||
|
||||
// Perform tail call to the entry.
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
@ -1005,18 +1012,13 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
// Return address is on the stack.
|
||||
__ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1);
|
||||
|
||||
__ pop(ebx);
|
||||
__ push(edx); // receiver
|
||||
__ push(ecx); // name
|
||||
__ push(ebx); // return address
|
||||
__ pop(KeyedLoadIC_TempRegister());
|
||||
__ push(ReceiverRegister()); // receiver
|
||||
__ push(NameRegister()); // name
|
||||
__ push(KeyedLoadIC_TempRegister()); // return address
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
@ -1039,16 +1041,11 @@ const Register KeyedLoadIC::NameRegister() { return LoadIC::NameRegister(); }
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
__ pop(ebx);
|
||||
__ push(edx); // receiver
|
||||
__ push(ecx); // name
|
||||
__ push(ebx); // return address
|
||||
// Return address is on the stack.
|
||||
__ pop(KeyedLoadIC_TempRegister());
|
||||
__ push(ReceiverRegister()); // receiver
|
||||
__ push(NameRegister()); // name
|
||||
__ push(KeyedLoadIC_TempRegister()); // return address
|
||||
|
||||
// Perform tail call to the entry.
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
|
@ -2832,10 +2832,10 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
|
||||
|
||||
void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(esi));
|
||||
ASSERT(ToRegister(instr->global_object()).is(edx));
|
||||
ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->result()).is(eax));
|
||||
|
||||
__ mov(ecx, instr->name());
|
||||
__ mov(LoadIC::NameRegister(), instr->name());
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
@ -2966,10 +2966,10 @@ void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
|
||||
|
||||
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(esi));
|
||||
ASSERT(ToRegister(instr->object()).is(edx));
|
||||
ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->result()).is(eax));
|
||||
|
||||
__ mov(ecx, instr->name());
|
||||
__ mov(LoadIC::NameRegister(), instr->name());
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
@ -3207,8 +3207,8 @@ Operand LCodeGen::BuildFastArrayOperand(
|
||||
|
||||
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(esi));
|
||||
ASSERT(ToRegister(instr->object()).is(edx));
|
||||
ASSERT(ToRegister(instr->key()).is(ecx));
|
||||
ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
|
@ -2090,7 +2090,8 @@ LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), esi);
|
||||
LOperand* global_object = UseFixed(instr->global_object(), edx);
|
||||
LOperand* global_object = UseFixed(instr->global_object(),
|
||||
LoadIC::ReceiverRegister());
|
||||
LLoadGlobalGeneric* result =
|
||||
new(zone()) LLoadGlobalGeneric(context, global_object);
|
||||
return MarkAsCall(DefineFixed(result, eax), instr);
|
||||
@ -2145,7 +2146,7 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), esi);
|
||||
LOperand* object = UseFixed(instr->object(), edx);
|
||||
LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
|
||||
LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object);
|
||||
return MarkAsCall(DefineFixed(result, eax), instr);
|
||||
}
|
||||
@ -2203,8 +2204,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), esi);
|
||||
LOperand* object = UseFixed(instr->object(), edx);
|
||||
LOperand* key = UseFixed(instr->key(), ecx);
|
||||
LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
|
||||
LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
|
||||
|
||||
LLoadKeyedGeneric* result =
|
||||
new(zone()) LLoadKeyedGeneric(context, object, key);
|
||||
|
@ -1454,6 +1454,8 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(edx.is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(ecx.is(KeyedLoadIC::NameRegister()));
|
||||
Label slow, miss;
|
||||
|
||||
// This stub is meant to be tail-jumped to, the receiver must already
|
||||
|
@ -89,34 +89,6 @@ void RegExpConstructResultStub::InitializeInterfaceDescriptor(
|
||||
}
|
||||
|
||||
|
||||
void LoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { rax };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadFieldStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { rdx };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { rax, rcx };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStringLengthStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { rdx, rax };
|
||||
descriptor->Initialize(ARRAY_SIZE(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
|
||||
CodeStubInterfaceDescriptor* descriptor) {
|
||||
Register registers[] = { rdx, rcx, rax };
|
||||
|
@ -162,11 +162,9 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for IC load call (from ic-x64.cc).
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), 0, false);
|
||||
Register receiver = LoadIC::ReceiverRegister();
|
||||
Register name = LoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
|
||||
}
|
||||
|
||||
|
||||
@ -184,11 +182,9 @@ void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for keyed IC load call (from ic-x64.cc).
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, rax.bit() | rdx.bit(), 0, false);
|
||||
Register receiver = KeyedLoadIC::ReceiverRegister();
|
||||
Register name = KeyedLoadIC::NameRegister();
|
||||
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1372,8 +1372,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
|
||||
|
||||
// All extension objects were empty and it is safe to use a global
|
||||
// load IC call.
|
||||
__ movp(rax, GlobalObjectOperand());
|
||||
__ Move(rcx, var->name());
|
||||
__ movp(LoadIC::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ Move(LoadIC::NameRegister(), var->name());
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
: CONTEXTUAL;
|
||||
@ -1452,10 +1452,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
switch (var->location()) {
|
||||
case Variable::UNALLOCATED: {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
// Use inline caching. Variable name is passed in rcx and the global
|
||||
// object on the stack.
|
||||
__ Move(rcx, var->name());
|
||||
__ movp(rax, GlobalObjectOperand());
|
||||
__ Move(LoadIC::NameRegister(), var->name());
|
||||
__ movp(LoadIC::ReceiverRegister(), GlobalObjectOperand());
|
||||
CallLoadIC(CONTEXTUAL);
|
||||
context()->Plug(rax);
|
||||
break;
|
||||
@ -2044,6 +2042,11 @@ 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
|
||||
@ -2051,8 +2054,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// result = receiver[f](arg);
|
||||
__ bind(&l_call);
|
||||
__ movp(rdx, Operand(rsp, kPointerSize));
|
||||
__ movp(rax, Operand(rsp, 2 * kPointerSize));
|
||||
__ movp(keyedload_receiver, Operand(rsp, kPointerSize));
|
||||
__ movp(keyedload_name, Operand(rsp, 2 * kPointerSize));
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ movp(rdi, rax);
|
||||
@ -2065,17 +2068,22 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
// if (!result.done) goto l_try;
|
||||
__ bind(&l_loop);
|
||||
__ Push(rax); // save result
|
||||
__ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in rax
|
||||
Register load_receiver = LoadIC::ReceiverRegister();
|
||||
Register load_name = LoadIC::NameRegister();
|
||||
ASSERT(load_receiver.is(rax));
|
||||
ASSERT(load_name.is(rcx));
|
||||
|
||||
__ Push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // rax=result.done
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
__ testp(result_register(), result_register());
|
||||
__ j(zero, &l_try);
|
||||
|
||||
// result.value
|
||||
__ Pop(rax); // result
|
||||
__ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value"
|
||||
__ Pop(load_receiver); // result
|
||||
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in rax
|
||||
context()->DropAndPlug(2, rax); // drop iter and g
|
||||
break;
|
||||
@ -2236,7 +2244,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
__ Move(rcx, key->value());
|
||||
__ Move(LoadIC::NameRegister(), key->value());
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
|
||||
@ -2495,13 +2503,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForAccumulatorValue(expr->obj());
|
||||
ASSERT(rax.is(LoadIC::ReceiverRegister()));
|
||||
EmitNamedPropertyLoad(expr);
|
||||
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
|
||||
context()->Plug(rax);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj());
|
||||
VisitForAccumulatorValue(expr->key());
|
||||
__ Pop(rdx);
|
||||
ASSERT(rax.is(KeyedLoadIC::NameRegister()));
|
||||
__ Pop(KeyedLoadIC::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
context()->Plug(rax);
|
||||
}
|
||||
@ -2534,7 +2544,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
} else {
|
||||
// Load the function from the receiver.
|
||||
ASSERT(callee->IsProperty());
|
||||
__ movp(rax, Operand(rsp, 0));
|
||||
__ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
|
||||
EmitNamedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
// Push the target function under the receiver.
|
||||
@ -2551,12 +2561,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(rdx, Operand(rsp, 0));
|
||||
__ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0));
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
|
||||
@ -4034,8 +4045,8 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
__ Push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
|
||||
|
||||
// Load the function from the receiver.
|
||||
__ movp(rax, Operand(rsp, 0));
|
||||
__ Move(rcx, expr->name());
|
||||
__ movp(LoadIC::ReceiverRegister(), Operand(rsp, 0));
|
||||
__ Move(LoadIC::NameRegister(), expr->name());
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
|
||||
// Push the target function under the receiver.
|
||||
@ -4214,13 +4225,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
VisitForAccumulatorValue(prop->obj());
|
||||
ASSERT(rax.is(LoadIC::ReceiverRegister()));
|
||||
__ Push(rax); // Copy of receiver, needed for later store.
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
__ movp(rdx, Operand(rsp, 0)); // Leave receiver on stack
|
||||
__ Push(rax); // Copy of key, needed for later store.
|
||||
ASSERT(rax.is(KeyedLoadIC::NameRegister()));
|
||||
// Leave receiver on stack
|
||||
__ movp(KeyedLoadIC::ReceiverRegister(), Operand(rsp, 0));
|
||||
// Copy of key, needed for later store.
|
||||
__ Push(KeyedLoadIC::NameRegister());
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
}
|
||||
@ -4373,8 +4388,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
|
||||
if (proxy != NULL && proxy->var()->IsUnallocated()) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ Move(rcx, proxy->name());
|
||||
__ movp(rax, GlobalObjectOperand());
|
||||
__ Move(LoadIC::NameRegister(), proxy->name());
|
||||
__ movp(LoadIC::ReceiverRegister(), GlobalObjectOperand());
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
@ -332,6 +332,8 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rdx.is(ReceiverRegister()));
|
||||
ASSERT(rax.is(NameRegister()));
|
||||
Label slow, check_name, index_smi, index_name, property_array_property;
|
||||
Label probe_dictionary, check_number_dictionary;
|
||||
|
||||
@ -490,17 +492,14 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
// Return address is on the stack.
|
||||
Label miss;
|
||||
|
||||
Register receiver = rdx;
|
||||
Register index = rax;
|
||||
Register receiver = ReceiverRegister();
|
||||
Register index = NameRegister();
|
||||
Register scratch = rcx;
|
||||
Register result = rax;
|
||||
ASSERT(!scratch.is(receiver) && !scratch.is(index));
|
||||
|
||||
StringCharAtGenerator char_at_generator(receiver,
|
||||
index,
|
||||
@ -522,35 +521,36 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
// Return address is on the stack.
|
||||
Label slow;
|
||||
|
||||
Register receiver = ReceiverRegister();
|
||||
Register key = NameRegister();
|
||||
Register scratch = rcx;
|
||||
ASSERT(!scratch.is(receiver) && !scratch.is(key));
|
||||
|
||||
// Check that the receiver isn't a smi.
|
||||
__ JumpIfSmi(rdx, &slow);
|
||||
__ JumpIfSmi(receiver, &slow);
|
||||
|
||||
// Check that the key is an array index, that is Uint32.
|
||||
STATIC_ASSERT(kSmiValueSize <= 32);
|
||||
__ JumpUnlessNonNegativeSmi(rax, &slow);
|
||||
__ JumpUnlessNonNegativeSmi(key, &slow);
|
||||
|
||||
// Get the map of the receiver.
|
||||
__ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
|
||||
__ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
|
||||
|
||||
// Check that it has indexed interceptor and access checks
|
||||
// are not enabled for this object.
|
||||
__ movb(rcx, FieldOperand(rcx, Map::kBitFieldOffset));
|
||||
__ andb(rcx, Immediate(kSlowCaseBitFieldMask));
|
||||
__ cmpb(rcx, Immediate(1 << Map::kHasIndexedInterceptor));
|
||||
__ movb(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
|
||||
__ andb(scratch, Immediate(kSlowCaseBitFieldMask));
|
||||
__ cmpb(scratch, Immediate(1 << Map::kHasIndexedInterceptor));
|
||||
__ j(not_zero, &slow);
|
||||
|
||||
// Everything is fine, call runtime.
|
||||
__ PopReturnAddressTo(rcx);
|
||||
__ Push(rdx); // receiver
|
||||
__ Push(rax); // key
|
||||
__ PushReturnAddressFrom(rcx);
|
||||
__ PopReturnAddressTo(scratch);
|
||||
__ Push(receiver); // receiver
|
||||
__ Push(key); // key
|
||||
__ PushReturnAddressFrom(scratch);
|
||||
|
||||
// Perform tail call to the entry.
|
||||
__ TailCallExternalReference(
|
||||
@ -892,6 +892,8 @@ void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rdx.is(ReceiverRegister()));
|
||||
ASSERT(rax.is(NameRegister()));
|
||||
Label slow, notin;
|
||||
Operand mapped_location =
|
||||
GenerateMappedArgumentsLookup(
|
||||
@ -956,6 +958,8 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rax.is(ReceiverRegister()));
|
||||
ASSERT(rcx.is(NameRegister()));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
|
||||
@ -972,6 +976,8 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rax.is(ReceiverRegister()));
|
||||
ASSERT(rcx.is(NameRegister()));
|
||||
Label miss, slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
|
||||
@ -991,20 +997,25 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
// A register that isn't one of the parameters to the load ic.
|
||||
static const Register LoadIC_TempRegister() { return rbx; }
|
||||
|
||||
|
||||
static const Register KeyedLoadIC_TempRegister() {
|
||||
return rbx;
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
// The return address is on the stack.
|
||||
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->load_miss(), 1);
|
||||
|
||||
__ PopReturnAddressTo(rbx);
|
||||
__ Push(rax); // receiver
|
||||
__ Push(rcx); // name
|
||||
__ PushReturnAddressFrom(rbx);
|
||||
__ PopReturnAddressTo(LoadIC_TempRegister());
|
||||
__ Push(ReceiverRegister()); // receiver
|
||||
__ Push(NameRegister()); // name
|
||||
__ PushReturnAddressFrom(LoadIC_TempRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
@ -1014,16 +1025,12 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
// The return address is on the stack.
|
||||
|
||||
__ PopReturnAddressTo(rbx);
|
||||
__ Push(rax); // receiver
|
||||
__ Push(rcx); // name
|
||||
__ PushReturnAddressFrom(rbx);
|
||||
__ PopReturnAddressTo(LoadIC_TempRegister());
|
||||
__ Push(ReceiverRegister()); // receiver
|
||||
__ Push(NameRegister()); // name
|
||||
__ PushReturnAddressFrom(LoadIC_TempRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
|
||||
@ -1031,19 +1038,14 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
// The return address is on the stack.
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_load_miss(), 1);
|
||||
|
||||
__ PopReturnAddressTo(rbx);
|
||||
__ Push(rdx); // receiver
|
||||
__ Push(rax); // name
|
||||
__ PushReturnAddressFrom(rbx);
|
||||
__ PopReturnAddressTo(KeyedLoadIC_TempRegister());
|
||||
__ Push(ReceiverRegister()); // receiver
|
||||
__ Push(NameRegister()); // name
|
||||
__ PushReturnAddressFrom(KeyedLoadIC_TempRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
@ -1060,16 +1062,12 @@ const Register KeyedLoadIC::NameRegister() { return rax; }
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
// The return address is on the stack.
|
||||
|
||||
__ PopReturnAddressTo(rbx);
|
||||
__ Push(rdx); // receiver
|
||||
__ Push(rax); // name
|
||||
__ PushReturnAddressFrom(rbx);
|
||||
__ PopReturnAddressTo(KeyedLoadIC_TempRegister());
|
||||
__ Push(ReceiverRegister()); // receiver
|
||||
__ Push(NameRegister()); // name
|
||||
__ PushReturnAddressFrom(KeyedLoadIC_TempRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
||||
|
@ -2849,10 +2849,10 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
|
||||
|
||||
void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(rsi));
|
||||
ASSERT(ToRegister(instr->global_object()).is(rax));
|
||||
ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->result()).is(rax));
|
||||
|
||||
__ Move(rcx, instr->name());
|
||||
__ Move(LoadIC::NameRegister(), instr->name());
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
@ -2989,10 +2989,10 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
|
||||
|
||||
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(rsi));
|
||||
ASSERT(ToRegister(instr->object()).is(rax));
|
||||
ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->result()).is(rax));
|
||||
|
||||
__ Move(rcx, instr->name());
|
||||
__ Move(LoadIC::NameRegister(), instr->name());
|
||||
Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL);
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
@ -3286,8 +3286,8 @@ Operand LCodeGen::BuildFastArrayOperand(
|
||||
|
||||
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
|
||||
ASSERT(ToRegister(instr->context()).is(rsi));
|
||||
ASSERT(ToRegister(instr->object()).is(rdx));
|
||||
ASSERT(ToRegister(instr->key()).is(rax));
|
||||
ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
|
||||
|
||||
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
|
@ -2040,7 +2040,8 @@ LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), rsi);
|
||||
LOperand* global_object = UseFixed(instr->global_object(), rax);
|
||||
LOperand* global_object = UseFixed(instr->global_object(),
|
||||
LoadIC::ReceiverRegister());
|
||||
LLoadGlobalGeneric* result =
|
||||
new(zone()) LLoadGlobalGeneric(context, global_object);
|
||||
return MarkAsCall(DefineFixed(result, rax), instr);
|
||||
@ -2107,7 +2108,7 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), rsi);
|
||||
LOperand* object = UseFixed(instr->object(), rax);
|
||||
LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
|
||||
LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object);
|
||||
return MarkAsCall(DefineFixed(result, rax), instr);
|
||||
}
|
||||
@ -2193,8 +2194,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), rsi);
|
||||
LOperand* object = UseFixed(instr->object(), rdx);
|
||||
LOperand* key = UseFixed(instr->key(), rax);
|
||||
LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
|
||||
LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
|
||||
|
||||
LLoadKeyedGeneric* result =
|
||||
new(zone()) LLoadKeyedGeneric(context, object, key);
|
||||
|
@ -1398,6 +1398,8 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
ASSERT(rdx.is(KeyedLoadIC::ReceiverRegister()));
|
||||
ASSERT(rax.is(KeyedLoadIC::NameRegister()));
|
||||
Label slow, miss;
|
||||
|
||||
// This stub is meant to be tail-jumped to, the receiver must already
|
||||
|
Loading…
Reference in New Issue
Block a user