Revision: 3841
Author: [email protected]
Date: Fri Feb 12 02:32:24 2010
Log: Change LoadIC interface on ia32 to take arguments in registers.
Review URL: http://codereview.chromium.org/573009
http://code.google.com/p/v8/source/detail?r=3841
Modified:
/branches/bleeding_edge/src/full-codegen.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/debug-ia32.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/ic-ia32.cc
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
/branches/bleeding_edge/src/ia32/virtual-frame-ia32.h
=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Mon Feb 8 05:44:49 2010
+++ /branches/bleeding_edge/src/full-codegen.cc Fri Feb 12 02:32:24 2010
@@ -1050,7 +1050,13 @@
// Nothing to do here.
break;
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;
case KEYED_PROPERTY:
VisitForValue(prop->obj(), kStack);
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 12 02:28:40
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 12 02:32:24
2010
@@ -2327,6 +2327,7 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
__ IncrementCounter(&Counters::named_load_inline_miss, 1);
if (!dst_.is(eax)) __ mov(dst_, eax);
- __ pop(receiver_);
}
@@ -6570,6 +6570,9 @@
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 @@
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 @@
__ 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 @@
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:
+ default:
UNREACHABLE();
}
-
- if (!persist_after_get_) {
- cgen_->UnloadReference(this);
- }
}
=======================================
--- /branches/bleeding_edge/src/ia32/debug-ia32.cc Tue Feb 2 10:35:53 2010
+++ /branches/bleeding_edge/src/ia32/debug-ia32.cc Fri Feb 12 02:32:24 2010
@@ -125,9 +125,10 @@
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);
}
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed Feb 3
08:12:55 2010
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Feb 12
02:32:24 2010
@@ -808,7 +808,7 @@
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 @@
// 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 @@
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 @@
!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 @@
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);
}
=======================================
--- /branches/bleeding_edge/src/ia32/ic-ia32.cc Tue Feb 9 07:18:37 2010
+++ /branches/bleeding_edge/src/ia32/ic-ia32.cc Fri Feb 12 02:32:24 2010
@@ -50,28 +50,29 @@
// 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 @@
__ 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 @@
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::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::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 @@
__ 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 @@
// 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 @@
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::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 @@
// 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 @@
// 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
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Feb 9 08:14:14
2010
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Feb 12 02:32:24
2010
@@ -1767,13 +1767,12 @@
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 @@
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* 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 @@
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 @@
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 @@
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);
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Mon Feb 8
05:44:49 2010
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Fri Feb 12
02:32:24 2010
@@ -888,13 +888,28 @@
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.
- name.ToRegister(ecx);
+ 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);
}
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Mon Feb 8
05:44:49 2010
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Fri Feb 12
02:32:24 2010
@@ -333,7 +333,7 @@
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
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev