Commit d931c9b7 authored by whesse@chromium.org's avatar whesse@chromium.org

Improve stores to global variables.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3921 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a9202fc4
...@@ -695,8 +695,10 @@ void CodeGenerator::LoadReference(Reference* ref) { ...@@ -695,8 +695,10 @@ void CodeGenerator::LoadReference(Reference* ref) {
// The expression is a variable proxy that does not rewrite to a // The expression is a variable proxy that does not rewrite to a
// property. Global variables are treated as named property references. // property. Global variables are treated as named property references.
if (var->is_global()) { if (var->is_global()) {
// Named loads require object in eax. Named stores don't use references. // If eax is free, the register allocator prefers it. Thus the code
// Spilling eax makes it free, so LoadGlobal loads directly into eax. // 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); frame_->Spill(eax);
LoadGlobal(); LoadGlobal();
ref->set_type(Reference::NAMED); ref->set_type(Reference::NAMED);
...@@ -4316,6 +4318,10 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( ...@@ -4316,6 +4318,10 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
// All extension objects were empty and it is safe to use a global // All extension objects were empty and it is safe to use a global
// load IC call. // 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(); LoadGlobal();
frame_->Push(slot->var()->name()); frame_->Push(slot->var()->name());
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
...@@ -4601,8 +4607,8 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { ...@@ -4601,8 +4607,8 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
// Duplicate the object as the IC receiver. // Duplicate the object as the IC receiver.
frame_->Dup(); frame_->Dup();
Load(property->value()); Load(property->value());
frame_->Push(key); Result dummy = frame_->CallStoreIC(Handle<String>::cast(key), false);
Result ignored = frame_->CallStoreIC(); dummy.Unuse();
break; break;
} }
// Fall through // Fall through
...@@ -4776,10 +4782,9 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { ...@@ -4776,10 +4782,9 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
bool is_trivial_receiver = false; bool is_trivial_receiver = false;
if (var != NULL) { if (var != NULL) {
name = var->name(); name = var->name();
LoadGlobal();
} else { } else {
Literal* lit = prop->key()->AsLiteral(); Literal* lit = prop->key()->AsLiteral();
ASSERT(lit != NULL); ASSERT_NOT_NULL(lit);
name = Handle<String>::cast(lit->handle()); name = Handle<String>::cast(lit->handle());
// Do not materialize the receiver on the frame if it is trivial. // Do not materialize the receiver on the frame if it is trivial.
is_trivial_receiver = prop->obj()->IsTrivial(); is_trivial_receiver = prop->obj()->IsTrivial();
...@@ -4787,6 +4792,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { ...@@ -4787,6 +4792,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
} }
if (node->starts_initialization_block()) { if (node->starts_initialization_block()) {
ASSERT_EQ(NULL, var);
// Change to slow case in the beginning of an initialization block to // Change to slow case in the beginning of an initialization block to
// avoid the quadratic behavior of repeatedly adding fast properties. // avoid the quadratic behavior of repeatedly adding fast properties.
if (is_trivial_receiver) { if (is_trivial_receiver) {
...@@ -4807,6 +4813,11 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { ...@@ -4807,6 +4813,11 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
if (node->is_compound()) { if (node->is_compound()) {
if (is_trivial_receiver) { if (is_trivial_receiver) {
frame()->Push(prop->obj()); 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 { } else {
frame()->Dup(); frame()->Dup();
} }
...@@ -4826,17 +4837,19 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { ...@@ -4826,17 +4837,19 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
// Perform the assignment. It is safe to ignore constants here. // Perform the assignment. It is safe to ignore constants here.
ASSERT(var == NULL || var->mode() != Variable::CONST); ASSERT(var == NULL || var->mode() != Variable::CONST);
ASSERT(node->op() != Token::INIT_CONST); ASSERT_NE(Token::INIT_CONST, node->op());
if (is_trivial_receiver) { if (is_trivial_receiver) {
Result value = frame()->Pop(); Result value = frame()->Pop();
frame()->Push(prop->obj()); frame()->Push(prop->obj());
frame()->Push(&value); frame()->Push(&value);
} }
CodeForSourcePosition(node->position()); CodeForSourcePosition(node->position());
Result answer = EmitNamedStore(name); bool is_contextual = (var != NULL);
Result answer = EmitNamedStore(name, is_contextual);
frame()->Push(&answer); frame()->Push(&answer);
if (node->ends_initialization_block()) { if (node->ends_initialization_block()) {
ASSERT_EQ(NULL, var);
// The argument to the runtime call is the receiver. // The argument to the runtime call is the receiver.
if (is_trivial_receiver) { if (is_trivial_receiver) {
frame()->Push(prop->obj()); frame()->Push(prop->obj());
...@@ -4851,7 +4864,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { ...@@ -4851,7 +4864,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
} }
ASSERT(frame()->height() == original_height + 1); ASSERT_EQ(frame()->height(), original_height + 1);
} }
...@@ -4861,7 +4874,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) { ...@@ -4861,7 +4874,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
#endif #endif
Comment cmnt(masm_, "[ Named Property Assignment"); Comment cmnt(masm_, "[ Named Property Assignment");
Property* prop = node->target()->AsProperty(); Property* prop = node->target()->AsProperty();
ASSERT(prop != NULL); ASSERT_NOT_NULL(prop);
// Evaluate the receiver subexpression. // Evaluate the receiver subexpression.
Load(prop->obj()); Load(prop->obj());
...@@ -6779,14 +6792,13 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { ...@@ -6779,14 +6792,13 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
} }
Result CodeGenerator::EmitNamedStore(Handle<String> name) { Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
#ifdef DEBUG #ifdef DEBUG
int original_height = frame()->height(); int expected_height = frame()->height() - (is_contextual ? 1 : 2);
#endif #endif
frame()->Push(name); Result result = frame()->CallStoreIC(name, is_contextual);
Result result = frame()->CallStoreIC();
ASSERT(frame()->height() == original_height - 2); ASSERT_EQ(expected_height, frame()->height());
return result; return result;
} }
...@@ -7103,7 +7115,7 @@ void Reference::SetValue(InitState init_state) { ...@@ -7103,7 +7115,7 @@ void Reference::SetValue(InitState init_state) {
case NAMED: { case NAMED: {
Comment cmnt(masm, "[ Store to named Property"); Comment cmnt(masm, "[ Store to named Property");
Result answer = cgen_->EmitNamedStore(GetName()); Result answer = cgen_->EmitNamedStore(GetName(), false);
cgen_->frame()->Push(&answer); cgen_->frame()->Push(&answer);
set_unloaded(); set_unloaded();
break; break;
......
...@@ -438,8 +438,9 @@ class CodeGenerator: public AstVisitor { ...@@ -438,8 +438,9 @@ class CodeGenerator: public AstVisitor {
// Receiver is passed on the frame and consumed. // Receiver is passed on the frame and consumed.
Result EmitNamedLoad(Handle<String> name, bool is_contextual); Result EmitNamedLoad(Handle<String> name, bool is_contextual);
// Reciever and value are passed on the frame and consumed. // If the store is contextual, value is passed on the frame and consumed.
Result EmitNamedStore(Handle<String> name); // 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. // Receiver and key are passed on the frame and consumed.
Result EmitKeyedLoad(); Result EmitKeyedLoad();
......
...@@ -948,47 +948,38 @@ Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) { ...@@ -948,47 +948,38 @@ Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
} }
Result VirtualFrame::CallStoreIC() { Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) {
// Name, value, and receiver are on top of the frame. The IC // Value and (if not contextual) receiver are on top of the frame.
// expects name in ecx, value in eax, and receiver in edx. // The IC expects name in ecx, value in eax, and receiver in edx.
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
Result name = Pop();
Result value = Pop(); Result value = Pop();
Result receiver = Pop(); if (is_contextual) {
PrepareForCall(0, 0); 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);
// Optimized for case in which name is a constant value. if (value.is_register() && value.reg().is(edx)) {
if (name.is_register() && (name.reg().is(edx) || name.reg().is(eax))) { if (receiver.is_register() && receiver.reg().is(eax)) {
if (!is_used(ecx)) { // Wrong registers.
name.ToRegister(ecx); __ xchg(eax, edx);
} else if (!is_used(ebx)) { } else {
name.ToRegister(ebx); // Register eax is free for value, which frees edx for receiver.
} else { value.ToRegister(eax);
ASSERT(!is_used(edi)); // Only three results are live, so edi is free. receiver.ToRegister(edx);
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 { } else {
// Register eax is free for value, which frees edx for receiver. // Register edx is free for receiver, which guarantees eax is free for
value.ToRegister(eax); // value.
receiver.ToRegister(edx); receiver.ToRegister(edx);
value.ToRegister(eax);
} }
} 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. __ mov(ecx, name);
name.ToRegister(ecx);
name.Unuse();
value.Unuse(); value.Unuse();
receiver.Unuse();
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
} }
......
...@@ -339,12 +339,12 @@ class VirtualFrame: public ZoneObject { ...@@ -339,12 +339,12 @@ class VirtualFrame: public ZoneObject {
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
// frame. They are not dropped. // frame. Both are dropped.
Result CallKeyedLoadIC(RelocInfo::Mode mode); Result CallKeyedLoadIC(RelocInfo::Mode mode);
// Call store IC. Name, value, and receiver are found on top of the // Call store IC. If the load is contextual, value is found on top of the
// frame. Receiver is not dropped. // frame. If not, value and receiver are on the frame. Both are dropped.
Result CallStoreIC(); Result CallStoreIC(Handle<String> name, bool is_contextual);
// Call keyed store IC. Value, key, and receiver are found on top // Call keyed store IC. Value, key, and receiver are found on top
// of the frame. Key and receiver are not dropped. // of the frame. Key and receiver are not dropped.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment