diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc index 9902894f05..8d9052a2ed 100644 --- a/src/codegen-arm.cc +++ b/src/codegen-arm.cc @@ -284,7 +284,11 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { DeleteFrame(); // Process any deferred code using the register allocator. - ProcessDeferred(); + if (HasStackOverflow()) { + ClearDeferred(); + } else { + ProcessDeferred(); + } allocator_ = NULL; scope_ = NULL; @@ -1133,6 +1137,7 @@ void CodeGenerator::VisitBlock(Block* node) { if (node->break_target()->is_linked()) { node->break_target()->Bind(); } + node->break_target()->Unuse(); ASSERT(!has_valid_frame() || frame_->height() == original_height); } @@ -1594,6 +1599,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { if (node->break_target()->is_linked()) { node->break_target()->Bind(); } + node->break_target()->Unuse(); ASSERT(!has_valid_frame() || frame_->height() == original_height); } @@ -1781,6 +1787,8 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { if (node->break_target()->is_linked()) { node->break_target()->Bind(); } + node->continue_target()->Unuse(); + node->break_target()->Unuse(); ASSERT(!has_valid_frame() || frame_->height() == original_height); } @@ -1971,6 +1979,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { // Exit. exit.Bind(); + node->continue_target()->Unuse(); + node->break_target()->Unuse(); ASSERT(frame_->height() == original_height); } diff --git a/src/codegen-arm.h b/src/codegen-arm.h index e648141b9e..29fe2d4f47 100644 --- a/src/codegen-arm.h +++ b/src/codegen-arm.h @@ -195,6 +195,8 @@ class CodeGenerator: public AstVisitor { // Accessors Scope* scope() const { return scope_; } + // Clearing and generating deferred code. + void ClearDeferred(); void ProcessDeferred(); bool is_eval() { return is_eval_; } diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc index ec5813bb4b..f13af68008 100644 --- a/src/codegen-ia32.cc +++ b/src/codegen-ia32.cc @@ -307,7 +307,11 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { DeleteFrame(); // Process any deferred code using the register allocator. - ProcessDeferred(); + if (HasStackOverflow()) { + ClearDeferred(); + } else { + ProcessDeferred(); + } // There is no need to delete the register allocator, it is a // stack-allocated local. @@ -1567,6 +1571,7 @@ void CodeGenerator::VisitBlock(Block* node) { if (node->break_target()->is_linked()) { node->break_target()->Bind(); } + node->break_target()->Unuse(); } @@ -2094,37 +2099,39 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { // There are two ways to reach the body: from the corresponding // test or as the fall through of the previous body. - if (!clause->body_target()->is_linked() && !has_valid_frame()) { - // If we have neither, skip this body. - continue; - } else if (clause->body_target()->is_linked() && has_valid_frame()) { - // If we have both, put a jump on the fall through path to avoid - // the dropping of the switch value on the test path. The - // exception is the default which has already had the switch - // value dropped. - if (clause->is_default()) { - clause->body_target()->Bind(); + if (clause->body_target()->is_linked() || has_valid_frame()) { + if (clause->body_target()->is_linked()) { + if (has_valid_frame()) { + // If we have both a jump to the test and a fall through, put + // a jump on the fall through path to avoid the dropping of + // the switch value on the test path. The exception is the + // default which has already had the switch value dropped. + if (clause->is_default()) { + clause->body_target()->Bind(); + } else { + JumpTarget body(this); + body.Jump(); + clause->body_target()->Bind(); + frame_->Drop(); + body.Bind(); + } + } else { + // No fall through to worry about. + clause->body_target()->Bind(); + if (!clause->is_default()) { + frame_->Drop(); + } + } } else { - JumpTarget body(this); - body.Jump(); - clause->body_target()->Bind(); - frame_->Drop(); - body.Bind(); + // Otherwise, we have only fall through. + ASSERT(has_valid_frame()); } - } else if (clause->body_target()->is_linked()) { - // No fall through to worry about. - clause->body_target()->Bind(); - if (!clause->is_default()) { - frame_->Drop(); - } - } else { - // Otherwise, we have only fall through. - ASSERT(has_valid_frame()); - } - // We are now prepared to compile the body. - Comment cmnt(masm_, "[ Case body"); - VisitStatements(clause->statements()); + // We are now prepared to compile the body. + Comment cmnt(masm_, "[ Case body"); + VisitStatements(clause->statements()); + } + clause->body_target()->Unuse(); } // We may not have a valid frame here so bind the break target only @@ -2132,6 +2139,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { if (node->break_target()->is_linked()) { node->break_target()->Bind(); } + node->break_target()->Unuse(); } @@ -2452,6 +2460,8 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { } DecrementLoopNesting(); + node->continue_target()->Unuse(); + node->break_target()->Unuse(); } @@ -2636,6 +2646,9 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { // Exit. exit.Bind(); + + node->continue_target()->Unuse(); + node->break_target()->Unuse(); } diff --git a/src/codegen-ia32.h b/src/codegen-ia32.h index af248d9673..dfa59788eb 100644 --- a/src/codegen-ia32.h +++ b/src/codegen-ia32.h @@ -340,6 +340,8 @@ class CodeGenerator: public AstVisitor { // Accessors Scope* scope() const { return scope_; } + // Clearing and generating deferred code. + void ClearDeferred(); void ProcessDeferred(); bool is_eval() { return is_eval_; } diff --git a/src/codegen.cc b/src/codegen.cc index f43e01ce14..558e854850 100644 --- a/src/codegen.cc +++ b/src/codegen.cc @@ -53,6 +53,13 @@ DeferredCode::DeferredCode(CodeGenerator* generator) } +void CodeGenerator::ClearDeferred() { + for (int i = 0; i < deferred_.length(); i++) { + deferred_[i]->Clear(); + } +} + + void CodeGenerator::ProcessDeferred() { while (!deferred_.is_empty()) { DeferredCode* code = deferred_.RemoveLast(); @@ -66,6 +73,7 @@ void CodeGenerator::ProcessDeferred() { Comment cmnt(masm, code->comment()); code->Generate(); ASSERT(code->enter()->is_bound()); + code->Clear(); } } diff --git a/src/codegen.h b/src/codegen.h index 1bfebdc36f..3086638fc5 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -52,6 +52,7 @@ // CodeGenerator::CodeGenerator // CodeGenerator::~CodeGenerator // CodeGenerator::ProcessDeferred +// CodeGenerator::ClearDeferred // CodeGenerator::GenCode // CodeGenerator::BuildBoilerplate // CodeGenerator::ComputeCallInitialize @@ -92,6 +93,14 @@ class DeferredCode: public ZoneObject { virtual void Generate() = 0; + // Unuse the entry and exit targets, deallocating all virtual frames + // held by them. It will be impossible to emit a (correct) jump + // into or out of the deferred code after clearing. + void Clear() { + enter_.Unuse(); + exit_.Unuse(); + } + MacroAssembler* masm() const { return masm_; } CodeGenerator* generator() const { return generator_; }