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