| Index: runtime/vm/intermediate_language_ia32.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_ia32.cc (revision 30153)
|
| +++ runtime/vm/intermediate_language_ia32.cc (working copy)
|
| @@ -327,20 +327,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);
|
| }
|
| }
|
| }
|
| @@ -349,7 +348,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());
|
| @@ -366,22 +365,7 @@
|
| } else {
|
| __ cmpl(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());
|
| - __ jmp(&done);
|
| - __ Bind(&is_true);
|
| - __ LoadObject(result, Bool::True());
|
| - __ Bind(&done);
|
| - }
|
| + EmitBranchOnCondition(compiler, true_condition, labels);
|
| }
|
|
|
|
|
| @@ -429,7 +413,7 @@
|
| static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
|
| const LocationSummary& locs,
|
| Token::Kind kind,
|
| - BranchInstr* branch) {
|
| + BranchLabels labels) {
|
| ASSERT(Token::IsEqualityOperator(kind));
|
| XmmRegister left = locs.in(0).fpu_reg();
|
| XmmRegister right = locs.in(1).fpu_reg();
|
| @@ -440,34 +424,18 @@
|
|
|
| Condition true_condition = TokenKindToMintCondition(kind);
|
| __ cmpl(temp, Immediate(-1));
|
| -
|
| - 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());
|
| - __ jmp(&done);
|
| - __ Bind(&is_true);
|
| - __ LoadObject(result, Bool::True());
|
| - __ Bind(&done);
|
| - }
|
| + EmitBranchOnCondition(compiler, true_condition, labels);
|
| }
|
|
|
|
|
| static void EmitUnboxedMintComparisonOp(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();
|
| Register left_tmp = locs.temp(0).reg();
|
| Register right_tmp = locs.temp(1).reg();
|
| - Register result = branch == NULL ? locs.out().reg() : kNoRegister;
|
|
|
| Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW;
|
| switch (kind) {
|
| @@ -496,34 +464,14 @@
|
| __ pextrd(left_tmp, left, Immediate(1));
|
| __ pextrd(right_tmp, right, Immediate(1));
|
| __ cmpl(left_tmp, right_tmp);
|
| - if (branch != NULL) {
|
| - __ j(hi_cond, compiler->GetJumpLabel(branch->true_successor()));
|
| - __ j(FlipCondition(hi_cond),
|
| - compiler->GetJumpLabel(branch->false_successor()));
|
| - } else {
|
| - __ j(hi_cond, &is_true);
|
| - __ j(FlipCondition(hi_cond), &is_false);
|
| - }
|
| + __ j(hi_cond, labels.true_label);
|
| + __ j(FlipCondition(hi_cond), labels.false_label);
|
|
|
| // If upper is equal, compare lower half.
|
| __ pextrd(left_tmp, left, Immediate(0));
|
| __ pextrd(right_tmp, right, Immediate(0));
|
| __ cmpl(left_tmp, right_tmp);
|
| - if (branch != NULL) {
|
| - EmitBranchOnCondition(compiler,
|
| - branch->true_successor(),
|
| - branch->false_successor(),
|
| - lo_cond);
|
| - } else {
|
| - Label done;
|
| - __ j(lo_cond, &is_true);
|
| - __ Bind(&is_false);
|
| - __ LoadObject(result, Bool::False());
|
| - __ jmp(&done);
|
| - __ Bind(&is_true);
|
| - __ LoadObject(result, Bool::True());
|
| - __ Bind(&done);
|
| - }
|
| + EmitBranchOnCondition(compiler, lo_cond, labels);
|
| }
|
|
|
|
|
| @@ -542,96 +490,62 @@
|
| }
|
|
|
|
|
| -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());
|
| - __ jmp(&done);
|
| - __ Bind(&is_true);
|
| - __ LoadObject(result, Bool::True());
|
| - __ 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::kNE) || (kind() == Token::kEQ));
|
| - 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 if (operation_cid() == kMintCid) {
|
| + EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
|
| + } else {
|
| + ASSERT(operation_cid() == kDoubleCid);
|
| + EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
|
| }
|
| - if (operation_cid() == kMintCid) {
|
| - EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
|
| - return;
|
| - }
|
| - 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());
|
| + __ jmp(&done, Assembler::kNearJump);
|
| + __ Bind(&is_true);
|
| + __ LoadObject(result, Bool::True());
|
| + __ 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 if (operation_cid() == kMintCid) {
|
| + EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
|
| + } else {
|
| + ASSERT(operation_cid() == kDoubleCid);
|
| + EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
|
| }
|
| - if (operation_cid() == kMintCid) {
|
| - EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
|
| - return;
|
| - }
|
| - if (operation_cid() == kDoubleCid) {
|
| - EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
|
| - return;
|
| - }
|
| - UNREACHABLE();
|
| }
|
|
|
|
|
| @@ -656,7 +570,9 @@
|
|
|
| void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
| BranchInstr* branch) {
|
| - Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
|
| + BranchLabels labels = compiler->CreateBranchLabels(branch);
|
| +
|
| + Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
|
| Register left = locs()->in(0).reg();
|
| Location right = locs()->in(1);
|
| if (right.IsConstant()) {
|
| @@ -667,10 +583,7 @@
|
| } else {
|
| __ testl(left, right.reg());
|
| }
|
| - EmitBranchOnCondition(compiler,
|
| - branch->true_successor(),
|
| - branch->false_successor(),
|
| - branch_condition);
|
| + EmitBranchOnCondition(compiler, true_condition, labels);
|
| }
|
|
|
|
|
| @@ -711,31 +624,40 @@
|
|
|
|
|
| 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 if (operation_cid() == kMintCid) {
|
| + EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
|
| + } else {
|
| + ASSERT(operation_cid() == kDoubleCid);
|
| + EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
|
| }
|
| - if (operation_cid() == kMintCid) {
|
| - EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL);
|
| - return;
|
| - }
|
| - ASSERT(operation_cid() == kDoubleCid);
|
| - EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
|
| + Register result = locs()->out().reg();
|
| + Label done;
|
| + __ Bind(&is_false);
|
| + __ LoadObject(result, Bool::False());
|
| + __ jmp(&done, Assembler::kNearJump);
|
| + __ Bind(&is_true);
|
| + __ LoadObject(result, Bool::True());
|
| + __ 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 if (operation_cid() == kMintCid) {
|
| + EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
|
| + } else {
|
| + ASSERT(operation_cid() == kDoubleCid);
|
| + EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
|
| }
|
| - if (operation_cid() == kMintCid) {
|
| - EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
|
| - return;
|
| - }
|
| - ASSERT(operation_cid() == kDoubleCid);
|
| - EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
|
| }
|
|
|
|
|
| @@ -4696,36 +4618,52 @@
|
| }
|
|
|
|
|
| -// 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());
|
| __ jmp(&done, Assembler::kNearJump);
|
| - __ Bind(&load_true);
|
| + __ Bind(&is_true);
|
| __ LoadObject(result, Bool::True());
|
| __ Bind(&done);
|
| }
|
| @@ -4734,31 +4672,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);
|
| }
|
|
|
|
|
|
|