Revision: 4681
Author: [email protected]
Date: Wed May 19 03:29:19 2010
Log: ARM: Don't require the receiver on the stack for load IC
Previously the receier was passed in both r0 and on the stack for a load
IC. With this change the receiver is in r0 only.
Review URL: http://codereview.chromium.org/2119007
http://code.google.com/p/v8/source/detail?r=4681
Modified:
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/arm/virtual-frame-arm.cc
/branches/bleeding_edge/src/arm/virtual-frame-arm.h
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Mon May 17 23:57:12 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Wed May 19 03:29:19 2010
@@ -1370,6 +1370,7 @@
// give us a megamorphic load site. Not super, but it works.
LoadAndSpill(applicand);
Handle<String> name = Factory::LookupAsciiSymbol("apply");
+ frame_->Dup();
frame_->CallLoadIC(name, RelocInfo::CODE_TARGET);
frame_->EmitPush(r0);
@@ -3009,8 +3010,6 @@
typeof_state == INSIDE_TYPEOF
? RelocInfo::CODE_TARGET
: RelocInfo::CODE_TARGET_CONTEXT);
- // Drop the global object. The result is in r0.
- frame_->Drop();
}
@@ -3424,7 +3423,6 @@
frame_->Dup();
}
EmitNamedLoad(name, var != NULL);
- frame_->Drop(); // Receiver is left on the stack.
frame_->EmitPush(r0);
// Perform the binary operation.
@@ -5430,26 +5428,30 @@
class DeferredReferenceGetNamedValue: public DeferredCode {
public:
- explicit DeferredReferenceGetNamedValue(Handle<String> name) :
name_(name) {
+ explicit DeferredReferenceGetNamedValue(Register receiver,
+ Handle<String> name)
+ : receiver_(receiver), name_(name) {
set_comment("[ DeferredReferenceGetNamedValue");
}
virtual void Generate();
private:
+ Register receiver_;
Handle<String> name_;
};
void DeferredReferenceGetNamedValue::Generate() {
+ ASSERT(receiver_.is(r0) || receiver_.is(r1));
+
Register scratch1 = VirtualFrame::scratch0();
Register scratch2 = VirtualFrame::scratch1();
__ DecrementCounter(&Counters::named_load_inline, 1, scratch1, scratch2);
__ IncrementCounter(&Counters::named_load_inline_miss, 1, scratch1,
scratch2);
- // Setup the registers and call load IC.
- // On entry to this deferred code, r0 is assumed to already contain the
- // receiver from the top of the stack.
+ // Ensure receiver in r0 and name in r2 to match load ic calling
convention.
+ __ Move(r0, receiver_);
__ mov(r2, Operand(name_));
// The rest of the instructions in the deferred code must be together.
@@ -5588,10 +5590,11 @@
// this code
// Load the receiver from the stack.
- frame_->SpillAllButCopyTOSToR0();
+ Register receiver = frame_->PopToRegister();
+ VirtualFrame::SpilledScope spilled(frame_);
DeferredReferenceGetNamedValue* deferred =
- new DeferredReferenceGetNamedValue(name);
+ new DeferredReferenceGetNamedValue(receiver, name);
#ifdef DEBUG
int kInlinedNamedLoadInstructions = 7;
@@ -5601,19 +5604,19 @@
{ Assembler::BlockConstPoolScope block_const_pool(masm_);
// Check that the receiver is a heap object.
- __ tst(r0, Operand(kSmiTagMask));
+ __ tst(receiver, Operand(kSmiTagMask));
deferred->Branch(eq);
// Check the map. The null map used below is patched by the inline
cache
// code.
- __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
+ __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
__ mov(r3, Operand(Factory::null_value()));
__ cmp(r2, r3);
deferred->Branch(ne);
// Initially use an invalid index. The index will be patched by the
// inline cache code.
- __ ldr(r0, MemOperand(r0, 0));
+ __ ldr(r0, MemOperand(receiver, 0));
// Make sure that the expected number of instructions are generated.
ASSERT_EQ(kInlinedNamedLoadInstructions,
@@ -5862,19 +5865,20 @@
Variable* var = expression_->AsVariableProxy()->AsVariable();
bool is_global = var != NULL;
ASSERT(!is_global || var->is_global());
+ if (persist_after_get_) {
+ cgen_->frame()->Dup();
+ }
cgen_->EmitNamedLoad(GetName(), is_global);
cgen_->frame()->EmitPush(r0);
- if (!persist_after_get_) {
- cgen_->UnloadReference(this);
- }
+ if (!persist_after_get_) set_unloaded();
break;
}
case KEYED: {
+ ASSERT(property != NULL);
if (persist_after_get_) {
cgen_->frame()->Dup2();
}
- ASSERT(property != NULL);
cgen_->EmitKeyedLoad();
cgen_->frame()->EmitPush(r0);
if (!persist_after_get_) set_unloaded();
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed May 19 00:32:32
2010
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed May 19 03:29:19
2010
@@ -707,13 +707,12 @@
if (var->is_global() && !var->is_this()) {
Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in r2 and the global
- // object on the stack.
+ // object (receiver) in r0.
__ ldr(r0, CodeGenerator::GlobalObject());
- __ push(r0);
__ mov(r2, Operand(var->name()));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
- DropAndApply(1, context, r0);
+ Apply(context, r0);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
Comment cmnt(masm_, "Lookup slot");
@@ -1019,7 +1018,7 @@
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
__ mov(r2, Operand(key->handle()));
- __ ldr(r0, MemOperand(sp, 0));
+ // Call load IC. It has arguments receiver and property name r0 and r2.
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
}
@@ -1213,14 +1212,12 @@
Comment cmnt(masm_, "[ Property");
Expression* key = expr->key();
- // Evaluate 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_, r0);
+ Apply(context_, r0);
} else {
+ VisitForValue(expr->obj(), kStack);
VisitForValue(expr->key(), kAccumulator);
__ pop(r1);
EmitKeyedPropertyLoad(expr);
@@ -1493,13 +1490,12 @@
proxy->var()->is_global()) {
Comment cmnt(masm_, "Global variable");
__ ldr(r0, CodeGenerator::GlobalObject());
- __ push(r0);
__ mov(r2, Operand(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);
- __ str(r0, MemOperand(sp));
+ __ push(r0);
} else if (proxy != NULL &&
proxy->var()->slot() != NULL &&
proxy->var()->slot()->type() == Slot::LOOKUP) {
@@ -1605,10 +1601,13 @@
__ mov(ip, Operand(Smi::FromInt(0)));
__ push(ip);
}
- 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(r0);
EmitNamedPropertyLoad(prop);
} else {
+ VisitForValue(prop->obj(), kStack);
VisitForValue(prop->key(), kAccumulator);
__ ldr(r1, MemOperand(sp, 0));
__ push(r0);
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Wed May 19 01:36:14
2010
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Wed May 19 03:29:19
2010
@@ -1617,15 +1617,11 @@
JSObject* object,
JSObject* last) {
// ----------- S t a t e -------------
- // -- r2 : name
+ // -- r0 : receiver
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
Label miss;
- // Load receiver.
- __ ldr(r0, MemOperand(sp, 0));
-
// Check that receiver is not a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
@@ -1662,14 +1658,12 @@
int index,
String* name) {
// ----------- S t a t e -------------
+ // -- r0 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
Label miss;
- __ ldr(r0, MemOperand(sp, 0));
-
GenerateLoadField(object, holder, r0, r3, r1, index, name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC);
@@ -1684,13 +1678,12 @@
JSObject* holder,
AccessorInfo* callback) {
// ----------- S t a t e -------------
+ // -- r0 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
Label miss;
- __ ldr(r0, MemOperand(sp, 0));
Failure* failure = Failure::InternalError();
bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1,
callback, name, &miss, &failure);
@@ -1709,14 +1702,12 @@
Object* value,
String* name) {
// ----------- S t a t e -------------
+ // -- r0 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
Label miss;
- __ ldr(r0, MemOperand(sp, 0));
-
GenerateLoadConstant(object, holder, r0, r3, r1, value, name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC);
@@ -1730,14 +1721,12 @@
JSObject* holder,
String* name) {
// ----------- S t a t e -------------
+ // -- r0 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
Label miss;
- __ ldr(r0, MemOperand(sp, 0));
-
LookupResult lookup;
LookupPostInterceptor(holder, name, &lookup);
GenerateLoadInterceptor(object,
@@ -1763,10 +1752,9 @@
String* name,
bool is_dont_delete) {
// ----------- S t a t e -------------
+ // -- r0 : receiver
// -- r2 : name
// -- lr : return address
- // -- r0 : receiver
- // -- sp[0] : receiver
// -----------------------------------
Label miss;
=======================================
--- /branches/bleeding_edge/src/arm/virtual-frame-arm.cc Mon May 17
23:57:12 2010
+++ /branches/bleeding_edge/src/arm/virtual-frame-arm.cc Wed May 19
03:29:19 2010
@@ -309,7 +309,8 @@
void VirtualFrame::CallLoadIC(Handle<String> name, RelocInfo::Mode mode) {
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
- SpillAllButCopyTOSToR0();
+ PopToR0();
+ SpillAll();
__ mov(r2, Operand(name));
CallCodeObject(ic, mode, 0);
}
@@ -509,36 +510,40 @@
void VirtualFrame::Dup() {
- AssertIsNotSpilled();
- switch (top_of_stack_state_) {
- case NO_TOS_REGISTERS:
- __ ldr(r0, MemOperand(sp, 0));
- top_of_stack_state_ = R0_TOS;
- break;
- case R0_TOS:
- __ mov(r1, r0);
- // r0 and r1 contains the same value. Prefer a state with r0 holding
TOS.
- top_of_stack_state_ = R0_R1_TOS;
- break;
- case R1_TOS:
- __ mov(r0, r1);
- // r0 and r1 contains the same value. Prefer a state with r0 holding
TOS.
- top_of_stack_state_ = R0_R1_TOS;
- break;
- case R0_R1_TOS:
- __ push(r1);
- __ mov(r1, r0);
- // r0 and r1 contains the same value. Prefer a state with r0 holding
TOS.
- top_of_stack_state_ = R0_R1_TOS;
- break;
- case R1_R0_TOS:
- __ push(r0);
- __ mov(r0, r1);
- // r0 and r1 contains the same value. Prefer a state with r0 holding
TOS.
- top_of_stack_state_ = R0_R1_TOS;
- break;
- default:
- UNREACHABLE();
+ if (SpilledScope::is_spilled()) {
+ __ ldr(ip, MemOperand(sp, 0));
+ __ push(ip);
+ } else {
+ switch (top_of_stack_state_) {
+ case NO_TOS_REGISTERS:
+ __ ldr(r0, MemOperand(sp, 0));
+ top_of_stack_state_ = R0_TOS;
+ break;
+ case R0_TOS:
+ __ mov(r1, r0);
+ // r0 and r1 contains the same value. Prefer state with r0 holding
TOS.
+ top_of_stack_state_ = R0_R1_TOS;
+ break;
+ case R1_TOS:
+ __ mov(r0, r1);
+ // r0 and r1 contains the same value. Prefer state with r0 holding
TOS.
+ top_of_stack_state_ = R0_R1_TOS;
+ break;
+ case R0_R1_TOS:
+ __ push(r1);
+ __ mov(r1, r0);
+ // r0 and r1 contains the same value. Prefer state with r0 holding
TOS.
+ top_of_stack_state_ = R0_R1_TOS;
+ break;
+ case R1_R0_TOS:
+ __ push(r0);
+ __ mov(r0, r1);
+ // r0 and r1 contains the same value. Prefer state with r0 holding
TOS.
+ top_of_stack_state_ = R0_R1_TOS;
+ break;
+ default:
+ UNREACHABLE();
+ }
}
element_count_++;
}
=======================================
--- /branches/bleeding_edge/src/arm/virtual-frame-arm.h Mon May 17 23:57:12
2010
+++ /branches/bleeding_edge/src/arm/virtual-frame-arm.h Wed May 19 03:29:19
2010
@@ -278,7 +278,8 @@
InvokeJSFlags flag,
int arg_count);
- // Call load IC. Receiver is on the stack. Result is returned in r0.
+ // Call load IC. Receiver is on the stack and is consumed. Result is
returned
+ // in r0.
void CallLoadIC(Handle<String> name, RelocInfo::Mode mode);
// Call store IC. If the load is contextual, value is found on top of the
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev