From 59b0bb1e2a3549260b7ea1d05b3e2c291b71104a Mon Sep 17 00:00:00 2001 From: "kasperl@chromium.org" Date: Wed, 25 Aug 2010 08:57:21 +0000 Subject: [PATCH] Improve the code generated by the full codegen by keeping track of the fall-through label and avoiding silly jumps. Review URL: http://codereview.chromium.org/3166033 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5337 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/full-codegen-arm.cc | 127 ++++++++++++++++++++------------------- src/full-codegen.cc | 115 +++++++++++++++++++++++------------ src/full-codegen.h | 15 ++++- src/ia32/full-codegen-ia32.cc | 135 ++++++++++++++++++++++-------------------- src/x64/full-codegen-x64.cc | 132 +++++++++++++++++++++-------------------- 5 files changed, 294 insertions(+), 230 deletions(-) diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 9922be4..e0caa91 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -269,7 +269,7 @@ void FullCodeGenerator::Apply(Expression::Context context, Register reg) { case Expression::kTest: // For simplicity we always test the accumulator register. if (!reg.is(result_register())) __ mov(result_register(), reg); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -332,7 +332,7 @@ void FullCodeGenerator::ApplyTOS(Expression::Context context) { case Expression::kTest: __ pop(result_register()); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -367,31 +367,7 @@ void FullCodeGenerator::DropAndApply(int count, case Expression::kTest: __ Drop(count); if (!reg.is(result_register())) __ mov(result_register(), reg); - DoTest(true_label_, false_label_, NULL); - break; - } -} - -void FullCodeGenerator::PrepareTest(Label* materialize_true, - Label* materialize_false, - Label** if_true, - Label** if_false) { - switch (context_) { - case Expression::kUninitialized: - UNREACHABLE(); - break; - case Expression::kEffect: - // In an effect context, the true and the false case branch to the - // same label. - *if_true = *if_false = materialize_true; - break; - case Expression::kValue: - *if_true = materialize_true; - *if_false = materialize_false; - break; - case Expression::kTest: - *if_true = true_label_; - *if_false = false_label_; + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -462,7 +438,11 @@ void FullCodeGenerator::Apply(Expression::Context context, bool flag) { break; } case Expression::kTest: - __ b(flag ? true_label_ : false_label_); + if (flag) { + if (true_label_ != fall_through_) __ b(true_label_); + } else { + if (false_label_ != fall_through_) __ b(false_label_); + } break; } } @@ -1735,7 +1715,9 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_true); __ b(if_false); @@ -1752,10 +1734,12 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ tst(r0, Operand(kSmiTagMask | 0x80000000)); - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1769,7 +1753,10 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); + __ BranchOnSmi(r0, if_false); __ LoadRoot(ip, Heap::kNullValueRootIndex); __ cmp(r0, ip); @@ -1783,7 +1770,7 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); __ b(lt, if_false); __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); - Split(le, if_true, if_false, NULL); + Split(le, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1797,11 +1784,13 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); - Split(ge, if_true, if_false, NULL); + Split(ge, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1815,13 +1804,15 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); __ tst(r1, Operand(1 << Map::kIsUndetectable)); - Split(ne, if_true, if_false, NULL); + Split(ne, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1837,7 +1828,9 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only // used in a few functions in runtime.js which should not normally be hit by @@ -1855,11 +1848,13 @@ void FullCodeGenerator::EmitIsFunction(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1873,11 +1868,13 @@ void FullCodeGenerator::EmitIsArray(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1891,11 +1888,13 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1908,7 +1907,9 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // Get the frame pointer for the calling frame. __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); @@ -1924,7 +1925,7 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { __ bind(&check_frame_marker); __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1940,11 +1941,13 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ pop(r1); __ cmp(r0, r1); - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -2617,12 +2620,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; + Label* fall_through = NULL; // Notice that the labels are swapped. - PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); - - VisitForControl(expr->expression(), if_true, if_false); - + PrepareTest(&materialize_true, &materialize_false, + &if_false, &if_true, &fall_through); + VisitForControl(expr->expression(), if_true, if_false, fall_through); Apply(context_, if_false, if_true); // Labels swapped. break; } @@ -2979,14 +2982,16 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // First we try a fast inlined version of the compare when one of // the operands is a literal. Token::Value op = expr->op(); Expression* left = expr->left(); Expression* right = expr->right(); - if (TryLiteralCompare(op, left, right, if_true, if_false, NULL)) { + if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { Apply(context_, if_true, if_false); return; } @@ -2998,7 +3003,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { __ InvokeBuiltin(Builtins::IN, CALL_JS); __ LoadRoot(ip, Heap::kTrueValueRootIndex); __ cmp(r0, ip); - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); break; case Token::INSTANCEOF: { @@ -3007,7 +3012,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { __ CallStub(&stub); // The stub returns 0 for true. __ tst(r0, r0); - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); break; } @@ -3062,7 +3067,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0); __ CallStub(&stub); __ cmp(r0, Operand(0)); - Split(cc, if_true, if_false, NULL); + Split(cc, if_true, if_false, fall_through); } } @@ -3077,13 +3082,15 @@ void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); VisitForValue(expr->expression(), kAccumulator); __ LoadRoot(r1, Heap::kNullValueRootIndex); __ cmp(r0, r1); if (expr->is_strict()) { - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); } else { __ b(eq, if_true); __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); @@ -3096,7 +3103,7 @@ void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); __ cmp(r1, Operand(1 << Map::kIsUndetectable)); - Split(eq, if_true, if_false, NULL); + Split(eq, if_true, if_false, fall_through); } Apply(context_, if_true, if_false); } diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 9bbd390..2402fda 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -317,6 +317,33 @@ int FullCodeGenerator::SlotOffset(Slot* slot) { } +void FullCodeGenerator::PrepareTest(Label* materialize_true, + Label* materialize_false, + Label** if_true, + Label** if_false, + Label** fall_through) { + switch (context_) { + case Expression::kUninitialized: + UNREACHABLE(); + break; + case Expression::kEffect: + // In an effect context, the true and the false case branch to the + // same label. + *if_true = *if_false = *fall_through = materialize_true; + break; + case Expression::kValue: + *if_true = *fall_through = materialize_true; + *if_false = materialize_false; + break; + case Expression::kTest: + *if_true = true_label_; + *if_false = false_label_; + *fall_through = fall_through_; + break; + } +} + + void FullCodeGenerator::VisitDeclarations( ZoneList* declarations) { int length = declarations->length(); @@ -521,13 +548,13 @@ void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { case Expression::kUninitialized: UNREACHABLE(); case Expression::kEffect: - VisitForControl(expr->left(), &done, &eval_right); + VisitForControl(expr->left(), &done, &eval_right, &eval_right); break; case Expression::kValue: VisitLogicalForValue(expr->left(), expr->op(), location_, &done); break; case Expression::kTest: - VisitForControl(expr->left(), true_label_, &eval_right); + VisitForControl(expr->left(), true_label_, &eval_right, &eval_right); break; } } else { @@ -536,13 +563,13 @@ void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { case Expression::kUninitialized: UNREACHABLE(); case Expression::kEffect: - VisitForControl(expr->left(), &eval_right, &done); + VisitForControl(expr->left(), &eval_right, &done, &eval_right); break; case Expression::kValue: VisitLogicalForValue(expr->left(), expr->op(), location_, &done); break; case Expression::kTest: - VisitForControl(expr->left(), &eval_right, false_label_); + VisitForControl(expr->left(), &eval_right, false_label_, &eval_right); break; } } @@ -618,16 +645,19 @@ void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) { SetStatementPosition(stmt); Label then_part, else_part, done; - // Do not worry about optimizing for empty then or else bodies. - VisitForControl(stmt->condition(), &then_part, &else_part); - - __ bind(&then_part); - Visit(stmt->then_statement()); - __ jmp(&done); - - __ bind(&else_part); - Visit(stmt->else_statement()); + if (stmt->HasElseStatement()) { + VisitForControl(stmt->condition(), &then_part, &else_part, &then_part); + __ bind(&then_part); + Visit(stmt->then_statement()); + __ jmp(&done); + __ bind(&else_part); + Visit(stmt->else_statement()); + } else { + VisitForControl(stmt->condition(), &then_part, &done, &then_part); + __ bind(&then_part); + Visit(stmt->then_statement()); + } __ bind(&done); } @@ -715,7 +745,7 @@ void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { Comment cmnt(masm_, "[ DoWhileStatement"); SetStatementPosition(stmt); - Label body, stack_limit_hit, stack_check_success; + Label body, stack_limit_hit, stack_check_success, done; Iteration loop_statement(this, stmt); increment_loop_depth(); @@ -727,21 +757,24 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { __ StackLimitCheck(&stack_limit_hit); __ bind(&stack_check_success); + // Record the position of the do while condition and make sure it is + // possible to break on the condition. __ bind(loop_statement.continue_target()); - - // Record the position of the do while condition and make sure it is possible - // to break on the condition. SetExpressionPosition(stmt->cond(), stmt->condition_position()); + VisitForControl(stmt->cond(), + &body, + loop_statement.break_target(), + loop_statement.break_target()); - VisitForControl(stmt->cond(), &body, loop_statement.break_target()); + __ bind(loop_statement.break_target()); + __ jmp(&done); __ bind(&stack_limit_hit); StackCheckStub stack_stub; __ CallStub(&stack_stub); __ jmp(&stack_check_success); - __ bind(loop_statement.break_target()); - + __ bind(&done); decrement_loop_depth(); } @@ -756,24 +789,27 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { // Emit the test at the bottom of the loop. __ jmp(loop_statement.continue_target()); + __ bind(&stack_limit_hit); + StackCheckStub stack_stub; + __ CallStub(&stack_stub); + __ jmp(&stack_check_success); + __ bind(&body); Visit(stmt->body()); - __ bind(loop_statement.continue_target()); - // Emit the statement position here as this is where the while statement code - // starts. + + // Emit the statement position here as this is where the while + // statement code starts. SetStatementPosition(stmt); // Check stack before looping. __ StackLimitCheck(&stack_limit_hit); __ bind(&stack_check_success); - VisitForControl(stmt->cond(), &body, loop_statement.break_target()); - - __ bind(&stack_limit_hit); - StackCheckStub stack_stub; - __ CallStub(&stack_stub); - __ jmp(&stack_check_success); + VisitForControl(stmt->cond(), + &body, + loop_statement.break_target(), + loop_statement.break_target()); __ bind(loop_statement.break_target()); decrement_loop_depth(); @@ -793,6 +829,11 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { // Emit the test at the bottom of the loop (even if empty). __ jmp(&test); + __ bind(&stack_limit_hit); + StackCheckStub stack_stub; + __ CallStub(&stack_stub); + __ jmp(&stack_check_success); + __ bind(&body); Visit(stmt->body()); @@ -804,8 +845,8 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { } __ bind(&test); - // Emit the statement position here as this is where the for statement code - // starts. + // Emit the statement position here as this is where the for + // statement code starts. SetStatementPosition(stmt); // Check stack before looping. @@ -813,16 +854,14 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { __ bind(&stack_check_success); if (stmt->cond() != NULL) { - VisitForControl(stmt->cond(), &body, loop_statement.break_target()); + VisitForControl(stmt->cond(), + &body, + loop_statement.break_target(), + loop_statement.break_target()); } else { __ jmp(&body); } - __ bind(&stack_limit_hit); - StackCheckStub stack_stub; - __ CallStub(&stack_stub); - __ jmp(&stack_check_success); - __ bind(loop_statement.break_target()); decrement_loop_depth(); } @@ -949,7 +988,7 @@ void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { void FullCodeGenerator::VisitConditional(Conditional* expr) { Comment cmnt(masm_, "[ Conditional"); Label true_case, false_case, done; - VisitForControl(expr->condition(), &true_case, &false_case); + VisitForControl(expr->condition(), &true_case, &false_case, &true_case); __ bind(&true_case); SetExpressionPosition(expr->then_expression(), diff --git a/src/full-codegen.h b/src/full-codegen.h index 3ea85f7..8f5f07f 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h @@ -73,7 +73,8 @@ class FullCodeGenerator: public AstVisitor { loop_depth_(0), location_(kStack), true_label_(NULL), - false_label_(NULL) { + false_label_(NULL), + fall_through_(NULL) { } static Handle MakeCode(CompilationInfo* info); @@ -258,7 +259,8 @@ class FullCodeGenerator: public AstVisitor { void PrepareTest(Label* materialize_true, Label* materialize_false, Label** if_true, - Label** if_false); + Label** if_false, + Label** fall_through); // Emit code to convert pure control flow to a pair of labels into the // result expected according to an expression context. @@ -307,17 +309,23 @@ class FullCodeGenerator: public AstVisitor { location_ = saved_location; } - void VisitForControl(Expression* expr, Label* if_true, Label* if_false) { + void VisitForControl(Expression* expr, + Label* if_true, + Label* if_false, + Label* fall_through) { Expression::Context saved_context = context_; Label* saved_true = true_label_; Label* saved_false = false_label_; + Label* saved_fall_through = fall_through_; context_ = Expression::kTest; true_label_ = if_true; false_label_ = if_false; + fall_through_ = fall_through; Visit(expr); context_ = saved_context; true_label_ = saved_true; false_label_ = saved_false; + fall_through_ = saved_fall_through; } void VisitDeclarations(ZoneList* declarations); @@ -459,6 +467,7 @@ class FullCodeGenerator: public AstVisitor { Location location_; Label* true_label_; Label* false_label_; + Label* fall_through_; friend class NestedStatement; diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index a98904d..c00f626 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -246,7 +246,7 @@ void FullCodeGenerator::Apply(Expression::Context context, Register reg) { case Expression::kTest: // For simplicity we always test the accumulator register. if (!reg.is(result_register())) __ mov(result_register(), reg); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -276,7 +276,7 @@ void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { case Expression::kTest: // For simplicity we always test the accumulator register. Move(result_register(), slot); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -304,7 +304,7 @@ void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { case Expression::kTest: // For simplicity we always test the accumulator register. __ mov(result_register(), lit->handle()); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -332,7 +332,7 @@ void FullCodeGenerator::ApplyTOS(Expression::Context context) { case Expression::kTest: // For simplicity we always test the accumulator register. __ pop(result_register()); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -368,32 +368,7 @@ void FullCodeGenerator::DropAndApply(int count, // For simplicity we always test the accumulator register. __ Drop(count); if (!reg.is(result_register())) __ mov(result_register(), reg); - DoTest(true_label_, false_label_, NULL); - break; - } -} - - -void FullCodeGenerator::PrepareTest(Label* materialize_true, - Label* materialize_false, - Label** if_true, - Label** if_false) { - switch (context_) { - case Expression::kUninitialized: - UNREACHABLE(); - break; - case Expression::kEffect: - // In an effect context, the true and the false case branch to the - // same label. - *if_true = *if_false = materialize_true; - break; - case Expression::kValue: - *if_true = materialize_true; - *if_false = materialize_false; - break; - case Expression::kTest: - *if_true = true_label_; - *if_false = false_label_; + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -461,7 +436,11 @@ void FullCodeGenerator::Apply(Expression::Context context, bool flag) { break; } case Expression::kTest: - __ jmp(flag ? true_label_ : false_label_); + if (flag) { + if (true_label_ != fall_through_) __ jmp(true_label_); + } else { + if (false_label_ != fall_through_) __ jmp(false_label_); + } break; } } @@ -1735,10 +1714,12 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ test(eax, Immediate(kSmiTagMask)); - Split(zero, if_true, if_false, NULL); + Split(zero, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1752,10 +1733,12 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ test(eax, Immediate(kSmiTagMask | 0x80000000)); - Split(zero, if_true, if_false, NULL); + Split(zero, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1769,7 +1752,9 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ test(eax, Immediate(kSmiTagMask)); __ j(zero, if_false); @@ -1784,7 +1769,7 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { __ cmp(ecx, FIRST_JS_OBJECT_TYPE); __ j(below, if_false); __ cmp(ecx, LAST_JS_OBJECT_TYPE); - Split(below_equal, if_true, if_false, NULL); + Split(below_equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1798,12 +1783,14 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ test(eax, Immediate(kSmiTagMask)); __ j(equal, if_false); __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx); - Split(above_equal, if_true, if_false, NULL); + Split(above_equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1817,14 +1804,16 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ test(eax, Immediate(kSmiTagMask)); __ j(zero, if_false); __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); __ test(ebx, Immediate(1 << Map::kIsUndetectable)); - Split(not_zero, if_true, if_false, NULL); + Split(not_zero, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1839,7 +1828,9 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only // used in a few functions in runtime.js which should not normally be hit by @@ -1857,12 +1848,14 @@ void FullCodeGenerator::EmitIsFunction(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ test(eax, Immediate(kSmiTagMask)); __ j(zero, if_false); __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1876,12 +1869,14 @@ void FullCodeGenerator::EmitIsArray(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ test(eax, Immediate(kSmiTagMask)); __ j(equal, if_false); __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1895,12 +1890,14 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ test(eax, Immediate(kSmiTagMask)); __ j(equal, if_false); __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1913,7 +1910,9 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // Get the frame pointer for the calling frame. __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); @@ -1929,7 +1928,7 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { __ bind(&check_frame_marker); __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset), Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1945,11 +1944,13 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ pop(ebx); __ cmp(eax, Operand(ebx)); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -2613,15 +2614,15 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { case Token::NOT: { Comment cmnt(masm_, "[ UnaryOperation (NOT)"); + Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - + Label* fall_through = NULL; // Notice that the labels are swapped. - PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); - - VisitForControl(expr->expression(), if_true, if_false); - + PrepareTest(&materialize_true, &materialize_false, + &if_false, &if_true, &fall_through); + VisitForControl(expr->expression(), if_true, if_false, fall_through); Apply(context_, if_false, if_true); // Labels swapped. break; } @@ -2988,14 +2989,16 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // First we try a fast inlined version of the compare when one of // the operands is a literal. Token::Value op = expr->op(); Expression* left = expr->left(); Expression* right = expr->right(); - if (TryLiteralCompare(op, left, right, if_true, if_false, NULL)) { + if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { Apply(context_, if_true, if_false); return; } @@ -3006,7 +3009,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { VisitForValue(expr->right(), kStack); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); __ cmp(eax, Factory::true_value()); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); break; case Token::INSTANCEOF: { @@ -3015,7 +3018,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { __ CallStub(&stub); __ test(eax, Operand(eax)); // The stub returns 0 for true. - Split(zero, if_true, if_false, NULL); + Split(zero, if_true, if_false, fall_through); break; } @@ -3072,7 +3075,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { CompareStub stub(cc, strict); __ CallStub(&stub); __ test(eax, Operand(eax)); - Split(cc, if_true, if_false, NULL); + Split(cc, if_true, if_false, fall_through); } } @@ -3086,12 +3089,14 @@ void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); VisitForValue(expr->expression(), kAccumulator); __ cmp(eax, Factory::null_value()); if (expr->is_strict()) { - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); } else { __ j(equal, if_true); __ cmp(eax, Factory::undefined_value()); @@ -3102,7 +3107,7 @@ void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset)); __ test(edx, Immediate(1 << Map::kIsUndetectable)); - Split(not_zero, if_true, if_false, NULL); + Split(not_zero, if_true, if_false, fall_through); } Apply(context_, if_true, if_false); } diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 559647a..b5f7fe4 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -253,7 +253,7 @@ void FullCodeGenerator::Apply(Expression::Context context, Register reg) { case Expression::kTest: // For simplicity we always test the accumulator register. if (!reg.is(result_register())) __ movq(result_register(), reg); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -282,7 +282,7 @@ void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { case Expression::kTest: Move(result_register(), slot); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -308,7 +308,7 @@ void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { case Expression::kTest: __ Move(result_register(), lit->handle()); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -335,7 +335,7 @@ void FullCodeGenerator::ApplyTOS(Expression::Context context) { case Expression::kTest: __ pop(result_register()); - DoTest(true_label_, false_label_, NULL); + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -370,32 +370,7 @@ void FullCodeGenerator::DropAndApply(int count, case Expression::kTest: __ Drop(count); if (!reg.is(result_register())) __ movq(result_register(), reg); - DoTest(true_label_, false_label_, NULL); - break; - } -} - - -void FullCodeGenerator::PrepareTest(Label* materialize_true, - Label* materialize_false, - Label** if_true, - Label** if_false) { - switch (context_) { - case Expression::kUninitialized: - UNREACHABLE(); - break; - case Expression::kEffect: - // In an effect context, the true and the false case branch to the - // same label. - *if_true = *if_false = materialize_true; - break; - case Expression::kValue: - *if_true = materialize_true; - *if_false = materialize_false; - break; - case Expression::kTest: - *if_true = true_label_; - *if_false = false_label_; + DoTest(true_label_, false_label_, fall_through_); break; } } @@ -463,7 +438,11 @@ void FullCodeGenerator::Apply(Expression::Context context, bool flag) { break; } case Expression::kTest: - __ jmp(flag ? true_label_ : false_label_); + if (flag) { + if (true_label_ != fall_through_) __ jmp(true_label_); + } else { + if (false_label_ != fall_through_) __ jmp(false_label_); + } break; } } @@ -1744,7 +1723,9 @@ void FullCodeGenerator::EmitIsSmi(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ JumpIfSmi(rax, if_true); __ jmp(if_false); @@ -1761,10 +1742,12 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); Condition positive_smi = __ CheckPositiveSmi(rax); - Split(positive_smi, if_true, if_false, NULL); + Split(positive_smi, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1778,7 +1761,9 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ JumpIfSmi(rax, if_false); __ CompareRoot(rax, Heap::kNullValueRootIndex); @@ -1792,7 +1777,7 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); __ j(below, if_false); __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); - Split(below_equal, if_true, if_false, NULL); + Split(below_equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1806,11 +1791,13 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ JumpIfSmi(rax, if_false); __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); - Split(above_equal, if_true, if_false, NULL); + Split(above_equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1824,13 +1811,15 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ JumpIfSmi(rax, if_false); __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); __ testb(FieldOperand(rbx, Map::kBitFieldOffset), Immediate(1 << Map::kIsUndetectable)); - Split(not_zero, if_true, if_false, NULL); + Split(not_zero, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1845,7 +1834,9 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only // used in a few functions in runtime.js which should not normally be hit by @@ -1863,11 +1854,13 @@ void FullCodeGenerator::EmitIsFunction(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ JumpIfSmi(rax, if_false); __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1881,11 +1874,13 @@ void FullCodeGenerator::EmitIsArray(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ JumpIfSmi(rax, if_false); __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1899,11 +1894,13 @@ void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ JumpIfSmi(rax, if_false); __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1916,7 +1913,9 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // Get the frame pointer for the calling frame. __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); @@ -1932,7 +1931,7 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { __ bind(&check_frame_marker); __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), Smi::FromInt(StackFrame::CONSTRUCT)); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -1948,11 +1947,13 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ pop(rbx); __ cmpq(rax, rbx); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); Apply(context_, if_true, if_false); } @@ -2612,12 +2613,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - + Label* fall_through = NULL; // Notice that the labels are swapped. - PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); - - VisitForControl(expr->expression(), if_true, if_false); - + PrepareTest(&materialize_true, &materialize_false, + &if_false, &if_true, &fall_through); + VisitForControl(expr->expression(), if_true, if_false, fall_through); Apply(context_, if_false, if_true); // Labels swapped. break; } @@ -2979,14 +2979,16 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // First we try a fast inlined version of the compare when one of // the operands is a literal. Token::Value op = expr->op(); Expression* left = expr->left(); Expression* right = expr->right(); - if (TryLiteralCompare(op, left, right, if_true, if_false, NULL)) { + if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { Apply(context_, if_true, if_false); return; } @@ -2997,7 +2999,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { VisitForValue(expr->right(), kStack); __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); __ CompareRoot(rax, Heap::kTrueValueRootIndex); - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); break; case Token::INSTANCEOF: { @@ -3006,7 +3008,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { __ CallStub(&stub); __ testq(rax, rax); // The stub returns 0 for true. - Split(zero, if_true, if_false, NULL); + Split(zero, if_true, if_false, fall_through); break; } @@ -3060,7 +3062,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { CompareStub stub(cc, strict); __ CallStub(&stub); __ testq(rax, rax); - Split(cc, if_true, if_false, NULL); + Split(cc, if_true, if_false, fall_through); } } @@ -3075,12 +3077,14 @@ void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; - PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); + Label* fall_through = NULL; + PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); VisitForValue(expr->expression(), kAccumulator); __ CompareRoot(rax, Heap::kNullValueRootIndex); if (expr->is_strict()) { - Split(equal, if_true, if_false, NULL); + Split(equal, if_true, if_false, fall_through); } else { __ j(equal, if_true); __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); @@ -3091,7 +3095,7 @@ void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); __ testb(FieldOperand(rdx, Map::kBitFieldOffset), Immediate(1 << Map::kIsUndetectable)); - Split(not_zero, if_true, if_false, NULL); + Split(not_zero, if_true, if_false, fall_through); } Apply(context_, if_true, if_false); } -- 2.7.4