Author: [email protected]
Date: Mon Dec 15 07:46:43 2008
New Revision: 980
Modified:
branches/experimental/toiger/src/codegen-ia32.cc
branches/experimental/toiger/src/codegen-ia32.h
branches/experimental/toiger/src/codegen.cc
branches/experimental/toiger/src/virtual-frame-ia32.cc
branches/experimental/toiger/src/virtual-frame-ia32.h
Log:
Experimental: introduce a helper class to delmite a scope where the
virtual frame is expected to be spilled. Add versions of code
generator helper functions that spill the virtual frame before
returning.
This change should preserve semantics (one redundant spill was
removed) and is mostly for documentation purposes. It should make
reading and reviewing the code easier.
Review URL: http://codereview.chromium.org/14423
Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc Mon Dec 15 07:46:43
2008
@@ -86,7 +86,8 @@
is_inside_try_(false),
break_stack_height_(0),
loop_nesting_(0),
- function_return_is_shadowed_(false) {
+ function_return_is_shadowed_(false),
+ in_spilled_code_(false) {
}
@@ -133,6 +134,7 @@
cc_reg_ = no_condition;
function_return_.set_code_generator(this);
function_return_is_shadowed_ = false;
+ set_in_spilled_code(false);
// Adjust for function-level loop nesting.
loop_nesting_ += fun->loop_nesting();
@@ -166,7 +168,7 @@
ASSERT(scope_->arguments_shadow() != NULL);
Comment cmnt(masm_, "[ Allocate arguments object");
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
__ lea(eax, frame_->Receiver());
frame_->EmitPush(frame_->Function());
frame_->EmitPush(eax);
@@ -179,7 +181,7 @@
Comment cmnt(masm_, "[ allocate local context");
// Allocate local context.
// Get outer context and create a new context based on it.
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPush(frame_->Function());
frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the
result
@@ -214,7 +216,7 @@
Variable* par = scope_->parameter(i);
Slot* slot = par->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
ASSERT(!scope_->is_global_scope()); // no parameters in global
scope
__ mov(eax, frame_->ParameterAt(i));
// Loads ecx with context; used below in RecordWrite.
@@ -233,7 +235,7 @@
// initialization because the arguments object may be stored in the
// context.
if (scope_->arguments() != NULL) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ store arguments object");
{ Reference shadow_ref(this, scope_->arguments_shadow());
ASSERT(shadow_ref.is_slot());
@@ -380,6 +382,7 @@
JumpTarget* true_target,
JumpTarget* false_target,
bool force_cc) {
+ ASSERT(!in_spilled_code());
ASSERT(!has_cc());
{ CodeGenState new_state(this, typeof_state, true_target, false_target);
@@ -388,7 +391,7 @@
if (force_cc && frame_ != NULL && !has_cc()) {
// Convert the TOS value to a boolean in the condition code register.
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
ToBoolean(true_target, false_target);
}
@@ -397,13 +400,14 @@
void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
+ ASSERT(!in_spilled_code());
JumpTarget true_target(this);
JumpTarget false_target(this);
LoadCondition(x, typeof_state, &true_target, &false_target, false);
if (has_cc()) {
ASSERT(frame_ != NULL);
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
// Convert cc_reg_ into a boolean value.
JumpTarget loaded(this);
JumpTarget materialize_true(this);
@@ -427,7 +431,7 @@
// Load "true" if necessary.
if (true_target.is_linked()) {
true_target.Bind();
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPush(Immediate(Factory::true_value()));
}
// If both "true" and "false" need to be reincarnated jump across the
@@ -438,7 +442,7 @@
// Load "false" if necessary.
if (false_target.is_linked()) {
false_target.Bind();
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPush(Immediate(Factory::false_value()));
}
// A value is loaded on all paths reaching this point.
@@ -474,11 +478,9 @@
// TODO(1241834): Fetch the position from the variable instead of using
// no position.
Property property(&global, &key, RelocInfo::kNoPosition);
- Load(&property);
- frame_->SpillAll();
+ LoadAndSpill(&property);
} else {
- Load(x, INSIDE_TYPEOF);
- frame_->SpillAll();
+ LoadAndSpill(x, INSIDE_TYPEOF);
}
}
@@ -501,10 +503,10 @@
Variable* var = e->AsVariableProxy()->AsVariable();
if (property != NULL) {
+ VirtualFrame::SpilledScope spilled_scope(this);
// The expression is either a property or a variable proxy that
rewrites
// to a property.
- Load(property->obj());
- frame_->SpillAll();
+ LoadAndSpill(property->obj());
// We use a named reference if the key is a literal symbol, unless it
is
// a string that can be legally parsed as an integer. This is because
// otherwise we will not get into the slow case code that handles [] on
@@ -516,15 +518,14 @@
!String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
ref->set_type(Reference::NAMED);
} else {
- Load(property->key());
- frame_->SpillAll();
+ LoadAndSpill(property->key());
ref->set_type(Reference::KEYED);
}
} else if (var != NULL) {
// 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()) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
LoadGlobal();
ref->set_type(Reference::NAMED);
} else {
@@ -532,9 +533,9 @@
ref->set_type(Reference::SLOT);
}
} else {
+ VirtualFrame::SpilledScope spilled_scope(this);
// Anything else is a runtime error.
- Load(e);
- frame_->SpillAll();
+ LoadAndSpill(e);
frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
}
}
@@ -1269,8 +1270,7 @@
// Push the arguments ("left-to-right") on the stack.
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- Load(args->at(i));
- frame_->SpillAll();
+ LoadAndSpill(args->at(i));
}
// Record the position for debugging purposes.
@@ -1312,6 +1312,7 @@
void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
+ ASSERT(!in_spilled_code());
for (int i = 0; frame_ != NULL && i < statements->length(); i++) {
Visit(statements->at(i));
}
@@ -1319,6 +1320,7 @@
void CodeGenerator::VisitBlock(Block* node) {
+ ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ Block");
RecordStatementPosition(node);
node->set_break_stack_height(break_stack_height_);
@@ -1331,7 +1333,7 @@
void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPush(Immediate(pairs));
frame_->EmitPush(esi);
frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
@@ -1354,7 +1356,7 @@
// during variable resolution and must have mode DYNAMIC.
ASSERT(var->mode() == Variable::DYNAMIC);
// For now, just do a runtime call.
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPush(esi);
frame_->EmitPush(Immediate(var->name()));
// Declaration nodes are always introduced in one of two modes.
@@ -1368,8 +1370,7 @@
if (node->mode() == Variable::CONST) {
frame_->EmitPush(Immediate(Factory::the_hole_value()));
} else if (node->fun() != NULL) {
- Load(node->fun());
- frame_->SpillAll();
+ LoadAndSpill(node->fun());
} else {
frame_->EmitPush(Immediate(0)); // no initial value!
}
@@ -1389,12 +1390,11 @@
}
if (val != NULL) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
// Set initial value.
Reference target(this, node->proxy());
ASSERT(target.is_slot());
- Load(val);
- frame_->SpillAll();
+ LoadAndSpill(val);
target.SetValue(NOT_CONST_INIT);
// Get rid of the assigned value (declarations are statements). It's
// safe to pop the value lying on top of the reference before unloading
@@ -1406,6 +1406,7 @@
void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
+ ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ ExpressionStatement");
RecordStatementPosition(node);
Expression* expression = node->expression();
@@ -1417,14 +1418,16 @@
void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "// EmptyStatement");
// nothing to do
}
void CodeGenerator::VisitIfStatement(IfStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ IfStatement");
// Generate different code depending on which parts of the if statement
// are present or not.
@@ -1437,7 +1440,8 @@
JumpTarget then(this);
JumpTarget else_(this);
// if (cond)
- LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_,
true);
+ LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+ &then, &else_, true);
if (frame_ != NULL) {
// A NULL frame here indicates that the code for the condition cannot
// fall-through, i.e. it causes unconditional branchs to targets.
@@ -1448,14 +1452,13 @@
// If control flow can reach the then part via fall-through from the
// test or a branch to the target, compile it.
then.Bind();
- Visit(node->then_statement());
+ VisitAndSpill(node->then_statement());
}
if (frame_ != NULL) {
// A NULL frame here indicates that control did not fall out of the
// then statement, it escaped on all branches. In that case, a jump
// to the exit label would be dead code (and impossible, because we
// don't have a current virtual frame to set at the exit label).
- frame_->SpillAll();
exit.Jump();
}
// else
@@ -1463,43 +1466,45 @@
// Control flow for if-then-else does not fall-through to the else
// part, it can only reach here via jump if at all.
else_.Bind();
- Visit(node->else_statement());
+ VisitAndSpill(node->else_statement());
}
} else if (has_then_stm) {
ASSERT(!has_else_stm);
JumpTarget then(this);
// if (cond)
- LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit,
true);
+ LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+ &then, &exit, true);
if (frame_ != NULL) {
Branch(false, &exit);
}
// then
if (frame_ != NULL || then.is_linked()) {
then.Bind();
- Visit(node->then_statement());
+ VisitAndSpill(node->then_statement());
}
} else if (has_else_stm) {
ASSERT(!has_then_stm);
JumpTarget else_(this);
// if (!cond)
- LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_,
true);
+ LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+ &exit, &else_, true);
if (frame_ != NULL) {
Branch(true, &exit);
}
// else
if (frame_ != NULL || else_.is_linked()) {
else_.Bind();
- Visit(node->else_statement());
+ VisitAndSpill(node->else_statement());
}
} else {
ASSERT(!has_then_stm && !has_else_stm);
// if (cond)
- LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit,
false);
+ LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+ &exit, &exit, false);
if (frame_ != NULL) {
- frame_->SpillAll();
if (has_cc()) {
cc_reg_ = no_condition;
} else {
@@ -1524,7 +1529,8 @@
void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ ContinueStatement");
RecordStatementPosition(node);
CleanStack(break_stack_height_ - node->target()->break_stack_height());
@@ -1533,7 +1539,8 @@
void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ BreakStatement");
RecordStatementPosition(node);
CleanStack(break_stack_height_ - node->target()->break_stack_height());
@@ -1542,11 +1549,11 @@
void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ ReturnStatement");
RecordStatementPosition(node);
- Load(node->expression());
- frame_->SpillAll();
+ LoadAndSpill(node->expression());
// Move the function result into eax
frame_->EmitPop(eax);
@@ -1583,11 +1590,11 @@
void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ WithEnterStatement");
RecordStatementPosition(node);
- Load(node->expression());
- frame_->SpillAll();
+ LoadAndSpill(node->expression());
frame_->CallRuntime(Runtime::kPushContext, 1);
if (kDebug) {
@@ -1605,7 +1612,8 @@
void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ WithExitStatement");
// Pop context.
__ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX));
@@ -1692,14 +1700,14 @@
void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ SwitchStatement");
RecordStatementPosition(node);
node->set_break_stack_height(break_stack_height_);
node->break_target()->set_code_generator(this);
- Load(node->tag());
- frame_->SpillAll();
+ LoadAndSpill(node->tag());
if (TryGenerateFastCaseSwitchStatement(node)) {
return;
@@ -1728,8 +1736,7 @@
// Duplicate TOS.
__ mov(eax, frame_->Top());
frame_->EmitPush(eax);
- Load(clause->label());
- frame_->SpillAll();
+ LoadAndSpill(clause->label());
Comparison(equal, true);
Branch(false, &next_test);
@@ -1744,12 +1751,11 @@
fall_through.Bind();
fall_through.Unuse();
}
- VisitStatements(clause->statements());
+ VisitStatementsAndSpill(clause->statements());
// If control flow can fall through from the body, jump to the next
body
// or the end of the statement.
if (frame_ != NULL) {
- frame_->SpillAll();
if (i < length - 1 && cases->at(i + 1)->is_default()) {
default_entry.Jump();
} else {
@@ -1766,9 +1772,8 @@
if (default_clause != NULL) {
Comment cmnt(masm_, "[ Default clause");
default_entry.Bind();
- VisitStatements(default_clause->statements());
+ VisitStatementsAndSpill(default_clause->statements());
if (frame_ != NULL) {
- frame_->SpillAll();
}
// If control flow can fall out of the default and there is a case
after
// it, jump to that case's body.
@@ -1788,6 +1793,7 @@
void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
+ ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ LoopStatement");
RecordStatementPosition(node);
node->set_break_stack_height(break_stack_height_);
@@ -1814,7 +1820,7 @@
switch (node->type()) {
case LoopStatement::DO_LOOP: {
// The new code generator does not yet compile do loops.
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
JumpTarget body(this);
IncrementLoopNesting();
// Label the body.
@@ -1827,10 +1833,7 @@
body.Bind();
}
CheckStack(); // TODO(1222600): ignore if body contains calls.
- Visit(node->body());
- if (frame_ != NULL) {
- frame_->SpillAll();
- }
+ VisitAndSpill(node->body());
// Compile the "test".
if (info == ALWAYS_TRUE) {
@@ -1851,8 +1854,8 @@
// control flow falling out of the body or via continue.
if (frame_ != NULL || node->continue_target()->is_linked()) {
node->continue_target()->Bind();
- LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
- &body, node->break_target(), true);
+ LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
+ &body, node->break_target(), true);
if (frame_ != NULL) {
// A NULL frame here indicates that control flow did not fall
// out of the test expression.
@@ -1865,7 +1868,7 @@
case LoopStatement::WHILE_LOOP: {
// The new code generator does not yet compile while loops.
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
JumpTarget body(this);
IncrementLoopNesting();
// Generate the loop header.
@@ -1880,8 +1883,8 @@
// body with the body target.
ASSERT(info == DONT_KNOW);
node->continue_target()->Bind();
- LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
- &body, node->break_target(), true);
+ LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
+ &body, node->break_target(), true);
if (frame_ != NULL) {
// A NULL frame indicates that control did not fall out of the
// test expression.
@@ -1893,11 +1896,10 @@
}
if (frame_ != NULL) {
CheckStack(); // TODO(1222600): ignore if body contains calls.
- Visit(node->body());
+ VisitAndSpill(node->body());
// If control flow can fall out of the body, jump back to the top.
if (frame_ != NULL) {
- frame_->SpillAll();
node->continue_target()->Jump();
}
}
@@ -1975,7 +1977,8 @@
void CodeGenerator::VisitForInStatement(ForInStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ ForInStatement");
RecordStatementPosition(node);
@@ -1997,8 +2000,7 @@
JumpTarget exit(this);
// Get the object to enumerate over (converted to JSObject).
- Load(node->enumerable());
- frame_->SpillAll();
+ LoadAndSpill(node->enumerable());
// Both SpiderMonkey and kjs ignore null and undefined in contrast
// to the specification. 12.6.4 mandates a call to ToObject.
@@ -2140,10 +2142,7 @@
// Body.
CheckStack(); // TODO(1222600): ignore if body contains calls.
- Visit(node->body());
- if (frame_ != NULL) {
- frame_->SpillAll();
- }
+ VisitAndSpill(node->body());
// Next.
node->continue_target()->Bind();
@@ -2165,7 +2164,8 @@
void CodeGenerator::VisitTryCatch(TryCatch* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ TryCatch");
JumpTarget try_block(this);
@@ -2187,9 +2187,8 @@
// Remove the exception from the stack.
frame_->Drop();
- VisitStatements(node->catch_block()->statements());
+ VisitStatementsAndSpill(node->catch_block()->statements());
if (frame_ != NULL) {
- frame_->SpillAll();
exit.Jump();
}
@@ -2219,10 +2218,7 @@
// Generate code for the statements in the try block.
bool was_inside_try = is_inside_try_;
is_inside_try_ = true;
- VisitStatements(node->try_block()->statements());
- if (frame_ != NULL) {
- frame_->SpillAll();
- }
+ VisitStatementsAndSpill(node->try_block()->statements());
is_inside_try_ = was_inside_try;
// Stop the introduced shadowing and count the number of required
unlinks.
@@ -2285,7 +2281,8 @@
void CodeGenerator::VisitTryFinally(TryFinally* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ TryFinally");
// State: Used to keep track of reason for entering the finally
@@ -2330,10 +2327,7 @@
// Generate code for the statements in the try block.
bool was_inside_try = is_inside_try_;
is_inside_try_ = true;
- VisitStatements(node->try_block()->statements());
- if (frame_ != NULL) {
- frame_->SpillAll();
- }
+ VisitStatementsAndSpill(node->try_block()->statements());
is_inside_try_ = was_inside_try;
// Stop the introduced shadowing and count the number of required
unlinks.
@@ -2406,11 +2400,10 @@
break_stack_height_ += kFinallyStackSize;
// Generate code for the statements in the finally block.
- VisitStatements(node->finally_block()->statements());
+ VisitStatementsAndSpill(node->finally_block()->statements());
break_stack_height_ -= kFinallyStackSize;
if (frame_ != NULL) {
- frame_->SpillAll();
JumpTarget exit(this);
// Restore state and return value or faked TOS.
frame_->EmitPop(ecx);
@@ -2440,7 +2433,8 @@
void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
- frame_->SpillAll();
+ ASSERT(!in_spilled_code());
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ DebuggerStatement");
RecordStatementPosition(node);
frame_->CallRuntime(Runtime::kDebugBreak, 0);
@@ -2462,7 +2456,7 @@
void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ FunctionLiteral");
// Build the function boilerplate and instantiate it.
@@ -2475,32 +2469,31 @@
void CodeGenerator::VisitFunctionBoilerplateLiteral(
FunctionBoilerplateLiteral* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
InstantiateBoilerplate(node->boilerplate());
}
void CodeGenerator::VisitConditional(Conditional* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Conditional");
JumpTarget then(this);
JumpTarget else_(this);
JumpTarget exit(this);
- LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
+ LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+ &then, &else_, true);
if (frame_ != NULL) {
Branch(false, &else_);
}
if (frame_ != NULL || then.is_linked()) {
then.Bind();
- Load(node->then_expression(), typeof_state());
- frame_->SpillAll();
+ LoadAndSpill(node->then_expression(), typeof_state());
exit.Jump();
}
if (else_.is_linked()) {
else_.Bind();
- Load(node->else_expression(), typeof_state());
- frame_->SpillAll();
+ LoadAndSpill(node->else_expression(), typeof_state());
}
exit.Bind();
}
@@ -2511,7 +2504,7 @@
ASSERT(slot->var()->mode() == Variable::DYNAMIC);
// For now, just do a runtime call.
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPush(esi);
frame_->EmitPush(Immediate(slot->var()->name()));
@@ -2530,7 +2523,7 @@
// Const slots may contain 'the hole' value (the constant hasn't been
// initialized yet) which needs to be converted into the 'undefined'
// value.
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Load const");
JumpTarget exit(this);
__ mov(eax, SlotOperand(slot, ecx));
@@ -2548,7 +2541,7 @@
// The other remaining slot types (LOOKUP and GLOBAL) cannot reach
// here.
ASSERT(slot->type() == Slot::CONTEXT);
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPush(SlotOperand(slot, ecx));
}
}
@@ -2561,7 +2554,7 @@
ASSERT(slot->var()->mode() == Variable::DYNAMIC);
// For now, just do a runtime call.
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPush(frame_->Context());
frame_->EmitPush(Immediate(slot->var()->name()));
@@ -2599,7 +2592,7 @@
// still contains 'the hole' value). When the assignment is executed,
// the code is identical to a normal store (see below).
Comment cmnt(masm_, "[ Init const");
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
__ mov(eax, SlotOperand(slot, ecx));
__ cmp(eax, Factory::the_hole_value());
exit.Branch(not_equal);
@@ -2619,7 +2612,7 @@
} else {
// The other slot types (LOOKUP and GLOBAL) cannot reach here.
ASSERT(slot->type() == Slot::CONTEXT);
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPop(eax);
__ mov(SlotOperand(slot, ecx), eax);
frame_->EmitPush(eax); // RecordWrite may destroy the value in eax.
@@ -2713,7 +2706,7 @@
void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ RegExp Literal");
RegExpDeferred* deferred = new RegExpDeferred(this, node);
@@ -2774,7 +2767,7 @@
void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ ObjectLiteral");
ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
@@ -2815,8 +2808,7 @@
if (key->IsSymbol()) {
__ mov(eax, frame_->Top());
frame_->EmitPush(eax);
- Load(property->value());
- frame_->SpillAll();
+ LoadAndSpill(property->value());
frame_->EmitPop(eax);
__ Set(ecx, Immediate(key));
frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
@@ -2829,10 +2821,8 @@
case ObjectLiteral::Property::PROTOTYPE: {
__ mov(eax, frame_->Top());
frame_->EmitPush(eax);
- Load(property->key());
- frame_->SpillAll();
- Load(property->value());
- frame_->SpillAll();
+ LoadAndSpill(property->key());
+ LoadAndSpill(property->value());
frame_->CallRuntime(Runtime::kSetProperty, 3);
// Ignore result.
break;
@@ -2842,11 +2832,9 @@
// function will pop the three arguments passed in.
__ mov(eax, frame_->Top());
frame_->EmitPush(eax);
- Load(property->key());
- frame_->SpillAll();
+ LoadAndSpill(property->key());
frame_->EmitPush(Immediate(Smi::FromInt(1)));
- Load(property->value());
- frame_->SpillAll();
+ LoadAndSpill(property->value());
frame_->CallRuntime(Runtime::kDefineAccessor, 4);
// Ignore result.
break;
@@ -2856,11 +2844,9 @@
// function will pop the three arguments passed in.
__ mov(eax, frame_->Top());
frame_->EmitPush(eax);
- Load(property->key());
- frame_->SpillAll();
+ LoadAndSpill(property->key());
frame_->EmitPush(Immediate(Smi::FromInt(0)));
- Load(property->value());
- frame_->SpillAll();
+ LoadAndSpill(property->value());
frame_->CallRuntime(Runtime::kDefineAccessor, 4);
// Ignore result.
break;
@@ -2872,7 +2858,7 @@
void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ ArrayLiteral");
// Call runtime to create the array literal.
@@ -2896,8 +2882,7 @@
// set in the boilerplate object.
if (value->AsLiteral() == NULL) {
// The property must be set by generated code.
- Load(value);
- frame_->SpillAll();
+ LoadAndSpill(value);
// Get the value off the stack.
frame_->EmitPop(eax);
@@ -2942,16 +2927,14 @@
Load(node->value());
} else {
- frame_->SpillAll();
- target.GetValue(NOT_INSIDE_TYPEOF);
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
+ target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
Literal* literal = node->value()->AsLiteral();
if (IsInlineSmi(literal)) {
SmiOperation(node->binary_op(), node->type(), literal->handle(),
false,
NO_OVERWRITE);
} else {
- Load(node->value());
- frame_->SpillAll();
+ LoadAndSpill(node->value());
GenericBinaryOperation(node->binary_op(), node->type());
}
}
@@ -2977,11 +2960,10 @@
void CodeGenerator::VisitThrow(Throw* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Throw");
- Load(node->exception());
- frame_->SpillAll();
+ LoadAndSpill(node->exception());
__ RecordPosition(node->position());
frame_->CallRuntime(Runtime::kThrow, 1);
frame_->EmitPush(eax);
@@ -2989,15 +2971,15 @@
void CodeGenerator::VisitProperty(Property* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Property");
Reference property(this, node);
- property.GetValue(typeof_state());
+ property.GetValueAndSpill(typeof_state());
}
void CodeGenerator::VisitCall(Call* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Call");
ZoneList<Expression*>* args = node->arguments();
@@ -3033,8 +3015,7 @@
// Load the arguments.
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- Load(args->at(i));
- frame_->SpillAll();
+ LoadAndSpill(args->at(i));
}
// Setup the receiver register and call the IC initialization code.
@@ -3079,14 +3060,12 @@
// Push the name of the function and the receiver onto the stack.
frame_->EmitPush(Immediate(literal->handle()));
- Load(property->obj());
- frame_->SpillAll();
+ LoadAndSpill(property->obj());
// Load the arguments.
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- Load(args->at(i));
- frame_->SpillAll();
+ LoadAndSpill(args->at(i));
}
// Call the IC initialization code.
@@ -3107,8 +3086,7 @@
// Load the function to call from the property through a reference.
Reference ref(this, property);
- ref.GetValue(NOT_INSIDE_TYPEOF);
- frame_->SpillAll();
+ ref.GetValueAndSpill(NOT_INSIDE_TYPEOF);
// Pass receiver to called function.
// The reference's size is non-negative.
@@ -3124,8 +3102,7 @@
// ----------------------------------
// Load the function.
- Load(function);
- frame_->SpillAll();
+ LoadAndSpill(function);
// Pass the global proxy as the receiver.
LoadGlobalReceiver(eax);
@@ -3137,7 +3114,7 @@
void CodeGenerator::VisitCallNew(CallNew* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ CallNew");
// According to ECMA-262, section 11.2.2, page 44, the function
@@ -3149,16 +3126,14 @@
// Compute function to call and use the global object as the
// receiver. There is no need to use the global proxy here because
// it will always be replaced with a newly allocated object.
- Load(node->expression());
- frame_->SpillAll();
+ LoadAndSpill(node->expression());
LoadGlobal();
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = node->arguments();
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- Load(args->at(i));
- frame_->SpillAll();
+ LoadAndSpill(args->at(i));
}
// Constructors are called with the number of arguments in register
@@ -3181,7 +3156,7 @@
void CodeGenerator::VisitCallEval(CallEval* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ CallEval");
// In a call to eval, we first call %ResolvePossiblyDirectEval to resolve
@@ -3194,14 +3169,12 @@
RecordStatementPosition(node);
// Prepare stack for call to resolved function.
- Load(function);
- frame_->SpillAll();
+ LoadAndSpill(function);
// Allocate a frame slot for the receiver.
frame_->EmitPush(Immediate(Factory::undefined_value()));
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- Load(args->at(i));
- frame_->SpillAll();
+ LoadAndSpill(args->at(i));
}
// Prepare stack for call to ResolvePossiblyDirectEval.
@@ -3235,8 +3208,7 @@
void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- Load(args->at(0));
- frame_->SpillAll();
+ LoadAndSpill(args->at(0));
frame_->EmitPop(eax);
__ test(eax, Immediate(kSmiTagMask));
cc_reg_ = zero;
@@ -3245,8 +3217,7 @@
void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- Load(args->at(0));
- frame_->SpillAll();
+ LoadAndSpill(args->at(0));
frame_->EmitPop(eax);
__ test(eax, Immediate(kSmiTagMask | 0x80000000));
cc_reg_ = zero;
@@ -3271,10 +3242,8 @@
JumpTarget got_char_code(this);
// Load the string into eax and the index into ebx.
- Load(args->at(0));
- frame_->SpillAll();
- Load(args->at(1));
- frame_->SpillAll();
+ LoadAndSpill(args->at(0));
+ LoadAndSpill(args->at(1));
frame_->EmitPop(ebx);
frame_->EmitPop(eax);
// If the receiver is a smi return undefined.
@@ -3374,8 +3343,7 @@
void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- Load(args->at(0));
- frame_->SpillAll();
+ LoadAndSpill(args->at(0));
JumpTarget answer(this);
// We need the CC bits to come out as not_equal in the case where the
// object is a smi. This can't be done with the usual test opcode so
@@ -3414,8 +3382,7 @@
void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
JumpTarget leave(this);
- Load(args->at(0)); // Load the object.
- frame_->SpillAll();
+ LoadAndSpill(args->at(0)); // Load the object.
__ mov(eax, frame_->Top());
// if (object->IsSmi()) return object.
__ test(eax, Immediate(kSmiTagMask));
@@ -3435,10 +3402,8 @@
void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
JumpTarget leave(this);
- Load(args->at(0)); // Load the object.
- frame_->SpillAll();
- Load(args->at(1)); // Load the value.
- frame_->SpillAll();
+ LoadAndSpill(args->at(0)); // Load the object.
+ LoadAndSpill(args->at(1)); // Load the value.
__ mov(eax, frame_->ElementAt(1));
__ mov(ecx, frame_->Top());
// if (object->IsSmi()) return object.
@@ -3467,8 +3432,7 @@
// Load the key onto the stack and set register eax to the formal
// parameters count for the currently executing function.
- Load(args->at(0));
- frame_->SpillAll();
+ LoadAndSpill(args->at(0));
__ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
// Call the shared stub to get to arguments[key].
@@ -3482,10 +3446,8 @@
ASSERT(args->length() == 2);
// Load the two objects into registers and perform the comparison.
- Load(args->at(0));
- frame_->SpillAll();
- Load(args->at(1));
- frame_->SpillAll();
+ LoadAndSpill(args->at(0));
+ LoadAndSpill(args->at(1));
frame_->EmitPop(eax);
frame_->EmitPop(ecx);
__ cmp(eax, Operand(ecx));
@@ -3494,7 +3456,7 @@
void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
if (CheckForInlineRuntimeCall(node)) {
return;
}
@@ -3514,8 +3476,7 @@
// Push the arguments ("left-to-right").
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- Load(args->at(i));
- frame_->SpillAll();
+ LoadAndSpill(args->at(i));
}
if (function == NULL) {
@@ -3534,7 +3495,7 @@
void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
// Note that because of NOT and an optimization in comparison of a typeof
// expression to a literal string, this function can fail to leave a
value
// on top of the frame or in the cc register.
@@ -3543,17 +3504,15 @@
Token::Value op = node->op();
if (op == Token::NOT) {
- LoadCondition(node->expression(), NOT_INSIDE_TYPEOF,
- false_target(), true_target(), true);
+ LoadConditionAndSpill(node->expression(), NOT_INSIDE_TYPEOF,
+ false_target(), true_target(), true);
cc_reg_ = NegateCondition(cc_reg_);
} else if (op == Token::DELETE) {
Property* property = node->expression()->AsProperty();
if (property != NULL) {
- Load(property->obj());
- frame_->SpillAll();
- Load(property->key());
- frame_->SpillAll();
+ LoadAndSpill(property->obj());
+ LoadAndSpill(property->key());
frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
frame_->EmitPush(eax);
return;
@@ -3588,8 +3547,7 @@
} else {
// Default: Result of deleting expressions is true.
- Load(node->expression()); // may have side-effects
- frame_->SpillAll();
+ LoadAndSpill(node->expression()); // may have side-effects
__ Set(frame_->Top(), Immediate(Factory::true_value()));
}
@@ -3601,8 +3559,7 @@
frame_->EmitPush(eax);
} else {
- Load(node->expression());
- frame_->SpillAll();
+ LoadAndSpill(node->expression());
switch (op) {
case Token::NOT:
case Token::DELETE:
@@ -3751,7 +3708,7 @@
void CodeGenerator::VisitCountOperation(CountOperation* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ CountOperation");
bool is_postfix = node->is_postfix();
@@ -3774,8 +3731,7 @@
}
return;
}
- target.GetValue(NOT_INSIDE_TYPEOF);
- frame_->SpillAll();
+ target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
CountOperationDeferred* deferred =
new CountOperationDeferred(this, is_postfix, is_increment,
@@ -3816,7 +3772,7 @@
void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
// Note that due to an optimization in comparison operations (typeof
// compared to a string literal), we can evaluate a binary expression
such
// as AND or OR and not leave a value on the frame or in the cc register.
@@ -3837,8 +3793,8 @@
if (op == Token::AND) {
JumpTarget is_true(this);
- LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &is_true,
- false_target(), false);
+ LoadConditionAndSpill(node->left(), NOT_INSIDE_TYPEOF,
+ &is_true, false_target(), false);
if (has_cc() || frame_ == NULL) {
if (has_cc()) {
ASSERT(frame_ != NULL);
@@ -3848,11 +3804,10 @@
if (frame_ != NULL || is_true.is_linked()) {
// Evaluate right side expression.
is_true.Bind();
- LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
- false_target(), false);
+ LoadConditionAndSpill(node->right(), NOT_INSIDE_TYPEOF,
+ true_target(), false_target(), false);
}
} else {
- frame_->SpillAll();
// We have a materialized value on the frame.
JumpTarget pop_and_continue(this);
JumpTarget exit(this);
@@ -3873,8 +3828,7 @@
// Evaluate right side expression.
is_true.Bind();
- Load(node->right());
- frame_->SpillAll();
+ LoadAndSpill(node->right());
// Exit (always with a materialized value).
exit.Bind();
@@ -3882,8 +3836,8 @@
} else if (op == Token::OR) {
JumpTarget is_false(this);
- LoadCondition(node->left(), NOT_INSIDE_TYPEOF, true_target(),
- &is_false, false);
+ LoadConditionAndSpill(node->left(), NOT_INSIDE_TYPEOF,
+ true_target(), &is_false, false);
if (has_cc() || frame_ == NULL) {
if (has_cc()) {
ASSERT(frame_ != NULL);
@@ -3893,12 +3847,11 @@
if (frame_ != NULL || is_false.is_linked()) {
// Evaluate right side expression.
is_false.Bind();
- LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
- false_target(), false);
+ LoadConditionAndSpill(node->right(), NOT_INSIDE_TYPEOF,
+ true_target(), false_target(), false);
}
} else {
- frame_->SpillAll();
// We have a materialized value on the frame.
JumpTarget pop_and_continue(this);
JumpTarget exit(this);
@@ -3918,8 +3871,7 @@
// Evaluate right side expression.
is_false.Bind();
- Load(node->right());
- frame_->SpillAll();
+ LoadAndSpill(node->right());
// Exit (always with a materialized value).
exit.Bind();
@@ -3943,20 +3895,16 @@
Literal* rliteral = node->right()->AsLiteral();
if (IsInlineSmi(rliteral)) {
- Load(node->left());
- frame_->SpillAll();
+ LoadAndSpill(node->left());
SmiOperation(node->op(), node->type(), rliteral->handle(), false,
overwrite_mode);
} else if (IsInlineSmi(lliteral)) {
- Load(node->right());
- frame_->SpillAll();
+ LoadAndSpill(node->right());
SmiOperation(node->op(), node->type(), lliteral->handle(), true,
overwrite_mode);
} else {
- Load(node->left());
- frame_->SpillAll();
- Load(node->right());
- frame_->SpillAll();
+ LoadAndSpill(node->left());
+ LoadAndSpill(node->right());
GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
}
}
@@ -3964,7 +3912,7 @@
void CodeGenerator::VisitThisFunction(ThisFunction* node) {
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
frame_->EmitPush(frame_->Function());
}
@@ -4000,9 +3948,8 @@
right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
// The 'null' value can only be equal to 'null' or 'undefined'.
if (left_is_null || right_is_null) {
- frame_->SpillAll();
- Load(left_is_null ? right : left);
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
+ LoadAndSpill(left_is_null ? right : left);
frame_->EmitPop(eax);
__ cmp(eax, Factory::null_value());
@@ -4039,10 +3986,9 @@
right->AsLiteral()->handle()->IsString())) {
Handle<String> check(String::cast(*right->AsLiteral()->handle()));
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
// Load the operand and move it to register edx.
LoadTypeofExpression(operation->expression());
- frame_->SpillAll();
frame_->EmitPop(edx);
if (check->Equals(Heap::number_symbol())) {
@@ -4149,21 +4095,17 @@
cc = greater_equal;
break;
case Token::IN: {
- frame_->SpillAll();
- Load(left);
- frame_->SpillAll();
- Load(right);
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
+ LoadAndSpill(left);
+ LoadAndSpill(right);
frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
frame_->EmitPush(eax); // push the result
return;
}
case Token::INSTANCEOF: {
- frame_->SpillAll();
- Load(left);
- frame_->SpillAll();
- Load(right);
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
+ LoadAndSpill(left);
+ LoadAndSpill(right);
InstanceofStub stub;
frame_->CallStub(&stub, 2);
__ test(eax, Operand(eax));
@@ -4177,9 +4119,7 @@
// Optimize for the case where (at least) one of the expressions
// is a literal small integer.
if (IsInlineSmi(left->AsLiteral())) {
- frame_->SpillAll();
Load(right);
- frame_->SpillAll();
SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(),
strict);
return;
}
@@ -4189,11 +4129,9 @@
return;
}
- frame_->SpillAll();
- Load(left);
- frame_->SpillAll();
- Load(right);
- frame_->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(this);
+ LoadAndSpill(left);
+ LoadAndSpill(right);
Comparison(cc, strict);
}
@@ -4236,6 +4174,7 @@
void Reference::GetValue(TypeofState typeof_state) {
+ ASSERT(!cgen_->in_spilled_code());
ASSERT(!is_illegal());
ASSERT(!cgen_->has_cc());
MacroAssembler* masm = cgen_->masm();
@@ -4255,7 +4194,7 @@
// there is a chance that reference errors can be thrown below, we
// must distinguish between the two kinds of loads (typeof expression
// loads must not throw a reference error).
- frame->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(cgen_);
Comment cmnt(masm, "[ Load from named Property");
Handle<String> name(GetName());
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
@@ -4276,7 +4215,7 @@
case KEYED: {
// TODO(1241834): Make sure that this it is safe to ignore the
// distinction between expressions in a typeof and not in a typeof.
- frame->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(cgen_);
Comment cmnt(masm, "[ Load from keyed Property");
Property* property = expression_->AsProperty();
ASSERT(property != NULL);
@@ -4315,7 +4254,7 @@
}
case NAMED: {
- frame->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(cgen_);
Comment cmnt(masm, "[ Store to named Property");
// Call the appropriate IC code.
Handle<String> name(GetName());
@@ -4330,7 +4269,7 @@
}
case KEYED: {
- frame->SpillAll();
+ VirtualFrame::SpilledScope spilled_scope(cgen_);
Comment cmnt(masm, "[ Store to keyed Property");
Property* property = expression_->AsProperty();
ASSERT(property != NULL);
Modified: branches/experimental/toiger/src/codegen-ia32.h
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.h (original)
+++ branches/experimental/toiger/src/codegen-ia32.h Mon Dec 15 07:46:43 2008
@@ -82,6 +82,11 @@
// the expression stack, and it is left in place with its value above it.
void GetValue(TypeofState typeof_state);
+ // Generate code to push the value of a reference on top of the
expression
+ // stack and then spill the stack frame. This function is used
temporarily while
+ // the code generator is being transformed.
+ inline void GetValueAndSpill(TypeofState typeof_state);
+
// Generate code to store the value on top of the expression stack in the
// reference. The reference is expected to be immediately below the
value
// on the expression stack. The stored value is left in place (with the
@@ -186,6 +191,9 @@
void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
+ bool in_spilled_code() const { return in_spilled_code_; }
+ void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
+
private:
// Construction/Destruction
CodeGenerator(int buffer_size, Handle<Script> script, bool is_eval);
@@ -218,6 +226,32 @@
NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
+ // Visit a statement and then spill the virtual frame if control flow can
+ // reach the end of the statement (ie, it does not exit via break,
+ // continue, return, or throw). This function is used temporarily while
+ // the code generator is being transformed.
+ void VisitAndSpill(Statement* statement) {
+ ASSERT(in_spilled_code());
+ set_in_spilled_code(false);
+ Visit(statement);
+ if (frame_ != NULL) {
+ frame_->SpillAll();
+ }
+ set_in_spilled_code(true);
+ }
+
+ // Visit a list of statements and then spill the virtual frame if control
+ // flow can reach the end of the list.
+ void VisitStatementsAndSpill(ZoneList<Statement*>* statements) {
+ ASSERT(in_spilled_code());
+ set_in_spilled_code(false);
+ VisitStatements(statements);
+ if (frame_ != NULL) {
+ frame_->SpillAll();
+ }
+ set_in_spilled_code(true);
+ }
+
// Main code generation function
void GenCode(FunctionLiteral* fun);
@@ -246,6 +280,36 @@
void LoadGlobal();
void LoadGlobalReceiver(Register scratch);
+ // Generate code to push the value of an expression on top of the frame
+ // and then spill the frame fully to memory. This function is used
+ // temporarily while the code generator is being transformed.
+ void LoadAndSpill(Expression* expression,
+ TypeofState typeof_state = NOT_INSIDE_TYPEOF) {
+ ASSERT(in_spilled_code());
+ set_in_spilled_code(false);
+ Load(expression, typeof_state);
+ frame_->SpillAll();
+ set_in_spilled_code(true);
+ }
+
+ // Call LoadCondition and then spill the virtual frame unless control
flow
+ // cannot reach the end of the expression (ie, by emitting only
+ // unconditional jumps to the control targets).
+ void LoadConditionAndSpill(Expression* expression,
+ TypeofState typeof_state,
+ JumpTarget* true_target,
+ JumpTarget* false_target,
+ bool force_cc) {
+ ASSERT(in_spilled_code());
+ set_in_spilled_code(false);
+ LoadCondition(expression, typeof_state, true_target, false_target,
+ force_cc);
+ if (frame_ != NULL) {
+ frame_->SpillAll();
+ }
+ set_in_spilled_code(true);
+ }
+
// Read a value from a slot and leave it on top of the expression stack.
void LoadFromSlot(Slot* slot, TypeofState typeof_state);
@@ -409,12 +473,27 @@
// to some unlinking code).
bool function_return_is_shadowed_;
+ // True when we are in code that expects the virtual frame to be fully
+ // spilled. Some virtual frame function are disabled in DEBUG builds
when
+ // called from spilled code, because they do not leave the virtual frame
+ // in a spilled state.
+ bool in_spilled_code_;
+
friend class VirtualFrame;
friend class JumpTarget;
friend class Reference;
DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
};
+
+
+void Reference::GetValueAndSpill(TypeofState typeof_state) {
+ ASSERT(cgen_->in_spilled_code());
+ cgen_->set_in_spilled_code(false);
+ GetValue(typeof_state);
+ cgen_->frame()->SpillAll();
+ cgen_->set_in_spilled_code(true);
+}
} } // namespace v8::internal
Modified: branches/experimental/toiger/src/codegen.cc
==============================================================================
--- branches/experimental/toiger/src/codegen.cc (original)
+++ branches/experimental/toiger/src/codegen.cc Mon Dec 15 07:46:43 2008
@@ -413,7 +413,7 @@
for (int i = 0; i < length; i++) {
Comment cmnt(masm(), "[ Case clause");
case_labels[i].Bind();
- VisitStatements(cases->at(i)->statements());
+ VisitStatementsAndSpill(cases->at(i)->statements());
// All of the labels match the same expected frame as the table start.
// If control flow cannot fall off the end of the case statement, we
Modified: branches/experimental/toiger/src/virtual-frame-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-ia32.cc (original)
+++ branches/experimental/toiger/src/virtual-frame-ia32.cc Mon Dec 15
07:46:43 2008
@@ -73,6 +73,20 @@
//
-------------------------------------------------------------------------
// VirtualFrame implementation.
+VirtualFrame::SpilledScope::SpilledScope(CodeGenerator* cgen)
+ : cgen_(cgen),
+ previous_state_(cgen->in_spilled_code()) {
+ ASSERT(cgen->frame() != NULL);
+ cgen->frame()->SpillAll();
+ cgen->set_in_spilled_code(true);
+}
+
+
+VirtualFrame::SpilledScope::~SpilledScope() {
+ cgen_->set_in_spilled_code(previous_state_);
+}
+
+
// On entry to a function, the virtual frame already contains the receiver,
// the parameters, and a return address. All frame elements are in memory.
VirtualFrame::VirtualFrame(CodeGenerator* cgen)
Modified: branches/experimental/toiger/src/virtual-frame-ia32.h
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-ia32.h (original)
+++ branches/experimental/toiger/src/virtual-frame-ia32.h Mon Dec 15
07:46:43 2008
@@ -186,6 +186,22 @@
class VirtualFrame : public Malloced {
public:
+ // A utility class to introduce a scope where the virtual frame is
+ // expected to remain spilled. The constructor spills the code
+ // generator's current frame, but no attempt is made to require it to
stay
+ // stay spilled. It is intended as documentation while the code
generator
+ // is being transformed.
+ class SpilledScope BASE_EMBEDDED {
+ public:
+ explicit SpilledScope(CodeGenerator* cgen);
+
+ ~SpilledScope();
+
+ private:
+ CodeGenerator* cgen_;
+ bool previous_state_;
+ };
+
// Construct an initial virtual frame on entry to a JS function.
explicit VirtualFrame(CodeGenerator* cgen);
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---