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, |