| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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_DBC. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_DBC. |
| 6 #if defined(TARGET_ARCH_DBC) | 6 #if defined(TARGET_ARCH_DBC) |
| 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 12 matching lines...) Expand all Loading... |
| 23 | 23 |
| 24 #define __ compiler->assembler()-> | 24 #define __ compiler->assembler()-> |
| 25 | 25 |
| 26 namespace dart { | 26 namespace dart { |
| 27 | 27 |
| 28 DECLARE_FLAG(bool, emit_edge_counters); | 28 DECLARE_FLAG(bool, emit_edge_counters); |
| 29 DECLARE_FLAG(int, optimization_counter_threshold); | 29 DECLARE_FLAG(int, optimization_counter_threshold); |
| 30 | 30 |
| 31 // List of instructions that are still unimplemented by DBC backend. | 31 // List of instructions that are still unimplemented by DBC backend. |
| 32 #define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \ | 32 #define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \ |
| 33 M(IndirectGoto) \ | |
| 34 M(LoadCodeUnits) \ | 33 M(LoadCodeUnits) \ |
| 35 M(LoadUntagged) \ | 34 M(LoadUntagged) \ |
| 36 M(AllocateUninitializedContext) \ | 35 M(AllocateUninitializedContext) \ |
| 37 M(BinaryInt32Op) \ | 36 M(BinaryInt32Op) \ |
| 38 M(UnaryDoubleOp) \ | 37 M(UnaryDoubleOp) \ |
| 39 M(SmiToDouble) \ | 38 M(SmiToDouble) \ |
| 40 M(Int32ToDouble) \ | 39 M(Int32ToDouble) \ |
| 41 M(MintToDouble) \ | 40 M(MintToDouble) \ |
| 42 M(DoubleToInteger) \ | 41 M(DoubleToInteger) \ |
| 43 M(DoubleToSmi) \ | 42 M(DoubleToSmi) \ |
| 44 M(DoubleToDouble) \ | 43 M(DoubleToDouble) \ |
| 45 M(DoubleToFloat) \ | 44 M(DoubleToFloat) \ |
| 46 M(FloatToDouble) \ | 45 M(FloatToDouble) \ |
| 47 M(UnboxedConstant) \ | 46 M(UnboxedConstant) \ |
| 48 M(BinaryDoubleOp) \ | 47 M(BinaryDoubleOp) \ |
| 49 M(MathUnary) \ | 48 M(MathUnary) \ |
| 50 M(MathMinMax) \ | 49 M(MathMinMax) \ |
| 51 M(Box) \ | 50 M(Box) \ |
| 52 M(Unbox) \ | 51 M(Unbox) \ |
| 53 M(BoxInt64) \ | 52 M(BoxInt64) \ |
| 54 M(CaseInsensitiveCompareUC16) \ | |
| 55 M(BinaryMintOp) \ | 53 M(BinaryMintOp) \ |
| 56 M(ShiftMintOp) \ | 54 M(ShiftMintOp) \ |
| 57 M(UnaryMintOp) \ | 55 M(UnaryMintOp) \ |
| 58 M(InvokeMathCFunction) \ | 56 M(InvokeMathCFunction) \ |
| 59 M(MergedMath) \ | 57 M(MergedMath) \ |
| 60 M(GuardFieldClass) \ | 58 M(GuardFieldClass) \ |
| 61 M(GuardFieldLength) \ | 59 M(GuardFieldLength) \ |
| 62 M(IfThenElse) \ | 60 M(IfThenElse) \ |
| 63 M(BinaryFloat32x4Op) \ | 61 M(BinaryFloat32x4Op) \ |
| 64 M(Simd32x4Shuffle) \ | 62 M(Simd32x4Shuffle) \ |
| (...skipping 10 matching lines...) Expand all Loading... |
| 75 M(Float32x4Clamp) \ | 73 M(Float32x4Clamp) \ |
| 76 M(Float32x4With) \ | 74 M(Float32x4With) \ |
| 77 M(Float32x4ToInt32x4) \ | 75 M(Float32x4ToInt32x4) \ |
| 78 M(Int32x4Constructor) \ | 76 M(Int32x4Constructor) \ |
| 79 M(Int32x4BoolConstructor) \ | 77 M(Int32x4BoolConstructor) \ |
| 80 M(Int32x4GetFlag) \ | 78 M(Int32x4GetFlag) \ |
| 81 M(Int32x4Select) \ | 79 M(Int32x4Select) \ |
| 82 M(Int32x4SetFlag) \ | 80 M(Int32x4SetFlag) \ |
| 83 M(Int32x4ToFloat32x4) \ | 81 M(Int32x4ToFloat32x4) \ |
| 84 M(BinaryInt32x4Op) \ | 82 M(BinaryInt32x4Op) \ |
| 85 M(TestCids) \ | |
| 86 M(BinaryFloat64x2Op) \ | 83 M(BinaryFloat64x2Op) \ |
| 87 M(Float64x2Zero) \ | 84 M(Float64x2Zero) \ |
| 88 M(Float64x2Constructor) \ | 85 M(Float64x2Constructor) \ |
| 89 M(Float64x2Splat) \ | 86 M(Float64x2Splat) \ |
| 90 M(Float32x4ToFloat64x2) \ | 87 M(Float32x4ToFloat64x2) \ |
| 91 M(Float64x2ToFloat32x4) \ | 88 M(Float64x2ToFloat32x4) \ |
| 92 M(Simd64x2Shuffle) \ | 89 M(Simd64x2Shuffle) \ |
| 93 M(Float64x2ZeroArg) \ | 90 M(Float64x2ZeroArg) \ |
| 94 M(Float64x2OneArg) \ | 91 M(Float64x2OneArg) \ |
| 95 M(ExtractNthOutput) \ | 92 M(ExtractNthOutput) \ |
| 96 M(BinaryUint32Op) \ | 93 M(BinaryUint32Op) \ |
| 97 M(ShiftUint32Op) \ | 94 M(ShiftUint32Op) \ |
| 98 M(UnaryUint32Op) \ | 95 M(UnaryUint32Op) \ |
| 99 M(UnboxedIntConverter) \ | 96 M(UnboxedIntConverter) \ |
| 100 M(GrowRegExpStack) \ | |
| 101 M(BoxInteger32) \ | 97 M(BoxInteger32) \ |
| 102 M(UnboxInteger32) \ | 98 M(UnboxInteger32) \ |
| 103 M(CheckedSmiOp) \ | 99 M(CheckedSmiOp) \ |
| 104 M(CheckArrayBound) \ | 100 M(CheckArrayBound) \ |
| 105 M(RelationalOp) \ | 101 M(RelationalOp) \ |
| 106 M(EqualityCompare) \ | 102 M(EqualityCompare) \ |
| 107 M(LoadIndexed) | 103 M(LoadIndexed) |
| 108 | 104 |
| 105 // List of instructions that are not used by DBC. |
| 106 #define FOR_EACH_UNREACHABLE_INSTRUCTION(M) \ |
| 107 M(CaseInsensitiveCompareUC16) \ |
| 108 M(GrowRegExpStack) \ |
| 109 M(IndirectGoto) |
| 110 |
| 109 // Location summaries actually are not used by the unoptimizing DBC compiler | 111 // Location summaries actually are not used by the unoptimizing DBC compiler |
| 110 // because we don't allocate any registers. | 112 // because we don't allocate any registers. |
| 111 static LocationSummary* CreateLocationSummary( | 113 static LocationSummary* CreateLocationSummary( |
| 112 Zone* zone, | 114 Zone* zone, |
| 113 intptr_t num_inputs, | 115 intptr_t num_inputs, |
| 114 Location output = Location::NoLocation(), | 116 Location output = Location::NoLocation(), |
| 115 LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall) { | 117 LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall) { |
| 116 const intptr_t kNumTemps = 0; | 118 const intptr_t kNumTemps = 0; |
| 117 LocationSummary* locs = new(zone) LocationSummary( | 119 LocationSummary* locs = new(zone) LocationSummary( |
| 118 zone, num_inputs, kNumTemps, contains_call); | 120 zone, num_inputs, kNumTemps, contains_call); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 138 DEFINE_MAKE_LOCATION_SUMMARY(Name, __VA_ARGS__); \ | 140 DEFINE_MAKE_LOCATION_SUMMARY(Name, __VA_ARGS__); \ |
| 139 void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) \ | 141 void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) \ |
| 140 | 142 |
| 141 #define DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ | 143 #define DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ |
| 142 LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt) \ | 144 LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt) \ |
| 143 const { \ | 145 const { \ |
| 144 if (!opt) UNIMPLEMENTED(); \ | 146 if (!opt) UNIMPLEMENTED(); \ |
| 145 return NULL; \ | 147 return NULL; \ |
| 146 } \ | 148 } \ |
| 147 | 149 |
| 150 #define DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name) \ |
| 151 LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt) \ |
| 152 const { \ |
| 153 UNREACHABLE(); \ |
| 154 return NULL; \ |
| 155 } \ |
| 156 |
| 148 #define DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ | 157 #define DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ |
| 149 void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) { \ | 158 void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) { \ |
| 150 UNIMPLEMENTED(); \ | 159 UNIMPLEMENTED(); \ |
| 151 } | 160 } |
| 152 | 161 |
| 162 #define DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name) \ |
| 163 void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) { \ |
| 164 UNREACHABLE(); \ |
| 165 } |
| 166 |
| 153 #define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name) \ | 167 #define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name) \ |
| 154 void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) { \ | 168 void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) { \ |
| 155 UNIMPLEMENTED(); \ | 169 UNIMPLEMENTED(); \ |
| 156 } \ | 170 } \ |
| 157 Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*, \ | 171 Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*, \ |
| 158 BranchLabels) { \ | 172 BranchLabels) { \ |
| 159 UNIMPLEMENTED(); \ | 173 UNIMPLEMENTED(); \ |
| 160 return NEXT_IS_TRUE; \ | 174 return NEXT_IS_TRUE; \ |
| 161 } | 175 } |
| 162 | 176 |
| 163 #define DEFINE_UNIMPLEMENTED(Name) \ | 177 #define DEFINE_UNIMPLEMENTED(Name) \ |
| 164 DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ | 178 DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ |
| 165 DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ | 179 DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ |
| 166 | 180 |
| 167 FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED) | 181 FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED) |
| 168 | 182 |
| 169 #undef DEFINE_UNIMPLEMENTED | 183 #undef DEFINE_UNIMPLEMENTED |
| 170 | 184 |
| 171 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestCids) | 185 #define DEFINE_UNREACHABLE(Name) \ |
| 186 DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name) \ |
| 187 DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name) \ |
| 188 |
| 189 FOR_EACH_UNREACHABLE_INSTRUCTION(DEFINE_UNREACHABLE) |
| 190 |
| 191 #undef DEFINE_UNREACHABLE |
| 192 |
| 172 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp) | 193 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp) |
| 173 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare) | 194 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare) |
| 174 | 195 |
| 175 | 196 |
| 176 EMIT_NATIVE_CODE(InstanceOf, 2, Location::SameAsFirstInput(), | 197 EMIT_NATIVE_CODE(InstanceOf, 2, Location::SameAsFirstInput(), |
| 177 LocationSummary::kCall) { | 198 LocationSummary::kCall) { |
| 178 SubtypeTestCache& test_cache = SubtypeTestCache::Handle(); | 199 SubtypeTestCache& test_cache = SubtypeTestCache::Handle(); |
| 179 if (!type().IsVoidType() && type().IsInstantiated()) { | 200 if (!type().IsVoidType() && type().IsInstantiated()) { |
| 180 test_cache = SubtypeTestCache::New(); | 201 test_cache = SubtypeTestCache::New(); |
| 181 } | 202 } |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 | 558 |
| 538 EMIT_NATIVE_CODE(TestSmi, | 559 EMIT_NATIVE_CODE(TestSmi, |
| 539 2, | 560 2, |
| 540 Location::RequiresRegister(), | 561 Location::RequiresRegister(), |
| 541 LocationSummary::kNoCall) { | 562 LocationSummary::kNoCall) { |
| 542 // Never emitted outside of the BranchInstr. | 563 // Never emitted outside of the BranchInstr. |
| 543 UNREACHABLE(); | 564 UNREACHABLE(); |
| 544 } | 565 } |
| 545 | 566 |
| 546 | 567 |
| 568 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 569 BranchLabels labels) { |
| 570 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
| 571 const Register value = locs()->in(0).reg(); |
| 572 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 573 |
| 574 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 575 const intptr_t num_cases = data.length() / 2; |
| 576 ASSERT(num_cases <= 255); |
| 577 __ TestCids(value, num_cases); |
| 578 |
| 579 bool result = false; |
| 580 for (intptr_t i = 0; i < data.length(); i += 2) { |
| 581 const intptr_t test_cid = data[i]; |
| 582 result = data[i + 1] == true_result; |
| 583 __ Nop(result ? 1 : 0, compiler->ToEmbeddableCid(test_cid, this)); |
| 584 } |
| 585 |
| 586 // No match found, deoptimize or false. |
| 587 if (CanDeoptimize()) { |
| 588 compiler->EmitDeopt(deopt_id(), |
| 589 ICData::kDeoptTestCids, |
| 590 licm_hoisted_ ? ICData::kHoisted : 0); |
| 591 } else { |
| 592 Label* target = result ? labels.false_label : labels.true_label; |
| 593 __ Jump(target); |
| 594 } |
| 595 |
| 596 return NEXT_IS_TRUE; |
| 597 } |
| 598 |
| 599 |
| 600 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 601 BranchInstr* branch) { |
| 602 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 603 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 604 EmitBranchOnCondition(compiler, true_condition, labels); |
| 605 } |
| 606 |
| 607 |
| 608 EMIT_NATIVE_CODE(TestCids, 1, Location::RequiresRegister(), |
| 609 LocationSummary::kNoCall) { |
| 610 Register result_reg = locs()->out(0).reg(); |
| 611 Label is_true, is_false, done; |
| 612 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 613 EmitComparisonCode(compiler, labels); |
| 614 __ Jump(&is_true); |
| 615 __ Bind(&is_false); |
| 616 __ LoadConstant(result_reg, Bool::False()); |
| 617 __ Jump(&done); |
| 618 __ Bind(&is_true); |
| 619 __ LoadConstant(result_reg, Bool::True()); |
| 620 __ Bind(&done); |
| 621 } |
| 622 |
| 623 |
| 547 EMIT_NATIVE_CODE(CreateArray, | 624 EMIT_NATIVE_CODE(CreateArray, |
| 548 2, Location::RequiresRegister(), | 625 2, Location::RequiresRegister(), |
| 549 LocationSummary::kCall) { | 626 LocationSummary::kCall) { |
| 550 if (compiler->is_optimizing()) { | 627 if (compiler->is_optimizing()) { |
| 551 __ Push(locs()->in(0).reg()); | 628 __ Push(locs()->in(0).reg()); |
| 552 __ Push(locs()->in(1).reg()); | 629 __ Push(locs()->in(1).reg()); |
| 553 } | 630 } |
| 554 __ CreateArrayTOS(); | 631 __ CreateArrayTOS(); |
| 555 compiler->RecordSafepoint(locs()); | 632 compiler->RecordSafepoint(locs()); |
| 556 if (compiler->is_optimizing()) { | 633 if (compiler->is_optimizing()) { |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1126 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); | 1203 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); |
| 1127 break; | 1204 break; |
| 1128 default: | 1205 default: |
| 1129 UNREACHABLE(); | 1206 UNREACHABLE(); |
| 1130 } | 1207 } |
| 1131 } | 1208 } |
| 1132 | 1209 |
| 1133 } // namespace dart | 1210 } // namespace dart |
| 1134 | 1211 |
| 1135 #endif // defined TARGET_ARCH_DBC | 1212 #endif // defined TARGET_ARCH_DBC |
| OLD | NEW |