Change LoadIC interface on ia32 to take arguments in registers.

Review URL: http://codereview.chromium.org/573009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3841 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2010-02-12 10:32:24 +00:00
parent 85c24cee57
commit c7fe99d3ff
8 changed files with 99 additions and 76 deletions

View File

@ -1050,7 +1050,13 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
// Nothing to do here. // Nothing to do here.
break; break;
case NAMED_PROPERTY: case NAMED_PROPERTY:
VisitForValue(prop->obj(), kStack); if (expr->is_compound()) {
// We need the receiver both on the stack and in the accumulator.
VisitForValue(prop->obj(), kAccumulator);
__ push(result_register());
} else {
VisitForValue(prop->obj(), kStack);
}
break; break;
case KEYED_PROPERTY: case KEYED_PROPERTY:
VisitForValue(prop->obj(), kStack); VisitForValue(prop->obj(), kStack);

View File

@ -2327,6 +2327,7 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
// Load applicand.apply onto the stack. This will usually // Load applicand.apply onto the stack. This will usually
// give us a megamorphic load site. Not super, but it works. // give us a megamorphic load site. Not super, but it works.
Load(applicand); Load(applicand);
frame()->Dup();
Handle<String> name = Factory::LookupAsciiSymbol("apply"); Handle<String> name = Factory::LookupAsciiSymbol("apply");
frame()->Push(name); frame()->Push(name);
Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET);
@ -4197,8 +4198,6 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
// property case was inlined. Ensure that there is not a test eax // property case was inlined. Ensure that there is not a test eax
// instruction here. // instruction here.
__ nop(); __ nop();
// Discard the global object. The result is in answer.
frame_->Drop();
return answer; return answer;
} }
@ -6276,7 +6275,7 @@ bool CodeGenerator::HasValidEntryRegisters() {
// Emit a LoadIC call to get the value from receiver and leave it in // Emit a LoadIC call to get the value from receiver and leave it in
// dst. The receiver register is restored after the call. // dst.
class DeferredReferenceGetNamedValue: public DeferredCode { class DeferredReferenceGetNamedValue: public DeferredCode {
public: public:
DeferredReferenceGetNamedValue(Register dst, DeferredReferenceGetNamedValue(Register dst,
@ -6299,7 +6298,9 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
void DeferredReferenceGetNamedValue::Generate() { void DeferredReferenceGetNamedValue::Generate() {
__ push(receiver_); if (!receiver_.is(eax)) {
__ mov(eax, receiver_);
}
__ Set(ecx, Immediate(name_)); __ Set(ecx, Immediate(name_));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET); __ call(ic, RelocInfo::CODE_TARGET);
@ -6316,7 +6317,6 @@ void DeferredReferenceGetNamedValue::Generate() {
__ IncrementCounter(&Counters::named_load_inline_miss, 1); __ IncrementCounter(&Counters::named_load_inline_miss, 1);
if (!dst_.is(eax)) __ mov(dst_, eax); if (!dst_.is(eax)) __ mov(dst_, eax);
__ pop(receiver_);
} }
@ -6570,6 +6570,9 @@ void Reference::GetValue() {
Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
ASSERT(slot != NULL); ASSERT(slot != NULL);
cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
if (!persist_after_get_) {
cgen_->UnloadReference(this);
}
break; break;
} }
@ -6578,6 +6581,9 @@ void Reference::GetValue() {
bool is_global = var != NULL; bool is_global = var != NULL;
ASSERT(!is_global || var->is_global()); ASSERT(!is_global || var->is_global());
if (persist_after_get_) {
cgen_->frame()->Dup();
}
// Do not inline the inobject property case for loads from the global // Do not inline the inobject property case for loads from the global
// object. Also do not inline for unoptimized code. This saves time // object. Also do not inline for unoptimized code. This saves time
// in the code generator. Unoptimized code is toplevel code or code // in the code generator. Unoptimized code is toplevel code or code
@ -6636,9 +6642,11 @@ void Reference::GetValue() {
__ IncrementCounter(&Counters::named_load_inline, 1); __ IncrementCounter(&Counters::named_load_inline, 1);
deferred->BindExit(); deferred->BindExit();
cgen_->frame()->Push(&receiver);
cgen_->frame()->Push(&value); cgen_->frame()->Push(&value);
} }
if (!persist_after_get_) {
set_unloaded();
}
break; break;
} }
@ -6648,16 +6656,15 @@ void Reference::GetValue() {
ASSERT(!is_global || var->is_global()); ASSERT(!is_global || var->is_global());
Result value = cgen_->EmitKeyedLoad(is_global); Result value = cgen_->EmitKeyedLoad(is_global);
cgen_->frame()->Push(&value); cgen_->frame()->Push(&value);
if (!persist_after_get_) {
cgen_->UnloadReference(this);
}
break; break;
} }
default: default:
UNREACHABLE(); UNREACHABLE();
} }
if (!persist_after_get_) {
cgen_->UnloadReference(this);
}
} }

View File

@ -125,9 +125,10 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { void Debug::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 ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// ----------------------------------- // -----------------------------------
Generate_DebugBreakCallHelper(masm, ecx.bit(), false); Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false);
} }

View File

@ -808,7 +808,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
Comment cmnt(masm_, "Global variable"); Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in ecx and the global // Use inline caching. Variable name is passed in ecx and the global
// object on the stack. // object on the stack.
__ push(CodeGenerator::GlobalObject()); __ mov(eax, CodeGenerator::GlobalObject());
__ mov(ecx, var->name()); __ mov(ecx, var->name());
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET_CONTEXT); __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
@ -817,7 +817,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
// Remember that the assembler may choose to do peephole optimization // Remember that the assembler may choose to do peephole optimization
// (eg, push/pop elimination). // (eg, push/pop elimination).
__ nop(); __ nop();
DropAndApply(1, context, eax); Apply(context, eax);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) { } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
Comment cmnt(masm_, "Lookup slot"); Comment cmnt(masm_, "Lookup slot");
@ -1183,14 +1183,12 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property"); Comment cmnt(masm_, "[ Property");
Expression* key = expr->key(); Expression* key = expr->key();
// Evaluate the receiver.
VisitForValue(expr->obj(), kStack);
if (key->IsPropertyName()) { if (key->IsPropertyName()) {
VisitForValue(expr->obj(), kAccumulator);
EmitNamedPropertyLoad(expr); EmitNamedPropertyLoad(expr);
// Drop receiver left on the stack by IC. Apply(context_, eax);
DropAndApply(1, context_, eax);
} else { } else {
VisitForValue(expr->obj(), kStack);
VisitForValue(expr->key(), kStack); VisitForValue(expr->key(), kStack);
EmitKeyedPropertyLoad(expr); EmitKeyedPropertyLoad(expr);
// Drop key and receiver left on the stack by IC. // Drop key and receiver left on the stack by IC.
@ -1455,13 +1453,13 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
!proxy->var()->is_this() && !proxy->var()->is_this() &&
proxy->var()->is_global()) { proxy->var()->is_global()) {
Comment cmnt(masm_, "Global variable"); Comment cmnt(masm_, "Global variable");
__ push(CodeGenerator::GlobalObject()); __ mov(eax, CodeGenerator::GlobalObject());
__ mov(ecx, Immediate(proxy->name())); __ mov(ecx, Immediate(proxy->name()));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
// 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.
__ call(ic, RelocInfo::CODE_TARGET); __ call(ic, RelocInfo::CODE_TARGET);
__ mov(Operand(esp, 0), eax); __ push(eax);
} else if (proxy != NULL && } else if (proxy != NULL &&
proxy->var()->slot() != NULL && proxy->var()->slot() != NULL &&
proxy->var()->slot()->type() == Slot::LOOKUP) { proxy->var()->slot()->type() == Slot::LOOKUP) {
@ -1565,10 +1563,13 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix() && context_ != Expression::kEffect) { if (expr->is_postfix() && context_ != Expression::kEffect) {
__ push(Immediate(Smi::FromInt(0))); __ push(Immediate(Smi::FromInt(0)));
} }
VisitForValue(prop->obj(), kStack);
if (assign_type == NAMED_PROPERTY) { if (assign_type == NAMED_PROPERTY) {
// Put the object both on the stack and in the accumulator.
VisitForValue(prop->obj(), kAccumulator);
__ push(eax);
EmitNamedPropertyLoad(prop); EmitNamedPropertyLoad(prop);
} else { } else {
VisitForValue(prop->obj(), kStack);
VisitForValue(prop->key(), kStack); VisitForValue(prop->key(), kStack);
EmitKeyedPropertyLoad(prop); EmitKeyedPropertyLoad(prop);
} }

View File

@ -50,28 +50,29 @@ namespace internal {
// or if name is not a symbol, and will jump to the miss_label in that case. // or if name is not a symbol, and will jump to the miss_label in that case.
static void GenerateDictionaryLoad(MacroAssembler* masm, static void GenerateDictionaryLoad(MacroAssembler* masm,
Label* miss_label, Label* miss_label,
Register receiver,
Register name,
Register r0, Register r0,
Register r1, Register r1,
Register r2, Register r2,
Register name,
DictionaryCheck check_dictionary) { DictionaryCheck check_dictionary) {
// Register use: // Register use:
// //
// name - holds the name of the property and is unchanged.
// receiver - holds the receiver and is unchanged.
// Scratch registers:
// r0 - used to hold the property dictionary. // r0 - used to hold the property dictionary.
// //
// r1 - initially the receiver // r1 - used for the index into the property dictionary
// - used for the index into the property dictionary
// - holds the result on exit. // - holds the result on exit.
// //
// r2 - used to hold the capacity of the property dictionary. // r2 - used to hold the capacity of the property dictionary.
//
// name - holds the name of the property and is unchanged.
Label done; Label done;
// Check for the absence of an interceptor. // Check for the absence of an interceptor.
// Load the map into r0. // Load the map into r0.
__ mov(r0, FieldOperand(r1, JSObject::kMapOffset)); __ mov(r0, FieldOperand(receiver, JSObject::kMapOffset));
// Test the has_named_interceptor bit in the map. // Test the has_named_interceptor bit in the map.
__ test(FieldOperand(r0, Map::kInstanceAttributesOffset), __ test(FieldOperand(r0, Map::kInstanceAttributesOffset),
Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8)))); Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8))));
@ -91,7 +92,7 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
__ j(equal, miss_label, not_taken); __ j(equal, miss_label, not_taken);
// Load properties array. // Load properties array.
__ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
// Check that the properties array is a dictionary. // Check that the properties array is a dictionary.
if (check_dictionary == CHECK_DICTIONARY) { if (check_dictionary == CHECK_DICTIONARY) {
@ -176,14 +177,12 @@ const int LoadIC::kOffsetToLoadInstruction = 13;
void LoadIC::GenerateArrayLength(MacroAssembler* masm) { void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ mov(eax, Operand(esp, kPointerSize));
StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
@ -192,14 +191,12 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
void LoadIC::GenerateStringLength(MacroAssembler* masm) { void LoadIC::GenerateStringLength(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ mov(eax, Operand(esp, kPointerSize));
StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss); StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
@ -208,14 +205,12 @@ void LoadIC::GenerateStringLength(MacroAssembler* masm) {
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ mov(eax, Operand(esp, kPointerSize));
StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
@ -364,13 +359,14 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ bind(&probe_dictionary); __ bind(&probe_dictionary);
GenerateDictionaryLoad(masm, GenerateDictionaryLoad(masm,
&slow, &slow,
ebx,
ecx, ecx,
edx,
eax, eax,
ebx,
edx,
edi,
DICTIONARY_CHECK_DONE); DICTIONARY_CHECK_DONE);
GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, edx); GenerateCheckNonObjectOrLoaded(masm, &slow, edx, ebx);
__ mov(eax, Operand(ecx)); __ mov(eax, Operand(edx));
__ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
__ ret(0); __ ret(0);
@ -1001,7 +997,7 @@ static void GenerateNormalHelper(MacroAssembler* masm,
// Search dictionary - put result in register edi. // Search dictionary - put result in register edi.
__ mov(edi, edx); __ mov(edi, edx);
GenerateDictionaryLoad(masm, miss, eax, edi, ebx, ecx, CHECK_DICTIONARY); GenerateDictionaryLoad(masm, miss, edx, ecx, eax, edi, ebx, CHECK_DICTIONARY);
// Check that the result is not a smi. // Check that the result is not a smi.
__ test(edi, Immediate(kSmiTagMask)); __ test(edi, Immediate(kSmiTagMask));
@ -1150,13 +1146,11 @@ Object* LoadIC_Miss(Arguments args);
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
__ mov(eax, Operand(esp, kPointerSize));
// Probe the stub cache. // Probe the stub cache.
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
NOT_IN_LOOP, NOT_IN_LOOP,
@ -1170,14 +1164,12 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
void LoadIC::GenerateNormal(MacroAssembler* masm) { void LoadIC::GenerateNormal(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
Label miss, probe, global; Label miss, probe, global;
__ mov(eax, Operand(esp, kPointerSize));
// Check that the receiver isn't a smi. // Check that the receiver isn't a smi.
__ test(eax, Immediate(kSmiTagMask)); __ test(eax, Immediate(kSmiTagMask));
__ j(zero, &miss, not_taken); __ j(zero, &miss, not_taken);
@ -1202,8 +1194,16 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
// Search the dictionary placing the result in eax. // Search the dictionary placing the result in eax.
__ bind(&probe); __ bind(&probe);
GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx, CHECK_DICTIONARY); GenerateDictionaryLoad(masm,
GenerateCheckNonObjectOrLoaded(masm, &miss, eax, edx); &miss,
eax,
ecx,
edx,
edi,
ebx,
CHECK_DICTIONARY);
GenerateCheckNonObjectOrLoaded(masm, &miss, edi, edx);
__ mov(eax, edi);
__ ret(0); __ ret(0);
// Global object access: Check access rights. // Global object access: Check access rights.
@ -1213,20 +1213,19 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
// Cache miss: Restore receiver from stack and jump to runtime. // Cache miss: Restore receiver from stack and jump to runtime.
__ bind(&miss); __ bind(&miss);
__ mov(eax, Operand(esp, 1 * kPointerSize));
GenerateMiss(masm); GenerateMiss(masm);
} }
void LoadIC::GenerateMiss(MacroAssembler* masm) { void LoadIC::GenerateMiss(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
__ pop(ebx); __ pop(ebx);
__ push(Operand(esp, 0)); // receiver __ push(eax); // receiver
__ push(ecx); // name __ push(ecx); // name
__ push(ebx); // return address __ push(ebx); // return address

View File

@ -1767,13 +1767,12 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object,
int index, int index,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ mov(eax, Operand(esp, kPointerSize));
GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss); GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
@ -1788,13 +1787,12 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name,
JSObject* holder, JSObject* holder,
AccessorInfo* callback) { AccessorInfo* callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ mov(eax, Operand(esp, kPointerSize));
Failure* failure = Failure::InternalError(); Failure* failure = Failure::InternalError();
bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
callback, name, &miss, &failure); callback, name, &miss, &failure);
@ -1813,13 +1811,12 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
Object* value, Object* value,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ mov(eax, Operand(esp, kPointerSize));
GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss); GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
@ -1833,16 +1830,15 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
LookupResult lookup; LookupResult lookup;
LookupPostInterceptor(holder, name, &lookup); LookupPostInterceptor(holder, name, &lookup);
__ mov(eax, Operand(esp, kPointerSize));
// TODO(368): Compile in the whole chain: all the interceptors in // TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer. // prototypes and ultimate answer.
GenerateLoadInterceptor(receiver, GenerateLoadInterceptor(receiver,
@ -1869,15 +1865,12 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
String* name, String* name,
bool is_dont_delete) { bool is_dont_delete) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Get the receiver from the stack.
__ mov(eax, Operand(esp, kPointerSize));
// If the object is the holder then we know that it's a global // If the object is the holder then we know that it's a global
// object which can only happen for contextual loads. In this case, // object which can only happen for contextual loads. In this case,
// the receiver cannot be a smi. // the receiver cannot be a smi.
@ -1890,19 +1883,20 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
CheckPrototypes(object, eax, holder, ebx, edx, name, &miss); CheckPrototypes(object, eax, holder, ebx, edx, name, &miss);
// Get the value from the cell. // Get the value from the cell.
__ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell))); __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
__ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted. // Check for deleted property if property can actually be deleted.
if (!is_dont_delete) { if (!is_dont_delete) {
__ cmp(eax, Factory::the_hole_value()); __ cmp(ebx, Factory::the_hole_value());
__ j(equal, &miss, not_taken); __ j(equal, &miss, not_taken);
} else if (FLAG_debug_code) { } else if (FLAG_debug_code) {
__ cmp(eax, Factory::the_hole_value()); __ cmp(ebx, Factory::the_hole_value());
__ Check(not_equal, "DontDelete cells can't contain the hole"); __ Check(not_equal, "DontDelete cells can't contain the hole");
} }
__ IncrementCounter(&Counters::named_load_global_inline, 1); __ IncrementCounter(&Counters::named_load_global_inline, 1);
__ mov(eax, ebx);
__ ret(0); __ ret(0);
__ bind(&miss); __ bind(&miss);

View File

@ -888,13 +888,28 @@ Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
// Name and receiver are on the top of the frame. The IC expects // Name and receiver are on the top of the frame. The IC expects
// name in ecx and receiver on the stack. It does not drop the // name in ecx and receiver in eax.
// receiver.
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
Result name = Pop(); Result name = Pop();
PrepareForCall(1, 0); // One stack arg, not callee-dropped. Result receiver = Pop();
name.ToRegister(ecx); PrepareForCall(0, 0); // No stack arguments.
// Move results to the right registers:
if (name.is_register() && name.reg().is(eax)) {
if (receiver.is_register() && receiver.reg().is(ecx)) {
// Wrong registers.
__ xchg(eax, ecx);
} else {
// Register ecx is free for name, which frees eax for receiver.
name.ToRegister(ecx);
receiver.ToRegister(eax);
}
} else {
// Register eax is free for receiver, which frees ecx for name.
receiver.ToRegister(eax);
name.ToRegister(ecx);
}
name.Unuse(); name.Unuse();
receiver.Unuse();
return RawCallCodeObject(ic, mode); return RawCallCodeObject(ic, mode);
} }

View File

@ -333,7 +333,7 @@ class VirtualFrame: public ZoneObject {
Result InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag, int arg_count); Result InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag, int arg_count);
// Call load IC. Name and receiver are found on top of the frame. // Call load IC. Name and receiver are found on top of the frame.
// Receiver is not dropped. // Both are dropped.
Result CallLoadIC(RelocInfo::Mode mode); Result CallLoadIC(RelocInfo::Mode mode);
// Call keyed load IC. Key and receiver are found on top of the // Call keyed load IC. Key and receiver are found on top of the