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) {
// 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 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
// 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 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
// 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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
}
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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
// 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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
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) {
#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::EmitNamedLoad(Handle<String> name, bool is_contextual) {
}
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();
Result result = frame()->CallStoreIC(name, is_contextual);
ASSERT(frame()->height() == original_height - 2);
ASSERT_EQ(expected_height, frame()->height());
return result;
}
......@@ -7103,7 +7115,7 @@ void Reference::SetValue(InitState init_state) {
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;
......
......@@ -438,8 +438,9 @@ class CodeGenerator: public AstVisitor {
// 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();
......
......@@ -948,47 +948,38 @@ Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
}
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);
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);
// 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);
} 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);
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 {
// 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);
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.
name.ToRegister(ecx);
name.Unuse();
__ mov(ecx, name);
value.Unuse();
receiver.Unuse();
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
}
......
......@@ -339,12 +339,12 @@ class VirtualFrame: public ZoneObject {
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.
......
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