| Index: runtime/vm/intermediate_language_x64.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_x64.cc (revision 30153)
|
| +++ runtime/vm/intermediate_language_x64.cc (working copy)
|
| @@ -410,20 +410,19 @@
|
|
|
|
|
| static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
|
| - TargetEntryInstr* true_successor,
|
| - TargetEntryInstr* false_successor,
|
| - Condition true_condition) {
|
| - if (compiler->CanFallThroughTo(false_successor)) {
|
| + Condition true_condition,
|
| + BranchLabels labels) {
|
| + if (labels.fall_through == labels.false_label) {
|
| // If the next block is the false successor, fall through to it.
|
| - __ j(true_condition, compiler->GetJumpLabel(true_successor));
|
| + __ j(true_condition, labels.true_label);
|
| } else {
|
| // If the next block is not the false successor, branch to it.
|
| Condition false_condition = NegateCondition(true_condition);
|
| - __ j(false_condition, compiler->GetJumpLabel(false_successor));
|
| + __ j(false_condition, labels.false_label);
|
|
|
| // Fall through or jump to the true successor.
|
| - if (!compiler->CanFallThroughTo(true_successor)) {
|
| - __ jmp(compiler->GetJumpLabel(true_successor));
|
| + if (labels.fall_through != labels.true_label) {
|
| + __ jmp(labels.true_label);
|
| }
|
| }
|
| }
|
| @@ -432,7 +431,7 @@
|
| static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
|
| const LocationSummary& locs,
|
| Token::Kind kind,
|
| - BranchInstr* branch) {
|
| + BranchLabels labels) {
|
| Location left = locs.in(0);
|
| Location right = locs.in(1);
|
| ASSERT(!left.IsConstant() || !right.IsConstant());
|
| @@ -449,22 +448,7 @@
|
| } else {
|
| __ cmpq(left.reg(), right.reg());
|
| }
|
| -
|
| - if (branch != NULL) {
|
| - EmitBranchOnCondition(compiler,
|
| - branch->true_successor(),
|
| - branch->false_successor(),
|
| - true_condition);
|
| - } else {
|
| - Register result = locs.out().reg();
|
| - Label done, is_true;
|
| - __ j(true_condition, &is_true);
|
| - __ LoadObject(result, Bool::False(), PP);
|
| - __ jmp(&done);
|
| - __ Bind(&is_true);
|
| - __ LoadObject(result, Bool::True(), PP);
|
| - __ Bind(&done);
|
| - }
|
| + EmitBranchOnCondition(compiler, true_condition, labels);
|
| }
|
|
|
|
|
| @@ -483,87 +467,58 @@
|
| }
|
|
|
|
|
| -static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler,
|
| - Condition true_condition,
|
| - FpuRegister left,
|
| - FpuRegister right,
|
| - BranchInstr* branch) {
|
| - ASSERT(branch != NULL);
|
| - __ comisd(left, right);
|
| - BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ?
|
| - branch->true_successor() : branch->false_successor();
|
| - __ j(PARITY_EVEN, compiler->GetJumpLabel(nan_result));
|
| - EmitBranchOnCondition(compiler,
|
| - branch->true_successor(),
|
| - branch->false_successor(),
|
| - true_condition);
|
| -}
|
| -
|
| -
|
| -static void EmitDoubleCompareBool(FlowGraphCompiler* compiler,
|
| - Condition true_condition,
|
| - FpuRegister left,
|
| - FpuRegister right,
|
| - Register result) {
|
| - __ comisd(left, right);
|
| - Label is_false, is_true, done;
|
| - // x == NaN -> false, x != NaN -> true.
|
| - Label* nan_label = (true_condition == NOT_EQUAL) ? &is_true : &is_false;
|
| - __ j(PARITY_EVEN, nan_label, Assembler::kNearJump);
|
| - __ j(true_condition, &is_true, Assembler::kNearJump);
|
| - __ Bind(&is_false);
|
| - __ LoadObject(result, Bool::False(), PP);
|
| - __ jmp(&done);
|
| - __ Bind(&is_true);
|
| - __ LoadObject(result, Bool::True(), PP);
|
| - __ Bind(&done);
|
| -}
|
| -
|
| -
|
| static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
|
| const LocationSummary& locs,
|
| Token::Kind kind,
|
| - BranchInstr* branch) {
|
| + BranchLabels labels) {
|
| XmmRegister left = locs.in(0).fpu_reg();
|
| XmmRegister right = locs.in(1).fpu_reg();
|
|
|
| + __ comisd(left, right);
|
| +
|
| Condition true_condition = TokenKindToDoubleCondition(kind);
|
| - if (branch != NULL) {
|
| - EmitDoubleCompareBranch(compiler, true_condition, left, right, branch);
|
| - } else {
|
| - EmitDoubleCompareBool(compiler, true_condition,
|
| - left, right, locs.out().reg());
|
| - }
|
| + Label* nan_result = (true_condition == NOT_EQUAL)
|
| + ? labels.true_label : labels.false_label;
|
| + __ j(PARITY_EVEN, nan_result);
|
| + EmitBranchOnCondition(compiler, true_condition, labels);
|
| }
|
|
|
|
|
| void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
|
| - BranchInstr* kNoBranch = NULL;
|
| +
|
| + Label is_true, is_false;
|
| + BranchLabels labels = { &is_true, &is_false, &is_false };
|
| +
|
| if (operation_cid() == kSmiCid) {
|
| - EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
|
| - return;
|
| + EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
|
| + } else {
|
| + ASSERT(operation_cid() == kDoubleCid);
|
| + EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
|
| }
|
| - if (operation_cid() == kDoubleCid) {
|
| - EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
|
| - return;
|
| - }
|
| - UNREACHABLE();
|
| + Register result = locs()->out().reg();
|
| + Label done;
|
| + __ Bind(&is_false);
|
| + __ LoadObject(result, Bool::False(), PP);
|
| + __ jmp(&done);
|
| + __ Bind(&is_true);
|
| + __ LoadObject(result, Bool::True(), PP);
|
| + __ Bind(&done);
|
| }
|
|
|
|
|
| void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
| BranchInstr* branch) {
|
| ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
| +
|
| + BranchLabels labels = compiler->CreateBranchLabels(branch);
|
| +
|
| if (operation_cid() == kSmiCid) {
|
| - EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
|
| - return;
|
| + EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
|
| + } else {
|
| + ASSERT(operation_cid() == kDoubleCid);
|
| + EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
|
| }
|
| - if (operation_cid() == kDoubleCid) {
|
| - EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
|
| - return;
|
| - }
|
| - UNREACHABLE();
|
| }
|
|
|
|
|
| @@ -588,6 +543,8 @@
|
|
|
| void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
| BranchInstr* branch) {
|
| + BranchLabels labels = compiler->CreateBranchLabels(branch);
|
| +
|
| Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
|
| Register left_reg = locs()->in(0).reg();
|
| Location right = locs()->in(1);
|
| @@ -599,10 +556,7 @@
|
| } else {
|
| __ testq(left_reg, right.reg());
|
| }
|
| - EmitBranchOnCondition(compiler,
|
| - branch->true_successor(),
|
| - branch->false_successor(),
|
| - branch_condition);
|
| + EmitBranchOnCondition(compiler, branch_condition, labels);
|
| }
|
|
|
|
|
| @@ -632,23 +586,36 @@
|
|
|
|
|
| void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + Label is_true, is_false;
|
| + BranchLabels labels = { &is_true, &is_false, &is_false };
|
| +
|
| if (operation_cid() == kSmiCid) {
|
| - EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
|
| - return;
|
| + EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
|
| + } else {
|
| + ASSERT(operation_cid() == kDoubleCid);
|
| + EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
|
| }
|
| - ASSERT(operation_cid() == kDoubleCid);
|
| - EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
|
| + Register result = locs()->out().reg();
|
| + Label done;
|
| + __ Bind(&is_false);
|
| + __ LoadObject(result, Bool::False(), PP);
|
| + __ jmp(&done);
|
| + __ Bind(&is_true);
|
| + __ LoadObject(result, Bool::True(), PP);
|
| + __ Bind(&done);
|
| }
|
|
|
|
|
| void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
| BranchInstr* branch) {
|
| + BranchLabels labels = compiler->CreateBranchLabels(branch);
|
| +
|
| if (operation_cid() == kSmiCid) {
|
| - EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
|
| - return;
|
| + EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
|
| + } else {
|
| + ASSERT(operation_cid() == kDoubleCid);
|
| + EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
|
| }
|
| - ASSERT(operation_cid() == kDoubleCid);
|
| - EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
|
| }
|
|
|
|
|
| @@ -4443,36 +4410,53 @@
|
| }
|
|
|
|
|
| -// Special code for numbers (compare values instead of references.)
|
| -void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| - ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
| - Location left = locs()->in(0);
|
| - Location right = locs()->in(1);
|
| +static void EmitStrictComparison(FlowGraphCompiler* compiler,
|
| + StrictCompareInstr* compare,
|
| + BranchLabels labels) {
|
| + LocationSummary* locs = compare->locs();
|
| + bool needs_number_check = compare->needs_number_check();
|
| + intptr_t token_pos = compare->token_pos();
|
| + Token::Kind kind = compare->kind();
|
| + Location left = locs->in(0);
|
| + Location right = locs->in(1);
|
| ASSERT(!left.IsConstant() || !right.IsConstant());
|
| if (left.IsConstant()) {
|
| compiler->EmitEqualityRegConstCompare(right.reg(),
|
| left.constant(),
|
| - needs_number_check(),
|
| - token_pos());
|
| + needs_number_check,
|
| + token_pos);
|
| } else if (right.IsConstant()) {
|
| compiler->EmitEqualityRegConstCompare(left.reg(),
|
| right.constant(),
|
| - needs_number_check(),
|
| - token_pos());
|
| + needs_number_check,
|
| + token_pos);
|
| } else {
|
| compiler->EmitEqualityRegRegCompare(left.reg(),
|
| - right.reg(),
|
| - needs_number_check(),
|
| - token_pos());
|
| + right.reg(),
|
| + needs_number_check,
|
| + token_pos);
|
| }
|
|
|
| + Condition true_condition = (kind == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
|
| + EmitBranchOnCondition(compiler, true_condition, labels);
|
| +}
|
| +
|
| +
|
| +// Special code for numbers (compare values instead of references.)
|
| +void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
| +
|
| + Label is_true, is_false;
|
| + BranchLabels labels = { &is_true, &is_false, &is_false };
|
| +
|
| + EmitStrictComparison(compiler, this, labels);
|
| +
|
| Register result = locs()->out().reg();
|
| - Label load_true, done;
|
| - Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
|
| - __ j(true_condition, &load_true, Assembler::kNearJump);
|
| + Label done;
|
| + __ Bind(&is_false);
|
| __ LoadObject(result, Bool::False(), PP);
|
| - __ jmp(&done, Assembler::kNearJump);
|
| - __ Bind(&load_true);
|
| + __ jmp(&done);
|
| + __ Bind(&is_true);
|
| __ LoadObject(result, Bool::True(), PP);
|
| __ Bind(&done);
|
| }
|
| @@ -4481,31 +4465,10 @@
|
| void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
| BranchInstr* branch) {
|
| ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
| - Location left = locs()->in(0);
|
| - Location right = locs()->in(1);
|
| - ASSERT(!left.IsConstant() || !right.IsConstant());
|
| - if (left.IsConstant()) {
|
| - compiler->EmitEqualityRegConstCompare(right.reg(),
|
| - left.constant(),
|
| - needs_number_check(),
|
| - token_pos());
|
| - } else if (right.IsConstant()) {
|
| - compiler->EmitEqualityRegConstCompare(left.reg(),
|
| - right.constant(),
|
| - needs_number_check(),
|
| - token_pos());
|
| - } else {
|
| - compiler->EmitEqualityRegRegCompare(left.reg(),
|
| - right.reg(),
|
| - needs_number_check(),
|
| - token_pos());
|
| - }
|
|
|
| - Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
|
| - EmitBranchOnCondition(compiler,
|
| - branch->true_successor(),
|
| - branch->false_successor(),
|
| - true_condition);
|
| + BranchLabels labels = compiler->CreateBranchLabels(branch);
|
| +
|
| + EmitStrictComparison(compiler, this, labels);
|
| }
|
|
|
|
|
|
|