| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 // that will be overwritten by the patch instructions: a branch macro sequence. | 84 // that will be overwritten by the patch instructions: a branch macro sequence. |
| 85 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 85 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 86 const Register result = locs()->in(0).reg(); | 86 const Register result = locs()->in(0).reg(); |
| 87 ASSERT(result == R0); | 87 ASSERT(result == R0); |
| 88 #if defined(DEBUG) | 88 #if defined(DEBUG) |
| 89 Label stack_ok; | 89 Label stack_ok; |
| 90 __ Comment("Stack Check"); | 90 __ Comment("Stack Check"); |
| 91 const intptr_t fp_sp_dist = | 91 const intptr_t fp_sp_dist = |
| 92 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 92 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 93 ASSERT(fp_sp_dist <= 0); | 93 ASSERT(fp_sp_dist <= 0); |
| 94 __ sub(R2, SP, ShifterOperand(FP)); | 94 __ sub(R2, SP, Operand(FP)); |
| 95 __ CompareImmediate(R2, fp_sp_dist); | 95 __ CompareImmediate(R2, fp_sp_dist); |
| 96 __ b(&stack_ok, EQ); | 96 __ b(&stack_ok, EQ); |
| 97 __ bkpt(0); | 97 __ bkpt(0); |
| 98 __ Bind(&stack_ok); | 98 __ Bind(&stack_ok); |
| 99 #endif | 99 #endif |
| 100 __ LeaveDartFrame(); | 100 __ LeaveDartFrame(); |
| 101 __ Ret(); | 101 __ Ret(); |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 | 136 |
| 137 | 137 |
| 138 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 138 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 139 const Register result = locs()->out(0).reg(); | 139 const Register result = locs()->out(0).reg(); |
| 140 | 140 |
| 141 Location left = locs()->in(0); | 141 Location left = locs()->in(0); |
| 142 Location right = locs()->in(1); | 142 Location right = locs()->in(1); |
| 143 ASSERT(!left.IsConstant() || !right.IsConstant()); | 143 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 144 | 144 |
| 145 // Clear out register. | 145 // Clear out register. |
| 146 __ eor(result, result, ShifterOperand(result)); | 146 __ eor(result, result, Operand(result)); |
| 147 | 147 |
| 148 // Emit comparison code. This must not overwrite the result register. | 148 // Emit comparison code. This must not overwrite the result register. |
| 149 BranchLabels labels = { NULL, NULL, NULL }; | 149 BranchLabels labels = { NULL, NULL, NULL }; |
| 150 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 150 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 151 | 151 |
| 152 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 152 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 153 | 153 |
| 154 intptr_t true_value = if_true_; | 154 intptr_t true_value = if_true_; |
| 155 intptr_t false_value = if_false_; | 155 intptr_t false_value = if_false_; |
| 156 | 156 |
| 157 if (is_power_of_two_kind) { | 157 if (is_power_of_two_kind) { |
| 158 if (true_value == 0) { | 158 if (true_value == 0) { |
| 159 // We need to have zero in result on true_condition. | 159 // We need to have zero in result on true_condition. |
| 160 true_condition = NegateCondition(true_condition); | 160 true_condition = NegateCondition(true_condition); |
| 161 } | 161 } |
| 162 } else { | 162 } else { |
| 163 if (true_value == 0) { | 163 if (true_value == 0) { |
| 164 // Swap values so that false_value is zero. | 164 // Swap values so that false_value is zero. |
| 165 intptr_t temp = true_value; | 165 intptr_t temp = true_value; |
| 166 true_value = false_value; | 166 true_value = false_value; |
| 167 false_value = temp; | 167 false_value = temp; |
| 168 } else { | 168 } else { |
| 169 true_condition = NegateCondition(true_condition); | 169 true_condition = NegateCondition(true_condition); |
| 170 } | 170 } |
| 171 } | 171 } |
| 172 | 172 |
| 173 __ mov(result, ShifterOperand(1), true_condition); | 173 __ mov(result, Operand(1), true_condition); |
| 174 | 174 |
| 175 if (is_power_of_two_kind) { | 175 if (is_power_of_two_kind) { |
| 176 const intptr_t shift = | 176 const intptr_t shift = |
| 177 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 177 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 178 __ Lsl(result, result, shift + kSmiTagSize); | 178 __ Lsl(result, result, shift + kSmiTagSize); |
| 179 } else { | 179 } else { |
| 180 __ sub(result, result, ShifterOperand(1)); | 180 __ sub(result, result, Operand(1)); |
| 181 const int32_t val = | 181 const int32_t val = |
| 182 Smi::RawValue(true_value) - Smi::RawValue(false_value); | 182 Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| 183 __ AndImmediate(result, result, val); | 183 __ AndImmediate(result, result, val); |
| 184 if (false_value != 0) { | 184 if (false_value != 0) { |
| 185 __ AddImmediate(result, Smi::RawValue(false_value)); | 185 __ AddImmediate(result, Smi::RawValue(false_value)); |
| 186 } | 186 } |
| 187 } | 187 } |
| 188 } | 188 } |
| 189 | 189 |
| 190 | 190 |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 return NULL; | 433 return NULL; |
| 434 } | 434 } |
| 435 | 435 |
| 436 | 436 |
| 437 static void LoadValueCid(FlowGraphCompiler* compiler, | 437 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 438 Register value_cid_reg, | 438 Register value_cid_reg, |
| 439 Register value_reg, | 439 Register value_reg, |
| 440 Label* value_is_smi = NULL) { | 440 Label* value_is_smi = NULL) { |
| 441 Label done; | 441 Label done; |
| 442 if (value_is_smi == NULL) { | 442 if (value_is_smi == NULL) { |
| 443 __ mov(value_cid_reg, ShifterOperand(kSmiCid)); | 443 __ mov(value_cid_reg, Operand(kSmiCid)); |
| 444 } | 444 } |
| 445 __ tst(value_reg, ShifterOperand(kSmiTagMask)); | 445 __ tst(value_reg, Operand(kSmiTagMask)); |
| 446 if (value_is_smi == NULL) { | 446 if (value_is_smi == NULL) { |
| 447 __ b(&done, EQ); | 447 __ b(&done, EQ); |
| 448 } else { | 448 } else { |
| 449 __ b(value_is_smi, EQ); | 449 __ b(value_is_smi, EQ); |
| 450 } | 450 } |
| 451 __ LoadClassId(value_cid_reg, value_reg); | 451 __ LoadClassId(value_cid_reg, value_reg); |
| 452 __ Bind(&done); | 452 __ Bind(&done); |
| 453 } | 453 } |
| 454 | 454 |
| 455 | 455 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 ASSERT(!left.IsConstant() || !right.IsConstant()); | 499 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 500 | 500 |
| 501 Condition true_condition = TokenKindToSmiCondition(kind); | 501 Condition true_condition = TokenKindToSmiCondition(kind); |
| 502 | 502 |
| 503 if (left.IsConstant()) { | 503 if (left.IsConstant()) { |
| 504 __ CompareObject(right.reg(), left.constant()); | 504 __ CompareObject(right.reg(), left.constant()); |
| 505 true_condition = FlipCondition(true_condition); | 505 true_condition = FlipCondition(true_condition); |
| 506 } else if (right.IsConstant()) { | 506 } else if (right.IsConstant()) { |
| 507 __ CompareObject(left.reg(), right.constant()); | 507 __ CompareObject(left.reg(), right.constant()); |
| 508 } else { | 508 } else { |
| 509 __ cmp(left.reg(), ShifterOperand(right.reg())); | 509 __ cmp(left.reg(), Operand(right.reg())); |
| 510 } | 510 } |
| 511 return true_condition; | 511 return true_condition; |
| 512 } | 512 } |
| 513 | 513 |
| 514 | 514 |
| 515 static Condition TokenKindToMintCondition(Token::Kind kind) { | 515 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 516 switch (kind) { | 516 switch (kind) { |
| 517 case Token::kEQ: return EQ; | 517 case Token::kEQ: return EQ; |
| 518 case Token::kNE: return NE; | 518 case Token::kNE: return NE; |
| 519 case Token::kLT: return LT; | 519 case Token::kLT: return LT; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 532 Token::Kind kind) { | 532 Token::Kind kind) { |
| 533 ASSERT(Token::IsEqualityOperator(kind)); | 533 ASSERT(Token::IsEqualityOperator(kind)); |
| 534 PairLocation* left_pair = locs->in(0).AsPairLocation(); | 534 PairLocation* left_pair = locs->in(0).AsPairLocation(); |
| 535 Register left1 = left_pair->At(0).reg(); | 535 Register left1 = left_pair->At(0).reg(); |
| 536 Register left2 = left_pair->At(1).reg(); | 536 Register left2 = left_pair->At(1).reg(); |
| 537 PairLocation* right_pair = locs->in(1).AsPairLocation(); | 537 PairLocation* right_pair = locs->in(1).AsPairLocation(); |
| 538 Register right1 = right_pair->At(0).reg(); | 538 Register right1 = right_pair->At(0).reg(); |
| 539 Register right2 = right_pair->At(1).reg(); | 539 Register right2 = right_pair->At(1).reg(); |
| 540 | 540 |
| 541 // Compare lower. | 541 // Compare lower. |
| 542 __ cmp(left1, ShifterOperand(right1)); | 542 __ cmp(left1, Operand(right1)); |
| 543 // Compare upper if lower is equal. | 543 // Compare upper if lower is equal. |
| 544 __ cmp(left2, ShifterOperand(right2), EQ); | 544 __ cmp(left2, Operand(right2), EQ); |
| 545 return TokenKindToMintCondition(kind); | 545 return TokenKindToMintCondition(kind); |
| 546 } | 546 } |
| 547 | 547 |
| 548 | 548 |
| 549 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 549 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| 550 LocationSummary* locs, | 550 LocationSummary* locs, |
| 551 Token::Kind kind) { | 551 Token::Kind kind) { |
| 552 PairLocation* left_pair = locs->in(0).AsPairLocation(); | 552 PairLocation* left_pair = locs->in(0).AsPairLocation(); |
| 553 Register left1 = left_pair->At(0).reg(); | 553 Register left1 = left_pair->At(0).reg(); |
| 554 Register left2 = left_pair->At(1).reg(); | 554 Register left2 = left_pair->At(1).reg(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 573 hi_false_cond = LT; | 573 hi_false_cond = LT; |
| 574 lo_false_cond = (kind == Token::kGT) ? LS : CC; | 574 lo_false_cond = (kind == Token::kGT) ? LS : CC; |
| 575 break; | 575 break; |
| 576 default: | 576 default: |
| 577 UNREACHABLE(); | 577 UNREACHABLE(); |
| 578 hi_true_cond = hi_false_cond = lo_false_cond = VS; | 578 hi_true_cond = hi_false_cond = lo_false_cond = VS; |
| 579 } | 579 } |
| 580 | 580 |
| 581 Label is_true, is_false, done; | 581 Label is_true, is_false, done; |
| 582 // Compare upper halves first. | 582 // Compare upper halves first. |
| 583 __ cmp(left2, ShifterOperand(right2)); | 583 __ cmp(left2, Operand(right2)); |
| 584 __ LoadImmediate(out, 0, hi_false_cond); | 584 __ LoadImmediate(out, 0, hi_false_cond); |
| 585 __ LoadImmediate(out, 1, hi_true_cond); | 585 __ LoadImmediate(out, 1, hi_true_cond); |
| 586 // If higher words aren't equal, skip comparing lower words. | 586 // If higher words aren't equal, skip comparing lower words. |
| 587 __ b(&done, NE); | 587 __ b(&done, NE); |
| 588 | 588 |
| 589 __ cmp(left1, ShifterOperand(right1)); | 589 __ cmp(left1, Operand(right1)); |
| 590 __ LoadImmediate(out, 1); | 590 __ LoadImmediate(out, 1); |
| 591 __ LoadImmediate(out, 0, lo_false_cond); | 591 __ LoadImmediate(out, 0, lo_false_cond); |
| 592 __ Bind(&done); | 592 __ Bind(&done); |
| 593 | 593 |
| 594 return NegateCondition(lo_false_cond); | 594 return NegateCondition(lo_false_cond); |
| 595 } | 595 } |
| 596 | 596 |
| 597 | 597 |
| 598 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 598 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 599 switch (kind) { | 599 switch (kind) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 694 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 695 BranchLabels labels) { | 695 BranchLabels labels) { |
| 696 const Register left = locs()->in(0).reg(); | 696 const Register left = locs()->in(0).reg(); |
| 697 Location right = locs()->in(1); | 697 Location right = locs()->in(1); |
| 698 if (right.IsConstant()) { | 698 if (right.IsConstant()) { |
| 699 ASSERT(right.constant().IsSmi()); | 699 ASSERT(right.constant().IsSmi()); |
| 700 const int32_t imm = | 700 const int32_t imm = |
| 701 reinterpret_cast<int32_t>(right.constant().raw()); | 701 reinterpret_cast<int32_t>(right.constant().raw()); |
| 702 __ TestImmediate(left, imm); | 702 __ TestImmediate(left, imm); |
| 703 } else { | 703 } else { |
| 704 __ tst(left, ShifterOperand(right.reg())); | 704 __ tst(left, Operand(right.reg())); |
| 705 } | 705 } |
| 706 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 706 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
| 707 return true_condition; | 707 return true_condition; |
| 708 } | 708 } |
| 709 | 709 |
| 710 | 710 |
| 711 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 711 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 712 // Never emitted outside of the BranchInstr. | 712 // Never emitted outside of the BranchInstr. |
| 713 UNREACHABLE(); | 713 UNREACHABLE(); |
| 714 } | 714 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 741 const Register val_reg = locs()->in(0).reg(); | 741 const Register val_reg = locs()->in(0).reg(); |
| 742 const Register cid_reg = locs()->temp(0).reg(); | 742 const Register cid_reg = locs()->temp(0).reg(); |
| 743 | 743 |
| 744 Label* deopt = CanDeoptimize() ? | 744 Label* deopt = CanDeoptimize() ? |
| 745 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; | 745 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; |
| 746 | 746 |
| 747 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 747 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 748 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 748 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 749 ASSERT(data[0] == kSmiCid); | 749 ASSERT(data[0] == kSmiCid); |
| 750 bool result = data[1] == true_result; | 750 bool result = data[1] == true_result; |
| 751 __ tst(val_reg, ShifterOperand(kSmiTagMask)); | 751 __ tst(val_reg, Operand(kSmiTagMask)); |
| 752 __ b(result ? labels.true_label : labels.false_label, EQ); | 752 __ b(result ? labels.true_label : labels.false_label, EQ); |
| 753 __ LoadClassId(cid_reg, val_reg); | 753 __ LoadClassId(cid_reg, val_reg); |
| 754 | 754 |
| 755 for (intptr_t i = 2; i < data.length(); i += 2) { | 755 for (intptr_t i = 2; i < data.length(); i += 2) { |
| 756 const intptr_t test_cid = data[i]; | 756 const intptr_t test_cid = data[i]; |
| 757 ASSERT(test_cid != kSmiCid); | 757 ASSERT(test_cid != kSmiCid); |
| 758 result = data[i + 1] == true_result; | 758 result = data[i + 1] == true_result; |
| 759 __ CompareImmediate(cid_reg, test_cid); | 759 __ CompareImmediate(cid_reg, test_cid); |
| 760 __ b(result ? labels.true_label : labels.false_label, EQ); | 760 __ b(result ? labels.true_label : labels.false_label, EQ); |
| 761 } | 761 } |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 Location::RequiresRegister(), | 985 Location::RequiresRegister(), |
| 986 LocationSummary::kNoCall); | 986 LocationSummary::kNoCall); |
| 987 } | 987 } |
| 988 | 988 |
| 989 | 989 |
| 990 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 990 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 991 ASSERT(cid_ == kOneByteStringCid); | 991 ASSERT(cid_ == kOneByteStringCid); |
| 992 const Register str = locs()->in(0).reg(); | 992 const Register str = locs()->in(0).reg(); |
| 993 const Register result = locs()->out(0).reg(); | 993 const Register result = locs()->out(0).reg(); |
| 994 __ ldr(result, FieldAddress(str, String::length_offset())); | 994 __ ldr(result, FieldAddress(str, String::length_offset())); |
| 995 __ cmp(result, ShifterOperand(Smi::RawValue(1))); | 995 __ cmp(result, Operand(Smi::RawValue(1))); |
| 996 __ LoadImmediate(result, -1, NE); | 996 __ LoadImmediate(result, -1, NE); |
| 997 __ ldrb(result, FieldAddress(str, OneByteString::data_offset()), EQ); | 997 __ ldrb(result, FieldAddress(str, OneByteString::data_offset()), EQ); |
| 998 __ SmiTag(result); | 998 __ SmiTag(result); |
| 999 } | 999 } |
| 1000 | 1000 |
| 1001 | 1001 |
| 1002 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Isolate* isolate, | 1002 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Isolate* isolate, |
| 1003 bool opt) const { | 1003 bool opt) const { |
| 1004 const intptr_t kNumInputs = 1; | 1004 const intptr_t kNumInputs = 1; |
| 1005 const intptr_t kNumTemps = 0; | 1005 const intptr_t kNumTemps = 0; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 kNumInputs, | 1050 kNumInputs, |
| 1051 Location::RequiresRegister(), | 1051 Location::RequiresRegister(), |
| 1052 LocationSummary::kNoCall); | 1052 LocationSummary::kNoCall); |
| 1053 } | 1053 } |
| 1054 | 1054 |
| 1055 | 1055 |
| 1056 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1056 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1057 const Register object = locs()->in(0).reg(); | 1057 const Register object = locs()->in(0).reg(); |
| 1058 const Register result = locs()->out(0).reg(); | 1058 const Register result = locs()->out(0).reg(); |
| 1059 Label load, done; | 1059 Label load, done; |
| 1060 __ tst(object, ShifterOperand(kSmiTagMask)); | 1060 __ tst(object, Operand(kSmiTagMask)); |
| 1061 __ b(&load, NE); | 1061 __ b(&load, NE); |
| 1062 __ LoadImmediate(result, Smi::RawValue(kSmiCid)); | 1062 __ LoadImmediate(result, Smi::RawValue(kSmiCid)); |
| 1063 __ b(&done); | 1063 __ b(&done); |
| 1064 __ Bind(&load); | 1064 __ Bind(&load); |
| 1065 __ LoadClassId(result, object); | 1065 __ LoadClassId(result, object); |
| 1066 __ SmiTag(result); | 1066 __ SmiTag(result); |
| 1067 __ Bind(&done); | 1067 __ Bind(&done); |
| 1068 } | 1068 } |
| 1069 | 1069 |
| 1070 | 1070 |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 int32_t offset = | 1233 int32_t offset = |
| 1234 is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag); | 1234 is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag); |
| 1235 const OperandSize size = Address::OperandSizeFor(cid); | 1235 const OperandSize size = Address::OperandSizeFor(cid); |
| 1236 ASSERT(array != IP); | 1236 ASSERT(array != IP); |
| 1237 ASSERT(index != IP); | 1237 ASSERT(index != IP); |
| 1238 const Register base = is_load ? IP : index; | 1238 const Register base = is_load ? IP : index; |
| 1239 if ((offset != 0) || | 1239 if ((offset != 0) || |
| 1240 (size == kSWord) || (size == kDWord) || (size == kRegList)) { | 1240 (size == kSWord) || (size == kDWord) || (size == kRegList)) { |
| 1241 if (shift < 0) { | 1241 if (shift < 0) { |
| 1242 ASSERT(shift == -1); | 1242 ASSERT(shift == -1); |
| 1243 assembler->add(base, array, ShifterOperand(index, ASR, 1)); | 1243 assembler->add(base, array, Operand(index, ASR, 1)); |
| 1244 } else { | 1244 } else { |
| 1245 assembler->add(base, array, ShifterOperand(index, LSL, shift)); | 1245 assembler->add(base, array, Operand(index, LSL, shift)); |
| 1246 } | 1246 } |
| 1247 } else { | 1247 } else { |
| 1248 if (shift < 0) { | 1248 if (shift < 0) { |
| 1249 ASSERT(shift == -1); | 1249 ASSERT(shift == -1); |
| 1250 return Address(array, index, ASR, 1); | 1250 return Address(array, index, ASR, 1); |
| 1251 } else { | 1251 } else { |
| 1252 return Address(array, index, LSL, shift); | 1252 return Address(array, index, LSL, shift); |
| 1253 } | 1253 } |
| 1254 } | 1254 } |
| 1255 int32_t offset_mask = 0; | 1255 int32_t offset_mask = 0; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 case kTypedDataInt32ArrayCid: | 1317 case kTypedDataInt32ArrayCid: |
| 1318 // Load low word. | 1318 // Load low word. |
| 1319 __ ldr(result1, element_address); | 1319 __ ldr(result1, element_address); |
| 1320 // Sign extend into high word. | 1320 // Sign extend into high word. |
| 1321 __ SignFill(result2, result1); | 1321 __ SignFill(result2, result1); |
| 1322 break; | 1322 break; |
| 1323 case kTypedDataUint32ArrayCid: | 1323 case kTypedDataUint32ArrayCid: |
| 1324 // Load low word. | 1324 // Load low word. |
| 1325 __ ldr(result1, element_address); | 1325 __ ldr(result1, element_address); |
| 1326 // Zero high word. | 1326 // Zero high word. |
| 1327 __ eor(result2, result2, ShifterOperand(result2)); | 1327 __ eor(result2, result2, Operand(result2)); |
| 1328 break; | 1328 break; |
| 1329 default: | 1329 default: |
| 1330 UNREACHABLE(); | 1330 UNREACHABLE(); |
| 1331 break; | 1331 break; |
| 1332 } | 1332 } |
| 1333 return; | 1333 return; |
| 1334 } | 1334 } |
| 1335 | 1335 |
| 1336 ASSERT(representation() == kTagged); | 1336 ASSERT(representation() == kTagged); |
| 1337 | 1337 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 value = 0xFF; | 1535 value = 0xFF; |
| 1536 } else if (value < 0) { | 1536 } else if (value < 0) { |
| 1537 value = 0; | 1537 value = 0; |
| 1538 } | 1538 } |
| 1539 __ LoadImmediate(IP, static_cast<int8_t>(value)); | 1539 __ LoadImmediate(IP, static_cast<int8_t>(value)); |
| 1540 __ strb(IP, element_address); | 1540 __ strb(IP, element_address); |
| 1541 } else { | 1541 } else { |
| 1542 const Register value = locs()->in(2).reg(); | 1542 const Register value = locs()->in(2).reg(); |
| 1543 Label store_value; | 1543 Label store_value; |
| 1544 __ SmiUntag(value); | 1544 __ SmiUntag(value); |
| 1545 __ cmp(value, ShifterOperand(0xFF)); | 1545 __ cmp(value, Operand(0xFF)); |
| 1546 // Clamp to 0x00 or 0xFF respectively. | 1546 // Clamp to 0x00 or 0xFF respectively. |
| 1547 __ b(&store_value, LS); | 1547 __ b(&store_value, LS); |
| 1548 __ mov(value, ShifterOperand(0x00), LE); | 1548 __ mov(value, Operand(0x00), LE); |
| 1549 __ mov(value, ShifterOperand(0xFF), GT); | 1549 __ mov(value, Operand(0xFF), GT); |
| 1550 __ Bind(&store_value); | 1550 __ Bind(&store_value); |
| 1551 __ strb(value, element_address); | 1551 __ strb(value, element_address); |
| 1552 } | 1552 } |
| 1553 break; | 1553 break; |
| 1554 } | 1554 } |
| 1555 case kTypedDataInt16ArrayCid: | 1555 case kTypedDataInt16ArrayCid: |
| 1556 case kTypedDataUint16ArrayCid: { | 1556 case kTypedDataUint16ArrayCid: { |
| 1557 const Register value = locs()->in(2).reg(); | 1557 const Register value = locs()->in(2).reg(); |
| 1558 __ SmiUntag(value); | 1558 __ SmiUntag(value); |
| 1559 __ strh(value, element_address); | 1559 __ strh(value, element_address); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1670 FieldAddress field_length_operand( | 1670 FieldAddress field_length_operand( |
| 1671 field_reg, Field::guarded_list_length_offset()); | 1671 field_reg, Field::guarded_list_length_offset()); |
| 1672 | 1672 |
| 1673 ASSERT(value_cid_reg != kNoRegister); | 1673 ASSERT(value_cid_reg != kNoRegister); |
| 1674 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); | 1674 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); |
| 1675 | 1675 |
| 1676 if (value_cid == kDynamicCid) { | 1676 if (value_cid == kDynamicCid) { |
| 1677 LoadValueCid(compiler, value_cid_reg, value_reg); | 1677 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1678 Label skip_length_check; | 1678 Label skip_length_check; |
| 1679 __ ldr(IP, field_cid_operand); | 1679 __ ldr(IP, field_cid_operand); |
| 1680 __ cmp(value_cid_reg, ShifterOperand(IP)); | 1680 __ cmp(value_cid_reg, Operand(IP)); |
| 1681 __ b(&skip_length_check, NE); | 1681 __ b(&skip_length_check, NE); |
| 1682 if (field_has_length) { | 1682 if (field_has_length) { |
| 1683 ASSERT(temp_reg != kNoRegister); | 1683 ASSERT(temp_reg != kNoRegister); |
| 1684 // Field guard may have remembered list length, check it. | 1684 // Field guard may have remembered list length, check it. |
| 1685 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { | 1685 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { |
| 1686 __ ldr(temp_reg, | 1686 __ ldr(temp_reg, |
| 1687 FieldAddress(value_reg, Array::length_offset())); | 1687 FieldAddress(value_reg, Array::length_offset())); |
| 1688 __ CompareImmediate(temp_reg, Smi::RawValue(field_length)); | 1688 __ CompareImmediate(temp_reg, Smi::RawValue(field_length)); |
| 1689 } else if (RawObject::IsTypedDataClassId(field_cid)) { | 1689 } else if (RawObject::IsTypedDataClassId(field_cid)) { |
| 1690 __ ldr(temp_reg, | 1690 __ ldr(temp_reg, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1709 __ b(&no_fixed_length, EQ); | 1709 __ b(&no_fixed_length, EQ); |
| 1710 // Check for typed data array. | 1710 // Check for typed data array. |
| 1711 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid); | 1711 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid); |
| 1712 __ b(&no_fixed_length, GT); | 1712 __ b(&no_fixed_length, GT); |
| 1713 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid); | 1713 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid); |
| 1714 // Could still be a regular array. | 1714 // Could still be a regular array. |
| 1715 __ b(&check_array, LT); | 1715 __ b(&check_array, LT); |
| 1716 __ ldr(temp_reg, | 1716 __ ldr(temp_reg, |
| 1717 FieldAddress(value_reg, TypedData::length_offset())); | 1717 FieldAddress(value_reg, TypedData::length_offset())); |
| 1718 __ ldr(IP, field_length_operand); | 1718 __ ldr(IP, field_length_operand); |
| 1719 __ cmp(temp_reg, ShifterOperand(IP)); | 1719 __ cmp(temp_reg, Operand(IP)); |
| 1720 __ b(&length_compared); | 1720 __ b(&length_compared); |
| 1721 // Check for regular array. | 1721 // Check for regular array. |
| 1722 __ Bind(&check_array); | 1722 __ Bind(&check_array); |
| 1723 __ CompareImmediate(value_cid_reg, kImmutableArrayCid); | 1723 __ CompareImmediate(value_cid_reg, kImmutableArrayCid); |
| 1724 __ b(&no_fixed_length, GT); | 1724 __ b(&no_fixed_length, GT); |
| 1725 __ CompareImmediate(value_cid_reg, kArrayCid); | 1725 __ CompareImmediate(value_cid_reg, kArrayCid); |
| 1726 __ b(&no_fixed_length, LT); | 1726 __ b(&no_fixed_length, LT); |
| 1727 __ ldr(temp_reg, | 1727 __ ldr(temp_reg, |
| 1728 FieldAddress(value_reg, Array::length_offset())); | 1728 FieldAddress(value_reg, Array::length_offset())); |
| 1729 __ ldr(IP, field_length_operand); | 1729 __ ldr(IP, field_length_operand); |
| 1730 __ cmp(temp_reg, ShifterOperand(IP)); | 1730 __ cmp(temp_reg, Operand(IP)); |
| 1731 __ b(&length_compared); | 1731 __ b(&length_compared); |
| 1732 __ Bind(&no_fixed_length); | 1732 __ Bind(&no_fixed_length); |
| 1733 __ b(fail); | 1733 __ b(fail); |
| 1734 __ Bind(&length_compared); | 1734 __ Bind(&length_compared); |
| 1735 // Following branch cannot not occur, fall through. | 1735 // Following branch cannot not occur, fall through. |
| 1736 } | 1736 } |
| 1737 __ b(fail, NE); | 1737 __ b(fail, NE); |
| 1738 } | 1738 } |
| 1739 __ Bind(&skip_length_check); | 1739 __ Bind(&skip_length_check); |
| 1740 __ ldr(IP, field_nullability_operand); | 1740 __ ldr(IP, field_nullability_operand); |
| 1741 __ cmp(value_cid_reg, ShifterOperand(IP)); | 1741 __ cmp(value_cid_reg, Operand(IP)); |
| 1742 } else if (value_cid == kNullCid) { | 1742 } else if (value_cid == kNullCid) { |
| 1743 __ ldr(value_cid_reg, field_nullability_operand); | 1743 __ ldr(value_cid_reg, field_nullability_operand); |
| 1744 __ CompareImmediate(value_cid_reg, value_cid); | 1744 __ CompareImmediate(value_cid_reg, value_cid); |
| 1745 } else { | 1745 } else { |
| 1746 Label skip_length_check; | 1746 Label skip_length_check; |
| 1747 __ ldr(value_cid_reg, field_cid_operand); | 1747 __ ldr(value_cid_reg, field_cid_operand); |
| 1748 __ CompareImmediate(value_cid_reg, value_cid); | 1748 __ CompareImmediate(value_cid_reg, value_cid); |
| 1749 __ b(&skip_length_check, NE); | 1749 __ b(&skip_length_check, NE); |
| 1750 if (field_has_length) { | 1750 if (field_has_length) { |
| 1751 ASSERT(value_cid_reg != kNoRegister); | 1751 ASSERT(value_cid_reg != kNoRegister); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1853 } | 1853 } |
| 1854 } else { | 1854 } else { |
| 1855 ASSERT(compiler->is_optimizing()); | 1855 ASSERT(compiler->is_optimizing()); |
| 1856 ASSERT(deopt != NULL); | 1856 ASSERT(deopt != NULL); |
| 1857 // Field guard class has been initialized and is known. | 1857 // Field guard class has been initialized and is known. |
| 1858 if (field_reg != kNoRegister) { | 1858 if (field_reg != kNoRegister) { |
| 1859 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); | 1859 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); |
| 1860 } | 1860 } |
| 1861 if (value_cid == kDynamicCid) { | 1861 if (value_cid == kDynamicCid) { |
| 1862 // Field's guarded class id is fixed by value's class id is not known. | 1862 // Field's guarded class id is fixed by value's class id is not known. |
| 1863 __ tst(value_reg, ShifterOperand(kSmiTagMask)); | 1863 __ tst(value_reg, Operand(kSmiTagMask)); |
| 1864 | 1864 |
| 1865 if (field_cid != kSmiCid) { | 1865 if (field_cid != kSmiCid) { |
| 1866 __ b(fail, EQ); | 1866 __ b(fail, EQ); |
| 1867 __ LoadClassId(value_cid_reg, value_reg); | 1867 __ LoadClassId(value_cid_reg, value_reg); |
| 1868 __ CompareImmediate(value_cid_reg, field_cid); | 1868 __ CompareImmediate(value_cid_reg, field_cid); |
| 1869 } | 1869 } |
| 1870 | 1870 |
| 1871 if (field_has_length) { | 1871 if (field_has_length) { |
| 1872 __ b(fail, NE); | 1872 __ b(fail, NE); |
| 1873 // Classes are same, perform guarded list length check. | 1873 // Classes are same, perform guarded list length check. |
| 1874 ASSERT(field_reg != kNoRegister); | 1874 ASSERT(field_reg != kNoRegister); |
| 1875 ASSERT(value_cid_reg != kNoRegister); | 1875 ASSERT(value_cid_reg != kNoRegister); |
| 1876 FieldAddress field_length_operand( | 1876 FieldAddress field_length_operand( |
| 1877 field_reg, Field::guarded_list_length_offset()); | 1877 field_reg, Field::guarded_list_length_offset()); |
| 1878 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { | 1878 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { |
| 1879 // Destroy value_cid_reg (safe because we are finished with it). | 1879 // Destroy value_cid_reg (safe because we are finished with it). |
| 1880 __ ldr(value_cid_reg, | 1880 __ ldr(value_cid_reg, |
| 1881 FieldAddress(value_reg, Array::length_offset())); | 1881 FieldAddress(value_reg, Array::length_offset())); |
| 1882 } else if (RawObject::IsTypedDataClassId(field_cid)) { | 1882 } else if (RawObject::IsTypedDataClassId(field_cid)) { |
| 1883 // Destroy value_cid_reg (safe because we are finished with it). | 1883 // Destroy value_cid_reg (safe because we are finished with it). |
| 1884 __ ldr(value_cid_reg, | 1884 __ ldr(value_cid_reg, |
| 1885 FieldAddress(value_reg, TypedData::length_offset())); | 1885 FieldAddress(value_reg, TypedData::length_offset())); |
| 1886 } | 1886 } |
| 1887 __ ldr(IP, field_length_operand); | 1887 __ ldr(IP, field_length_operand); |
| 1888 __ cmp(value_cid_reg, ShifterOperand(IP)); | 1888 __ cmp(value_cid_reg, Operand(IP)); |
| 1889 } | 1889 } |
| 1890 | 1890 |
| 1891 if (field().is_nullable() && (field_cid != kNullCid)) { | 1891 if (field().is_nullable() && (field_cid != kNullCid)) { |
| 1892 __ b(&ok, EQ); | 1892 __ b(&ok, EQ); |
| 1893 __ CompareImmediate(value_reg, | 1893 __ CompareImmediate(value_reg, |
| 1894 reinterpret_cast<intptr_t>(Object::null())); | 1894 reinterpret_cast<intptr_t>(Object::null())); |
| 1895 } | 1895 } |
| 1896 __ b(fail, NE); | 1896 __ b(fail, NE); |
| 1897 } else { | 1897 } else { |
| 1898 // Both value's and field's class id is known. | 1898 // Both value's and field's class id is known. |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2063 Label store_float32x4; | 2063 Label store_float32x4; |
| 2064 Label store_float64x2; | 2064 Label store_float64x2; |
| 2065 | 2065 |
| 2066 __ LoadObject(temp, Field::ZoneHandle(field().raw())); | 2066 __ LoadObject(temp, Field::ZoneHandle(field().raw())); |
| 2067 | 2067 |
| 2068 __ ldr(temp2, FieldAddress(temp, Field::is_nullable_offset())); | 2068 __ ldr(temp2, FieldAddress(temp, Field::is_nullable_offset())); |
| 2069 __ CompareImmediate(temp2, kNullCid); | 2069 __ CompareImmediate(temp2, kNullCid); |
| 2070 __ b(&store_pointer, EQ); | 2070 __ b(&store_pointer, EQ); |
| 2071 | 2071 |
| 2072 __ ldrb(temp2, FieldAddress(temp, Field::kind_bits_offset())); | 2072 __ ldrb(temp2, FieldAddress(temp, Field::kind_bits_offset())); |
| 2073 __ tst(temp2, ShifterOperand(1 << Field::kUnboxingCandidateBit)); | 2073 __ tst(temp2, Operand(1 << Field::kUnboxingCandidateBit)); |
| 2074 __ b(&store_pointer, EQ); | 2074 __ b(&store_pointer, EQ); |
| 2075 | 2075 |
| 2076 __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); | 2076 __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); |
| 2077 __ CompareImmediate(temp2, kDoubleCid); | 2077 __ CompareImmediate(temp2, kDoubleCid); |
| 2078 __ b(&store_double, EQ); | 2078 __ b(&store_double, EQ); |
| 2079 | 2079 |
| 2080 __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); | 2080 __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); |
| 2081 __ CompareImmediate(temp2, kFloat32x4Cid); | 2081 __ CompareImmediate(temp2, kFloat32x4Cid); |
| 2082 __ b(&store_float32x4, EQ); | 2082 __ b(&store_float32x4, EQ); |
| 2083 | 2083 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2303 __ LoadImmediate(R6, heap->TopAddress()); | 2303 __ LoadImmediate(R6, heap->TopAddress()); |
| 2304 __ ldr(R0, Address(R6, 0)); // Potential new object start. | 2304 __ ldr(R0, Address(R6, 0)); // Potential new object start. |
| 2305 __ AddImmediate(R7, R0, kArraySize); // Potential next object start. | 2305 __ AddImmediate(R7, R0, kArraySize); // Potential next object start. |
| 2306 __ b(slow_path, VS); | 2306 __ b(slow_path, VS); |
| 2307 | 2307 |
| 2308 // Check if the allocation fits into the remaining space. | 2308 // Check if the allocation fits into the remaining space. |
| 2309 // R0: potential new object start. | 2309 // R0: potential new object start. |
| 2310 // R7: potential next object start. | 2310 // R7: potential next object start. |
| 2311 __ LoadImmediate(R3, heap->EndAddress()); | 2311 __ LoadImmediate(R3, heap->EndAddress()); |
| 2312 __ ldr(R3, Address(R3, 0)); | 2312 __ ldr(R3, Address(R3, 0)); |
| 2313 __ cmp(R7, ShifterOperand(R3)); | 2313 __ cmp(R7, Operand(R3)); |
| 2314 __ b(slow_path, CS); | 2314 __ b(slow_path, CS); |
| 2315 | 2315 |
| 2316 // Successfully allocated the object(s), now update top to point to | 2316 // Successfully allocated the object(s), now update top to point to |
| 2317 // next object start and initialize the object. | 2317 // next object start and initialize the object. |
| 2318 __ str(R7, Address(R6, 0)); | 2318 __ str(R7, Address(R6, 0)); |
| 2319 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); | 2319 __ add(R0, R0, Operand(kHeapObjectTag)); |
| 2320 __ LoadImmediate(R8, heap->TopAddress()); | 2320 __ LoadImmediate(R8, heap->TopAddress()); |
| 2321 __ UpdateAllocationStatsWithSize(kArrayCid, R8, R4); | 2321 __ UpdateAllocationStatsWithSize(kArrayCid, R8, R4); |
| 2322 | 2322 |
| 2323 | 2323 |
| 2324 // Initialize the tags. | 2324 // Initialize the tags. |
| 2325 // R0: new object start as a tagged pointer. | 2325 // R0: new object start as a tagged pointer. |
| 2326 { | 2326 { |
| 2327 uword tags = 0; | 2327 uword tags = 0; |
| 2328 tags = RawObject::ClassIdTag::update(kArrayCid, tags); | 2328 tags = RawObject::ClassIdTag::update(kArrayCid, tags); |
| 2329 tags = RawObject::SizeTag::update(kArraySize, tags); | 2329 tags = RawObject::SizeTag::update(kArraySize, tags); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2347 // R0: new object start as a tagged pointer. | 2347 // R0: new object start as a tagged pointer. |
| 2348 // R7: new object end address. | 2348 // R7: new object end address. |
| 2349 // R8: iterator which initially points to the start of the variable | 2349 // R8: iterator which initially points to the start of the variable |
| 2350 // data area to be initialized. | 2350 // data area to be initialized. |
| 2351 // R3: null | 2351 // R3: null |
| 2352 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); | 2352 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); |
| 2353 __ AddImmediate(R8, R0, sizeof(RawArray) - kHeapObjectTag); | 2353 __ AddImmediate(R8, R0, sizeof(RawArray) - kHeapObjectTag); |
| 2354 | 2354 |
| 2355 Label init_loop; | 2355 Label init_loop; |
| 2356 __ Bind(&init_loop); | 2356 __ Bind(&init_loop); |
| 2357 __ cmp(R8, ShifterOperand(R7)); | 2357 __ cmp(R8, Operand(R7)); |
| 2358 __ str(R3, Address(R8, 0), CC); | 2358 __ str(R3, Address(R8, 0), CC); |
| 2359 __ AddImmediate(R8, kWordSize, CC); | 2359 __ AddImmediate(R8, kWordSize, CC); |
| 2360 __ b(&init_loop, CC); | 2360 __ b(&init_loop, CC); |
| 2361 __ b(done); | 2361 __ b(done); |
| 2362 } | 2362 } |
| 2363 | 2363 |
| 2364 | 2364 |
| 2365 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2365 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2366 const Register kLengthReg = R2; | 2366 const Register kLengthReg = R2; |
| 2367 const Register kElemTypeReg = R1; | 2367 const Register kElemTypeReg = R1; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2446 const ExternalLabel label(stub.EntryPoint()); | 2446 const ExternalLabel label(stub.EntryPoint()); |
| 2447 | 2447 |
| 2448 LocationSummary* locs = instruction_->locs(); | 2448 LocationSummary* locs = instruction_->locs(); |
| 2449 locs->live_registers()->Remove(locs->out(0)); | 2449 locs->live_registers()->Remove(locs->out(0)); |
| 2450 | 2450 |
| 2451 compiler->SaveLiveRegisters(locs); | 2451 compiler->SaveLiveRegisters(locs); |
| 2452 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 2452 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 2453 &label, | 2453 &label, |
| 2454 PcDescriptors::kOther, | 2454 PcDescriptors::kOther, |
| 2455 locs); | 2455 locs); |
| 2456 __ mov(locs->out(0).reg(), ShifterOperand(R0)); | 2456 __ mov(locs->out(0).reg(), Operand(R0)); |
| 2457 compiler->RestoreLiveRegisters(locs); | 2457 compiler->RestoreLiveRegisters(locs); |
| 2458 | 2458 |
| 2459 __ b(exit_label()); | 2459 __ b(exit_label()); |
| 2460 } | 2460 } |
| 2461 | 2461 |
| 2462 private: | 2462 private: |
| 2463 Instruction* instruction_; | 2463 Instruction* instruction_; |
| 2464 }; | 2464 }; |
| 2465 | 2465 |
| 2466 | 2466 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2478 const ExternalLabel label(stub.EntryPoint()); | 2478 const ExternalLabel label(stub.EntryPoint()); |
| 2479 | 2479 |
| 2480 LocationSummary* locs = instruction_->locs(); | 2480 LocationSummary* locs = instruction_->locs(); |
| 2481 locs->live_registers()->Remove(locs->out(0)); | 2481 locs->live_registers()->Remove(locs->out(0)); |
| 2482 | 2482 |
| 2483 compiler->SaveLiveRegisters(locs); | 2483 compiler->SaveLiveRegisters(locs); |
| 2484 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 2484 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 2485 &label, | 2485 &label, |
| 2486 PcDescriptors::kOther, | 2486 PcDescriptors::kOther, |
| 2487 locs); | 2487 locs); |
| 2488 __ mov(locs->out(0).reg(), ShifterOperand(R0)); | 2488 __ mov(locs->out(0).reg(), Operand(R0)); |
| 2489 compiler->RestoreLiveRegisters(locs); | 2489 compiler->RestoreLiveRegisters(locs); |
| 2490 | 2490 |
| 2491 __ b(exit_label()); | 2491 __ b(exit_label()); |
| 2492 } | 2492 } |
| 2493 | 2493 |
| 2494 private: | 2494 private: |
| 2495 Instruction* instruction_; | 2495 Instruction* instruction_; |
| 2496 }; | 2496 }; |
| 2497 | 2497 |
| 2498 | 2498 |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2699 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2699 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 2700 !type_arguments().CanShareInstantiatorTypeArguments( | 2700 !type_arguments().CanShareInstantiatorTypeArguments( |
| 2701 instantiator_class())); | 2701 instantiator_class())); |
| 2702 // If the instantiator is null and if the type argument vector | 2702 // If the instantiator is null and if the type argument vector |
| 2703 // instantiated from null becomes a vector of dynamic, then use null as | 2703 // instantiated from null becomes a vector of dynamic, then use null as |
| 2704 // the type arguments. | 2704 // the type arguments. |
| 2705 Label type_arguments_instantiated; | 2705 Label type_arguments_instantiated; |
| 2706 const intptr_t len = type_arguments().Length(); | 2706 const intptr_t len = type_arguments().Length(); |
| 2707 if (type_arguments().IsRawInstantiatedRaw(len)) { | 2707 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 2708 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | 2708 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 2709 __ cmp(instantiator_reg, ShifterOperand(IP)); | 2709 __ cmp(instantiator_reg, Operand(IP)); |
| 2710 __ b(&type_arguments_instantiated, EQ); | 2710 __ b(&type_arguments_instantiated, EQ); |
| 2711 } | 2711 } |
| 2712 | 2712 |
| 2713 __ LoadObject(R2, type_arguments()); | 2713 __ LoadObject(R2, type_arguments()); |
| 2714 __ ldr(R2, FieldAddress(R2, TypeArguments::instantiations_offset())); | 2714 __ ldr(R2, FieldAddress(R2, TypeArguments::instantiations_offset())); |
| 2715 __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag); | 2715 __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag); |
| 2716 // The instantiations cache is initialized with Object::zero_array() and is | 2716 // The instantiations cache is initialized with Object::zero_array() and is |
| 2717 // therefore guaranteed to contain kNoInstantiator. No length check needed. | 2717 // therefore guaranteed to contain kNoInstantiator. No length check needed. |
| 2718 Label loop, found, slow_case; | 2718 Label loop, found, slow_case; |
| 2719 __ Bind(&loop); | 2719 __ Bind(&loop); |
| 2720 __ ldr(R1, Address(R2, 0 * kWordSize)); // Cached instantiator. | 2720 __ ldr(R1, Address(R2, 0 * kWordSize)); // Cached instantiator. |
| 2721 __ cmp(R1, ShifterOperand(R0)); | 2721 __ cmp(R1, Operand(R0)); |
| 2722 __ b(&found, EQ); | 2722 __ b(&found, EQ); |
| 2723 __ AddImmediate(R2, 2 * kWordSize); | 2723 __ AddImmediate(R2, 2 * kWordSize); |
| 2724 __ CompareImmediate(R1, Smi::RawValue(StubCode::kNoInstantiator)); | 2724 __ CompareImmediate(R1, Smi::RawValue(StubCode::kNoInstantiator)); |
| 2725 __ b(&loop, NE); | 2725 __ b(&loop, NE); |
| 2726 __ b(&slow_case); | 2726 __ b(&slow_case); |
| 2727 __ Bind(&found); | 2727 __ Bind(&found); |
| 2728 __ ldr(R0, Address(R2, 1 * kWordSize)); // Cached instantiated args. | 2728 __ ldr(R0, Address(R2, 1 * kWordSize)); // Cached instantiated args. |
| 2729 __ b(&type_arguments_instantiated); | 2729 __ b(&type_arguments_instantiated); |
| 2730 | 2730 |
| 2731 __ Bind(&slow_case); | 2731 __ Bind(&slow_case); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2899 Label osr_entry_label_; | 2899 Label osr_entry_label_; |
| 2900 }; | 2900 }; |
| 2901 | 2901 |
| 2902 | 2902 |
| 2903 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2903 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2904 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2904 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 2905 compiler->AddSlowPathCode(slow_path); | 2905 compiler->AddSlowPathCode(slow_path); |
| 2906 | 2906 |
| 2907 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); | 2907 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); |
| 2908 __ ldr(IP, Address(IP)); | 2908 __ ldr(IP, Address(IP)); |
| 2909 __ cmp(SP, ShifterOperand(IP)); | 2909 __ cmp(SP, Operand(IP)); |
| 2910 __ b(slow_path->entry_label(), LS); | 2910 __ b(slow_path->entry_label(), LS); |
| 2911 if (compiler->CanOSRFunction() && in_loop()) { | 2911 if (compiler->CanOSRFunction() && in_loop()) { |
| 2912 const Register temp = locs()->temp(0).reg(); | 2912 const Register temp = locs()->temp(0).reg(); |
| 2913 // In unoptimized code check the usage counter to trigger OSR at loop | 2913 // In unoptimized code check the usage counter to trigger OSR at loop |
| 2914 // stack checks. Use progressively higher thresholds for more deeply | 2914 // stack checks. Use progressively higher thresholds for more deeply |
| 2915 // nested loops to attempt to hit outer loops with OSR when possible. | 2915 // nested loops to attempt to hit outer loops with OSR when possible. |
| 2916 __ LoadObject(temp, compiler->parsed_function().function()); | 2916 __ LoadObject(temp, compiler->parsed_function().function()); |
| 2917 intptr_t threshold = | 2917 intptr_t threshold = |
| 2918 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2918 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
| 2919 __ ldr(temp, FieldAddress(temp, Function::usage_counter_offset())); | 2919 __ ldr(temp, FieldAddress(temp, Function::usage_counter_offset())); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2941 ASSERT(constant.IsSmi()); | 2941 ASSERT(constant.IsSmi()); |
| 2942 // Immediate shift operation takes 5 bits for the count. | 2942 // Immediate shift operation takes 5 bits for the count. |
| 2943 const intptr_t kCountLimit = 0x1F; | 2943 const intptr_t kCountLimit = 0x1F; |
| 2944 const intptr_t value = Smi::Cast(constant).Value(); | 2944 const intptr_t value = Smi::Cast(constant).Value(); |
| 2945 if (value == 0) { | 2945 if (value == 0) { |
| 2946 __ MoveRegister(result, left); | 2946 __ MoveRegister(result, left); |
| 2947 } else if ((value < 0) || (value >= kCountLimit)) { | 2947 } else if ((value < 0) || (value >= kCountLimit)) { |
| 2948 // This condition may not be known earlier in some cases because | 2948 // This condition may not be known earlier in some cases because |
| 2949 // of constant propagation, inlining, etc. | 2949 // of constant propagation, inlining, etc. |
| 2950 if ((value >= kCountLimit) && is_truncating) { | 2950 if ((value >= kCountLimit) && is_truncating) { |
| 2951 __ mov(result, ShifterOperand(0)); | 2951 __ mov(result, Operand(0)); |
| 2952 } else { | 2952 } else { |
| 2953 // Result is Mint or exception. | 2953 // Result is Mint or exception. |
| 2954 __ b(deopt); | 2954 __ b(deopt); |
| 2955 } | 2955 } |
| 2956 } else { | 2956 } else { |
| 2957 if (!is_truncating) { | 2957 if (!is_truncating) { |
| 2958 // Check for overflow (preserve left). | 2958 // Check for overflow (preserve left). |
| 2959 __ Lsl(IP, left, value); | 2959 __ Lsl(IP, left, value); |
| 2960 __ cmp(left, ShifterOperand(IP, ASR, value)); | 2960 __ cmp(left, Operand(IP, ASR, value)); |
| 2961 __ b(deopt, NE); // Overflow. | 2961 __ b(deopt, NE); // Overflow. |
| 2962 } | 2962 } |
| 2963 // Shift for result now we know there is no overflow. | 2963 // Shift for result now we know there is no overflow. |
| 2964 __ Lsl(result, left, value); | 2964 __ Lsl(result, left, value); |
| 2965 } | 2965 } |
| 2966 return; | 2966 return; |
| 2967 } | 2967 } |
| 2968 | 2968 |
| 2969 // Right (locs.in(1)) is not constant. | 2969 // Right (locs.in(1)) is not constant. |
| 2970 const Register right = locs.in(1).reg(); | 2970 const Register right = locs.in(1).reg(); |
| 2971 Range* right_range = shift_left->right()->definition()->range(); | 2971 Range* right_range = shift_left->right()->definition()->range(); |
| 2972 if (shift_left->left()->BindsToConstant() && !is_truncating) { | 2972 if (shift_left->left()->BindsToConstant() && !is_truncating) { |
| 2973 // TODO(srdjan): Implement code below for is_truncating(). | 2973 // TODO(srdjan): Implement code below for is_truncating(). |
| 2974 // If left is constant, we know the maximal allowed size for right. | 2974 // If left is constant, we know the maximal allowed size for right. |
| 2975 const Object& obj = shift_left->left()->BoundConstant(); | 2975 const Object& obj = shift_left->left()->BoundConstant(); |
| 2976 if (obj.IsSmi()) { | 2976 if (obj.IsSmi()) { |
| 2977 const intptr_t left_int = Smi::Cast(obj).Value(); | 2977 const intptr_t left_int = Smi::Cast(obj).Value(); |
| 2978 if (left_int == 0) { | 2978 if (left_int == 0) { |
| 2979 __ cmp(right, ShifterOperand(0)); | 2979 __ cmp(right, Operand(0)); |
| 2980 __ b(deopt, MI); | 2980 __ b(deopt, MI); |
| 2981 __ mov(result, ShifterOperand(0)); | 2981 __ mov(result, Operand(0)); |
| 2982 return; | 2982 return; |
| 2983 } | 2983 } |
| 2984 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2984 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
| 2985 const bool right_needs_check = | 2985 const bool right_needs_check = |
| 2986 (right_range == NULL) || | 2986 (right_range == NULL) || |
| 2987 !right_range->IsWithin(0, max_right - 1); | 2987 !right_range->IsWithin(0, max_right - 1); |
| 2988 if (right_needs_check) { | 2988 if (right_needs_check) { |
| 2989 __ cmp(right, | 2989 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right)))); |
| 2990 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right)))); | |
| 2991 __ b(deopt, CS); | 2990 __ b(deopt, CS); |
| 2992 } | 2991 } |
| 2993 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 2992 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 2994 __ Lsl(result, left, IP); | 2993 __ Lsl(result, left, IP); |
| 2995 } | 2994 } |
| 2996 return; | 2995 return; |
| 2997 } | 2996 } |
| 2998 | 2997 |
| 2999 const bool right_needs_check = | 2998 const bool right_needs_check = |
| 3000 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); | 2999 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); |
| 3001 if (is_truncating) { | 3000 if (is_truncating) { |
| 3002 if (right_needs_check) { | 3001 if (right_needs_check) { |
| 3003 const bool right_may_be_negative = | 3002 const bool right_may_be_negative = |
| 3004 (right_range == NULL) || | 3003 (right_range == NULL) || |
| 3005 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); | 3004 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); |
| 3006 if (right_may_be_negative) { | 3005 if (right_may_be_negative) { |
| 3007 ASSERT(shift_left->CanDeoptimize()); | 3006 ASSERT(shift_left->CanDeoptimize()); |
| 3008 __ cmp(right, ShifterOperand(0)); | 3007 __ cmp(right, Operand(0)); |
| 3009 __ b(deopt, MI); | 3008 __ b(deopt, MI); |
| 3010 } | 3009 } |
| 3011 | 3010 |
| 3012 __ cmp(right, | 3011 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
| 3013 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 3012 __ mov(result, Operand(0), CS); |
| 3014 __ mov(result, ShifterOperand(0), CS); | |
| 3015 __ Asr(IP, right, kSmiTagSize, CC); // SmiUntag right into IP if CC. | 3013 __ Asr(IP, right, kSmiTagSize, CC); // SmiUntag right into IP if CC. |
| 3016 __ Lsl(result, left, IP, CC); | 3014 __ Lsl(result, left, IP, CC); |
| 3017 } else { | 3015 } else { |
| 3018 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3016 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 3019 __ Lsl(result, left, IP); | 3017 __ Lsl(result, left, IP); |
| 3020 } | 3018 } |
| 3021 } else { | 3019 } else { |
| 3022 if (right_needs_check) { | 3020 if (right_needs_check) { |
| 3023 ASSERT(shift_left->CanDeoptimize()); | 3021 ASSERT(shift_left->CanDeoptimize()); |
| 3024 __ cmp(right, | 3022 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
| 3025 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | |
| 3026 __ b(deopt, CS); | 3023 __ b(deopt, CS); |
| 3027 } | 3024 } |
| 3028 // Left is not a constant. | 3025 // Left is not a constant. |
| 3029 // Check if count too large for handling it inlined. | 3026 // Check if count too large for handling it inlined. |
| 3030 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3027 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 3031 // Overflow test (preserve left, right, and IP); | 3028 // Overflow test (preserve left, right, and IP); |
| 3032 const Register temp = locs.temp(0).reg(); | 3029 const Register temp = locs.temp(0).reg(); |
| 3033 __ Lsl(temp, left, IP); | 3030 __ Lsl(temp, left, IP); |
| 3034 __ cmp(left, ShifterOperand(temp, ASR, IP)); | 3031 __ cmp(left, Operand(temp, ASR, IP)); |
| 3035 __ b(deopt, NE); // Overflow. | 3032 __ b(deopt, NE); // Overflow. |
| 3036 // Shift for result now we know there is no overflow. | 3033 // Shift for result now we know there is no overflow. |
| 3037 __ Lsl(result, left, IP); | 3034 __ Lsl(result, left, IP); |
| 3038 } | 3035 } |
| 3039 } | 3036 } |
| 3040 | 3037 |
| 3041 | 3038 |
| 3042 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Isolate* isolate, | 3039 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Isolate* isolate, |
| 3043 bool opt) const { | 3040 bool opt) const { |
| 3044 const intptr_t kNumInputs = 2; | 3041 const intptr_t kNumInputs = 2; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3122 __ SubImmediateSetFlags(result, left, imm); | 3119 __ SubImmediateSetFlags(result, left, imm); |
| 3123 __ b(deopt, VS); | 3120 __ b(deopt, VS); |
| 3124 } | 3121 } |
| 3125 break; | 3122 break; |
| 3126 } | 3123 } |
| 3127 case Token::kMUL: { | 3124 case Token::kMUL: { |
| 3128 // Keep left value tagged and untag right value. | 3125 // Keep left value tagged and untag right value. |
| 3129 const intptr_t value = Smi::Cast(constant).Value(); | 3126 const intptr_t value = Smi::Cast(constant).Value(); |
| 3130 if (deopt == NULL) { | 3127 if (deopt == NULL) { |
| 3131 if (value == 2) { | 3128 if (value == 2) { |
| 3132 __ mov(result, ShifterOperand(left, LSL, 1)); | 3129 __ mov(result, Operand(left, LSL, 1)); |
| 3133 } else { | 3130 } else { |
| 3134 __ LoadImmediate(IP, value); | 3131 __ LoadImmediate(IP, value); |
| 3135 __ mul(result, left, IP); | 3132 __ mul(result, left, IP); |
| 3136 } | 3133 } |
| 3137 } else { | 3134 } else { |
| 3138 if (value == 2) { | 3135 if (value == 2) { |
| 3139 __ mov(IP, ShifterOperand(left, ASR, 31)); // IP = sign of left. | 3136 __ mov(IP, Operand(left, ASR, 31)); // IP = sign of left. |
| 3140 __ mov(result, ShifterOperand(left, LSL, 1)); | 3137 __ mov(result, Operand(left, LSL, 1)); |
| 3141 // IP: result bits 32..63. | 3138 // IP: result bits 32..63. |
| 3142 __ cmp(IP, ShifterOperand(result, ASR, 31)); | 3139 __ cmp(IP, Operand(result, ASR, 31)); |
| 3143 __ b(deopt, NE); | 3140 __ b(deopt, NE); |
| 3144 } else { | 3141 } else { |
| 3145 if (TargetCPUFeatures::arm_version() == ARMv7) { | 3142 if (TargetCPUFeatures::arm_version() == ARMv7) { |
| 3146 __ LoadImmediate(IP, value); | 3143 __ LoadImmediate(IP, value); |
| 3147 __ smull(result, IP, left, IP); | 3144 __ smull(result, IP, left, IP); |
| 3148 // IP: result bits 32..63. | 3145 // IP: result bits 32..63. |
| 3149 __ cmp(IP, ShifterOperand(result, ASR, 31)); | 3146 __ cmp(IP, Operand(result, ASR, 31)); |
| 3150 __ b(deopt, NE); | 3147 __ b(deopt, NE); |
| 3151 } else { | 3148 } else { |
| 3152 const QRegister qtmp = locs()->temp(0).fpu_reg(); | 3149 const QRegister qtmp = locs()->temp(0).fpu_reg(); |
| 3153 const DRegister dtmp0 = EvenDRegisterOf(qtmp); | 3150 const DRegister dtmp0 = EvenDRegisterOf(qtmp); |
| 3154 const DRegister dtmp1 = OddDRegisterOf(qtmp); | 3151 const DRegister dtmp1 = OddDRegisterOf(qtmp); |
| 3155 __ LoadImmediate(IP, value); | 3152 __ LoadImmediate(IP, value); |
| 3156 __ CheckMultSignedOverflow(left, IP, result, dtmp0, dtmp1, deopt); | 3153 __ CheckMultSignedOverflow(left, IP, result, dtmp0, dtmp1, deopt); |
| 3157 __ mul(result, left, IP); | 3154 __ mul(result, left, IP); |
| 3158 } | 3155 } |
| 3159 } | 3156 } |
| 3160 } | 3157 } |
| 3161 break; | 3158 break; |
| 3162 } | 3159 } |
| 3163 case Token::kTRUNCDIV: { | 3160 case Token::kTRUNCDIV: { |
| 3164 const intptr_t value = Smi::Cast(constant).Value(); | 3161 const intptr_t value = Smi::Cast(constant).Value(); |
| 3165 if (value == 1) { | 3162 if (value == 1) { |
| 3166 __ MoveRegister(result, left); | 3163 __ MoveRegister(result, left); |
| 3167 break; | 3164 break; |
| 3168 } else if (value == -1) { | 3165 } else if (value == -1) { |
| 3169 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3166 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 3170 // case we cannot negate the result. | 3167 // case we cannot negate the result. |
| 3171 __ CompareImmediate(left, 0x80000000); | 3168 __ CompareImmediate(left, 0x80000000); |
| 3172 __ b(deopt, EQ); | 3169 __ b(deopt, EQ); |
| 3173 __ rsb(result, left, ShifterOperand(0)); | 3170 __ rsb(result, left, Operand(0)); |
| 3174 break; | 3171 break; |
| 3175 } | 3172 } |
| 3176 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); | 3173 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); |
| 3177 const intptr_t shift_count = | 3174 const intptr_t shift_count = |
| 3178 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; | 3175 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; |
| 3179 ASSERT(kSmiTagSize == 1); | 3176 ASSERT(kSmiTagSize == 1); |
| 3180 __ mov(IP, ShifterOperand(left, ASR, 31)); | 3177 __ mov(IP, Operand(left, ASR, 31)); |
| 3181 ASSERT(shift_count > 1); // 1, -1 case handled above. | 3178 ASSERT(shift_count > 1); // 1, -1 case handled above. |
| 3182 const Register temp = locs()->temp(0).reg(); | 3179 const Register temp = locs()->temp(0).reg(); |
| 3183 __ add(temp, left, ShifterOperand(IP, LSR, 32 - shift_count)); | 3180 __ add(temp, left, Operand(IP, LSR, 32 - shift_count)); |
| 3184 ASSERT(shift_count > 0); | 3181 ASSERT(shift_count > 0); |
| 3185 __ mov(result, ShifterOperand(temp, ASR, shift_count)); | 3182 __ mov(result, Operand(temp, ASR, shift_count)); |
| 3186 if (value < 0) { | 3183 if (value < 0) { |
| 3187 __ rsb(result, result, ShifterOperand(0)); | 3184 __ rsb(result, result, Operand(0)); |
| 3188 } | 3185 } |
| 3189 __ SmiTag(result); | 3186 __ SmiTag(result); |
| 3190 break; | 3187 break; |
| 3191 } | 3188 } |
| 3192 case Token::kBIT_AND: { | 3189 case Token::kBIT_AND: { |
| 3193 // No overflow check. | 3190 // No overflow check. |
| 3194 ShifterOperand shifter_op; | 3191 Operand o; |
| 3195 if (ShifterOperand::CanHold(imm, &shifter_op)) { | 3192 if (Operand::CanHold(imm, &o)) { |
| 3196 __ and_(result, left, shifter_op); | 3193 __ and_(result, left, o); |
| 3197 } else if (ShifterOperand::CanHold(~imm, &shifter_op)) { | 3194 } else if (Operand::CanHold(~imm, &o)) { |
| 3198 __ bic(result, left, shifter_op); | 3195 __ bic(result, left, o); |
| 3199 } else { | 3196 } else { |
| 3200 __ LoadImmediate(IP, imm); | 3197 __ LoadImmediate(IP, imm); |
| 3201 __ and_(result, left, ShifterOperand(IP)); | 3198 __ and_(result, left, Operand(IP)); |
| 3202 } | 3199 } |
| 3203 break; | 3200 break; |
| 3204 } | 3201 } |
| 3205 case Token::kBIT_OR: { | 3202 case Token::kBIT_OR: { |
| 3206 // No overflow check. | 3203 // No overflow check. |
| 3207 ShifterOperand shifter_op; | 3204 Operand o; |
| 3208 if (ShifterOperand::CanHold(imm, &shifter_op)) { | 3205 if (Operand::CanHold(imm, &o)) { |
| 3209 __ orr(result, left, shifter_op); | 3206 __ orr(result, left, o); |
| 3210 } else { | 3207 } else { |
| 3211 __ LoadImmediate(IP, imm); | 3208 __ LoadImmediate(IP, imm); |
| 3212 __ orr(result, left, ShifterOperand(IP)); | 3209 __ orr(result, left, Operand(IP)); |
| 3213 } | 3210 } |
| 3214 break; | 3211 break; |
| 3215 } | 3212 } |
| 3216 case Token::kBIT_XOR: { | 3213 case Token::kBIT_XOR: { |
| 3217 // No overflow check. | 3214 // No overflow check. |
| 3218 ShifterOperand shifter_op; | 3215 Operand o; |
| 3219 if (ShifterOperand::CanHold(imm, &shifter_op)) { | 3216 if (Operand::CanHold(imm, &o)) { |
| 3220 __ eor(result, left, shifter_op); | 3217 __ eor(result, left, o); |
| 3221 } else { | 3218 } else { |
| 3222 __ LoadImmediate(IP, imm); | 3219 __ LoadImmediate(IP, imm); |
| 3223 __ eor(result, left, ShifterOperand(IP)); | 3220 __ eor(result, left, Operand(IP)); |
| 3224 } | 3221 } |
| 3225 break; | 3222 break; |
| 3226 } | 3223 } |
| 3227 case Token::kSHR: { | 3224 case Token::kSHR: { |
| 3228 // sarl operation masks the count to 5 bits. | 3225 // sarl operation masks the count to 5 bits. |
| 3229 const intptr_t kCountLimit = 0x1F; | 3226 const intptr_t kCountLimit = 0x1F; |
| 3230 intptr_t value = Smi::Cast(constant).Value(); | 3227 intptr_t value = Smi::Cast(constant).Value(); |
| 3231 | 3228 |
| 3232 if (value == 0) { | 3229 if (value == 0) { |
| 3233 // TODO(vegorov): should be handled outside. | 3230 // TODO(vegorov): should be handled outside. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3254 break; | 3251 break; |
| 3255 } | 3252 } |
| 3256 return; | 3253 return; |
| 3257 } | 3254 } |
| 3258 | 3255 |
| 3259 const Register right = locs()->in(1).reg(); | 3256 const Register right = locs()->in(1).reg(); |
| 3260 Range* right_range = this->right()->definition()->range(); | 3257 Range* right_range = this->right()->definition()->range(); |
| 3261 switch (op_kind()) { | 3258 switch (op_kind()) { |
| 3262 case Token::kADD: { | 3259 case Token::kADD: { |
| 3263 if (deopt == NULL) { | 3260 if (deopt == NULL) { |
| 3264 __ add(result, left, ShifterOperand(right)); | 3261 __ add(result, left, Operand(right)); |
| 3265 } else { | 3262 } else { |
| 3266 __ adds(result, left, ShifterOperand(right)); | 3263 __ adds(result, left, Operand(right)); |
| 3267 __ b(deopt, VS); | 3264 __ b(deopt, VS); |
| 3268 } | 3265 } |
| 3269 break; | 3266 break; |
| 3270 } | 3267 } |
| 3271 case Token::kSUB: { | 3268 case Token::kSUB: { |
| 3272 if (deopt == NULL) { | 3269 if (deopt == NULL) { |
| 3273 __ sub(result, left, ShifterOperand(right)); | 3270 __ sub(result, left, Operand(right)); |
| 3274 } else { | 3271 } else { |
| 3275 __ subs(result, left, ShifterOperand(right)); | 3272 __ subs(result, left, Operand(right)); |
| 3276 __ b(deopt, VS); | 3273 __ b(deopt, VS); |
| 3277 } | 3274 } |
| 3278 break; | 3275 break; |
| 3279 } | 3276 } |
| 3280 case Token::kMUL: { | 3277 case Token::kMUL: { |
| 3281 __ Asr(IP, left, kSmiTagSize); // SmiUntag left into IP. | 3278 __ Asr(IP, left, kSmiTagSize); // SmiUntag left into IP. |
| 3282 if (deopt == NULL) { | 3279 if (deopt == NULL) { |
| 3283 __ mul(result, IP, right); | 3280 __ mul(result, IP, right); |
| 3284 } else { | 3281 } else { |
| 3285 if (TargetCPUFeatures::arm_version() == ARMv7) { | 3282 if (TargetCPUFeatures::arm_version() == ARMv7) { |
| 3286 __ smull(result, IP, IP, right); | 3283 __ smull(result, IP, IP, right); |
| 3287 // IP: result bits 32..63. | 3284 // IP: result bits 32..63. |
| 3288 __ cmp(IP, ShifterOperand(result, ASR, 31)); | 3285 __ cmp(IP, Operand(result, ASR, 31)); |
| 3289 __ b(deopt, NE); | 3286 __ b(deopt, NE); |
| 3290 } else { | 3287 } else { |
| 3291 const QRegister qtmp = locs()->temp(0).fpu_reg(); | 3288 const QRegister qtmp = locs()->temp(0).fpu_reg(); |
| 3292 const DRegister dtmp0 = EvenDRegisterOf(qtmp); | 3289 const DRegister dtmp0 = EvenDRegisterOf(qtmp); |
| 3293 const DRegister dtmp1 = OddDRegisterOf(qtmp); | 3290 const DRegister dtmp1 = OddDRegisterOf(qtmp); |
| 3294 __ CheckMultSignedOverflow(IP, right, result, dtmp0, dtmp1, deopt); | 3291 __ CheckMultSignedOverflow(IP, right, result, dtmp0, dtmp1, deopt); |
| 3295 __ mul(result, IP, right); | 3292 __ mul(result, IP, right); |
| 3296 } | 3293 } |
| 3297 } | 3294 } |
| 3298 break; | 3295 break; |
| 3299 } | 3296 } |
| 3300 case Token::kBIT_AND: { | 3297 case Token::kBIT_AND: { |
| 3301 // No overflow check. | 3298 // No overflow check. |
| 3302 __ and_(result, left, ShifterOperand(right)); | 3299 __ and_(result, left, Operand(right)); |
| 3303 break; | 3300 break; |
| 3304 } | 3301 } |
| 3305 case Token::kBIT_OR: { | 3302 case Token::kBIT_OR: { |
| 3306 // No overflow check. | 3303 // No overflow check. |
| 3307 __ orr(result, left, ShifterOperand(right)); | 3304 __ orr(result, left, Operand(right)); |
| 3308 break; | 3305 break; |
| 3309 } | 3306 } |
| 3310 case Token::kBIT_XOR: { | 3307 case Token::kBIT_XOR: { |
| 3311 // No overflow check. | 3308 // No overflow check. |
| 3312 __ eor(result, left, ShifterOperand(right)); | 3309 __ eor(result, left, Operand(right)); |
| 3313 break; | 3310 break; |
| 3314 } | 3311 } |
| 3315 case Token::kTRUNCDIV: { | 3312 case Token::kTRUNCDIV: { |
| 3316 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3313 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 3317 // Handle divide by zero in runtime. | 3314 // Handle divide by zero in runtime. |
| 3318 __ cmp(right, ShifterOperand(0)); | 3315 __ cmp(right, Operand(0)); |
| 3319 __ b(deopt, EQ); | 3316 __ b(deopt, EQ); |
| 3320 } | 3317 } |
| 3321 const Register temp = locs()->temp(0).reg(); | 3318 const Register temp = locs()->temp(0).reg(); |
| 3322 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 3319 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
| 3323 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3320 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
| 3324 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3321 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 3325 | 3322 |
| 3326 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 3323 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
| 3327 | 3324 |
| 3328 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3325 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 3329 // case we cannot tag the result. | 3326 // case we cannot tag the result. |
| 3330 __ CompareImmediate(result, 0x40000000); | 3327 __ CompareImmediate(result, 0x40000000); |
| 3331 __ b(deopt, EQ); | 3328 __ b(deopt, EQ); |
| 3332 __ SmiTag(result); | 3329 __ SmiTag(result); |
| 3333 break; | 3330 break; |
| 3334 } | 3331 } |
| 3335 case Token::kMOD: { | 3332 case Token::kMOD: { |
| 3336 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3333 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 3337 // Handle divide by zero in runtime. | 3334 // Handle divide by zero in runtime. |
| 3338 __ cmp(right, ShifterOperand(0)); | 3335 __ cmp(right, Operand(0)); |
| 3339 __ b(deopt, EQ); | 3336 __ b(deopt, EQ); |
| 3340 } | 3337 } |
| 3341 const Register temp = locs()->temp(0).reg(); | 3338 const Register temp = locs()->temp(0).reg(); |
| 3342 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 3339 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
| 3343 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3340 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
| 3344 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3341 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 3345 | 3342 |
| 3346 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 3343 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
| 3347 | 3344 |
| 3348 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3345 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 3349 __ mls(result, IP, result, temp); // result <- left - right * result | 3346 __ mls(result, IP, result, temp); // result <- left - right * result |
| 3350 __ SmiTag(result); | 3347 __ SmiTag(result); |
| 3351 // res = left % right; | 3348 // res = left % right; |
| 3352 // if (res < 0) { | 3349 // if (res < 0) { |
| 3353 // if (right < 0) { | 3350 // if (right < 0) { |
| 3354 // res = res - right; | 3351 // res = res - right; |
| 3355 // } else { | 3352 // } else { |
| 3356 // res = res + right; | 3353 // res = res + right; |
| 3357 // } | 3354 // } |
| 3358 // } | 3355 // } |
| 3359 Label done; | 3356 Label done; |
| 3360 __ cmp(result, ShifterOperand(0)); | 3357 __ cmp(result, Operand(0)); |
| 3361 __ b(&done, GE); | 3358 __ b(&done, GE); |
| 3362 // Result is negative, adjust it. | 3359 // Result is negative, adjust it. |
| 3363 __ cmp(right, ShifterOperand(0)); | 3360 __ cmp(right, Operand(0)); |
| 3364 __ sub(result, result, ShifterOperand(right), LT); | 3361 __ sub(result, result, Operand(right), LT); |
| 3365 __ add(result, result, ShifterOperand(right), GE); | 3362 __ add(result, result, Operand(right), GE); |
| 3366 __ Bind(&done); | 3363 __ Bind(&done); |
| 3367 break; | 3364 break; |
| 3368 } | 3365 } |
| 3369 case Token::kSHR: { | 3366 case Token::kSHR: { |
| 3370 if (CanDeoptimize()) { | 3367 if (CanDeoptimize()) { |
| 3371 __ CompareImmediate(right, 0); | 3368 __ CompareImmediate(right, 0); |
| 3372 __ b(deopt, LT); | 3369 __ b(deopt, LT); |
| 3373 } | 3370 } |
| 3374 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3371 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 3375 // sarl operation masks the count to 5 bits. | 3372 // sarl operation masks the count to 5 bits. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3421 | 3418 |
| 3422 | 3419 |
| 3423 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3420 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3424 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3421 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 3425 ICData::kDeoptBinaryDoubleOp); | 3422 ICData::kDeoptBinaryDoubleOp); |
| 3426 intptr_t left_cid = left()->Type()->ToCid(); | 3423 intptr_t left_cid = left()->Type()->ToCid(); |
| 3427 intptr_t right_cid = right()->Type()->ToCid(); | 3424 intptr_t right_cid = right()->Type()->ToCid(); |
| 3428 const Register left = locs()->in(0).reg(); | 3425 const Register left = locs()->in(0).reg(); |
| 3429 const Register right = locs()->in(1).reg(); | 3426 const Register right = locs()->in(1).reg(); |
| 3430 if (this->left()->definition() == this->right()->definition()) { | 3427 if (this->left()->definition() == this->right()->definition()) { |
| 3431 __ tst(left, ShifterOperand(kSmiTagMask)); | 3428 __ tst(left, Operand(kSmiTagMask)); |
| 3432 } else if (left_cid == kSmiCid) { | 3429 } else if (left_cid == kSmiCid) { |
| 3433 __ tst(right, ShifterOperand(kSmiTagMask)); | 3430 __ tst(right, Operand(kSmiTagMask)); |
| 3434 } else if (right_cid == kSmiCid) { | 3431 } else if (right_cid == kSmiCid) { |
| 3435 __ tst(left, ShifterOperand(kSmiTagMask)); | 3432 __ tst(left, Operand(kSmiTagMask)); |
| 3436 } else { | 3433 } else { |
| 3437 __ orr(IP, left, ShifterOperand(right)); | 3434 __ orr(IP, left, Operand(right)); |
| 3438 __ tst(IP, ShifterOperand(kSmiTagMask)); | 3435 __ tst(IP, Operand(kSmiTagMask)); |
| 3439 } | 3436 } |
| 3440 __ b(deopt, EQ); | 3437 __ b(deopt, EQ); |
| 3441 } | 3438 } |
| 3442 | 3439 |
| 3443 | 3440 |
| 3444 LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate, | 3441 LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate, |
| 3445 bool opt) const { | 3442 bool opt) const { |
| 3446 const intptr_t kNumInputs = 1; | 3443 const intptr_t kNumInputs = 1; |
| 3447 const intptr_t kNumTemps = 1; | 3444 const intptr_t kNumTemps = 1; |
| 3448 LocationSummary* summary = new(isolate) LocationSummary( | 3445 LocationSummary* summary = new(isolate) LocationSummary( |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3508 const Register temp = locs()->temp(0).reg(); | 3505 const Register temp = locs()->temp(0).reg(); |
| 3509 if (value_type->is_nullable() && | 3506 if (value_type->is_nullable() && |
| 3510 (value_type->ToNullableCid() == kDoubleCid)) { | 3507 (value_type->ToNullableCid() == kDoubleCid)) { |
| 3511 __ CompareImmediate(value, reinterpret_cast<intptr_t>(Object::null())); | 3508 __ CompareImmediate(value, reinterpret_cast<intptr_t>(Object::null())); |
| 3512 __ b(deopt, EQ); | 3509 __ b(deopt, EQ); |
| 3513 // It must be double now. | 3510 // It must be double now. |
| 3514 __ LoadDFromOffset(result, value, | 3511 __ LoadDFromOffset(result, value, |
| 3515 Double::value_offset() - kHeapObjectTag); | 3512 Double::value_offset() - kHeapObjectTag); |
| 3516 } else { | 3513 } else { |
| 3517 Label is_smi, done; | 3514 Label is_smi, done; |
| 3518 __ tst(value, ShifterOperand(kSmiTagMask)); | 3515 __ tst(value, Operand(kSmiTagMask)); |
| 3519 __ b(&is_smi, EQ); | 3516 __ b(&is_smi, EQ); |
| 3520 __ CompareClassId(value, kDoubleCid, temp); | 3517 __ CompareClassId(value, kDoubleCid, temp); |
| 3521 __ b(deopt, NE); | 3518 __ b(deopt, NE); |
| 3522 __ LoadDFromOffset(result, value, | 3519 __ LoadDFromOffset(result, value, |
| 3523 Double::value_offset() - kHeapObjectTag); | 3520 Double::value_offset() - kHeapObjectTag); |
| 3524 __ b(&done); | 3521 __ b(&done); |
| 3525 __ Bind(&is_smi); | 3522 __ Bind(&is_smi); |
| 3526 // TODO(regis): Why do we preserve value here but not above? | 3523 // TODO(regis): Why do we preserve value here but not above? |
| 3527 __ mov(IP, ShifterOperand(value, ASR, 1)); // Copy and untag. | 3524 __ mov(IP, Operand(value, ASR, 1)); // Copy and untag. |
| 3528 __ vmovsr(STMP, IP); | 3525 __ vmovsr(STMP, IP); |
| 3529 __ vcvtdi(result, STMP); | 3526 __ vcvtdi(result, STMP); |
| 3530 __ Bind(&done); | 3527 __ Bind(&done); |
| 3531 } | 3528 } |
| 3532 } | 3529 } |
| 3533 } | 3530 } |
| 3534 | 3531 |
| 3535 | 3532 |
| 3536 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, | 3533 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, |
| 3537 bool opt) const { | 3534 bool opt) const { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3585 | 3582 |
| 3586 | 3583 |
| 3587 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3584 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3588 const intptr_t value_cid = value()->Type()->ToCid(); | 3585 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3589 const Register value = locs()->in(0).reg(); | 3586 const Register value = locs()->in(0).reg(); |
| 3590 const QRegister result = locs()->out(0).fpu_reg(); | 3587 const QRegister result = locs()->out(0).fpu_reg(); |
| 3591 | 3588 |
| 3592 if (value_cid != kFloat32x4Cid) { | 3589 if (value_cid != kFloat32x4Cid) { |
| 3593 const Register temp = locs()->temp(0).reg(); | 3590 const Register temp = locs()->temp(0).reg(); |
| 3594 Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass); | 3591 Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass); |
| 3595 __ tst(value, ShifterOperand(kSmiTagMask)); | 3592 __ tst(value, Operand(kSmiTagMask)); |
| 3596 __ b(deopt, EQ); | 3593 __ b(deopt, EQ); |
| 3597 __ CompareClassId(value, kFloat32x4Cid, temp); | 3594 __ CompareClassId(value, kFloat32x4Cid, temp); |
| 3598 __ b(deopt, NE); | 3595 __ b(deopt, NE); |
| 3599 } | 3596 } |
| 3600 | 3597 |
| 3601 const DRegister dresult0 = EvenDRegisterOf(result); | 3598 const DRegister dresult0 = EvenDRegisterOf(result); |
| 3602 __ LoadMultipleDFromOffset(dresult0, 2, value, | 3599 __ LoadMultipleDFromOffset(dresult0, 2, value, |
| 3603 Float32x4::value_offset() - kHeapObjectTag); | 3600 Float32x4::value_offset() - kHeapObjectTag); |
| 3604 } | 3601 } |
| 3605 | 3602 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3656 | 3653 |
| 3657 | 3654 |
| 3658 void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3655 void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3659 const intptr_t value_cid = value()->Type()->ToCid(); | 3656 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3660 const Register value = locs()->in(0).reg(); | 3657 const Register value = locs()->in(0).reg(); |
| 3661 const QRegister result = locs()->out(0).fpu_reg(); | 3658 const QRegister result = locs()->out(0).fpu_reg(); |
| 3662 | 3659 |
| 3663 if (value_cid != kFloat64x2Cid) { | 3660 if (value_cid != kFloat64x2Cid) { |
| 3664 const Register temp = locs()->temp(0).reg(); | 3661 const Register temp = locs()->temp(0).reg(); |
| 3665 Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass); | 3662 Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass); |
| 3666 __ tst(value, ShifterOperand(kSmiTagMask)); | 3663 __ tst(value, Operand(kSmiTagMask)); |
| 3667 __ b(deopt, EQ); | 3664 __ b(deopt, EQ); |
| 3668 __ CompareClassId(value, kFloat64x2Cid, temp); | 3665 __ CompareClassId(value, kFloat64x2Cid, temp); |
| 3669 __ b(deopt, NE); | 3666 __ b(deopt, NE); |
| 3670 } | 3667 } |
| 3671 | 3668 |
| 3672 const DRegister dresult0 = EvenDRegisterOf(result); | 3669 const DRegister dresult0 = EvenDRegisterOf(result); |
| 3673 __ LoadMultipleDFromOffset(dresult0, 2, value, | 3670 __ LoadMultipleDFromOffset(dresult0, 2, value, |
| 3674 Float64x2::value_offset() - kHeapObjectTag); | 3671 Float64x2::value_offset() - kHeapObjectTag); |
| 3675 } | 3672 } |
| 3676 | 3673 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3704 const ExternalLabel label(stub.EntryPoint()); | 3701 const ExternalLabel label(stub.EntryPoint()); |
| 3705 | 3702 |
| 3706 LocationSummary* locs = instruction_->locs(); | 3703 LocationSummary* locs = instruction_->locs(); |
| 3707 locs->live_registers()->Remove(locs->out(0)); | 3704 locs->live_registers()->Remove(locs->out(0)); |
| 3708 | 3705 |
| 3709 compiler->SaveLiveRegisters(locs); | 3706 compiler->SaveLiveRegisters(locs); |
| 3710 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 3707 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 3711 &label, | 3708 &label, |
| 3712 PcDescriptors::kOther, | 3709 PcDescriptors::kOther, |
| 3713 locs); | 3710 locs); |
| 3714 __ mov(locs->out(0).reg(), ShifterOperand(R0)); | 3711 __ mov(locs->out(0).reg(), Operand(R0)); |
| 3715 compiler->RestoreLiveRegisters(locs); | 3712 compiler->RestoreLiveRegisters(locs); |
| 3716 | 3713 |
| 3717 __ b(exit_label()); | 3714 __ b(exit_label()); |
| 3718 } | 3715 } |
| 3719 | 3716 |
| 3720 private: | 3717 private: |
| 3721 BoxInt32x4Instr* instruction_; | 3718 BoxInt32x4Instr* instruction_; |
| 3722 }; | 3719 }; |
| 3723 | 3720 |
| 3724 | 3721 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3758 | 3755 |
| 3759 | 3756 |
| 3760 void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3757 void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3761 const intptr_t value_cid = value()->Type()->ToCid(); | 3758 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3762 const Register value = locs()->in(0).reg(); | 3759 const Register value = locs()->in(0).reg(); |
| 3763 const QRegister result = locs()->out(0).fpu_reg(); | 3760 const QRegister result = locs()->out(0).fpu_reg(); |
| 3764 | 3761 |
| 3765 if (value_cid != kInt32x4Cid) { | 3762 if (value_cid != kInt32x4Cid) { |
| 3766 const Register temp = locs()->temp(0).reg(); | 3763 const Register temp = locs()->temp(0).reg(); |
| 3767 Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass); | 3764 Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass); |
| 3768 __ tst(value, ShifterOperand(kSmiTagMask)); | 3765 __ tst(value, Operand(kSmiTagMask)); |
| 3769 __ b(deopt, EQ); | 3766 __ b(deopt, EQ); |
| 3770 __ CompareClassId(value, kInt32x4Cid, temp); | 3767 __ CompareClassId(value, kInt32x4Cid, temp); |
| 3771 __ b(deopt, NE); | 3768 __ b(deopt, NE); |
| 3772 } | 3769 } |
| 3773 | 3770 |
| 3774 const DRegister dresult0 = EvenDRegisterOf(result); | 3771 const DRegister dresult0 = EvenDRegisterOf(result); |
| 3775 __ LoadMultipleDFromOffset(dresult0, 2, value, | 3772 __ LoadMultipleDFromOffset(dresult0, 2, value, |
| 3776 Int32x4::value_offset() - kHeapObjectTag); | 3773 Int32x4::value_offset() - kHeapObjectTag); |
| 3777 } | 3774 } |
| 3778 | 3775 |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4039 | 4036 |
| 4040 const Register out = locs()->out(0).reg(); | 4037 const Register out = locs()->out(0).reg(); |
| 4041 const Register temp = locs()->temp(0).reg(); | 4038 const Register temp = locs()->temp(0).reg(); |
| 4042 | 4039 |
| 4043 // X lane. | 4040 // X lane. |
| 4044 __ vmovrs(out, EvenSRegisterOf(dvalue0)); | 4041 __ vmovrs(out, EvenSRegisterOf(dvalue0)); |
| 4045 __ Lsr(out, out, 31); | 4042 __ Lsr(out, out, 31); |
| 4046 // Y lane. | 4043 // Y lane. |
| 4047 __ vmovrs(temp, OddSRegisterOf(dvalue0)); | 4044 __ vmovrs(temp, OddSRegisterOf(dvalue0)); |
| 4048 __ Lsr(temp, temp, 31); | 4045 __ Lsr(temp, temp, 31); |
| 4049 __ orr(out, out, ShifterOperand(temp, LSL, 1)); | 4046 __ orr(out, out, Operand(temp, LSL, 1)); |
| 4050 // Z lane. | 4047 // Z lane. |
| 4051 __ vmovrs(temp, EvenSRegisterOf(dvalue1)); | 4048 __ vmovrs(temp, EvenSRegisterOf(dvalue1)); |
| 4052 __ Lsr(temp, temp, 31); | 4049 __ Lsr(temp, temp, 31); |
| 4053 __ orr(out, out, ShifterOperand(temp, LSL, 2)); | 4050 __ orr(out, out, Operand(temp, LSL, 2)); |
| 4054 // W lane. | 4051 // W lane. |
| 4055 __ vmovrs(temp, OddSRegisterOf(dvalue1)); | 4052 __ vmovrs(temp, OddSRegisterOf(dvalue1)); |
| 4056 __ Lsr(temp, temp, 31); | 4053 __ Lsr(temp, temp, 31); |
| 4057 __ orr(out, out, ShifterOperand(temp, LSL, 3)); | 4054 __ orr(out, out, Operand(temp, LSL, 3)); |
| 4058 // Tag. | 4055 // Tag. |
| 4059 __ SmiTag(out); | 4056 __ SmiTag(out); |
| 4060 } | 4057 } |
| 4061 | 4058 |
| 4062 | 4059 |
| 4063 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 4060 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 4064 Isolate* isolate, bool opt) const { | 4061 Isolate* isolate, bool opt) const { |
| 4065 const intptr_t kNumInputs = 4; | 4062 const intptr_t kNumInputs = 4; |
| 4066 const intptr_t kNumTemps = 0; | 4063 const intptr_t kNumTemps = 0; |
| 4067 LocationSummary* summary = new(isolate) LocationSummary( | 4064 LocationSummary* summary = new(isolate) LocationSummary( |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4592 const DRegister dvalue1 = OddDRegisterOf(q); | 4589 const DRegister dvalue1 = OddDRegisterOf(q); |
| 4593 | 4590 |
| 4594 const Register out = locs()->out(0).reg(); | 4591 const Register out = locs()->out(0).reg(); |
| 4595 | 4592 |
| 4596 // Upper 32-bits of X lane. | 4593 // Upper 32-bits of X lane. |
| 4597 __ vmovrs(out, OddSRegisterOf(dvalue0)); | 4594 __ vmovrs(out, OddSRegisterOf(dvalue0)); |
| 4598 __ Lsr(out, out, 31); | 4595 __ Lsr(out, out, 31); |
| 4599 // Upper 32-bits of Y lane. | 4596 // Upper 32-bits of Y lane. |
| 4600 __ vmovrs(TMP, OddSRegisterOf(dvalue1)); | 4597 __ vmovrs(TMP, OddSRegisterOf(dvalue1)); |
| 4601 __ Lsr(TMP, TMP, 31); | 4598 __ Lsr(TMP, TMP, 31); |
| 4602 __ orr(out, out, ShifterOperand(TMP, LSL, 1)); | 4599 __ orr(out, out, Operand(TMP, LSL, 1)); |
| 4603 // Tag. | 4600 // Tag. |
| 4604 __ SmiTag(out); | 4601 __ SmiTag(out); |
| 4605 return; | 4602 return; |
| 4606 } | 4603 } |
| 4607 ASSERT(representation() == kUnboxedFloat64x2); | 4604 ASSERT(representation() == kUnboxedFloat64x2); |
| 4608 const QRegister r = locs()->out(0).fpu_reg(); | 4605 const QRegister r = locs()->out(0).fpu_reg(); |
| 4609 | 4606 |
| 4610 const DRegister dvalue0 = EvenDRegisterOf(q); | 4607 const DRegister dvalue0 = EvenDRegisterOf(q); |
| 4611 const DRegister dvalue1 = OddDRegisterOf(q); | 4608 const DRegister dvalue1 = OddDRegisterOf(q); |
| 4612 const DRegister dresult0 = EvenDRegisterOf(r); | 4609 const DRegister dresult0 = EvenDRegisterOf(r); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4784 break; | 4781 break; |
| 4785 case MethodRecognizer::kInt32x4GetFlagZ: | 4782 case MethodRecognizer::kInt32x4GetFlagZ: |
| 4786 __ vmovrs(result, svalue2); | 4783 __ vmovrs(result, svalue2); |
| 4787 break; | 4784 break; |
| 4788 case MethodRecognizer::kInt32x4GetFlagW: | 4785 case MethodRecognizer::kInt32x4GetFlagW: |
| 4789 __ vmovrs(result, svalue3); | 4786 __ vmovrs(result, svalue3); |
| 4790 break; | 4787 break; |
| 4791 default: UNREACHABLE(); | 4788 default: UNREACHABLE(); |
| 4792 } | 4789 } |
| 4793 | 4790 |
| 4794 __ tst(result, ShifterOperand(result)); | 4791 __ tst(result, Operand(result)); |
| 4795 __ LoadObject(result, Bool::True(), NE); | 4792 __ LoadObject(result, Bool::True(), NE); |
| 4796 __ LoadObject(result, Bool::False(), EQ); | 4793 __ LoadObject(result, Bool::False(), EQ); |
| 4797 } | 4794 } |
| 4798 | 4795 |
| 4799 | 4796 |
| 4800 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Isolate* isolate, | 4797 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Isolate* isolate, |
| 4801 bool opt) const { | 4798 bool opt) const { |
| 4802 const intptr_t kNumInputs = 3; | 4799 const intptr_t kNumInputs = 3; |
| 4803 const intptr_t kNumTemps = 1; | 4800 const intptr_t kNumTemps = 1; |
| 4804 LocationSummary* summary = new(isolate) LocationSummary( | 4801 LocationSummary* summary = new(isolate) LocationSummary( |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5043 __ b(&done); | 5040 __ b(&done); |
| 5044 | 5041 |
| 5045 __ Bind(&are_equal); | 5042 __ Bind(&are_equal); |
| 5046 // Check for negative zero: -0.0 is equal 0.0 but min or max must return | 5043 // Check for negative zero: -0.0 is equal 0.0 but min or max must return |
| 5047 // -0.0 or 0.0 respectively. | 5044 // -0.0 or 0.0 respectively. |
| 5048 // Check for negative left value (get the sign bit): | 5045 // Check for negative left value (get the sign bit): |
| 5049 // - min -> left is negative ? left : right. | 5046 // - min -> left is negative ? left : right. |
| 5050 // - max -> left is negative ? right : left | 5047 // - max -> left is negative ? right : left |
| 5051 // Check the sign bit. | 5048 // Check the sign bit. |
| 5052 __ vmovrrd(IP, temp, left); // Sign bit is in bit 31 of temp. | 5049 __ vmovrrd(IP, temp, left); // Sign bit is in bit 31 of temp. |
| 5053 __ cmp(temp, ShifterOperand(0)); | 5050 __ cmp(temp, Operand(0)); |
| 5054 if (is_min) { | 5051 if (is_min) { |
| 5055 ASSERT(left == result); | 5052 ASSERT(left == result); |
| 5056 __ vmovd(result, right, GE); | 5053 __ vmovd(result, right, GE); |
| 5057 } else { | 5054 } else { |
| 5058 __ vmovd(result, right, LT); | 5055 __ vmovd(result, right, LT); |
| 5059 ASSERT(left == result); | 5056 ASSERT(left == result); |
| 5060 } | 5057 } |
| 5061 __ Bind(&done); | 5058 __ Bind(&done); |
| 5062 return; | 5059 return; |
| 5063 } | 5060 } |
| 5064 | 5061 |
| 5065 ASSERT(result_cid() == kSmiCid); | 5062 ASSERT(result_cid() == kSmiCid); |
| 5066 const Register left = locs()->in(0).reg(); | 5063 const Register left = locs()->in(0).reg(); |
| 5067 const Register right = locs()->in(1).reg(); | 5064 const Register right = locs()->in(1).reg(); |
| 5068 const Register result = locs()->out(0).reg(); | 5065 const Register result = locs()->out(0).reg(); |
| 5069 __ cmp(left, ShifterOperand(right)); | 5066 __ cmp(left, Operand(right)); |
| 5070 ASSERT(result == left); | 5067 ASSERT(result == left); |
| 5071 if (is_min) { | 5068 if (is_min) { |
| 5072 __ mov(result, ShifterOperand(right), GT); | 5069 __ mov(result, Operand(right), GT); |
| 5073 } else { | 5070 } else { |
| 5074 __ mov(result, ShifterOperand(right), LT); | 5071 __ mov(result, Operand(right), LT); |
| 5075 } | 5072 } |
| 5076 } | 5073 } |
| 5077 | 5074 |
| 5078 | 5075 |
| 5079 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Isolate* isolate, | 5076 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5080 bool opt) const { | 5077 bool opt) const { |
| 5081 const intptr_t kNumInputs = 1; | 5078 const intptr_t kNumInputs = 1; |
| 5082 const intptr_t kNumTemps = 0; | 5079 const intptr_t kNumTemps = 0; |
| 5083 LocationSummary* summary = new(isolate) LocationSummary( | 5080 LocationSummary* summary = new(isolate) LocationSummary( |
| 5084 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5081 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5085 summary->set_in(0, Location::RequiresRegister()); | 5082 summary->set_in(0, Location::RequiresRegister()); |
| 5086 // We make use of 3-operand instructions by not requiring result register | 5083 // We make use of 3-operand instructions by not requiring result register |
| 5087 // to be identical to first input register as on Intel. | 5084 // to be identical to first input register as on Intel. |
| 5088 summary->set_out(0, Location::RequiresRegister()); | 5085 summary->set_out(0, Location::RequiresRegister()); |
| 5089 return summary; | 5086 return summary; |
| 5090 } | 5087 } |
| 5091 | 5088 |
| 5092 | 5089 |
| 5093 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5090 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5094 const Register value = locs()->in(0).reg(); | 5091 const Register value = locs()->in(0).reg(); |
| 5095 const Register result = locs()->out(0).reg(); | 5092 const Register result = locs()->out(0).reg(); |
| 5096 switch (op_kind()) { | 5093 switch (op_kind()) { |
| 5097 case Token::kNEGATE: { | 5094 case Token::kNEGATE: { |
| 5098 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 5095 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
| 5099 __ rsbs(result, value, ShifterOperand(0)); | 5096 __ rsbs(result, value, Operand(0)); |
| 5100 __ b(deopt, VS); | 5097 __ b(deopt, VS); |
| 5101 break; | 5098 break; |
| 5102 } | 5099 } |
| 5103 case Token::kBIT_NOT: | 5100 case Token::kBIT_NOT: |
| 5104 __ mvn(result, ShifterOperand(value)); | 5101 __ mvn(result, Operand(value)); |
| 5105 // Remove inverted smi-tag. | 5102 // Remove inverted smi-tag. |
| 5106 __ bic(result, result, ShifterOperand(kSmiTagMask)); | 5103 __ bic(result, result, Operand(kSmiTagMask)); |
| 5107 break; | 5104 break; |
| 5108 default: | 5105 default: |
| 5109 UNREACHABLE(); | 5106 UNREACHABLE(); |
| 5110 } | 5107 } |
| 5111 } | 5108 } |
| 5112 | 5109 |
| 5113 | 5110 |
| 5114 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate, | 5111 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5115 bool opt) const { | 5112 bool opt) const { |
| 5116 const intptr_t kNumInputs = 1; | 5113 const intptr_t kNumInputs = 1; |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5511 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5508 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 5512 Location in_loc = pair->At(index()); | 5509 Location in_loc = pair->At(index()); |
| 5513 if (representation() == kUnboxedDouble) { | 5510 if (representation() == kUnboxedDouble) { |
| 5514 const QRegister out = locs()->out(0).fpu_reg(); | 5511 const QRegister out = locs()->out(0).fpu_reg(); |
| 5515 const QRegister in = in_loc.fpu_reg(); | 5512 const QRegister in = in_loc.fpu_reg(); |
| 5516 __ vmovq(out, in); | 5513 __ vmovq(out, in); |
| 5517 } else { | 5514 } else { |
| 5518 ASSERT(representation() == kTagged); | 5515 ASSERT(representation() == kTagged); |
| 5519 const Register out = locs()->out(0).reg(); | 5516 const Register out = locs()->out(0).reg(); |
| 5520 const Register in = in_loc.reg(); | 5517 const Register in = in_loc.reg(); |
| 5521 __ mov(out, ShifterOperand(in)); | 5518 __ mov(out, Operand(in)); |
| 5522 } | 5519 } |
| 5523 } | 5520 } |
| 5524 | 5521 |
| 5525 | 5522 |
| 5526 LocationSummary* MergedMathInstr::MakeLocationSummary(Isolate* isolate, | 5523 LocationSummary* MergedMathInstr::MakeLocationSummary(Isolate* isolate, |
| 5527 bool opt) const { | 5524 bool opt) const { |
| 5528 if (kind() == MergedMathInstr::kTruncDivMod) { | 5525 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 5529 const intptr_t kNumInputs = 2; | 5526 const intptr_t kNumInputs = 2; |
| 5530 const intptr_t kNumTemps = 2; | 5527 const intptr_t kNumTemps = 2; |
| 5531 LocationSummary* summary = new(isolate) LocationSummary( | 5528 LocationSummary* summary = new(isolate) LocationSummary( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 5552 if (kind() == MergedMathInstr::kTruncDivMod) { | 5549 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 5553 const Register left = locs()->in(0).reg(); | 5550 const Register left = locs()->in(0).reg(); |
| 5554 const Register right = locs()->in(1).reg(); | 5551 const Register right = locs()->in(1).reg(); |
| 5555 ASSERT(locs()->out(0).IsPairLocation()); | 5552 ASSERT(locs()->out(0).IsPairLocation()); |
| 5556 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5553 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 5557 const Register result_div = pair->At(0).reg(); | 5554 const Register result_div = pair->At(0).reg(); |
| 5558 const Register result_mod = pair->At(1).reg(); | 5555 const Register result_mod = pair->At(1).reg(); |
| 5559 Range* right_range = InputAt(1)->definition()->range(); | 5556 Range* right_range = InputAt(1)->definition()->range(); |
| 5560 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 5557 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 5561 // Handle divide by zero in runtime. | 5558 // Handle divide by zero in runtime. |
| 5562 __ cmp(right, ShifterOperand(0)); | 5559 __ cmp(right, Operand(0)); |
| 5563 __ b(deopt, EQ); | 5560 __ b(deopt, EQ); |
| 5564 } | 5561 } |
| 5565 const Register temp = locs()->temp(0).reg(); | 5562 const Register temp = locs()->temp(0).reg(); |
| 5566 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 5563 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
| 5567 | 5564 |
| 5568 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 5565 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
| 5569 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 5566 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 5570 | 5567 |
| 5571 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP); | 5568 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP); |
| 5572 | 5569 |
| 5573 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 5570 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 5574 // case we cannot tag the result. | 5571 // case we cannot tag the result. |
| 5575 __ CompareImmediate(result_div, 0x40000000); | 5572 __ CompareImmediate(result_div, 0x40000000); |
| 5576 __ b(deopt, EQ); | 5573 __ b(deopt, EQ); |
| 5577 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 5574 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 5578 // result_mod <- left - right * result_div. | 5575 // result_mod <- left - right * result_div. |
| 5579 __ mls(result_mod, IP, result_div, temp); | 5576 __ mls(result_mod, IP, result_div, temp); |
| 5580 __ SmiTag(result_div); | 5577 __ SmiTag(result_div); |
| 5581 __ SmiTag(result_mod); | 5578 __ SmiTag(result_mod); |
| 5582 // Correct MOD result: | 5579 // Correct MOD result: |
| 5583 // res = left % right; | 5580 // res = left % right; |
| 5584 // if (res < 0) { | 5581 // if (res < 0) { |
| 5585 // if (right < 0) { | 5582 // if (right < 0) { |
| 5586 // res = res - right; | 5583 // res = res - right; |
| 5587 // } else { | 5584 // } else { |
| 5588 // res = res + right; | 5585 // res = res + right; |
| 5589 // } | 5586 // } |
| 5590 // } | 5587 // } |
| 5591 Label done; | 5588 Label done; |
| 5592 __ cmp(result_mod, ShifterOperand(0)); | 5589 __ cmp(result_mod, Operand(0)); |
| 5593 __ b(&done, GE); | 5590 __ b(&done, GE); |
| 5594 // Result is negative, adjust it. | 5591 // Result is negative, adjust it. |
| 5595 __ cmp(right, ShifterOperand(0)); | 5592 __ cmp(right, Operand(0)); |
| 5596 __ sub(result_mod, result_mod, ShifterOperand(right), LT); | 5593 __ sub(result_mod, result_mod, Operand(right), LT); |
| 5597 __ add(result_mod, result_mod, ShifterOperand(right), GE); | 5594 __ add(result_mod, result_mod, Operand(right), GE); |
| 5598 __ Bind(&done); | 5595 __ Bind(&done); |
| 5599 | 5596 |
| 5600 return; | 5597 return; |
| 5601 } | 5598 } |
| 5602 if (kind() == MergedMathInstr::kSinCos) { | 5599 if (kind() == MergedMathInstr::kSinCos) { |
| 5603 UNIMPLEMENTED(); | 5600 UNIMPLEMENTED(); |
| 5604 } | 5601 } |
| 5605 UNIMPLEMENTED(); | 5602 UNIMPLEMENTED(); |
| 5606 } | 5603 } |
| 5607 | 5604 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5690 } | 5687 } |
| 5691 | 5688 |
| 5692 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 5689 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| 5693 (unary_checks().NumberOfChecks() > 1)); | 5690 (unary_checks().NumberOfChecks() > 1)); |
| 5694 const Register value = locs()->in(0).reg(); | 5691 const Register value = locs()->in(0).reg(); |
| 5695 const Register temp = locs()->temp(0).reg(); | 5692 const Register temp = locs()->temp(0).reg(); |
| 5696 Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason); | 5693 Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason); |
| 5697 Label is_ok; | 5694 Label is_ok; |
| 5698 intptr_t cix = 0; | 5695 intptr_t cix = 0; |
| 5699 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { | 5696 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { |
| 5700 __ tst(value, ShifterOperand(kSmiTagMask)); | 5697 __ tst(value, Operand(kSmiTagMask)); |
| 5701 __ b(&is_ok, EQ); | 5698 __ b(&is_ok, EQ); |
| 5702 cix++; // Skip first check. | 5699 cix++; // Skip first check. |
| 5703 } else { | 5700 } else { |
| 5704 __ tst(value, ShifterOperand(kSmiTagMask)); | 5701 __ tst(value, Operand(kSmiTagMask)); |
| 5705 __ b(deopt, EQ); | 5702 __ b(deopt, EQ); |
| 5706 } | 5703 } |
| 5707 __ LoadClassId(temp, value); | 5704 __ LoadClassId(temp, value); |
| 5708 const intptr_t num_checks = unary_checks().NumberOfChecks(); | 5705 const intptr_t num_checks = unary_checks().NumberOfChecks(); |
| 5709 for (intptr_t i = cix; i < num_checks; i++) { | 5706 for (intptr_t i = cix; i < num_checks; i++) { |
| 5710 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid); | 5707 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid); |
| 5711 __ CompareImmediate(temp, unary_checks().GetReceiverClassIdAt(i)); | 5708 __ CompareImmediate(temp, unary_checks().GetReceiverClassIdAt(i)); |
| 5712 if (i == (num_checks - 1)) { | 5709 if (i == (num_checks - 1)) { |
| 5713 __ b(deopt, NE); | 5710 __ b(deopt, NE); |
| 5714 } else { | 5711 } else { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5726 LocationSummary* summary = new(isolate) LocationSummary( | 5723 LocationSummary* summary = new(isolate) LocationSummary( |
| 5727 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5724 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5728 summary->set_in(0, Location::RequiresRegister()); | 5725 summary->set_in(0, Location::RequiresRegister()); |
| 5729 return summary; | 5726 return summary; |
| 5730 } | 5727 } |
| 5731 | 5728 |
| 5732 | 5729 |
| 5733 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5730 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5734 const Register value = locs()->in(0).reg(); | 5731 const Register value = locs()->in(0).reg(); |
| 5735 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi); | 5732 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi); |
| 5736 __ tst(value, ShifterOperand(kSmiTagMask)); | 5733 __ tst(value, Operand(kSmiTagMask)); |
| 5737 __ b(deopt, NE); | 5734 __ b(deopt, NE); |
| 5738 } | 5735 } |
| 5739 | 5736 |
| 5740 | 5737 |
| 5741 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Isolate* isolate, | 5738 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Isolate* isolate, |
| 5742 bool opt) const { | 5739 bool opt) const { |
| 5743 const intptr_t kNumInputs = 2; | 5740 const intptr_t kNumInputs = 2; |
| 5744 const intptr_t kNumTemps = 0; | 5741 const intptr_t kNumTemps = 0; |
| 5745 LocationSummary* locs = new(isolate) LocationSummary( | 5742 LocationSummary* locs = new(isolate) LocationSummary( |
| 5746 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5743 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 5773 __ CompareImmediate(length, reinterpret_cast<int32_t>(index.raw())); | 5770 __ CompareImmediate(length, reinterpret_cast<int32_t>(index.raw())); |
| 5774 __ b(deopt, LS); | 5771 __ b(deopt, LS); |
| 5775 } else if (length_loc.IsConstant()) { | 5772 } else if (length_loc.IsConstant()) { |
| 5776 const Smi& length = Smi::Cast(length_loc.constant()); | 5773 const Smi& length = Smi::Cast(length_loc.constant()); |
| 5777 const Register index = index_loc.reg(); | 5774 const Register index = index_loc.reg(); |
| 5778 __ CompareImmediate(index, reinterpret_cast<int32_t>(length.raw())); | 5775 __ CompareImmediate(index, reinterpret_cast<int32_t>(length.raw())); |
| 5779 __ b(deopt, CS); | 5776 __ b(deopt, CS); |
| 5780 } else { | 5777 } else { |
| 5781 const Register length = length_loc.reg(); | 5778 const Register length = length_loc.reg(); |
| 5782 const Register index = index_loc.reg(); | 5779 const Register index = index_loc.reg(); |
| 5783 __ cmp(index, ShifterOperand(length)); | 5780 __ cmp(index, Operand(length)); |
| 5784 __ b(deopt, CS); | 5781 __ b(deopt, CS); |
| 5785 } | 5782 } |
| 5786 } | 5783 } |
| 5787 | 5784 |
| 5788 | 5785 |
| 5789 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, | 5786 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, |
| 5790 Label* overflow, | 5787 Label* overflow, |
| 5791 Register result_lo, | 5788 Register result_lo, |
| 5792 Register result_hi) { | 5789 Register result_hi) { |
| 5793 // Compare upper half. | 5790 // Compare upper half. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5837 result_lo, | 5834 result_lo, |
| 5838 value, | 5835 value, |
| 5839 Mint::value_offset() - kHeapObjectTag); | 5836 Mint::value_offset() - kHeapObjectTag); |
| 5840 // Load high word. | 5837 // Load high word. |
| 5841 __ LoadFromOffset(kWord, | 5838 __ LoadFromOffset(kWord, |
| 5842 result_hi, | 5839 result_hi, |
| 5843 value, | 5840 value, |
| 5844 Mint::value_offset() - kHeapObjectTag + kWordSize); | 5841 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 5845 } else if (value_cid == kSmiCid) { | 5842 } else if (value_cid == kSmiCid) { |
| 5846 // Load Smi into result_lo. | 5843 // Load Smi into result_lo. |
| 5847 __ mov(result_lo, ShifterOperand(value)); | 5844 __ mov(result_lo, Operand(value)); |
| 5848 // Untag. | 5845 // Untag. |
| 5849 __ SmiUntag(result_lo); | 5846 __ SmiUntag(result_lo); |
| 5850 __ SignFill(result_hi, result_lo); | 5847 __ SignFill(result_hi, result_lo); |
| 5851 } else { | 5848 } else { |
| 5852 const Register temp = locs()->temp(0).reg(); | 5849 const Register temp = locs()->temp(0).reg(); |
| 5853 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 5850 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
| 5854 ICData::kDeoptUnboxInteger); | 5851 ICData::kDeoptUnboxInteger); |
| 5855 Label is_smi, done; | 5852 Label is_smi, done; |
| 5856 __ tst(value, ShifterOperand(kSmiTagMask)); | 5853 __ tst(value, Operand(kSmiTagMask)); |
| 5857 __ b(&is_smi, EQ); | 5854 __ b(&is_smi, EQ); |
| 5858 __ CompareClassId(value, kMintCid, temp); | 5855 __ CompareClassId(value, kMintCid, temp); |
| 5859 __ b(deopt, NE); | 5856 __ b(deopt, NE); |
| 5860 | 5857 |
| 5861 // It's a Mint. | 5858 // It's a Mint. |
| 5862 // Load low word. | 5859 // Load low word. |
| 5863 __ LoadFromOffset(kWord, | 5860 __ LoadFromOffset(kWord, |
| 5864 result_lo, | 5861 result_lo, |
| 5865 value, | 5862 value, |
| 5866 Mint::value_offset() - kHeapObjectTag); | 5863 Mint::value_offset() - kHeapObjectTag); |
| 5867 // Load high word. | 5864 // Load high word. |
| 5868 __ LoadFromOffset(kWord, | 5865 __ LoadFromOffset(kWord, |
| 5869 result_hi, | 5866 result_hi, |
| 5870 value, | 5867 value, |
| 5871 Mint::value_offset() - kHeapObjectTag + kWordSize); | 5868 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 5872 __ b(&done); | 5869 __ b(&done); |
| 5873 | 5870 |
| 5874 // It's a Smi. | 5871 // It's a Smi. |
| 5875 __ Bind(&is_smi); | 5872 __ Bind(&is_smi); |
| 5876 // Load Smi into result_lo. | 5873 // Load Smi into result_lo. |
| 5877 __ mov(result_lo, ShifterOperand(value)); | 5874 __ mov(result_lo, Operand(value)); |
| 5878 // Untag. | 5875 // Untag. |
| 5879 __ SmiUntag(result_lo); | 5876 __ SmiUntag(result_lo); |
| 5880 // Sign extend result_lo into result_hi. | 5877 // Sign extend result_lo into result_hi. |
| 5881 __ SignFill(result_hi, result_lo); | 5878 __ SignFill(result_hi, result_lo); |
| 5882 __ Bind(&done); | 5879 __ Bind(&done); |
| 5883 } | 5880 } |
| 5884 } | 5881 } |
| 5885 | 5882 |
| 5886 | 5883 |
| 5887 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, | 5884 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 5915 const ExternalLabel label(stub.EntryPoint()); | 5912 const ExternalLabel label(stub.EntryPoint()); |
| 5916 | 5913 |
| 5917 LocationSummary* locs = instruction_->locs(); | 5914 LocationSummary* locs = instruction_->locs(); |
| 5918 locs->live_registers()->Remove(locs->out(0)); | 5915 locs->live_registers()->Remove(locs->out(0)); |
| 5919 | 5916 |
| 5920 compiler->SaveLiveRegisters(locs); | 5917 compiler->SaveLiveRegisters(locs); |
| 5921 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 5918 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 5922 &label, | 5919 &label, |
| 5923 PcDescriptors::kOther, | 5920 PcDescriptors::kOther, |
| 5924 locs); | 5921 locs); |
| 5925 __ mov(locs->out(0).reg(), ShifterOperand(R0)); | 5922 __ mov(locs->out(0).reg(), Operand(R0)); |
| 5926 compiler->RestoreLiveRegisters(locs); | 5923 compiler->RestoreLiveRegisters(locs); |
| 5927 | 5924 |
| 5928 __ b(exit_label()); | 5925 __ b(exit_label()); |
| 5929 } | 5926 } |
| 5930 | 5927 |
| 5931 private: | 5928 private: |
| 5932 BoxIntegerInstr* instruction_; | 5929 BoxIntegerInstr* instruction_; |
| 5933 }; | 5930 }; |
| 5934 | 5931 |
| 5935 | 5932 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 5960 __ b(¬_smi); | 5957 __ b(¬_smi); |
| 5961 | 5958 |
| 5962 __ Bind(&maybe_neg_smi); | 5959 __ Bind(&maybe_neg_smi); |
| 5963 __ CompareImmediate(value_lo, 0); | 5960 __ CompareImmediate(value_lo, 0); |
| 5964 __ b(¬_smi, GE); | 5961 __ b(¬_smi, GE); |
| 5965 __ CompareImmediate(value_lo, kSmiMin); | 5962 __ CompareImmediate(value_lo, kSmiMin); |
| 5966 __ b(¬_smi, LT); | 5963 __ b(¬_smi, LT); |
| 5967 | 5964 |
| 5968 // lo is a Smi. Tag it and return. | 5965 // lo is a Smi. Tag it and return. |
| 5969 __ Bind(&is_smi); | 5966 __ Bind(&is_smi); |
| 5970 __ mov(out_reg, ShifterOperand(value_lo)); | 5967 __ mov(out_reg, Operand(value_lo)); |
| 5971 __ SmiTag(out_reg); | 5968 __ SmiTag(out_reg); |
| 5972 __ b(&done); | 5969 __ b(&done); |
| 5973 | 5970 |
| 5974 // Not a smi. Box it. | 5971 // Not a smi. Box it. |
| 5975 __ Bind(¬_smi); | 5972 __ Bind(¬_smi); |
| 5976 __ TryAllocate( | 5973 __ TryAllocate( |
| 5977 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), | 5974 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
| 5978 slow_path->entry_label(), | 5975 slow_path->entry_label(), |
| 5979 out_reg, | 5976 out_reg, |
| 5980 tmp); | 5977 tmp); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6017 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6014 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6018 Register out_lo = out_pair->At(0).reg(); | 6015 Register out_lo = out_pair->At(0).reg(); |
| 6019 Register out_hi = out_pair->At(1).reg(); | 6016 Register out_hi = out_pair->At(1).reg(); |
| 6020 | 6017 |
| 6021 Label* deopt = NULL; | 6018 Label* deopt = NULL; |
| 6022 if (FLAG_throw_on_javascript_int_overflow) { | 6019 if (FLAG_throw_on_javascript_int_overflow) { |
| 6023 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6020 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6024 } | 6021 } |
| 6025 switch (op_kind()) { | 6022 switch (op_kind()) { |
| 6026 case Token::kBIT_AND: { | 6023 case Token::kBIT_AND: { |
| 6027 __ and_(out_lo, left_lo, ShifterOperand(right_lo)); | 6024 __ and_(out_lo, left_lo, Operand(right_lo)); |
| 6028 __ and_(out_hi, left_hi, ShifterOperand(right_hi)); | 6025 __ and_(out_hi, left_hi, Operand(right_hi)); |
| 6029 } | 6026 } |
| 6030 break; | 6027 break; |
| 6031 case Token::kBIT_OR: { | 6028 case Token::kBIT_OR: { |
| 6032 __ orr(out_lo, left_lo, ShifterOperand(right_lo)); | 6029 __ orr(out_lo, left_lo, Operand(right_lo)); |
| 6033 __ orr(out_hi, left_hi, ShifterOperand(right_hi)); | 6030 __ orr(out_hi, left_hi, Operand(right_hi)); |
| 6034 } | 6031 } |
| 6035 break; | 6032 break; |
| 6036 case Token::kBIT_XOR: { | 6033 case Token::kBIT_XOR: { |
| 6037 __ eor(out_lo, left_lo, ShifterOperand(right_lo)); | 6034 __ eor(out_lo, left_lo, Operand(right_lo)); |
| 6038 __ eor(out_hi, left_hi, ShifterOperand(right_hi)); | 6035 __ eor(out_hi, left_hi, Operand(right_hi)); |
| 6039 } | 6036 } |
| 6040 break; | 6037 break; |
| 6041 case Token::kADD: | 6038 case Token::kADD: |
| 6042 case Token::kSUB: { | 6039 case Token::kSUB: { |
| 6043 if (!FLAG_throw_on_javascript_int_overflow) { | 6040 if (!FLAG_throw_on_javascript_int_overflow) { |
| 6044 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6041 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6045 } | 6042 } |
| 6046 if (op_kind() == Token::kADD) { | 6043 if (op_kind() == Token::kADD) { |
| 6047 __ adds(out_lo, left_lo, ShifterOperand(right_lo)); | 6044 __ adds(out_lo, left_lo, Operand(right_lo)); |
| 6048 __ adcs(out_hi, left_hi, ShifterOperand(right_hi)); | 6045 __ adcs(out_hi, left_hi, Operand(right_hi)); |
| 6049 } else { | 6046 } else { |
| 6050 ASSERT(op_kind() == Token::kSUB); | 6047 ASSERT(op_kind() == Token::kSUB); |
| 6051 __ subs(out_lo, left_lo, ShifterOperand(right_lo)); | 6048 __ subs(out_lo, left_lo, Operand(right_lo)); |
| 6052 __ sbcs(out_hi, left_hi, ShifterOperand(right_hi)); | 6049 __ sbcs(out_hi, left_hi, Operand(right_hi)); |
| 6053 } | 6050 } |
| 6054 // Deopt on overflow. | 6051 // Deopt on overflow. |
| 6055 __ b(deopt, VS); | 6052 __ b(deopt, VS); |
| 6056 break; | 6053 break; |
| 6057 } | 6054 } |
| 6058 default: | 6055 default: |
| 6059 UNREACHABLE(); | 6056 UNREACHABLE(); |
| 6060 break; | 6057 break; |
| 6061 } | 6058 } |
| 6062 if (FLAG_throw_on_javascript_int_overflow) { | 6059 if (FLAG_throw_on_javascript_int_overflow) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 6089 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6086 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6090 Register out_lo = out_pair->At(0).reg(); | 6087 Register out_lo = out_pair->At(0).reg(); |
| 6091 Register out_hi = out_pair->At(1).reg(); | 6088 Register out_hi = out_pair->At(1).reg(); |
| 6092 Register temp = locs()->temp(0).reg(); | 6089 Register temp = locs()->temp(0).reg(); |
| 6093 | 6090 |
| 6094 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | 6091 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 6095 Label done; | 6092 Label done; |
| 6096 | 6093 |
| 6097 // Early out if shift is 0. | 6094 // Early out if shift is 0. |
| 6098 __ CompareImmediate(shift, 0); | 6095 __ CompareImmediate(shift, 0); |
| 6099 __ mov(out_lo, ShifterOperand(left_lo)); | 6096 __ mov(out_lo, Operand(left_lo)); |
| 6100 __ mov(out_hi, ShifterOperand(left_hi)); | 6097 __ mov(out_hi, Operand(left_hi)); |
| 6101 __ b(&done, EQ); | 6098 __ b(&done, EQ); |
| 6102 | 6099 |
| 6103 // Untag shift count. | 6100 // Untag shift count. |
| 6104 __ SmiUntag(shift); | 6101 __ SmiUntag(shift); |
| 6105 | 6102 |
| 6106 // Deopt if shift is negative. | 6103 // Deopt if shift is negative. |
| 6107 __ CompareImmediate(shift, 1); | 6104 __ CompareImmediate(shift, 1); |
| 6108 __ b(deopt, LT); | 6105 __ b(deopt, LT); |
| 6109 | 6106 |
| 6110 // Deopt if shift is larger than 63. | 6107 // Deopt if shift is larger than 63. |
| 6111 __ CompareImmediate(shift, 63); | 6108 __ CompareImmediate(shift, 63); |
| 6112 __ b(deopt, GT); | 6109 __ b(deopt, GT); |
| 6113 | 6110 |
| 6114 switch (op_kind()) { | 6111 switch (op_kind()) { |
| 6115 case Token::kSHR: { | 6112 case Token::kSHR: { |
| 6116 __ cmp(shift, ShifterOperand(32)); | 6113 __ cmp(shift, Operand(32)); |
| 6117 | 6114 |
| 6118 __ mov(out_lo, ShifterOperand(out_hi), HI); | 6115 __ mov(out_lo, Operand(out_hi), HI); |
| 6119 __ Asr(out_hi, out_hi, 31, HI); | 6116 __ Asr(out_hi, out_hi, 31, HI); |
| 6120 __ sub(shift, shift, ShifterOperand(32), HI); | 6117 __ sub(shift, shift, Operand(32), HI); |
| 6121 | 6118 |
| 6122 __ rsb(temp, shift, ShifterOperand(32)); | 6119 __ rsb(temp, shift, Operand(32)); |
| 6123 __ mov(temp, ShifterOperand(out_hi, LSL, temp)); | 6120 __ mov(temp, Operand(out_hi, LSL, temp)); |
| 6124 __ orr(out_lo, temp, ShifterOperand(out_lo, LSR, shift)); | 6121 __ orr(out_lo, temp, Operand(out_lo, LSR, shift)); |
| 6125 __ Asr(out_hi, out_hi, shift); | 6122 __ Asr(out_hi, out_hi, shift); |
| 6126 break; | 6123 break; |
| 6127 } | 6124 } |
| 6128 case Token::kSHL: { | 6125 case Token::kSHL: { |
| 6129 __ rsbs(temp, shift, ShifterOperand(32)); | 6126 __ rsbs(temp, shift, Operand(32)); |
| 6130 __ sub(temp, shift, ShifterOperand(32), MI); | 6127 __ sub(temp, shift, Operand(32), MI); |
| 6131 __ mov(out_hi, ShifterOperand(out_lo, LSL, temp), MI); | 6128 __ mov(out_hi, Operand(out_lo, LSL, temp), MI); |
| 6132 __ mov(out_hi, ShifterOperand(out_hi, LSL, shift), PL); | 6129 __ mov(out_hi, Operand(out_hi, LSL, shift), PL); |
| 6133 __ orr(out_hi, out_hi, ShifterOperand(out_lo, LSR, temp), PL); | 6130 __ orr(out_hi, out_hi, Operand(out_lo, LSR, temp), PL); |
| 6134 __ mov(out_lo, ShifterOperand(out_lo, LSL, shift)); | 6131 __ mov(out_lo, Operand(out_lo, LSL, shift)); |
| 6135 | 6132 |
| 6136 // Check for overflow. | 6133 // Check for overflow. |
| 6137 | 6134 |
| 6138 // Copy high word from output. | 6135 // Copy high word from output. |
| 6139 __ mov(temp, ShifterOperand(out_hi)); | 6136 __ mov(temp, Operand(out_hi)); |
| 6140 // Shift copy right. | 6137 // Shift copy right. |
| 6141 __ Asr(temp, temp, shift); | 6138 __ Asr(temp, temp, shift); |
| 6142 // Compare with high word from input. | 6139 // Compare with high word from input. |
| 6143 __ cmp(temp, ShifterOperand(left_hi)); | 6140 __ cmp(temp, Operand(left_hi)); |
| 6144 // Overflow if they aren't equal. | 6141 // Overflow if they aren't equal. |
| 6145 __ b(deopt, NE); | 6142 __ b(deopt, NE); |
| 6146 break; | 6143 break; |
| 6147 } | 6144 } |
| 6148 default: | 6145 default: |
| 6149 UNREACHABLE(); | 6146 UNREACHABLE(); |
| 6150 break; | 6147 break; |
| 6151 } | 6148 } |
| 6152 | 6149 |
| 6153 __ Bind(&done); | 6150 __ Bind(&done); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 6179 | 6176 |
| 6180 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6177 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6181 Register out_lo = out_pair->At(0).reg(); | 6178 Register out_lo = out_pair->At(0).reg(); |
| 6182 Register out_hi = out_pair->At(1).reg(); | 6179 Register out_hi = out_pair->At(1).reg(); |
| 6183 | 6180 |
| 6184 Label* deopt = NULL; | 6181 Label* deopt = NULL; |
| 6185 | 6182 |
| 6186 if (FLAG_throw_on_javascript_int_overflow) { | 6183 if (FLAG_throw_on_javascript_int_overflow) { |
| 6187 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | 6184 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
| 6188 } | 6185 } |
| 6189 __ mvn(out_lo, ShifterOperand(left_lo)); | 6186 __ mvn(out_lo, Operand(left_lo)); |
| 6190 __ mvn(out_hi, ShifterOperand(left_hi)); | 6187 __ mvn(out_hi, Operand(left_hi)); |
| 6191 if (FLAG_throw_on_javascript_int_overflow) { | 6188 if (FLAG_throw_on_javascript_int_overflow) { |
| 6192 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); | 6189 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); |
| 6193 } | 6190 } |
| 6194 } | 6191 } |
| 6195 | 6192 |
| 6196 | 6193 |
| 6197 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6194 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
| 6198 bool opt) const { | 6195 bool opt) const { |
| 6199 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6196 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
| 6200 } | 6197 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6289 LocationSummary* CurrentContextInstr::MakeLocationSummary(Isolate* isolate, | 6286 LocationSummary* CurrentContextInstr::MakeLocationSummary(Isolate* isolate, |
| 6290 bool opt) const { | 6287 bool opt) const { |
| 6291 return LocationSummary::Make(isolate, | 6288 return LocationSummary::Make(isolate, |
| 6292 0, | 6289 0, |
| 6293 Location::RequiresRegister(), | 6290 Location::RequiresRegister(), |
| 6294 LocationSummary::kNoCall); | 6291 LocationSummary::kNoCall); |
| 6295 } | 6292 } |
| 6296 | 6293 |
| 6297 | 6294 |
| 6298 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6295 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6299 __ mov(locs()->out(0).reg(), ShifterOperand(CTX)); | 6296 __ mov(locs()->out(0).reg(), Operand(CTX)); |
| 6300 } | 6297 } |
| 6301 | 6298 |
| 6302 | 6299 |
| 6303 LocationSummary* StrictCompareInstr::MakeLocationSummary(Isolate* isolate, | 6300 LocationSummary* StrictCompareInstr::MakeLocationSummary(Isolate* isolate, |
| 6304 bool opt) const { | 6301 bool opt) const { |
| 6305 const intptr_t kNumInputs = 2; | 6302 const intptr_t kNumInputs = 2; |
| 6306 const intptr_t kNumTemps = 0; | 6303 const intptr_t kNumTemps = 0; |
| 6307 if (needs_number_check()) { | 6304 if (needs_number_check()) { |
| 6308 LocationSummary* locs = new(isolate) LocationSummary( | 6305 LocationSummary* locs = new(isolate) LocationSummary( |
| 6309 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); | 6306 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6381 Location::RequiresRegister(), | 6378 Location::RequiresRegister(), |
| 6382 LocationSummary::kNoCall); | 6379 LocationSummary::kNoCall); |
| 6383 } | 6380 } |
| 6384 | 6381 |
| 6385 | 6382 |
| 6386 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6383 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6387 const Register value = locs()->in(0).reg(); | 6384 const Register value = locs()->in(0).reg(); |
| 6388 const Register result = locs()->out(0).reg(); | 6385 const Register result = locs()->out(0).reg(); |
| 6389 | 6386 |
| 6390 __ LoadObject(result, Bool::True()); | 6387 __ LoadObject(result, Bool::True()); |
| 6391 __ cmp(result, ShifterOperand(value)); | 6388 __ cmp(result, Operand(value)); |
| 6392 __ LoadObject(result, Bool::False(), EQ); | 6389 __ LoadObject(result, Bool::False(), EQ); |
| 6393 } | 6390 } |
| 6394 | 6391 |
| 6395 | 6392 |
| 6396 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Isolate* isolate, | 6393 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Isolate* isolate, |
| 6397 bool opt) const { | 6394 bool opt) const { |
| 6398 return MakeCallSummary(); | 6395 return MakeCallSummary(); |
| 6399 } | 6396 } |
| 6400 | 6397 |
| 6401 | 6398 |
| 6402 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6399 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6403 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls())); | 6400 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls())); |
| 6404 const ExternalLabel label(stub.EntryPoint()); | 6401 const ExternalLabel label(stub.EntryPoint()); |
| 6405 compiler->GenerateCall(token_pos(), | 6402 compiler->GenerateCall(token_pos(), |
| 6406 &label, | 6403 &label, |
| 6407 PcDescriptors::kOther, | 6404 PcDescriptors::kOther, |
| 6408 locs()); | 6405 locs()); |
| 6409 __ Drop(ArgumentCount()); // Discard arguments. | 6406 __ Drop(ArgumentCount()); // Discard arguments. |
| 6410 } | 6407 } |
| 6411 | 6408 |
| 6412 } // namespace dart | 6409 } // namespace dart |
| 6413 | 6410 |
| 6414 #endif // defined TARGET_ARCH_ARM | 6411 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |