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:
parent
85c24cee57
commit
c7fe99d3ff
@ -1050,7 +1050,13 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
// Nothing to do here.
|
||||
break;
|
||||
case NAMED_PROPERTY:
|
||||
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;
|
||||
case KEYED_PROPERTY:
|
||||
VisitForValue(prop->obj(), kStack);
|
||||
|
@ -2327,6 +2327,7 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
|
||||
// Load applicand.apply onto the stack. This will usually
|
||||
// give us a megamorphic load site. Not super, but it works.
|
||||
Load(applicand);
|
||||
frame()->Dup();
|
||||
Handle<String> name = Factory::LookupAsciiSymbol("apply");
|
||||
frame()->Push(name);
|
||||
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
|
||||
// instruction here.
|
||||
__ nop();
|
||||
// Discard the global object. The result is in answer.
|
||||
frame_->Drop();
|
||||
return answer;
|
||||
}
|
||||
|
||||
@ -6276,7 +6275,7 @@ bool CodeGenerator::HasValidEntryRegisters() {
|
||||
|
||||
|
||||
// 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 {
|
||||
public:
|
||||
DeferredReferenceGetNamedValue(Register dst,
|
||||
@ -6299,7 +6298,9 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
|
||||
|
||||
|
||||
void DeferredReferenceGetNamedValue::Generate() {
|
||||
__ push(receiver_);
|
||||
if (!receiver_.is(eax)) {
|
||||
__ mov(eax, receiver_);
|
||||
}
|
||||
__ Set(ecx, Immediate(name_));
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
@ -6316,7 +6317,6 @@ void DeferredReferenceGetNamedValue::Generate() {
|
||||
__ IncrementCounter(&Counters::named_load_inline_miss, 1);
|
||||
|
||||
if (!dst_.is(eax)) __ mov(dst_, eax);
|
||||
__ pop(receiver_);
|
||||
}
|
||||
|
||||
|
||||
@ -6570,6 +6570,9 @@ void Reference::GetValue() {
|
||||
Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
|
||||
ASSERT(slot != NULL);
|
||||
cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
|
||||
if (!persist_after_get_) {
|
||||
cgen_->UnloadReference(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -6578,6 +6581,9 @@ void Reference::GetValue() {
|
||||
bool is_global = var != NULL;
|
||||
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
|
||||
// object. Also do not inline for unoptimized code. This saves time
|
||||
// in the code generator. Unoptimized code is toplevel code or code
|
||||
@ -6636,9 +6642,11 @@ void Reference::GetValue() {
|
||||
|
||||
__ IncrementCounter(&Counters::named_load_inline, 1);
|
||||
deferred->BindExit();
|
||||
cgen_->frame()->Push(&receiver);
|
||||
cgen_->frame()->Push(&value);
|
||||
}
|
||||
if (!persist_after_get_) {
|
||||
set_unloaded();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -6648,16 +6656,15 @@ void Reference::GetValue() {
|
||||
ASSERT(!is_global || var->is_global());
|
||||
Result value = cgen_->EmitKeyedLoad(is_global);
|
||||
cgen_->frame()->Push(&value);
|
||||
if (!persist_after_get_) {
|
||||
cgen_->UnloadReference(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (!persist_after_get_) {
|
||||
cgen_->UnloadReference(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -125,9 +125,10 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
|
||||
void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for IC load call (from ic-ia32.cc).
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, ecx.bit(), false);
|
||||
Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -808,7 +808,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
// Use inline caching. Variable name is passed in ecx and the global
|
||||
// object on the stack.
|
||||
__ push(CodeGenerator::GlobalObject());
|
||||
__ mov(eax, CodeGenerator::GlobalObject());
|
||||
__ mov(ecx, var->name());
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
||||
__ 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
|
||||
// (eg, push/pop elimination).
|
||||
__ nop();
|
||||
DropAndApply(1, context, eax);
|
||||
Apply(context, eax);
|
||||
|
||||
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
|
||||
Comment cmnt(masm_, "Lookup slot");
|
||||
@ -1183,14 +1183,12 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
Expression* key = expr->key();
|
||||
|
||||
// Evaluate the receiver.
|
||||
VisitForValue(expr->obj(), kStack);
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
VisitForValue(expr->obj(), kAccumulator);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
// Drop receiver left on the stack by IC.
|
||||
DropAndApply(1, context_, eax);
|
||||
Apply(context_, eax);
|
||||
} else {
|
||||
VisitForValue(expr->obj(), kStack);
|
||||
VisitForValue(expr->key(), kStack);
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
// 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_global()) {
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
__ push(CodeGenerator::GlobalObject());
|
||||
__ mov(eax, CodeGenerator::GlobalObject());
|
||||
__ mov(ecx, Immediate(proxy->name()));
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
__ mov(Operand(esp, 0), eax);
|
||||
__ push(eax);
|
||||
} else if (proxy != NULL &&
|
||||
proxy->var()->slot() != NULL &&
|
||||
proxy->var()->slot()->type() == Slot::LOOKUP) {
|
||||
@ -1565,10 +1563,13 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
if (expr->is_postfix() && context_ != Expression::kEffect) {
|
||||
__ push(Immediate(Smi::FromInt(0)));
|
||||
}
|
||||
VisitForValue(prop->obj(), kStack);
|
||||
if (assign_type == NAMED_PROPERTY) {
|
||||
// Put the object both on the stack and in the accumulator.
|
||||
VisitForValue(prop->obj(), kAccumulator);
|
||||
__ push(eax);
|
||||
EmitNamedPropertyLoad(prop);
|
||||
} else {
|
||||
VisitForValue(prop->obj(), kStack);
|
||||
VisitForValue(prop->key(), kStack);
|
||||
EmitKeyedPropertyLoad(prop);
|
||||
}
|
||||
|
@ -50,28 +50,29 @@ namespace internal {
|
||||
// or if name is not a symbol, and will jump to the miss_label in that case.
|
||||
static void GenerateDictionaryLoad(MacroAssembler* masm,
|
||||
Label* miss_label,
|
||||
Register receiver,
|
||||
Register name,
|
||||
Register r0,
|
||||
Register r1,
|
||||
Register r2,
|
||||
Register name,
|
||||
DictionaryCheck check_dictionary) {
|
||||
// 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.
|
||||
//
|
||||
// r1 - initially the receiver
|
||||
// - used for the index into the property dictionary
|
||||
// r1 - used for the index into the property dictionary
|
||||
// - holds the result on exit.
|
||||
//
|
||||
// r2 - used to hold the capacity of the property dictionary.
|
||||
//
|
||||
// name - holds the name of the property and is unchanged.
|
||||
|
||||
Label done;
|
||||
|
||||
// Check for the absence of an interceptor.
|
||||
// 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(FieldOperand(r0, Map::kInstanceAttributesOffset),
|
||||
Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8))));
|
||||
@ -91,7 +92,7 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
|
||||
__ j(equal, miss_label, not_taken);
|
||||
|
||||
// Load properties array.
|
||||
__ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset));
|
||||
__ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
|
||||
|
||||
// Check that the properties array is a dictionary.
|
||||
if (check_dictionary == CHECK_DICTIONARY) {
|
||||
@ -176,14 +177,12 @@ const int LoadIC::kOffsetToLoadInstruction = 13;
|
||||
|
||||
void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
__ mov(eax, Operand(esp, kPointerSize));
|
||||
|
||||
StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
@ -192,14 +191,12 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
|
||||
|
||||
void LoadIC::GenerateStringLength(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
__ mov(eax, Operand(esp, kPointerSize));
|
||||
|
||||
StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
@ -208,14 +205,12 @@ void LoadIC::GenerateStringLength(MacroAssembler* masm) {
|
||||
|
||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
__ mov(eax, Operand(esp, kPointerSize));
|
||||
|
||||
StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
@ -364,13 +359,14 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ bind(&probe_dictionary);
|
||||
GenerateDictionaryLoad(masm,
|
||||
&slow,
|
||||
ebx,
|
||||
ecx,
|
||||
edx,
|
||||
eax,
|
||||
ebx,
|
||||
edx,
|
||||
edi,
|
||||
DICTIONARY_CHECK_DONE);
|
||||
GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, edx);
|
||||
__ mov(eax, Operand(ecx));
|
||||
GenerateCheckNonObjectOrLoaded(masm, &slow, edx, ebx);
|
||||
__ mov(eax, Operand(edx));
|
||||
__ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
|
||||
__ ret(0);
|
||||
|
||||
@ -1001,7 +997,7 @@ static void GenerateNormalHelper(MacroAssembler* masm,
|
||||
|
||||
// Search dictionary - put result in register edi.
|
||||
__ 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.
|
||||
__ test(edi, Immediate(kSmiTagMask));
|
||||
@ -1150,13 +1146,11 @@ Object* LoadIC_Miss(Arguments args);
|
||||
|
||||
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
|
||||
__ mov(eax, Operand(esp, kPointerSize));
|
||||
|
||||
// Probe the stub cache.
|
||||
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
|
||||
NOT_IN_LOOP,
|
||||
@ -1170,14 +1164,12 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
|
||||
void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss, probe, global;
|
||||
|
||||
__ mov(eax, Operand(esp, kPointerSize));
|
||||
|
||||
// Check that the receiver isn't a smi.
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
__ j(zero, &miss, not_taken);
|
||||
@ -1202,8 +1194,16 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
|
||||
// Search the dictionary placing the result in eax.
|
||||
__ bind(&probe);
|
||||
GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx, CHECK_DICTIONARY);
|
||||
GenerateCheckNonObjectOrLoaded(masm, &miss, eax, edx);
|
||||
GenerateDictionaryLoad(masm,
|
||||
&miss,
|
||||
eax,
|
||||
ecx,
|
||||
edx,
|
||||
edi,
|
||||
ebx,
|
||||
CHECK_DICTIONARY);
|
||||
GenerateCheckNonObjectOrLoaded(masm, &miss, edi, edx);
|
||||
__ mov(eax, edi);
|
||||
__ ret(0);
|
||||
|
||||
// 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.
|
||||
__ bind(&miss);
|
||||
__ mov(eax, Operand(esp, 1 * kPointerSize));
|
||||
GenerateMiss(masm);
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
|
||||
__ pop(ebx);
|
||||
__ push(Operand(esp, 0)); // receiver
|
||||
__ push(eax); // receiver
|
||||
__ push(ecx); // name
|
||||
__ push(ebx); // return address
|
||||
|
||||
|
@ -1767,13 +1767,12 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object,
|
||||
int index,
|
||||
String* name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
__ mov(eax, Operand(esp, kPointerSize));
|
||||
GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss);
|
||||
__ bind(&miss);
|
||||
GenerateLoadMiss(masm(), Code::LOAD_IC);
|
||||
@ -1788,13 +1787,12 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name,
|
||||
JSObject* holder,
|
||||
AccessorInfo* callback) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
__ mov(eax, Operand(esp, kPointerSize));
|
||||
Failure* failure = Failure::InternalError();
|
||||
bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
|
||||
callback, name, &miss, &failure);
|
||||
@ -1813,13 +1811,12 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
|
||||
Object* value,
|
||||
String* name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
__ mov(eax, Operand(esp, kPointerSize));
|
||||
GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss);
|
||||
__ bind(&miss);
|
||||
GenerateLoadMiss(masm(), Code::LOAD_IC);
|
||||
@ -1833,16 +1830,15 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
|
||||
JSObject* holder,
|
||||
String* name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
LookupResult lookup;
|
||||
LookupPostInterceptor(holder, name, &lookup);
|
||||
|
||||
__ mov(eax, Operand(esp, kPointerSize));
|
||||
// TODO(368): Compile in the whole chain: all the interceptors in
|
||||
// prototypes and ultimate answer.
|
||||
GenerateLoadInterceptor(receiver,
|
||||
@ -1869,15 +1865,12 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
|
||||
String* name,
|
||||
bool is_dont_delete) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : receiver
|
||||
// -- ecx : name
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
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
|
||||
// object which can only happen for contextual loads. In this case,
|
||||
// the receiver cannot be a smi.
|
||||
@ -1890,19 +1883,20 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
|
||||
CheckPrototypes(object, eax, holder, ebx, edx, name, &miss);
|
||||
|
||||
// Get the value from the cell.
|
||||
__ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell)));
|
||||
__ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset));
|
||||
__ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
|
||||
__ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
|
||||
|
||||
// Check for deleted property if property can actually be deleted.
|
||||
if (!is_dont_delete) {
|
||||
__ cmp(eax, Factory::the_hole_value());
|
||||
__ cmp(ebx, Factory::the_hole_value());
|
||||
__ j(equal, &miss, not_taken);
|
||||
} 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");
|
||||
}
|
||||
|
||||
__ IncrementCounter(&Counters::named_load_global_inline, 1);
|
||||
__ mov(eax, ebx);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&miss);
|
||||
|
@ -888,13 +888,28 @@ Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
|
||||
|
||||
Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
|
||||
// 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
|
||||
// receiver.
|
||||
// name in ecx and receiver in eax.
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
||||
Result name = Pop();
|
||||
PrepareForCall(1, 0); // One stack arg, not callee-dropped.
|
||||
Result receiver = Pop();
|
||||
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();
|
||||
receiver.Unuse();
|
||||
return RawCallCodeObject(ic, mode);
|
||||
}
|
||||
|
||||
|
@ -333,7 +333,7 @@ class VirtualFrame: public ZoneObject {
|
||||
Result InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag, int arg_count);
|
||||
|
||||
// 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);
|
||||
|
||||
// Call keyed load IC. Key and receiver are found on top of the
|
||||
|
Loading…
Reference in New Issue
Block a user