| 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 16 matching lines...) Expand all Loading... |
| 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(LoadCodeUnits) \ | 33 M(LoadCodeUnits) \ |
| 34 M(LoadUntagged) \ | 34 M(LoadUntagged) \ |
| 35 M(AllocateUninitializedContext) \ | 35 M(AllocateUninitializedContext) \ |
| 36 M(BinaryInt32Op) \ | 36 M(BinaryInt32Op) \ |
| 37 M(UnaryDoubleOp) \ | |
| 38 M(SmiToDouble) \ | |
| 39 M(Int32ToDouble) \ | 37 M(Int32ToDouble) \ |
| 40 M(MintToDouble) \ | |
| 41 M(DoubleToInteger) \ | 38 M(DoubleToInteger) \ |
| 42 M(DoubleToSmi) \ | 39 M(DoubleToSmi) \ |
| 43 M(DoubleToDouble) \ | 40 M(DoubleToDouble) \ |
| 44 M(DoubleToFloat) \ | 41 M(DoubleToFloat) \ |
| 45 M(FloatToDouble) \ | 42 M(FloatToDouble) \ |
| 46 M(UnboxedConstant) \ | 43 M(UnboxedConstant) \ |
| 47 M(BinaryDoubleOp) \ | |
| 48 M(MathUnary) \ | 44 M(MathUnary) \ |
| 49 M(MathMinMax) \ | 45 M(MathMinMax) \ |
| 50 M(Box) \ | |
| 51 M(Unbox) \ | |
| 52 M(BoxInt64) \ | 46 M(BoxInt64) \ |
| 53 M(BinaryMintOp) \ | |
| 54 M(ShiftMintOp) \ | |
| 55 M(UnaryMintOp) \ | |
| 56 M(InvokeMathCFunction) \ | 47 M(InvokeMathCFunction) \ |
| 57 M(MergedMath) \ | 48 M(MergedMath) \ |
| 58 M(GuardFieldClass) \ | 49 M(GuardFieldClass) \ |
| 59 M(GuardFieldLength) \ | 50 M(GuardFieldLength) \ |
| 60 M(IfThenElse) \ | 51 M(IfThenElse) \ |
| 52 M(ExtractNthOutput) \ |
| 53 M(BinaryUint32Op) \ |
| 54 M(ShiftUint32Op) \ |
| 55 M(UnaryUint32Op) \ |
| 56 M(UnboxedIntConverter) \ |
| 57 M(BoxInteger32) \ |
| 58 M(UnboxInteger32) \ |
| 59 |
| 60 // List of instructions that are not used by DBC. |
| 61 // Things we aren't planning to implement for DBC: |
| 62 // - Unboxed SIMD, |
| 63 // - Unboxed Mint, |
| 64 // - Optimized RegExps, |
| 65 // - Precompilation. |
| 66 #define FOR_EACH_UNREACHABLE_INSTRUCTION(M) \ |
| 67 M(CaseInsensitiveCompareUC16) \ |
| 68 M(GrowRegExpStack) \ |
| 69 M(IndirectGoto) \ |
| 70 M(MintToDouble) \ |
| 71 M(BinaryMintOp) \ |
| 72 M(ShiftMintOp) \ |
| 73 M(UnaryMintOp) \ |
| 61 M(BinaryFloat32x4Op) \ | 74 M(BinaryFloat32x4Op) \ |
| 62 M(Simd32x4Shuffle) \ | 75 M(Simd32x4Shuffle) \ |
| 63 M(Simd32x4ShuffleMix) \ | 76 M(Simd32x4ShuffleMix) \ |
| 64 M(Simd32x4GetSignMask) \ | 77 M(Simd32x4GetSignMask) \ |
| 65 M(Float32x4Constructor) \ | 78 M(Float32x4Constructor) \ |
| 66 M(Float32x4Zero) \ | 79 M(Float32x4Zero) \ |
| 67 M(Float32x4Splat) \ | 80 M(Float32x4Splat) \ |
| 68 M(Float32x4Comparison) \ | 81 M(Float32x4Comparison) \ |
| 69 M(Float32x4MinMax) \ | 82 M(Float32x4MinMax) \ |
| 70 M(Float32x4Scale) \ | 83 M(Float32x4Scale) \ |
| (...skipping 11 matching lines...) Expand all Loading... |
| 82 M(BinaryInt32x4Op) \ | 95 M(BinaryInt32x4Op) \ |
| 83 M(BinaryFloat64x2Op) \ | 96 M(BinaryFloat64x2Op) \ |
| 84 M(Float64x2Zero) \ | 97 M(Float64x2Zero) \ |
| 85 M(Float64x2Constructor) \ | 98 M(Float64x2Constructor) \ |
| 86 M(Float64x2Splat) \ | 99 M(Float64x2Splat) \ |
| 87 M(Float32x4ToFloat64x2) \ | 100 M(Float32x4ToFloat64x2) \ |
| 88 M(Float64x2ToFloat32x4) \ | 101 M(Float64x2ToFloat32x4) \ |
| 89 M(Simd64x2Shuffle) \ | 102 M(Simd64x2Shuffle) \ |
| 90 M(Float64x2ZeroArg) \ | 103 M(Float64x2ZeroArg) \ |
| 91 M(Float64x2OneArg) \ | 104 M(Float64x2OneArg) \ |
| 92 M(ExtractNthOutput) \ | |
| 93 M(BinaryUint32Op) \ | |
| 94 M(ShiftUint32Op) \ | |
| 95 M(UnaryUint32Op) \ | |
| 96 M(UnboxedIntConverter) \ | |
| 97 M(BoxInteger32) \ | |
| 98 M(UnboxInteger32) \ | |
| 99 M(CheckedSmiOp) \ | 105 M(CheckedSmiOp) \ |
| 100 | |
| 101 // List of instructions that are not used by DBC. | |
| 102 #define FOR_EACH_UNREACHABLE_INSTRUCTION(M) \ | |
| 103 M(CaseInsensitiveCompareUC16) \ | |
| 104 M(GenericCheckBound) \ | 106 M(GenericCheckBound) \ |
| 105 M(GrowRegExpStack) \ | |
| 106 M(IndirectGoto) | |
| 107 | 107 |
| 108 // Location summaries actually are not used by the unoptimizing DBC compiler | 108 // Location summaries actually are not used by the unoptimizing DBC compiler |
| 109 // because we don't allocate any registers. | 109 // because we don't allocate any registers. |
| 110 static LocationSummary* CreateLocationSummary( | 110 static LocationSummary* CreateLocationSummary( |
| 111 Zone* zone, | 111 Zone* zone, |
| 112 intptr_t num_inputs, | 112 intptr_t num_inputs, |
| 113 Location output = Location::NoLocation(), | 113 Location output = Location::NoLocation(), |
| 114 LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall) { | 114 LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall) { |
| 115 const intptr_t kNumTemps = 0; | 115 const intptr_t kNumTemps = 0; |
| 116 LocationSummary* locs = new(zone) LocationSummary( | 116 LocationSummary* locs = new(zone) LocationSummary( |
| (...skipping 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 | 1074 |
| 1075 EMIT_NATIVE_CODE(CheckSmi, 1) { | 1075 EMIT_NATIVE_CODE(CheckSmi, 1) { |
| 1076 __ CheckSmi(locs()->in(0).reg()); | 1076 __ CheckSmi(locs()->in(0).reg()); |
| 1077 compiler->EmitDeopt(deopt_id(), | 1077 compiler->EmitDeopt(deopt_id(), |
| 1078 ICData::kDeoptCheckSmi, | 1078 ICData::kDeoptCheckSmi, |
| 1079 licm_hoisted_ ? ICData::kHoisted : 0); | 1079 licm_hoisted_ ? ICData::kHoisted : 0); |
| 1080 } | 1080 } |
| 1081 | 1081 |
| 1082 | 1082 |
| 1083 EMIT_NATIVE_CODE(CheckEitherNonSmi, 2) { | 1083 EMIT_NATIVE_CODE(CheckEitherNonSmi, 2) { |
| 1084 intptr_t left_cid = left()->Type()->ToCid(); | |
| 1085 intptr_t right_cid = right()->Type()->ToCid(); | |
| 1086 const Register left = locs()->in(0).reg(); | 1084 const Register left = locs()->in(0).reg(); |
| 1087 const Register right = locs()->in(1).reg(); | 1085 const Register right = locs()->in(1).reg(); |
| 1088 if (this->left()->definition() == this->right()->definition()) { | 1086 __ CheckEitherNonSmi(left, right); |
| 1089 __ CheckSmi(left); | |
| 1090 } else if (left_cid == kSmiCid) { | |
| 1091 __ CheckSmi(right); | |
| 1092 } else if (right_cid == kSmiCid) { | |
| 1093 __ CheckSmi(left); | |
| 1094 } else { | |
| 1095 __ CheckSmi(left); | |
| 1096 compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp, | |
| 1097 licm_hoisted_ ? ICData::kHoisted : 0); | |
| 1098 __ CheckSmi(right); | |
| 1099 } | |
| 1100 compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp, | 1087 compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
| 1101 licm_hoisted_ ? ICData::kHoisted : 0); | 1088 licm_hoisted_ ? ICData::kHoisted : 0); |
| 1102 } | 1089 } |
| 1103 | 1090 |
| 1104 | 1091 |
| 1105 EMIT_NATIVE_CODE(CheckClassId, 1) { | 1092 EMIT_NATIVE_CODE(CheckClassId, 1) { |
| 1106 __ CheckClassId(locs()->in(0).reg(), | 1093 __ CheckClassId(locs()->in(0).reg(), |
| 1107 compiler->ToEmbeddableCid(cid_, this)); | 1094 compiler->ToEmbeddableCid(cid_, this)); |
| 1108 compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass); | 1095 compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass); |
| 1109 } | 1096 } |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1215 case Token::kNEGATE: { | 1202 case Token::kNEGATE: { |
| 1216 __ Neg(locs()->out(0).reg(), locs()->in(0).reg()); | 1203 __ Neg(locs()->out(0).reg(), locs()->in(0).reg()); |
| 1217 compiler->EmitDeopt(deopt_id(), ICData::kDeoptUnaryOp); | 1204 compiler->EmitDeopt(deopt_id(), ICData::kDeoptUnaryOp); |
| 1218 break; | 1205 break; |
| 1219 } | 1206 } |
| 1220 case Token::kBIT_NOT: | 1207 case Token::kBIT_NOT: |
| 1221 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); | 1208 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); |
| 1222 break; | 1209 break; |
| 1223 default: | 1210 default: |
| 1224 UNREACHABLE(); | 1211 UNREACHABLE(); |
| 1212 break; |
| 1225 } | 1213 } |
| 1226 } | 1214 } |
| 1227 | 1215 |
| 1228 | 1216 |
| 1217 EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) { |
| 1218 ASSERT(from_representation() == kUnboxedDouble); |
| 1219 const Register value = locs()->in(0).reg(); |
| 1220 const Register out = locs()->out(0).reg(); |
| 1221 const intptr_t kidx = __ AddConstant(compiler->double_class()); |
| 1222 __ Allocate(kidx); |
| 1223 compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, |
| 1224 Thread::kNoDeoptId, |
| 1225 token_pos()); |
| 1226 compiler->RecordSafepoint(locs()); |
| 1227 // __ Allocate puts the box at the top of the stack. |
| 1228 __ WriteIntoDouble(out, value); |
| 1229 } |
| 1230 |
| 1231 |
| 1232 EMIT_NATIVE_CODE(Unbox, 1, Location::RequiresRegister()) { |
| 1233 ASSERT(representation() == kUnboxedDouble); |
| 1234 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1235 const intptr_t box_cid = BoxCid(); |
| 1236 const Register box = locs()->in(0).reg(); |
| 1237 const Register result = locs()->out(0).reg(); |
| 1238 if (value_cid == box_cid) { |
| 1239 __ UnboxDouble(result, box); |
| 1240 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 1241 __ SmiToDouble(result, box); |
| 1242 } else if ((value()->Type()->ToNullableCid() == box_cid) && |
| 1243 value()->Type()->is_nullable()) { |
| 1244 __ IfEqNull(box); |
| 1245 compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass); |
| 1246 __ UnboxDouble(result, box); |
| 1247 } else { |
| 1248 __ CheckedUnboxDouble(result, box); |
| 1249 compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass); |
| 1250 } |
| 1251 } |
| 1252 |
| 1253 |
| 1254 EMIT_NATIVE_CODE(SmiToDouble, 1, Location::RequiresRegister()) { |
| 1255 const Register value = locs()->in(0).reg(); |
| 1256 const Register result = locs()->out(0).reg(); |
| 1257 __ SmiToDouble(result, value); |
| 1258 } |
| 1259 |
| 1260 |
| 1261 EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) { |
| 1262 const Register left = locs()->in(0).reg(); |
| 1263 const Register right = locs()->in(1).reg(); |
| 1264 const Register result = locs()->out(0).reg(); |
| 1265 switch (op_kind()) { |
| 1266 case Token::kADD: __ DAdd(result, left, right); break; |
| 1267 case Token::kSUB: __ DSub(result, left, right); break; |
| 1268 case Token::kMUL: __ DMul(result, left, right); break; |
| 1269 case Token::kDIV: __ DDiv(result, left, right); break; |
| 1270 default: UNREACHABLE(); |
| 1271 } |
| 1272 } |
| 1273 |
| 1274 |
| 1275 EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) { |
| 1276 const Register value = locs()->in(0).reg(); |
| 1277 const Register result = locs()->out(0).reg(); |
| 1278 __ DNeg(result, value); |
| 1279 } |
| 1280 |
| 1281 |
| 1229 static Token::Kind FlipCondition(Token::Kind kind) { | 1282 static Token::Kind FlipCondition(Token::Kind kind) { |
| 1230 switch (kind) { | 1283 switch (kind) { |
| 1231 case Token::kEQ: return Token::kNE; | 1284 case Token::kEQ: return Token::kNE; |
| 1232 case Token::kNE: return Token::kEQ; | 1285 case Token::kNE: return Token::kEQ; |
| 1233 case Token::kLT: return Token::kGTE; | 1286 case Token::kLT: return Token::kGTE; |
| 1234 case Token::kGT: return Token::kLTE; | 1287 case Token::kGT: return Token::kLTE; |
| 1235 case Token::kLTE: return Token::kGT; | 1288 case Token::kLTE: return Token::kGT; |
| 1236 case Token::kGTE: return Token::kLT; | 1289 case Token::kGTE: return Token::kLT; |
| 1237 default: | 1290 default: |
| 1238 UNREACHABLE(); | 1291 UNREACHABLE(); |
| 1239 return Token::kNE; | 1292 return Token::kNE; |
| 1240 } | 1293 } |
| 1241 } | 1294 } |
| 1242 | 1295 |
| 1243 | 1296 |
| 1244 static Bytecode::Opcode OpcodeForCondition(Token::Kind kind) { | 1297 static Bytecode::Opcode OpcodeForSmiCondition(Token::Kind kind) { |
| 1245 switch (kind) { | 1298 switch (kind) { |
| 1246 case Token::kEQ: return Bytecode::kIfEqStrict; | 1299 case Token::kEQ: return Bytecode::kIfEqStrict; |
| 1247 case Token::kNE: return Bytecode::kIfNeStrict; | 1300 case Token::kNE: return Bytecode::kIfNeStrict; |
| 1248 case Token::kLT: return Bytecode::kIfLt; | 1301 case Token::kLT: return Bytecode::kIfLt; |
| 1249 case Token::kGT: return Bytecode::kIfGt; | 1302 case Token::kGT: return Bytecode::kIfGt; |
| 1250 case Token::kLTE: return Bytecode::kIfLe; | 1303 case Token::kLTE: return Bytecode::kIfLe; |
| 1251 case Token::kGTE: return Bytecode::kIfGe; | 1304 case Token::kGTE: return Bytecode::kIfGe; |
| 1252 default: | 1305 default: |
| 1253 UNREACHABLE(); | 1306 UNREACHABLE(); |
| 1254 return Bytecode::kTrap; | 1307 return Bytecode::kTrap; |
| 1255 } | 1308 } |
| 1256 } | 1309 } |
| 1257 | 1310 |
| 1258 | 1311 |
| 1312 static Bytecode::Opcode OpcodeForDoubleCondition(Token::Kind kind) { |
| 1313 switch (kind) { |
| 1314 case Token::kEQ: return Bytecode::kIfDEq; |
| 1315 case Token::kNE: return Bytecode::kIfDNe; |
| 1316 case Token::kLT: return Bytecode::kIfDLt; |
| 1317 case Token::kGT: return Bytecode::kIfDGt; |
| 1318 case Token::kLTE: return Bytecode::kIfDLe; |
| 1319 case Token::kGTE: return Bytecode::kIfDGe; |
| 1320 default: |
| 1321 UNREACHABLE(); |
| 1322 return Bytecode::kTrap; |
| 1323 } |
| 1324 } |
| 1325 |
| 1326 |
| 1259 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 1327 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 1260 LocationSummary* locs, | 1328 LocationSummary* locs, |
| 1261 Token::Kind kind, | 1329 Token::Kind kind, |
| 1262 BranchLabels labels) { | 1330 BranchLabels labels) { |
| 1263 const Register left = locs->in(0).reg(); | 1331 const Register left = locs->in(0).reg(); |
| 1264 const Register right = locs->in(1).reg(); | 1332 const Register right = locs->in(1).reg(); |
| 1265 Token::Kind comparison = kind; | 1333 Token::Kind comparison = kind; |
| 1266 Condition condition = NEXT_IS_TRUE; | 1334 Condition condition = NEXT_IS_TRUE; |
| 1267 if (labels.fall_through != labels.false_label) { | 1335 if (labels.fall_through != labels.false_label) { |
| 1268 // If we aren't falling through to the false label, we can save a Jump | 1336 // If we aren't falling through to the false label, we can save a Jump |
| 1269 // instruction in the case that the true case is the fall through by | 1337 // instruction in the case that the true case is the fall through by |
| 1270 // flipping the sense of the test such that the instruction following the | 1338 // flipping the sense of the test such that the instruction following the |
| 1271 // test is the Jump to the false label. | 1339 // test is the Jump to the false label. |
| 1272 condition = NEXT_IS_FALSE; | 1340 condition = NEXT_IS_FALSE; |
| 1273 comparison = FlipCondition(kind); | 1341 comparison = FlipCondition(kind); |
| 1274 } | 1342 } |
| 1275 __ Emit(Bytecode::Encode(OpcodeForCondition(comparison), left, right)); | 1343 __ Emit(Bytecode::Encode(OpcodeForSmiCondition(comparison), left, right)); |
| 1276 return condition; | 1344 return condition; |
| 1277 } | 1345 } |
| 1278 | 1346 |
| 1347 |
| 1348 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 1349 LocationSummary* locs, |
| 1350 Token::Kind kind, |
| 1351 BranchLabels labels) { |
| 1352 const Register left = locs->in(0).reg(); |
| 1353 const Register right = locs->in(1).reg(); |
| 1354 Token::Kind comparison = kind; |
| 1355 Condition condition = NEXT_IS_TRUE; |
| 1356 if (labels.fall_through != labels.false_label) { |
| 1357 // If we aren't falling through to the false label, we can save a Jump |
| 1358 // instruction in the case that the true case is the fall through by |
| 1359 // flipping the sense of the test such that the instruction following the |
| 1360 // test is the Jump to the false label. |
| 1361 condition = NEXT_IS_FALSE; |
| 1362 comparison = FlipCondition(kind); |
| 1363 } |
| 1364 __ Emit(Bytecode::Encode(OpcodeForDoubleCondition(comparison), left, right)); |
| 1365 return condition; |
| 1366 } |
| 1367 |
| 1279 | 1368 |
| 1280 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 1369 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 1281 BranchLabels labels) { | 1370 BranchLabels labels) { |
| 1282 if (operation_cid() == kSmiCid) { | 1371 if (operation_cid() == kSmiCid) { |
| 1283 return EmitSmiComparisonOp(compiler, locs(), kind(), labels); | 1372 return EmitSmiComparisonOp(compiler, locs(), kind(), labels); |
| 1284 } else { | 1373 } else { |
| 1285 ASSERT(operation_cid() == kDoubleCid); | 1374 ASSERT(operation_cid() == kDoubleCid); |
| 1286 Unsupported(compiler); | 1375 return EmitDoubleComparisonOp(compiler, locs(), kind(), labels); |
| 1287 UNREACHABLE(); | |
| 1288 return NEXT_IS_FALSE; | |
| 1289 } | 1376 } |
| 1290 } | 1377 } |
| 1291 | 1378 |
| 1292 | 1379 |
| 1293 EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) { | 1380 EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) { |
| 1294 ASSERT(compiler->is_optimizing()); | 1381 ASSERT(compiler->is_optimizing()); |
| 1295 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 1382 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 1296 Label is_true, is_false; | 1383 Label is_true, is_false; |
| 1297 // These labels are not used. They are arranged so that EmitComparisonCode | 1384 // These labels are not used. They are arranged so that EmitComparisonCode |
| 1298 // emits a test that executes the following instruction when the test | 1385 // emits a test that executes the following instruction when the test |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1314 EmitBranchOnCondition(compiler, true_condition, labels); | 1401 EmitBranchOnCondition(compiler, true_condition, labels); |
| 1315 } | 1402 } |
| 1316 | 1403 |
| 1317 | 1404 |
| 1318 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 1405 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 1319 BranchLabels labels) { | 1406 BranchLabels labels) { |
| 1320 if (operation_cid() == kSmiCid) { | 1407 if (operation_cid() == kSmiCid) { |
| 1321 return EmitSmiComparisonOp(compiler, locs(), kind(), labels); | 1408 return EmitSmiComparisonOp(compiler, locs(), kind(), labels); |
| 1322 } else { | 1409 } else { |
| 1323 ASSERT(operation_cid() == kDoubleCid); | 1410 ASSERT(operation_cid() == kDoubleCid); |
| 1324 Unsupported(compiler); | 1411 return EmitDoubleComparisonOp(compiler, locs(), kind(), labels); |
| 1325 UNREACHABLE(); | |
| 1326 return NEXT_IS_FALSE; | |
| 1327 } | 1412 } |
| 1328 } | 1413 } |
| 1329 | 1414 |
| 1330 | 1415 |
| 1331 EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) { | 1416 EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) { |
| 1332 ASSERT(compiler->is_optimizing()); | 1417 ASSERT(compiler->is_optimizing()); |
| 1333 Label is_true, is_false; | 1418 Label is_true, is_false; |
| 1334 BranchLabels labels = { &is_true, &is_false, &is_false }; | 1419 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 1335 const Register result = locs()->out(0).reg(); | 1420 const Register result = locs()->out(0).reg(); |
| 1336 __ LoadConstant(result, Bool::False()); | 1421 __ LoadConstant(result, Bool::False()); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1362 __ IfULe(length, index); | 1447 __ IfULe(length, index); |
| 1363 compiler->EmitDeopt(deopt_id(), | 1448 compiler->EmitDeopt(deopt_id(), |
| 1364 ICData::kDeoptCheckArrayBound, | 1449 ICData::kDeoptCheckArrayBound, |
| 1365 (generalized_ ? ICData::kGeneralized : 0) | | 1450 (generalized_ ? ICData::kGeneralized : 0) | |
| 1366 (licm_hoisted_ ? ICData::kHoisted : 0)); | 1451 (licm_hoisted_ ? ICData::kHoisted : 0)); |
| 1367 } | 1452 } |
| 1368 | 1453 |
| 1369 } // namespace dart | 1454 } // namespace dart |
| 1370 | 1455 |
| 1371 #endif // defined TARGET_ARCH_DBC | 1456 #endif // defined TARGET_ARCH_DBC |
| OLD | NEW |