| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 61496aa8454b6b2ab5fdfe1aca2e7e29bb761626..ba602e50523d474be901f807b674ca9468cfb110 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,22 +2128,21 @@ void HGraphBuilder::VisitForControl(Expression* expr,
|
|
|
|
|
| void HGraphBuilder::VisitArgument(Expression* expr) {
|
| - VISIT_FOR_VALUE(expr);
|
| + CHECK_ALIVE(VisitForValue(expr));
|
| Push(AddInstruction(new(zone()) HPushArgument(Pop())));
|
| }
|
|
|
|
|
| void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
|
| for (int i = 0; i < arguments->length(); i++) {
|
| - VisitArgument(arguments->at(i));
|
| - if (HasStackOverflow() || current_block() == NULL) return;
|
| + CHECK_ALIVE(VisitArgument(arguments->at(i)));
|
| }
|
| }
|
|
|
|
|
| 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 +2273,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");
|
|
|
| HConstant* undefined_constant = new(zone()) HConstant(
|
| isolate()->factory()->undefined_value(), Representation::Tagged());
|
| @@ -2320,7 +2299,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);
|
| @@ -2335,8 +2314,7 @@ void HGraphBuilder::SetupScope(Scope* scope) {
|
|
|
| void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
|
| for (int i = 0; i < statements->length(); i++) {
|
| - Visit(statements->at(i));
|
| - if (HasStackOverflow() || current_block() == NULL) break;
|
| + CHECK_ALIVE(Visit(statements->at(i)));
|
| }
|
| }
|
|
|
| @@ -2358,10 +2336,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 +2353,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 +2380,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 +2438,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 +2448,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 +2458,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 +2477,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 +2491,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 +2530,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 +2542,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 +2604,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 +2664,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 +2675,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 +2686,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 +2708,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 +2722,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 +2751,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 +2767,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 +2803,34 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
|
|
|
|
|
| void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
| - BAILOUT("ForInStatement");
|
| + ASSERT(!HasStackOverflow());
|
| + 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 +2855,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 +2874,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 +2951,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 +3000,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 +3016,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 +3027,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 +3059,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 +3072,7 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
| AddInstruction(store);
|
| AddSimulate(key->id());
|
| } else {
|
| - VISIT_FOR_EFFECT(value);
|
| + CHECK_ALIVE(VisitForEffect(value));
|
| }
|
| break;
|
| }
|
| @@ -2998,7 +3080,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 +3101,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 +3123,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 +3144,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 +3326,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 +3357,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 +3420,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 +3437,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 +3446,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 +3460,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 +3478,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 +3487,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 +3506,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 +3526,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 +3540,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 +3557,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 +3565,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 +3832,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 +3847,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 +3873,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 +3900,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 +3962,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 +4001,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 +4178,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 +4234,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 +4364,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 +4384,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 +4395,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);
|
| @@ -4321,11 +4420,9 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
| expr->RecordTypeFeedback(oracle());
|
|
|
| if (TryCallApply(expr)) return;
|
| - CHECK_BAILOUT;
|
|
|
| - 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();
|
|
|
| @@ -4356,20 +4453,14 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
| } else {
|
| AddCheckConstantFunction(expr, receiver, receiver_map, true);
|
|
|
| - if (TryInline(expr)) {
|
| - 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));
|
| - }
|
| + if (TryInline(expr)) return;
|
| + call = PreProcessCall(
|
| + new(zone()) HCallConstantFunction(expr->target(),
|
| + argument_count));
|
| }
|
| } else if (types != NULL && types->length() > 1) {
|
| ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
|
| - HandlePolymorphicCallNamed(expr, receiver, types, name);
|
| + HandlePolymorphicCallNamed(expr, receiver, types, name)
|
| return;
|
|
|
| } else {
|
| @@ -4385,7 +4476,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 +4498,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 +4517,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,8 +4536,7 @@ 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));
|
| }
|
| @@ -4464,11 +4548,13 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
|
|
|
|
| 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 +4586,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 +4610,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 +4624,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 +4637,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 +4652,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,34 +4673,42 @@ 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());
|
| }
|
|
|
| } else if (op == Token::TYPEOF) {
|
| - VisitForTypeOf(expr->expression());
|
| - if (HasStackOverflow()) return;
|
| + CHECK_ALIVE(VisitForTypeOf(expr->expression()));
|
| 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 +4722,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 +4741,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 +4752,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 +4777,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 +4793,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 +4834,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 +4866,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| }
|
|
|
| } else {
|
| - BAILOUT("invalid lhs in count operation");
|
| + return Bailout("invalid lhs in count operation");
|
| }
|
| }
|
|
|
| @@ -4859,8 +4961,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 +4977,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 +5008,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 +5022,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 +5096,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());
|
| @@ -4994,8 +5117,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) &&
|
| left_unary != NULL && left_unary->op() == Token::TYPEOF &&
|
| right_literal != NULL && right_literal->handle()->IsString()) {
|
| - VisitForTypeOf(left_unary->expression());
|
| - if (HasStackOverflow()) return;
|
| + CHECK_ALIVE(VisitForTypeOf(left_unary->expression()));
|
| HValue* left = Pop();
|
| HInstruction* instr = new(zone()) HTypeofIs(left,
|
| Handle<String>::cast(right_literal->handle()));
|
| @@ -5004,8 +5126,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 +5172,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 +5185,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| break;
|
| }
|
| default:
|
| - BAILOUT("Unsupported non-primitive compare");
|
| + return Bailout("Unsupported non-primitive compare");
|
| break;
|
| }
|
| } else {
|
| @@ -5078,7 +5200,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 +5212,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 +5230,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 +5239,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 +5248,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 +5258,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 +5268,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 +5277,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 +5286,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 +5296,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 +5304,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 +5345,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 +5359,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 +5373,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 +5392,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 +5402,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 +5416,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 +5433,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 +5452,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 +5464,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 +5477,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 +5489,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 +5501,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 +5522,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 +5546,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 +5559,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 +5572,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 +5584,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 +5604,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,
|
|
|