Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 61496aa8454b6b2ab5fdfe1aca2e7e29bb761626..c3013562ac89e39cfc600fc831e62cbc432d36c8 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -242,7 +242,7 @@ void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) { |
| void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { |
| - if (!predecessors_.is_empty()) { |
| + if (HasPredecessor()) { |
| // Only loop header blocks can have a predecessor added after |
| // instructions have been added to the block (they have phis for all |
| // values in the environment, these phis may be eliminated later). |
| @@ -1808,7 +1808,7 @@ void HGraph::InsertRepresentationChangesForValue( |
| ZoneList<Representation>* to_convert_reps) { |
| Representation r = current->representation(); |
| if (r.IsNone()) return; |
| - if (current->uses()->length() == 0) return; |
| + if (current->uses()->is_empty()) return; |
| // Collect the representation changes in a sorted list. This allows |
| // us to avoid duplicate changes without searching the list. |
| @@ -2076,37 +2076,17 @@ void TestContext::BuildBranch(HValue* value) { |
| // HGraphBuilder infrastructure for bailing out and checking bailouts. |
| -#define BAILOUT(reason) \ |
| - do { \ |
| - Bailout(reason); \ |
| - return; \ |
| - } while (false) |
| - |
| - |
| -#define CHECK_BAILOUT \ |
| +#define CHECK_BAILOUT(call) \ |
| do { \ |
| + call; \ |
| if (HasStackOverflow()) return; \ |
| } while (false) |
| -#define VISIT_FOR_EFFECT(expr) \ |
| - do { \ |
| - VisitForEffect(expr); \ |
| - if (HasStackOverflow()) return; \ |
| - } while (false) |
| - |
| - |
| -#define VISIT_FOR_VALUE(expr) \ |
| - do { \ |
| - VisitForValue(expr); \ |
| - if (HasStackOverflow()) return; \ |
| - } while (false) |
| - |
| - |
| -#define VISIT_FOR_CONTROL(expr, true_block, false_block) \ |
| +#define CHECK_ALIVE(call) \ |
| do { \ |
| - VisitForControl(expr, true_block, false_block); \ |
| - if (HasStackOverflow()) return; \ |
| + call; \ |
| + if (HasStackOverflow() || current_block() == NULL) return; \ |
| } while (false) |
| @@ -2148,7 +2128,7 @@ void HGraphBuilder::VisitForControl(Expression* expr, |
| void HGraphBuilder::VisitArgument(Expression* expr) { |
| - VISIT_FOR_VALUE(expr); |
| + CHECK_ALIVE(VisitForValue(expr)); |
| Push(AddInstruction(new(zone()) HPushArgument(Pop()))); |
| } |
| @@ -2163,7 +2143,7 @@ void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { |
| void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { |
| for (int i = 0; i < exprs->length(); ++i) { |
| - VISIT_FOR_VALUE(exprs->at(i)); |
| + CHECK_ALIVE(VisitForValue(exprs->at(i))); |
| } |
| } |
| @@ -2294,7 +2274,7 @@ HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) { |
| void HGraphBuilder::SetupScope(Scope* scope) { |
| // We don't yet handle the function name for named function expressions. |
| - if (scope->function() != NULL) BAILOUT("named function expression"); |
| + if (scope->function() != NULL) return Bailout("named function expression"); |
|
danno
2011/04/13 12:00:43
I didn't know this actually works, returning the r
Kevin Millikin (Chromium)
2011/04/13 12:23:24
I'm not sure if it's done elsewhere, I can't think
|
| HConstant* undefined_constant = new(zone()) HConstant( |
| isolate()->factory()->undefined_value(), Representation::Tagged()); |
| @@ -2320,7 +2300,7 @@ void HGraphBuilder::SetupScope(Scope* scope) { |
| if (!scope->arguments()->IsStackAllocated() || |
| (scope->arguments_shadow() != NULL && |
| !scope->arguments_shadow()->IsStackAllocated())) { |
| - BAILOUT("context-allocated arguments"); |
| + return Bailout("context-allocated arguments"); |
| } |
| HArgumentsObject* object = new(zone()) HArgumentsObject; |
| AddInstruction(object); |
| @@ -2358,10 +2338,12 @@ HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
| void HGraphBuilder::VisitBlock(Block* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| BreakAndContinueInfo break_info(stmt); |
| { BreakAndContinueScope push(&break_info, this); |
| - VisitStatements(stmt->statements()); |
| - CHECK_BAILOUT; |
| + CHECK_BAILOUT(VisitStatements(stmt->statements())); |
| } |
| HBasicBlock* break_block = break_info.break_block(); |
| if (break_block != NULL) { |
| @@ -2373,15 +2355,24 @@ void HGraphBuilder::VisitBlock(Block* stmt) { |
| void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| VisitForEffect(stmt->expression()); |
| } |
| void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| } |
| void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| if (stmt->condition()->ToBooleanIsTrue()) { |
| AddSimulate(stmt->ThenId()); |
| Visit(stmt->then_statement()); |
| @@ -2391,20 +2382,27 @@ void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
| } else { |
| HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
| HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
| - VISIT_FOR_CONTROL(stmt->condition(), cond_true, cond_false); |
| - cond_true->SetJoinId(stmt->ThenId()); |
| - cond_false->SetJoinId(stmt->ElseId()); |
| + CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); |
| - set_current_block(cond_true); |
| - Visit(stmt->then_statement()); |
| - CHECK_BAILOUT; |
| - HBasicBlock* other = current_block(); |
| + if (cond_true->HasPredecessor()) { |
| + cond_true->SetJoinId(stmt->ThenId()); |
| + set_current_block(cond_true); |
| + CHECK_BAILOUT(Visit(stmt->then_statement())); |
| + cond_true = current_block(); |
| + } else { |
| + cond_true = NULL; |
| + } |
| - set_current_block(cond_false); |
| - Visit(stmt->else_statement()); |
| - CHECK_BAILOUT; |
| + if (cond_false->HasPredecessor()) { |
| + cond_false->SetJoinId(stmt->ElseId()); |
| + set_current_block(cond_false); |
| + CHECK_BAILOUT(Visit(stmt->else_statement())); |
| + cond_false = current_block(); |
| + } else { |
| + cond_false = NULL; |
| + } |
| - HBasicBlock* join = CreateJoin(other, current_block(), stmt->id()); |
| + HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->id()); |
| set_current_block(join); |
| } |
| } |
| @@ -2442,6 +2440,9 @@ HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( |
| void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); |
| current_block()->Goto(continue_block); |
| set_current_block(NULL); |
| @@ -2449,6 +2450,9 @@ void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
| void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); |
| current_block()->Goto(break_block); |
| set_current_block(NULL); |
| @@ -2456,10 +2460,13 @@ void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
| void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| AstContext* context = call_context(); |
| if (context == NULL) { |
| // Not an inlined return, so an actual one. |
| - VISIT_FOR_VALUE(stmt->expression()); |
| + CHECK_ALIVE(VisitForValue(stmt->expression())); |
| HValue* result = environment()->Pop(); |
| current_block()->FinishExit(new(zone()) HReturn(result)); |
| set_current_block(NULL); |
| @@ -2472,11 +2479,11 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| test->if_true(), |
| test->if_false()); |
| } else if (context->IsEffect()) { |
| - VISIT_FOR_EFFECT(stmt->expression()); |
| + CHECK_ALIVE(VisitForEffect(stmt->expression())); |
| current_block()->Goto(function_return(), false); |
| } else { |
| ASSERT(context->IsValue()); |
| - VISIT_FOR_VALUE(stmt->expression()); |
| + CHECK_ALIVE(VisitForValue(stmt->expression())); |
| HValue* return_value = environment()->Pop(); |
| current_block()->AddLeaveInlined(return_value, function_return()); |
| } |
| @@ -2486,26 +2493,35 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { |
| - BAILOUT("WithEnterStatement"); |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + return Bailout("WithEnterStatement"); |
| } |
| void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { |
| - BAILOUT("WithExitStatement"); |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + return Bailout("WithExitStatement"); |
| } |
| void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| // We only optimize switch statements with smi-literal smi comparisons, |
| // with a bounded number of clauses. |
| const int kCaseClauseLimit = 128; |
| ZoneList<CaseClause*>* clauses = stmt->cases(); |
| int clause_count = clauses->length(); |
| if (clause_count > kCaseClauseLimit) { |
| - BAILOUT("SwitchStatement: too many clauses"); |
| + return Bailout("SwitchStatement: too many clauses"); |
| } |
| - VISIT_FOR_VALUE(stmt->tag()); |
| + CHECK_ALIVE(VisitForValue(stmt->tag())); |
| AddSimulate(stmt->EntryId()); |
| HValue* tag_value = Pop(); |
| HBasicBlock* first_test_block = current_block(); |
| @@ -2516,7 +2532,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
| CaseClause* clause = clauses->at(i); |
| if (clause->is_default()) continue; |
| if (!clause->label()->IsSmiLiteral()) { |
| - BAILOUT("SwitchStatement: non-literal switch label"); |
| + return Bailout("SwitchStatement: non-literal switch label"); |
| } |
| // Unconditionally deoptimize on the first non-smi compare. |
| @@ -2528,7 +2544,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
| } |
| // Otherwise generate a compare and branch. |
| - VISIT_FOR_VALUE(clause->label()); |
| + CHECK_ALIVE(VisitForValue(clause->label())); |
| HValue* label_value = Pop(); |
| HCompare* compare = |
| new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); |
| @@ -2590,8 +2606,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
| set_current_block(join); |
| } |
| - VisitStatements(clause->statements()); |
| - CHECK_BAILOUT; |
| + CHECK_BAILOUT(VisitStatements(clause->statements())); |
| fall_through_block = current_block(); |
| } |
| } |
| @@ -2651,6 +2666,9 @@ void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
| void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| ASSERT(current_block() != NULL); |
| PreProcessOsrEntry(stmt); |
| HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| @@ -2659,8 +2677,7 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| BreakAndContinueInfo break_info(stmt); |
| { BreakAndContinueScope push(&break_info, this); |
| - Visit(stmt->body()); |
| - CHECK_BAILOUT; |
| + CHECK_BAILOUT(Visit(stmt->body())); |
| } |
| HBasicBlock* body_exit = |
| JoinContinue(stmt, current_block(), break_info.continue_block()); |
| @@ -2671,9 +2688,17 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| // back edge. |
| body_exit = graph()->CreateBasicBlock(); |
| loop_successor = graph()->CreateBasicBlock(); |
| - VISIT_FOR_CONTROL(stmt->cond(), body_exit, loop_successor); |
| - body_exit->SetJoinId(stmt->BackEdgeId()); |
| - loop_successor->SetJoinId(stmt->ExitId()); |
| + CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor)); |
| + if (body_exit->HasPredecessor()) { |
| + body_exit->SetJoinId(stmt->BackEdgeId()); |
| + } else { |
| + body_exit = NULL; |
| + } |
| + if (loop_successor->HasPredecessor()) { |
| + loop_successor->SetJoinId(stmt->ExitId()); |
| + } else { |
| + loop_successor = NULL; |
| + } |
| } |
| HBasicBlock* loop_exit = CreateLoop(stmt, |
| loop_entry, |
| @@ -2685,6 +2710,9 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| ASSERT(current_block() != NULL); |
| PreProcessOsrEntry(stmt); |
| HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| @@ -2696,16 +2724,22 @@ void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| if (!stmt->cond()->ToBooleanIsTrue()) { |
| HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
| loop_successor = graph()->CreateBasicBlock(); |
| - VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor); |
| - body_entry->SetJoinId(stmt->BodyId()); |
| - loop_successor->SetJoinId(stmt->ExitId()); |
| - set_current_block(body_entry); |
| + CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
| + if (body_entry->HasPredecessor()) { |
| + body_entry->SetJoinId(stmt->BodyId()); |
| + set_current_block(body_entry); |
| + } |
| + if (loop_successor->HasPredecessor()) { |
| + loop_successor->SetJoinId(stmt->ExitId()); |
| + } else { |
| + loop_successor = NULL; |
| + } |
| } |
| BreakAndContinueInfo break_info(stmt); |
| - { BreakAndContinueScope push(&break_info, this); |
| - Visit(stmt->body()); |
| - CHECK_BAILOUT; |
| + if (current_block() != NULL) { |
| + BreakAndContinueScope push(&break_info, this); |
| + CHECK_BAILOUT(Visit(stmt->body())); |
| } |
| HBasicBlock* body_exit = |
| JoinContinue(stmt, current_block(), break_info.continue_block()); |
| @@ -2719,9 +2753,11 @@ void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| if (stmt->init() != NULL) { |
| - Visit(stmt->init()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(Visit(stmt->init())); |
| } |
| ASSERT(current_block() != NULL); |
| PreProcessOsrEntry(stmt); |
| @@ -2733,24 +2769,29 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| if (stmt->cond() != NULL) { |
| HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
| loop_successor = graph()->CreateBasicBlock(); |
| - VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor); |
| - body_entry->SetJoinId(stmt->BodyId()); |
| - loop_successor->SetJoinId(stmt->ExitId()); |
| - set_current_block(body_entry); |
| + CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
| + if (body_entry->HasPredecessor()) { |
| + body_entry->SetJoinId(stmt->BodyId()); |
| + set_current_block(body_entry); |
| + } |
| + if (loop_successor->HasPredecessor()) { |
| + loop_successor->SetJoinId(stmt->ExitId()); |
| + } else { |
| + loop_successor = NULL; |
| + } |
| } |
| BreakAndContinueInfo break_info(stmt); |
| - { BreakAndContinueScope push(&break_info, this); |
| - Visit(stmt->body()); |
| - CHECK_BAILOUT; |
| + if (current_block() != NULL) { |
| + BreakAndContinueScope push(&break_info, this); |
| + CHECK_BAILOUT(Visit(stmt->body())); |
| } |
| HBasicBlock* body_exit = |
| JoinContinue(stmt, current_block(), break_info.continue_block()); |
| if (stmt->next() != NULL && body_exit != NULL) { |
| set_current_block(body_exit); |
| - Visit(stmt->next()); |
| - CHECK_BAILOUT; |
| + CHECK_BAILOUT(Visit(stmt->next())); |
| body_exit = current_block(); |
| } |
| @@ -2764,22 +2805,34 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| - BAILOUT("ForInStatement"); |
| + ASSERT(!HasStackOverflow()); |
|
danno
2011/04/13 12:00:43
Turn these three checks into a single check, like
Kevin Millikin (Chromium)
2011/04/13 12:23:24
OK, I'll do that.
|
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + return Bailout("ForInStatement"); |
| } |
| void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| - BAILOUT("TryCatchStatement"); |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + return Bailout("TryCatchStatement"); |
| } |
| void HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| - BAILOUT("TryFinallyStatement"); |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + return Bailout("TryFinallyStatement"); |
| } |
| void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| - BAILOUT("DebuggerStatement"); |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + return Bailout("DebuggerStatement"); |
| } |
| @@ -2804,13 +2857,17 @@ static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
| void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| Handle<SharedFunctionInfo> shared_info = |
| SearchSharedFunctionInfo(info()->shared_info()->code(), |
| expr); |
| if (shared_info.is_null()) { |
| shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
| } |
| - CHECK_BAILOUT; |
| + // We also have a stack overflow if the recursive compilation did. |
| + if (HasStackOverflow()) return; |
| HFunctionLiteral* instr = |
| new(zone()) HFunctionLiteral(shared_info, expr->pretenure()); |
| ast_context()->ReturnInstruction(instr, expr->id()); |
| @@ -2819,32 +2876,47 @@ void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| void HGraphBuilder::VisitSharedFunctionInfoLiteral( |
| SharedFunctionInfoLiteral* expr) { |
| - BAILOUT("SharedFunctionInfoLiteral"); |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + return Bailout("SharedFunctionInfoLiteral"); |
| } |
| void HGraphBuilder::VisitConditional(Conditional* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
| HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
| - VISIT_FOR_CONTROL(expr->condition(), cond_true, cond_false); |
| - cond_true->SetJoinId(expr->ThenId()); |
| - cond_false->SetJoinId(expr->ElseId()); |
| + CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); |
| // Visit the true and false subexpressions in the same AST context as the |
| // whole expression. |
| - set_current_block(cond_true); |
| - Visit(expr->then_expression()); |
| - CHECK_BAILOUT; |
| - HBasicBlock* other = current_block(); |
| + if (cond_true->HasPredecessor()) { |
| + cond_true->SetJoinId(expr->ThenId()); |
| + set_current_block(cond_true); |
| + CHECK_BAILOUT(Visit(expr->then_expression())); |
| + cond_true = current_block(); |
| + } else { |
| + cond_true = NULL; |
| + } |
| - set_current_block(cond_false); |
| - Visit(expr->else_expression()); |
| - CHECK_BAILOUT; |
| + if (cond_false->HasPredecessor()) { |
| + cond_false->SetJoinId(expr->ElseId()); |
| + set_current_block(cond_false); |
| + CHECK_BAILOUT(Visit(expr->else_expression())); |
| + cond_false = current_block(); |
| + } else { |
| + cond_false = NULL; |
| + } |
| if (!ast_context()->IsTest()) { |
| - HBasicBlock* join = CreateJoin(other, current_block(), expr->id()); |
| + HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
| set_current_block(join); |
| - if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| + if (join != NULL && !ast_context()->IsEffect()) { |
| + ast_context()->ReturnValue(Pop()); |
| + } |
| } |
| } |
| @@ -2881,17 +2953,20 @@ HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
| void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| Variable* variable = expr->AsVariable(); |
| if (variable == NULL) { |
| - BAILOUT("reference to rewritten variable"); |
| + return Bailout("reference to rewritten variable"); |
| } else if (variable->IsStackAllocated()) { |
| if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { |
| - BAILOUT("unsupported context for arguments object"); |
| + return Bailout("unsupported context for arguments object"); |
| } |
| ast_context()->ReturnValue(environment()->Lookup(variable)); |
| } else if (variable->IsContextSlot()) { |
| if (variable->mode() == Variable::CONST) { |
| - BAILOUT("reference to const context slot"); |
| + return Bailout("reference to const context slot"); |
| } |
| HValue* context = BuildContextChainWalk(variable); |
| int index = variable->AsSlot()->index(); |
| @@ -2927,12 +3002,15 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| } else { |
| - BAILOUT("reference to a variable which requires dynamic lookup"); |
| + return Bailout("reference to a variable which requires dynamic lookup"); |
| } |
| } |
| void HGraphBuilder::VisitLiteral(Literal* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| HConstant* instr = |
| new(zone()) HConstant(expr->handle(), Representation::Tagged()); |
| ast_context()->ReturnInstruction(instr, expr->id()); |
| @@ -2940,6 +3018,9 @@ void HGraphBuilder::VisitLiteral(Literal* expr) { |
| void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(), |
| expr->flags(), |
| expr->literal_index()); |
| @@ -2948,6 +3029,9 @@ void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HObjectLiteral* literal = |
| @@ -2977,7 +3061,7 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| case ObjectLiteral::Property::COMPUTED: |
| if (key->handle()->IsSymbol()) { |
| if (property->emit_store()) { |
| - VISIT_FOR_VALUE(value); |
| + CHECK_ALIVE(VisitForValue(value)); |
| HValue* value = Pop(); |
| Handle<String> name = Handle<String>::cast(key->handle()); |
| HStoreNamedGeneric* store = |
| @@ -2990,7 +3074,7 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| AddInstruction(store); |
| AddSimulate(key->id()); |
| } else { |
| - VISIT_FOR_EFFECT(value); |
| + CHECK_ALIVE(VisitForEffect(value)); |
| } |
| break; |
| } |
| @@ -2998,7 +3082,7 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| case ObjectLiteral::Property::PROTOTYPE: |
| case ObjectLiteral::Property::SETTER: |
| case ObjectLiteral::Property::GETTER: |
| - BAILOUT("Object literal with complex property"); |
| + return Bailout("Object literal with complex property"); |
| default: UNREACHABLE(); |
| } |
| } |
| @@ -3019,6 +3103,9 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| ZoneList<Expression*>* subexprs = expr->values(); |
| int length = subexprs->length(); |
| @@ -3038,9 +3125,9 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| // is already set in the cloned array. |
| if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| - VISIT_FOR_VALUE(subexpr); |
| + CHECK_ALIVE(VisitForValue(subexpr)); |
| HValue* value = Pop(); |
| - if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal"); |
| + if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); |
| // Load the elements array before the first store. |
| if (elements == NULL) { |
| @@ -3059,7 +3146,10 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| - BAILOUT("CatchExtensionObject"); |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + return Bailout("CatchExtensionObject"); |
| } |
| @@ -3238,14 +3328,14 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| Property* prop = expr->target()->AsProperty(); |
| ASSERT(prop != NULL); |
| expr->RecordTypeFeedback(oracle()); |
| - VISIT_FOR_VALUE(prop->obj()); |
| + CHECK_ALIVE(VisitForValue(prop->obj())); |
| HValue* value = NULL; |
| HInstruction* instr = NULL; |
| if (prop->key()->IsPropertyName()) { |
| // Named store. |
| - VISIT_FOR_VALUE(expr->value()); |
| + CHECK_ALIVE(VisitForValue(expr->value())); |
| value = Pop(); |
| HValue* object = Pop(); |
| @@ -3269,8 +3359,8 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| } else { |
| // Keyed store. |
| - VISIT_FOR_VALUE(prop->key()); |
| - VISIT_FOR_VALUE(expr->value()); |
| + CHECK_ALIVE(VisitForValue(prop->key())); |
| + CHECK_ALIVE(VisitForValue(expr->value())); |
| value = Pop(); |
| HValue* key = Pop(); |
| HValue* object = Pop(); |
| @@ -3332,7 +3422,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| BinaryOperation* operation = expr->binary_operation(); |
| if (var != NULL) { |
| - VISIT_FOR_VALUE(operation); |
| + CHECK_ALIVE(VisitForValue(operation)); |
| if (var->is_global()) { |
| HandleGlobalVariableAssignment(var, |
| @@ -3349,7 +3439,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| AddInstruction(instr); |
| if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| } else { |
| - BAILOUT("compound assignment to lookup slot"); |
| + return Bailout("compound assignment to lookup slot"); |
| } |
| ast_context()->ReturnValue(Pop()); |
| @@ -3358,7 +3448,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| if (prop->key()->IsPropertyName()) { |
| // Named property. |
| - VISIT_FOR_VALUE(prop->obj()); |
| + CHECK_ALIVE(VisitForValue(prop->obj())); |
| HValue* obj = Top(); |
| HInstruction* load = NULL; |
| @@ -3372,7 +3462,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| PushAndAdd(load); |
| if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); |
| - VISIT_FOR_VALUE(expr->value()); |
| + CHECK_ALIVE(VisitForValue(expr->value())); |
| HValue* right = Pop(); |
| HValue* left = Pop(); |
| @@ -3390,8 +3480,8 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| } else { |
| // Keyed property. |
| - VISIT_FOR_VALUE(prop->obj()); |
| - VISIT_FOR_VALUE(prop->key()); |
| + CHECK_ALIVE(VisitForValue(prop->obj())); |
| + CHECK_ALIVE(VisitForValue(prop->key())); |
| HValue* obj = environment()->ExpressionStackAt(1); |
| HValue* key = environment()->ExpressionStackAt(0); |
| @@ -3399,7 +3489,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| PushAndAdd(load); |
| if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); |
| - VISIT_FOR_VALUE(expr->value()); |
| + CHECK_ALIVE(VisitForValue(expr->value())); |
| HValue* right = Pop(); |
| HValue* left = Pop(); |
| @@ -3418,12 +3508,15 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| } |
| } else { |
| - BAILOUT("invalid lhs in compound assignment"); |
| + return Bailout("invalid lhs in compound assignment"); |
| } |
| } |
| void HGraphBuilder::VisitAssignment(Assignment* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| Variable* var = proxy->AsVariable(); |
| Property* prop = expr->target()->AsProperty(); |
| @@ -3435,7 +3528,7 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) { |
| } |
| if (var != NULL) { |
| - if (proxy->IsArguments()) BAILOUT("assignment to arguments"); |
| + if (proxy->IsArguments()) return Bailout("assignment to arguments"); |
| // Handle the assignment. |
| if (var->IsStackAllocated()) { |
| @@ -3449,14 +3542,14 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) { |
| if (rhs_var != NULL && rhs_var->IsStackAllocated()) { |
| value = environment()->Lookup(rhs_var); |
| } else { |
| - VISIT_FOR_VALUE(expr->value()); |
| + CHECK_ALIVE(VisitForValue(expr->value())); |
| value = Pop(); |
| } |
| Bind(var, value); |
| ast_context()->ReturnValue(value); |
| } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { |
| - VISIT_FOR_VALUE(expr->value()); |
| + CHECK_ALIVE(VisitForValue(expr->value())); |
| HValue* context = BuildContextChainWalk(var); |
| int index = var->AsSlot()->index(); |
| HStoreContextSlot* instr = |
| @@ -3466,7 +3559,7 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) { |
| ast_context()->ReturnValue(Pop()); |
| } else if (var->is_global()) { |
| - VISIT_FOR_VALUE(expr->value()); |
| + CHECK_ALIVE(VisitForValue(expr->value())); |
| HandleGlobalVariableAssignment(var, |
| Top(), |
| expr->position(), |
| @@ -3474,23 +3567,26 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) { |
| ast_context()->ReturnValue(Pop()); |
| } else { |
| - BAILOUT("assignment to LOOKUP or const CONTEXT variable"); |
| + return Bailout("assignment to LOOKUP or const CONTEXT variable"); |
| } |
| } else if (prop != NULL) { |
| HandlePropertyAssignment(expr); |
| } else { |
| - BAILOUT("invalid left-hand side in assignment"); |
| + return Bailout("invalid left-hand side in assignment"); |
| } |
| } |
| void HGraphBuilder::VisitThrow(Throw* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| // We don't optimize functions with invalid left-hand sides in |
| // assignments, count operations, or for-in. Consequently throw can |
| // currently only occur in an effect context. |
| ASSERT(ast_context()->IsEffect()); |
| - VISIT_FOR_VALUE(expr->exception()); |
| + CHECK_ALIVE(VisitForValue(expr->exception())); |
| HValue* value = environment()->Pop(); |
| HThrow* instr = new(zone()) HThrow(value); |
| @@ -3738,7 +3834,7 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) { |
| } else { |
| Push(graph()->GetArgumentsObject()); |
| VisitForValue(expr->key()); |
| - if (HasStackOverflow()) return false; |
| + if (HasStackOverflow() || current_block() == NULL) return true; |
| HValue* key = Pop(); |
| Drop(1); // Arguments object. |
| HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| @@ -3753,12 +3849,14 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) { |
| void HGraphBuilder::VisitProperty(Property* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| expr->RecordTypeFeedback(oracle()); |
| if (TryArgumentsAccess(expr)) return; |
| - CHECK_BAILOUT; |
| - VISIT_FOR_VALUE(expr->obj()); |
| + CHECK_ALIVE(VisitForValue(expr->obj())); |
| HInstruction* instr = NULL; |
| if (expr->IsArrayLength()) { |
| @@ -3777,7 +3875,7 @@ void HGraphBuilder::VisitProperty(Property* expr) { |
| LAST_STRING_TYPE)); |
| instr = new(zone()) HStringLength(string); |
| } else if (expr->IsStringAccess()) { |
| - VISIT_FOR_VALUE(expr->key()); |
| + CHECK_ALIVE(VisitForValue(expr->key())); |
| HValue* index = Pop(); |
| HValue* string = Pop(); |
| HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
| @@ -3804,7 +3902,7 @@ void HGraphBuilder::VisitProperty(Property* expr) { |
| } |
| } else { |
| - VISIT_FOR_VALUE(expr->key()); |
| + CHECK_ALIVE(VisitForValue(expr->key())); |
| HValue* key = Pop(); |
| HValue* obj = Pop(); |
| @@ -3866,9 +3964,6 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
| *name->ToCString()); |
| } |
| if (!FLAG_polymorphic_inlining || !TryInline(expr)) { |
| - // Check for bailout, as trying to inline might fail due to bailout |
| - // during hydrogen processing. |
| - CHECK_BAILOUT; |
| HCallConstantFunction* call = |
| new(zone()) HCallConstantFunction(expr->target(), argument_count); |
| call->set_position(expr->position()); |
| @@ -3908,10 +4003,12 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
| // even without predecessors to the join block, we set it as the exit |
| // block and continue by adding instructions there. |
| ASSERT(join != NULL); |
| - set_current_block(join); |
| if (join->HasPredecessor()) { |
| + set_current_block(join); |
| join->SetJoinId(expr->id()); |
| if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| + } else { |
| + set_current_block(NULL); |
| } |
| } |
| @@ -4083,7 +4180,7 @@ bool HGraphBuilder::TryInline(Call* expr) { |
| // Bail out if the inline function did, as we cannot residualize a call |
| // instead. |
| TraceInline(target, "inline graph construction failed"); |
| - return false; |
| + return true; |
| } |
| // Update inlined nodes count. |
| @@ -4139,9 +4236,11 @@ bool HGraphBuilder::TryInline(Call* expr) { |
| // flow to handle. |
| set_current_block(NULL); |
| - } else { |
| + } else if (function_return()->HasPredecessor()) { |
| function_return()->SetJoinId(expr->id()); |
| set_current_block(function_return()); |
| + } else { |
| + set_current_block(NULL); |
| } |
| return true; |
| @@ -4267,10 +4366,10 @@ bool HGraphBuilder::TryCallApply(Call* expr) { |
| // Found pattern f.apply(receiver, arguments). |
| VisitForValue(prop->obj()); |
| - if (HasStackOverflow()) return false; |
| + if (HasStackOverflow() || current_block() == NULL) return true; |
| HValue* function = Pop(); |
| VisitForValue(args->at(0)); |
| - if (HasStackOverflow()) return false; |
| + if (HasStackOverflow() || current_block() == NULL) return true; |
| HValue* receiver = Pop(); |
| HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
| @@ -4287,6 +4386,9 @@ bool HGraphBuilder::TryCallApply(Call* expr) { |
| void HGraphBuilder::VisitCall(Call* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| Expression* callee = expr->expression(); |
| int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| HInstruction* call = NULL; |
| @@ -4295,17 +4397,16 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| if (prop != NULL) { |
| if (!prop->key()->IsPropertyName()) { |
| // Keyed function call. |
| - VISIT_FOR_VALUE(prop->obj()); |
| + CHECK_ALIVE(VisitForValue(prop->obj())); |
| - VISIT_FOR_VALUE(prop->key()); |
| + CHECK_ALIVE(VisitForValue(prop->key())); |
| // Push receiver and key like the non-optimized code generator expects it. |
| HValue* key = Pop(); |
| HValue* receiver = Pop(); |
| Push(key); |
| Push(receiver); |
| - VisitExpressions(expr->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| @@ -4320,12 +4421,13 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| // Named function call. |
| expr->RecordTypeFeedback(oracle()); |
| - if (TryCallApply(expr)) return; |
| - CHECK_BAILOUT; |
| + if (TryCallApply(expr)) { |
| + ASSERT(current_block() == NULL || current_block()->HasPredecessor()); |
| + return; |
| + } |
| - VISIT_FOR_VALUE(prop->obj()); |
| - VisitExpressions(expr->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitForValue(prop->obj())); |
| + CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| @@ -4341,6 +4443,7 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| receiver, |
| receiver_map, |
| expr->check_type())) { |
| + ASSERT(current_block() == NULL || current_block()->HasPredecessor()); |
| return; |
| } |
| @@ -4357,11 +4460,9 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| AddCheckConstantFunction(expr, receiver, receiver_map, true); |
| if (TryInline(expr)) { |
| + ASSERT(current_block() == NULL || current_block()->HasPredecessor()); |
| return; |
| } else { |
| - // Check for bailout, as the TryInline call in the if condition above |
| - // might return false due to bailout during hydrogen processing. |
| - CHECK_BAILOUT; |
| call = PreProcessCall( |
| new(zone()) HCallConstantFunction(expr->target(), |
| argument_count)); |
| @@ -4370,6 +4471,7 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| } else if (types != NULL && types->length() > 1) { |
| ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
| HandlePolymorphicCallNamed(expr, receiver, types, name); |
| + ASSERT(current_block() == NULL || current_block()->HasPredecessor()); |
| return; |
| } else { |
| @@ -4385,7 +4487,7 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| if (!global_call) { |
| ++argument_count; |
| - VISIT_FOR_VALUE(expr->expression()); |
| + CHECK_ALIVE(VisitForValue(expr->expression())); |
| } |
| if (global_call) { |
| @@ -4407,10 +4509,9 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| AddInstruction(context); |
| PushAndAdd(global_object); |
| - VisitExpressions(expr->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| - VISIT_FOR_VALUE(expr->expression()); |
| + CHECK_ALIVE(VisitForValue(expr->expression())); |
| HValue* function = Pop(); |
| AddInstruction(new(zone()) HCheckFunction(function, expr->target())); |
| @@ -4427,18 +4528,13 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| if (TryInline(expr)) { |
| return; |
| } |
| - // Check for bailout, as trying to inline might fail due to bailout |
| - // during hydrogen processing. |
| - CHECK_BAILOUT; |
| - |
| call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| - argument_count)); |
| + argument_count)); |
| } else { |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| PushAndAdd(new(zone()) HGlobalObject(context)); |
| - VisitExpressions(expr->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| call = PreProcessCall(new(zone()) HCallGlobal(context, |
| var->name(), |
| @@ -4451,24 +4547,26 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| AddInstruction(context); |
| AddInstruction(global_object); |
| PushAndAdd(new(zone()) HGlobalReceiver(global_object)); |
| - VisitExpressions(expr->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); |
| } |
| } |
| call->set_position(expr->position()); |
| + ASSERT(current_block() == NULL || current_block()->HasPredecessor()); |
| ast_context()->ReturnInstruction(call, expr->id()); |
| } |
| void HGraphBuilder::VisitCallNew(CallNew* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| // The constructor function is also used as the receiver argument to the |
| // JS construct call builtin. |
| - VISIT_FOR_VALUE(expr->expression()); |
| - VisitExpressions(expr->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitForValue(expr->expression())); |
| + CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| @@ -4500,8 +4598,11 @@ const HGraphBuilder::InlineFunctionGenerator |
| void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| if (expr->is_jsruntime()) { |
| - BAILOUT("call to a JavaScript runtime function"); |
| + return Bailout("call to a JavaScript runtime function"); |
| } |
| const Runtime::Function* function = expr->function(); |
| @@ -4521,8 +4622,7 @@ void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| (this->*generator)(expr); |
| } else { |
| ASSERT(function->intrinsic_type == Runtime::RUNTIME); |
| - VisitArgumentList(expr->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| Handle<String> name = expr->name(); |
| int argument_count = expr->arguments()->length(); |
| @@ -4536,9 +4636,12 @@ void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| Token::Value op = expr->op(); |
| if (op == Token::VOID) { |
| - VISIT_FOR_EFFECT(expr->expression()); |
| + CHECK_ALIVE(VisitForEffect(expr->expression())); |
| ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| } else if (op == Token::DELETE) { |
| Property* prop = expr->expression()->AsProperty(); |
| @@ -4546,7 +4649,7 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| if (prop == NULL && var == NULL) { |
| // Result of deleting non-property, non-variable reference is true. |
| // Evaluate the subexpression for side effects. |
| - VISIT_FOR_EFFECT(expr->expression()); |
| + CHECK_ALIVE(VisitForEffect(expr->expression())); |
| ast_context()->ReturnValue(graph()->GetConstantTrue()); |
| } else if (var != NULL && |
| !var->is_global() && |
| @@ -4561,17 +4664,17 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| // to accesses on the arguments object. |
| ast_context()->ReturnValue(graph()->GetConstantFalse()); |
| } else { |
| - VISIT_FOR_VALUE(prop->obj()); |
| - VISIT_FOR_VALUE(prop->key()); |
| + CHECK_ALIVE(VisitForValue(prop->obj())); |
| + CHECK_ALIVE(VisitForValue(prop->key())); |
| HValue* key = Pop(); |
| HValue* obj = Pop(); |
| HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); |
| ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| } else if (var->is_global()) { |
| - BAILOUT("delete with global variable"); |
| + return Bailout("delete with global variable"); |
| } else { |
| - BAILOUT("delete with non-global variable"); |
| + return Bailout("delete with non-global variable"); |
| } |
| } else if (op == Token::NOT) { |
| if (ast_context()->IsTest()) { |
| @@ -4582,21 +4685,30 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| } else if (ast_context()->IsValue()) { |
| HBasicBlock* materialize_false = graph()->CreateBasicBlock(); |
| HBasicBlock* materialize_true = graph()->CreateBasicBlock(); |
| - VISIT_FOR_CONTROL(expr->expression(), |
| - materialize_false, |
| - materialize_true); |
| - materialize_false->SetJoinId(expr->expression()->id()); |
| - materialize_true->SetJoinId(expr->expression()->id()); |
| + CHECK_BAILOUT(VisitForControl(expr->expression(), |
| + materialize_false, |
| + materialize_true)); |
| + |
| + if (materialize_false->HasPredecessor()) { |
| + materialize_false->SetJoinId(expr->expression()->id()); |
| + set_current_block(materialize_false); |
| + Push(graph()->GetConstantFalse()); |
| + } else { |
| + materialize_false = NULL; |
| + } |
| - set_current_block(materialize_false); |
| - Push(graph()->GetConstantFalse()); |
| - set_current_block(materialize_true); |
| - Push(graph()->GetConstantTrue()); |
| + if (materialize_true->HasPredecessor()) { |
| + materialize_true->SetJoinId(expr->expression()->id()); |
| + set_current_block(materialize_true); |
| + Push(graph()->GetConstantTrue()); |
| + } else { |
| + materialize_true = NULL; |
| + } |
| HBasicBlock* join = |
| CreateJoin(materialize_false, materialize_true, expr->id()); |
| set_current_block(join); |
| - ast_context()->ReturnValue(Pop()); |
| + if (join != NULL) ast_context()->ReturnValue(Pop()); |
| } else { |
| ASSERT(ast_context()->IsEffect()); |
| VisitForEffect(expr->expression()); |
| @@ -4604,12 +4716,12 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| } else if (op == Token::TYPEOF) { |
| VisitForTypeOf(expr->expression()); |
|
fschneider
2011/04/13 11:20:16
CHECK_ALIVE(VisitForTypeOf(expr->expression()));
|
| - if (HasStackOverflow()) return; |
| + if (HasStackOverflow() || current_block() == NULL) return; |
| HValue* value = Pop(); |
| ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id()); |
| } else { |
| - VISIT_FOR_VALUE(expr->expression()); |
| + CHECK_ALIVE(VisitForValue(expr->expression())); |
| HValue* value = Pop(); |
| HInstruction* instr = NULL; |
| switch (op) { |
| @@ -4623,7 +4735,7 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| instr = new(zone()) HMul(value, graph_->GetConstant1()); |
| break; |
| default: |
| - BAILOUT("Value: unsupported unary operation"); |
| + return Bailout("Value: unsupported unary operation"); |
| break; |
| } |
| ast_context()->ReturnInstruction(instr, expr->id()); |
| @@ -4642,6 +4754,9 @@ HInstruction* HGraphBuilder::BuildIncrement(HValue* value, bool increment) { |
| void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| Expression* target = expr->expression(); |
| VariableProxy* proxy = target->AsVariableProxy(); |
| Variable* var = proxy->AsVariable(); |
| @@ -4650,7 +4765,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| bool inc = expr->op() == Token::INC; |
| if (var != NULL) { |
| - VISIT_FOR_VALUE(target); |
| + CHECK_ALIVE(VisitForValue(target)); |
| // Match the full code generator stack by simulating an extra stack |
| // element for postfix operations in a non-effect context. |
| @@ -4675,7 +4790,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| AddInstruction(instr); |
| if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| } else { |
| - BAILOUT("lookup variable in count operation"); |
| + return Bailout("lookup variable in count operation"); |
| } |
| Drop(has_extra ? 2 : 1); |
| ast_context()->ReturnValue(expr->is_postfix() ? before : after); |
| @@ -4691,7 +4806,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); |
| if (has_extra) Push(graph_->GetConstantUndefined()); |
| - VISIT_FOR_VALUE(prop->obj()); |
| + CHECK_ALIVE(VisitForValue(prop->obj())); |
| HValue* obj = Top(); |
| HInstruction* load = NULL; |
| @@ -4732,8 +4847,8 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); |
| if (has_extra) Push(graph_->GetConstantUndefined()); |
| - VISIT_FOR_VALUE(prop->obj()); |
| - VISIT_FOR_VALUE(prop->key()); |
| + CHECK_ALIVE(VisitForValue(prop->obj())); |
| + CHECK_ALIVE(VisitForValue(prop->key())); |
| HValue* obj = environment()->ExpressionStackAt(1); |
| HValue* key = environment()->ExpressionStackAt(0); |
| @@ -4764,7 +4879,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| } |
| } else { |
| - BAILOUT("invalid lhs in count operation"); |
| + return Bailout("invalid lhs in count operation"); |
| } |
| } |
| @@ -4859,8 +4974,11 @@ static bool IsClassOfTest(CompareOperation* expr) { |
| void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| if (expr->op() == Token::COMMA) { |
| - VISIT_FOR_EFFECT(expr->left()); |
| + CHECK_ALIVE(VisitForEffect(expr->left())); |
| // Visit the right subexpression in the same AST context as the entire |
| // expression. |
| Visit(expr->right()); |
| @@ -4872,19 +4990,25 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| // Translate left subexpression. |
| HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| if (is_logical_and) { |
| - VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false()); |
| + CHECK_BAILOUT(VisitForControl(expr->left(), |
| + eval_right, |
| + context->if_false())); |
| } else { |
| - VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right); |
| + CHECK_BAILOUT(VisitForControl(expr->left(), |
| + context->if_true(), |
| + eval_right)); |
| } |
| - eval_right->SetJoinId(expr->RightId()); |
| // Translate right subexpression by visiting it in the same AST |
| // context as the entire expression. |
| - set_current_block(eval_right); |
| - Visit(expr->right()); |
| + if (eval_right->HasPredecessor()) { |
| + eval_right->SetJoinId(expr->RightId()); |
| + set_current_block(eval_right); |
| + Visit(expr->right()); |
| + } |
| } else if (ast_context()->IsValue()) { |
| - VISIT_FOR_VALUE(expr->left()); |
| + CHECK_ALIVE(VisitForValue(expr->left())); |
| ASSERT(current_block() != NULL); |
| // We need an extra block to maintain edge-split form. |
| @@ -4897,7 +5021,7 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| set_current_block(eval_right); |
| Drop(1); // Value of the left subexpression. |
| - VISIT_FOR_VALUE(expr->right()); |
| + CHECK_BAILOUT(VisitForValue(expr->right())); |
| HBasicBlock* join_block = |
| CreateJoin(empty_block, current_block(), expr->id()); |
| @@ -4911,33 +5035,42 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| // extra block to maintain edge-split form. |
| HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
| HBasicBlock* right_block = graph()->CreateBasicBlock(); |
| - HBasicBlock* join_block = graph()->CreateBasicBlock(); |
| if (is_logical_and) { |
| - VISIT_FOR_CONTROL(expr->left(), right_block, empty_block); |
| + CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); |
| } else { |
| - VISIT_FOR_CONTROL(expr->left(), empty_block, right_block); |
| + CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block)); |
| } |
| + |
| // TODO(kmillikin): Find a way to fix this. It's ugly that there are |
| // actually two empty blocks (one here and one inserted by |
| // TestContext::BuildBranch, and that they both have an HSimulate |
| // though the second one is not a merge node, and that we really have |
| // no good AST ID to put on that first HSimulate. |
| - empty_block->SetJoinId(expr->id()); |
| - right_block->SetJoinId(expr->RightId()); |
| - set_current_block(right_block); |
| - VISIT_FOR_EFFECT(expr->right()); |
| - |
| - empty_block->Goto(join_block); |
| - current_block()->Goto(join_block); |
| - join_block->SetJoinId(expr->id()); |
| + if (empty_block->HasPredecessor()) { |
| + empty_block->SetJoinId(expr->id()); |
| + } else { |
| + empty_block = NULL; |
| + } |
| + |
| + if (right_block->HasPredecessor()) { |
| + right_block->SetJoinId(expr->RightId()); |
| + set_current_block(right_block); |
| + CHECK_BAILOUT(VisitForEffect(expr->right())); |
| + right_block = current_block(); |
| + } else { |
| + right_block = NULL; |
| + } |
| + |
| + HBasicBlock* join_block = |
| + CreateJoin(empty_block, right_block, expr->id()); |
| set_current_block(join_block); |
| // We did not materialize any value in the predecessor environments, |
| // so there is no need to handle it here. |
| } |
| } else { |
| - VISIT_FOR_VALUE(expr->left()); |
| - VISIT_FOR_VALUE(expr->right()); |
| + CHECK_ALIVE(VisitForValue(expr->left())); |
| + CHECK_ALIVE(VisitForValue(expr->right())); |
| HValue* right = Pop(); |
| HValue* left = Pop(); |
| @@ -4976,9 +5109,12 @@ Representation HGraphBuilder::ToRepresentation(TypeInfo info) { |
| void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| if (IsClassOfTest(expr)) { |
| CallRuntime* call = expr->left()->AsCallRuntime(); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| Literal* literal = expr->right()->AsLiteral(); |
| Handle<String> rhs = Handle<String>::cast(literal->handle()); |
| @@ -4995,7 +5131,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| left_unary != NULL && left_unary->op() == Token::TYPEOF && |
| right_literal != NULL && right_literal->handle()->IsString()) { |
| VisitForTypeOf(left_unary->expression()); |
|
fschneider
2011/04/13 11:20:16
CHECK_ALIVE(left_unary->expression());
|
| - if (HasStackOverflow()) return; |
| + if (HasStackOverflow() || current_block() == NULL) return; |
| HValue* left = Pop(); |
| HInstruction* instr = new(zone()) HTypeofIs(left, |
| Handle<String>::cast(right_literal->handle())); |
| @@ -5004,8 +5140,8 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| return; |
| } |
| - VISIT_FOR_VALUE(expr->left()); |
| - VISIT_FOR_VALUE(expr->right()); |
| + CHECK_ALIVE(VisitForValue(expr->left())); |
| + CHECK_ALIVE(VisitForValue(expr->right())); |
| HValue* right = Pop(); |
| HValue* left = Pop(); |
| @@ -5050,7 +5186,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| instr = new(zone()) HInstanceOfKnownGlobal(left, target); |
| } |
| } else if (op == Token::IN) { |
| - BAILOUT("Unsupported comparison: in"); |
| + return Bailout("Unsupported comparison: in"); |
| } else if (type_info.IsNonPrimitive()) { |
| switch (op) { |
| case Token::EQ: |
| @@ -5063,7 +5199,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| break; |
| } |
| default: |
| - BAILOUT("Unsupported non-primitive compare"); |
| + return Bailout("Unsupported non-primitive compare"); |
| break; |
| } |
| } else { |
| @@ -5078,7 +5214,10 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { |
| - VISIT_FOR_VALUE(expr->expression()); |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + CHECK_ALIVE(VisitForValue(expr->expression())); |
| HValue* value = Pop(); |
| HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict()); |
| @@ -5087,7 +5226,10 @@ void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { |
| void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| - BAILOUT("ThisFunction"); |
| + ASSERT(!HasStackOverflow()); |
| + ASSERT(current_block() != NULL); |
| + ASSERT(current_block()->HasPredecessor()); |
| + return Bailout("ThisFunction"); |
| } |
| @@ -5102,7 +5244,7 @@ void HGraphBuilder::VisitDeclaration(Declaration* decl) { |
| (slot != NULL && slot->type() == Slot::LOOKUP) || |
| decl->mode() == Variable::CONST || |
| decl->fun() != NULL) { |
| - BAILOUT("unsupported declaration"); |
| + return Bailout("unsupported declaration"); |
| } |
| } |
| @@ -5111,7 +5253,7 @@ void HGraphBuilder::VisitDeclaration(Declaration* decl) { |
| // Support for types. |
| void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HIsSmi* result = new(zone()) HIsSmi(value); |
| ast_context()->ReturnInstruction(result, call->id()); |
| @@ -5120,7 +5262,7 @@ void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
| void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HHasInstanceType* result = |
| new(zone()) HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); |
| @@ -5130,7 +5272,7 @@ void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
| void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HHasInstanceType* result = |
| new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE); |
| @@ -5140,7 +5282,7 @@ void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
| void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value); |
| ast_context()->ReturnInstruction(result, call->id()); |
| @@ -5149,7 +5291,7 @@ void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { |
| void HGraphBuilder::GenerateIsArray(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE); |
| ast_context()->ReturnInstruction(result, call->id()); |
| @@ -5158,7 +5300,7 @@ void HGraphBuilder::GenerateIsArray(CallRuntime* call) { |
| void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HHasInstanceType* result = |
| new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE); |
| @@ -5168,7 +5310,7 @@ void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { |
| void HGraphBuilder::GenerateIsObject(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HIsObject* test = new(zone()) HIsObject(value); |
| ast_context()->ReturnInstruction(test, call->id()); |
| @@ -5176,18 +5318,19 @@ void HGraphBuilder::GenerateIsObject(CallRuntime* call) { |
| void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: IsNonNegativeSmi"); |
| + return Bailout("inlined runtime function: IsNonNegativeSmi"); |
| } |
| void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: IsUndetectableObject"); |
| + return Bailout("inlined runtime function: IsUndetectableObject"); |
| } |
| void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
| CallRuntime* call) { |
| - BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
| + return Bailout( |
| + "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
| } |
| @@ -5216,7 +5359,7 @@ void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
| void HGraphBuilder::GenerateArguments(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* index = Pop(); |
| HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
| @@ -5230,13 +5373,13 @@ void HGraphBuilder::GenerateArguments(CallRuntime* call) { |
| void HGraphBuilder::GenerateClassOf(CallRuntime* call) { |
| // The special form detected by IsClassOfTest is detected before we get here |
| // and does not cause a bailout. |
| - BAILOUT("inlined runtime function: ClassOf"); |
| + return Bailout("inlined runtime function: ClassOf"); |
| } |
| void HGraphBuilder::GenerateValueOf(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HValueOf* result = new(zone()) HValueOf(value); |
| ast_context()->ReturnInstruction(result, call->id()); |
| @@ -5244,15 +5387,15 @@ void HGraphBuilder::GenerateValueOf(CallRuntime* call) { |
| void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: SetValueOf"); |
| + return Bailout("inlined runtime function: SetValueOf"); |
| } |
| // Fast support for charCodeAt(n). |
| void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 2); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| - VISIT_FOR_VALUE(call->arguments()->at(1)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| HValue* index = Pop(); |
| HValue* string = Pop(); |
| HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); |
| @@ -5263,7 +5406,7 @@ void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
| // Fast support for string.charAt(n) and string[n]. |
| void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* char_code = Pop(); |
| HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); |
| ast_context()->ReturnInstruction(result, call->id()); |
| @@ -5273,8 +5416,8 @@ void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
| // Fast support for string.charAt(n) and string[n]. |
| void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 2); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| - VISIT_FOR_VALUE(call->arguments()->at(1)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| HValue* index = Pop(); |
| HValue* string = Pop(); |
| HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
| @@ -5287,8 +5430,8 @@ void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
| // Fast support for object equality testing. |
| void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 2); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| - VISIT_FOR_VALUE(call->arguments()->at(1)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| HValue* right = Pop(); |
| HValue* left = Pop(); |
| HCompareJSObjectEq* result = new(zone()) HCompareJSObjectEq(left, right); |
| @@ -5304,15 +5447,14 @@ void HGraphBuilder::GenerateLog(CallRuntime* call) { |
| // Fast support for Math.random(). |
| void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: RandomHeapNumber"); |
| + return Bailout("inlined runtime function: RandomHeapNumber"); |
| } |
| // Fast support for StringAdd. |
| void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| ASSERT_EQ(2, call->arguments()->length()); |
| - VisitArgumentList(call->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); |
| @@ -5324,8 +5466,7 @@ void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| // Fast support for SubString. |
| void HGraphBuilder::GenerateSubString(CallRuntime* call) { |
| ASSERT_EQ(3, call->arguments()->length()); |
| - VisitArgumentList(call->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
| @@ -5337,8 +5478,7 @@ void HGraphBuilder::GenerateSubString(CallRuntime* call) { |
| // Fast support for StringCompare. |
| void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
| ASSERT_EQ(2, call->arguments()->length()); |
| - VisitArgumentList(call->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HCallStub* result = |
| @@ -5351,8 +5491,7 @@ void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
| // Support for direct calls from JavaScript to native RegExp code. |
| void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
| ASSERT_EQ(4, call->arguments()->length()); |
| - VisitArgumentList(call->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
| @@ -5364,8 +5503,7 @@ void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
| // Construct a RegExp exec result with two in-object properties. |
| void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
| ASSERT_EQ(3, call->arguments()->length()); |
| - VisitArgumentList(call->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HCallStub* result = |
| @@ -5377,15 +5515,14 @@ void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
| // Support for fast native caches. |
| void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: GetFromCache"); |
| + return Bailout("inlined runtime function: GetFromCache"); |
| } |
| // Fast support for number to string. |
| void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| ASSERT_EQ(1, call->arguments()->length()); |
| - VisitArgumentList(call->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HCallStub* result = |
| @@ -5399,21 +5536,21 @@ void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| // indices. This should only be used if the indices are known to be |
| // non-negative and within bounds of the elements array at the call site. |
| void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: SwapElements"); |
| + return Bailout("inlined runtime function: SwapElements"); |
| } |
| // Fast call for custom callbacks. |
| void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: CallFunction"); |
| + return Bailout("inlined runtime function: CallFunction"); |
| } |
| // Fast call to math functions. |
| void HGraphBuilder::GenerateMathPow(CallRuntime* call) { |
| ASSERT_EQ(2, call->arguments()->length()); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| - VISIT_FOR_VALUE(call->arguments()->at(1)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| HValue* right = Pop(); |
| HValue* left = Pop(); |
| HPower* result = new(zone()) HPower(left, right); |
| @@ -5423,8 +5560,7 @@ void HGraphBuilder::GenerateMathPow(CallRuntime* call) { |
| void HGraphBuilder::GenerateMathSin(CallRuntime* call) { |
| ASSERT_EQ(1, call->arguments()->length()); |
| - VisitArgumentList(call->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HCallStub* result = |
| @@ -5437,8 +5573,7 @@ void HGraphBuilder::GenerateMathSin(CallRuntime* call) { |
| void HGraphBuilder::GenerateMathCos(CallRuntime* call) { |
| ASSERT_EQ(1, call->arguments()->length()); |
| - VisitArgumentList(call->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HCallStub* result = |
| @@ -5451,8 +5586,7 @@ void HGraphBuilder::GenerateMathCos(CallRuntime* call) { |
| void HGraphBuilder::GenerateMathLog(CallRuntime* call) { |
| ASSERT_EQ(1, call->arguments()->length()); |
| - VisitArgumentList(call->arguments()); |
| - CHECK_BAILOUT; |
| + CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| HContext* context = new(zone()) HContext; |
| AddInstruction(context); |
| HCallStub* result = |
| @@ -5464,19 +5598,19 @@ void HGraphBuilder::GenerateMathLog(CallRuntime* call) { |
| void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: MathSqrt"); |
| + return Bailout("inlined runtime function: MathSqrt"); |
| } |
| // Check whether two RegExps are equivalent |
| void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: IsRegExpEquivalent"); |
| + return Bailout("inlined runtime function: IsRegExpEquivalent"); |
| } |
| void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
| ASSERT(call->arguments()->length() == 1); |
| - VISIT_FOR_VALUE(call->arguments()->at(0)); |
| + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
| ast_context()->ReturnInstruction(result, call->id()); |
| @@ -5484,15 +5618,12 @@ void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
| void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
| - BAILOUT("inlined runtime function: FastAsciiArrayJoin"); |
| + return Bailout("inlined runtime function: FastAsciiArrayJoin"); |
| } |
| -#undef BAILOUT |
| #undef CHECK_BAILOUT |
| -#undef VISIT_FOR_EFFECT |
| -#undef VISIT_FOR_VALUE |
| -#undef ADD_TO_SUBGRAPH |
| +#undef CHECK_ALIVE |
| HEnvironment::HEnvironment(HEnvironment* outer, |