Revision: 3921
Author: [email protected]
Date: Fri Feb 19 07:04:16 2010
Log: Improve stores to global variables.
Review URL: http://codereview.chromium.org/650028
http://code.google.com/p/v8/source/detail?r=3921
Modified:
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.h
/branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
/branches/bleeding_edge/src/ia32/virtual-frame-ia32.h
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 19 06:52:39
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 19 07:04:16
2010
@@ -695,8 +695,10 @@
// The expression is a variable proxy that does not rewrite to a
// property. Global variables are treated as named property
references.
if (var->is_global()) {
- // Named loads require object in eax. Named stores don't use
references.
- // Spilling eax makes it free, so LoadGlobal loads directly into eax.
+ // If eax is free, the register allocator prefers it. Thus the code
+ // generator will load the global object into eax, which is where
+ // LoadIC wants it. Most uses of Reference call LoadIC directly
+ // after the reference is created.
frame_->Spill(eax);
LoadGlobal();
ref->set_type(Reference::NAMED);
@@ -4316,6 +4318,10 @@
// All extension objects were empty and it is safe to use a global
// load IC call.
+ // The register allocator prefers eax if it is free, so the code
generator
+ // will load the global object directly into eax, which is where the
LoadIC
+ // expects it.
+ frame_->Spill(eax);
LoadGlobal();
frame_->Push(slot->var()->name());
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
@@ -4601,8 +4607,8 @@
// Duplicate the object as the IC receiver.
frame_->Dup();
Load(property->value());
- frame_->Push(key);
- Result ignored = frame_->CallStoreIC();
+ Result dummy = frame_->CallStoreIC(Handle<String>::cast(key),
false);
+ dummy.Unuse();
break;
}
// Fall through
@@ -4776,10 +4782,9 @@
bool is_trivial_receiver = false;
if (var != NULL) {
name = var->name();
- LoadGlobal();
} else {
Literal* lit = prop->key()->AsLiteral();
- ASSERT(lit != NULL);
+ ASSERT_NOT_NULL(lit);
name = Handle<String>::cast(lit->handle());
// Do not materialize the receiver on the frame if it is trivial.
is_trivial_receiver = prop->obj()->IsTrivial();
@@ -4787,6 +4792,7 @@
}
if (node->starts_initialization_block()) {
+ ASSERT_EQ(NULL, var);
// Change to slow case in the beginning of an initialization block to
// avoid the quadratic behavior of repeatedly adding fast properties.
if (is_trivial_receiver) {
@@ -4807,6 +4813,11 @@
if (node->is_compound()) {
if (is_trivial_receiver) {
frame()->Push(prop->obj());
+ } else if (var != NULL) {
+ // The LoadIC stub expects the object in eax.
+ // Freeing eax causes the code generator to load the global into it.
+ frame_->Spill(eax);
+ LoadGlobal();
} else {
frame()->Dup();
}
@@ -4826,17 +4837,19 @@
// Perform the assignment. It is safe to ignore constants here.
ASSERT(var == NULL || var->mode() != Variable::CONST);
- ASSERT(node->op() != Token::INIT_CONST);
+ ASSERT_NE(Token::INIT_CONST, node->op());
if (is_trivial_receiver) {
Result value = frame()->Pop();
frame()->Push(prop->obj());
frame()->Push(&value);
}
CodeForSourcePosition(node->position());
- Result answer = EmitNamedStore(name);
+ bool is_contextual = (var != NULL);
+ Result answer = EmitNamedStore(name, is_contextual);
frame()->Push(&answer);
if (node->ends_initialization_block()) {
+ ASSERT_EQ(NULL, var);
// The argument to the runtime call is the receiver.
if (is_trivial_receiver) {
frame()->Push(prop->obj());
@@ -4851,7 +4864,7 @@
Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
}
- ASSERT(frame()->height() == original_height + 1);
+ ASSERT_EQ(frame()->height(), original_height + 1);
}
@@ -4861,7 +4874,7 @@
#endif
Comment cmnt(masm_, "[ Named Property Assignment");
Property* prop = node->target()->AsProperty();
- ASSERT(prop != NULL);
+ ASSERT_NOT_NULL(prop);
// Evaluate the receiver subexpression.
Load(prop->obj());
@@ -6779,14 +6792,13 @@
}
-Result CodeGenerator::EmitNamedStore(Handle<String> name) {
+Result CodeGenerator::EmitNamedStore(Handle<String> name, bool
is_contextual) {
#ifdef DEBUG
- int original_height = frame()->height();
+ int expected_height = frame()->height() - (is_contextual ? 1 : 2);
#endif
- frame()->Push(name);
- Result result = frame()->CallStoreIC();
-
- ASSERT(frame()->height() == original_height - 2);
+ Result result = frame()->CallStoreIC(name, is_contextual);
+
+ ASSERT_EQ(expected_height, frame()->height());
return result;
}
@@ -7103,7 +7115,7 @@
case NAMED: {
Comment cmnt(masm, "[ Store to named Property");
- Result answer = cgen_->EmitNamedStore(GetName());
+ Result answer = cgen_->EmitNamedStore(GetName(), false);
cgen_->frame()->Push(&answer);
set_unloaded();
break;
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h Fri Feb 19 06:52:39 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h Fri Feb 19 07:04:16 2010
@@ -438,8 +438,9 @@
// Receiver is passed on the frame and consumed.
Result EmitNamedLoad(Handle<String> name, bool is_contextual);
- // Reciever and value are passed on the frame and consumed.
- Result EmitNamedStore(Handle<String> name);
+ // If the store is contextual, value is passed on the frame and consumed.
+ // Otherwise, receiver and value are passed on the frame and consumed.
+ Result EmitNamedStore(Handle<String> name, bool is_contextual);
// Receiver and key are passed on the frame and consumed.
Result EmitKeyedLoad();
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Fri Feb 19
01:01:31 2010
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Fri Feb 19
07:04:16 2010
@@ -948,47 +948,38 @@
}
-Result VirtualFrame::CallStoreIC() {
- // Name, value, and receiver are on top of the frame. The IC
- // expects name in ecx, value in eax, and receiver in edx.
+Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) {
+ // Value and (if not contextual) receiver are on top of the frame.
+ // The IC expects name in ecx, value in eax, and receiver in edx.
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- Result name = Pop();
Result value = Pop();
- Result receiver = Pop();
- PrepareForCall(0, 0);
-
- // Optimized for case in which name is a constant value.
- if (name.is_register() && (name.reg().is(edx) || name.reg().is(eax))) {
- if (!is_used(ecx)) {
- name.ToRegister(ecx);
- } else if (!is_used(ebx)) {
- name.ToRegister(ebx);
+ if (is_contextual) {
+ PrepareForCall(0, 0);
+ value.ToRegister(eax);
+ __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ mov(ecx, name);
+ } else {
+ Result receiver = Pop();
+ PrepareForCall(0, 0);
+
+ if (value.is_register() && value.reg().is(edx)) {
+ if (receiver.is_register() && receiver.reg().is(eax)) {
+ // Wrong registers.
+ __ xchg(eax, edx);
+ } else {
+ // Register eax is free for value, which frees edx for receiver.
+ value.ToRegister(eax);
+ receiver.ToRegister(edx);
+ }
} else {
- ASSERT(!is_used(edi)); // Only three results are live, so edi is
free.
- name.ToRegister(edi);
- }
- }
- // Now name is not in edx or eax, so we can fix them, then move name to
ecx.
- if (value.is_register() && value.reg().is(edx)) {
- if (receiver.is_register() && receiver.reg().is(eax)) {
- // Wrong registers.
- __ xchg(eax, edx);
- } else {
- // Register eax is free for value, which frees edx for receiver.
- value.ToRegister(eax);
+ // Register edx is free for receiver, which guarantees eax is free
for
+ // value.
receiver.ToRegister(edx);
- }
- } else {
- // Register edx is free for receiver, which guarantees eax is free for
- // value.
- receiver.ToRegister(edx);
- value.ToRegister(eax);
- }
- // Receiver and value are in the right place, so ecx is free for name.
- name.ToRegister(ecx);
- name.Unuse();
+ value.ToRegister(eax);
+ }
+ }
+ __ mov(ecx, name);
value.Unuse();
- receiver.Unuse();
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
}
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Fri Feb 19
01:01:31 2010
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Fri Feb 19
07:04:16 2010
@@ -339,12 +339,12 @@
Result CallLoadIC(RelocInfo::Mode mode);
// Call keyed load IC. Key and receiver are found on top of the
- // frame. They are not dropped.
+ // frame. Both are dropped.
Result CallKeyedLoadIC(RelocInfo::Mode mode);
- // Call store IC. Name, value, and receiver are found on top of the
- // frame. Receiver is not dropped.
- Result CallStoreIC();
+ // Call store IC. If the load is contextual, value is found on top of
the
+ // frame. If not, value and receiver are on the frame. Both are
dropped.
+ Result CallStoreIC(Handle<String> name, bool is_contextual);
// Call keyed store IC. Value, key, and receiver are found on top
// of the frame. Key and receiver are not dropped.
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev