Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(248)

Side by Side Diff: runtime/vm/intermediate_language_dbc.cc

Issue 2120703002: DBC: Enables unboxed doubles (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Comparison ops Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 106
101 // List of instructions that are not used by DBC.
102 #define FOR_EACH_UNREACHABLE_INSTRUCTION(M) \
103 M(CaseInsensitiveCompareUC16) \
104 M(GrowRegExpStack) \
105 M(IndirectGoto)
106
107 // Location summaries actually are not used by the unoptimizing DBC compiler 107 // Location summaries actually are not used by the unoptimizing DBC compiler
108 // because we don't allocate any registers. 108 // because we don't allocate any registers.
109 static LocationSummary* CreateLocationSummary( 109 static LocationSummary* CreateLocationSummary(
110 Zone* zone, 110 Zone* zone,
111 intptr_t num_inputs, 111 intptr_t num_inputs,
112 Location output = Location::NoLocation(), 112 Location output = Location::NoLocation(),
113 LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall) { 113 LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall) {
114 const intptr_t kNumTemps = 0; 114 const intptr_t kNumTemps = 0;
115 LocationSummary* locs = new(zone) LocationSummary( 115 LocationSummary* locs = new(zone) LocationSummary(
116 zone, num_inputs, kNumTemps, contains_call); 116 zone, num_inputs, kNumTemps, contains_call);
(...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after
1214 case Token::kNEGATE: { 1214 case Token::kNEGATE: {
1215 __ Neg(locs()->out(0).reg(), locs()->in(0).reg()); 1215 __ Neg(locs()->out(0).reg(), locs()->in(0).reg());
1216 compiler->EmitDeopt(deopt_id(), ICData::kDeoptUnaryOp); 1216 compiler->EmitDeopt(deopt_id(), ICData::kDeoptUnaryOp);
1217 break; 1217 break;
1218 } 1218 }
1219 case Token::kBIT_NOT: 1219 case Token::kBIT_NOT:
1220 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); 1220 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg());
1221 break; 1221 break;
1222 default: 1222 default:
1223 UNREACHABLE(); 1223 UNREACHABLE();
1224 break;
1224 } 1225 }
1225 } 1226 }
1226 1227
1227 1228
1229 EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) {
1230 ASSERT(from_representation() == kUnboxedDouble);
1231 const Register value = locs()->in(0).reg();
1232 const Register out = locs()->out(0).reg();
1233 const intptr_t kidx = __ AddConstant(compiler->double_class());
1234 __ Allocate(kidx);
1235 compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
1236 Thread::kNoDeoptId,
1237 token_pos());
1238 compiler->RecordSafepoint(locs());
1239 // __ Allocate puts the box at the top of the stack.
1240 __ BoxDouble(out, value);
1241 }
1242
1243
1244 EMIT_NATIVE_CODE(Unbox, 1, Location::RequiresRegister()) {
1245 ASSERT(representation() == kUnboxedDouble);
1246 const intptr_t value_cid = value()->Type()->ToCid();
1247 const intptr_t box_cid = BoxCid();
1248 const Register box = locs()->in(0).reg();
1249 const Register result = locs()->out(0).reg();
1250 if (value_cid == box_cid) {
1251 __ UnboxDouble(result, box);
1252 } else if (CanConvertSmi() && (value_cid == kSmiCid)) {
1253 __ SmiToDouble(result, box);
1254 } else if ((value()->Type()->ToNullableCid() == box_cid) &&
1255 value()->Type()->is_nullable()) {
1256 __ IfEqNull(box);
1257 compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
1258 __ UnboxDouble(result, box);
1259 } else {
1260 __ CheckedUnboxDouble(result, box);
1261 compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
1262 }
1263 }
1264
1265
1266 EMIT_NATIVE_CODE(SmiToDouble, 1, Location::RequiresRegister()) {
1267 const Register value = locs()->in(0).reg();
1268 const Register result = locs()->out(0).reg();
1269 __ SmiToDouble(result, value);
1270 }
1271
1272
1273 EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) {
1274 const Register left = locs()->in(0).reg();
1275 const Register right = locs()->in(1).reg();
1276 const Register result = locs()->out(0).reg();
1277 switch (op_kind()) {
1278 case Token::kADD: __ DAdd(result, left, right); break;
1279 case Token::kSUB: __ DSub(result, left, right); break;
1280 case Token::kMUL: __ DMul(result, left, right); break;
1281 case Token::kDIV: __ DDiv(result, left, right); break;
1282 default: UNREACHABLE();
1283 }
1284 }
1285
1286
1287 EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) {
1288 const Register value = locs()->in(0).reg();
1289 const Register result = locs()->out(0).reg();
1290 __ DNeg(result, value);
1291 }
1292
1293
1228 static Token::Kind FlipCondition(Token::Kind kind) { 1294 static Token::Kind FlipCondition(Token::Kind kind) {
1229 switch (kind) { 1295 switch (kind) {
1230 case Token::kEQ: return Token::kNE; 1296 case Token::kEQ: return Token::kNE;
1231 case Token::kNE: return Token::kEQ; 1297 case Token::kNE: return Token::kEQ;
1232 case Token::kLT: return Token::kGTE; 1298 case Token::kLT: return Token::kGTE;
1233 case Token::kGT: return Token::kLTE; 1299 case Token::kGT: return Token::kLTE;
1234 case Token::kLTE: return Token::kGT; 1300 case Token::kLTE: return Token::kGT;
1235 case Token::kGTE: return Token::kLT; 1301 case Token::kGTE: return Token::kLT;
1236 default: 1302 default:
1237 UNREACHABLE(); 1303 UNREACHABLE();
1238 return Token::kNE; 1304 return Token::kNE;
1239 } 1305 }
1240 } 1306 }
1241 1307
1242 1308
1243 static Bytecode::Opcode OpcodeForCondition(Token::Kind kind) { 1309 static Bytecode::Opcode OpcodeForSmiCondition(Token::Kind kind) {
1244 switch (kind) { 1310 switch (kind) {
1245 case Token::kEQ: return Bytecode::kIfEqStrict; 1311 case Token::kEQ: return Bytecode::kIfEqStrict;
1246 case Token::kNE: return Bytecode::kIfNeStrict; 1312 case Token::kNE: return Bytecode::kIfNeStrict;
1247 case Token::kLT: return Bytecode::kIfLt; 1313 case Token::kLT: return Bytecode::kIfLt;
1248 case Token::kGT: return Bytecode::kIfGt; 1314 case Token::kGT: return Bytecode::kIfGt;
1249 case Token::kLTE: return Bytecode::kIfLe; 1315 case Token::kLTE: return Bytecode::kIfLe;
1250 case Token::kGTE: return Bytecode::kIfGe; 1316 case Token::kGTE: return Bytecode::kIfGe;
1251 default: 1317 default:
1252 UNREACHABLE(); 1318 UNREACHABLE();
1253 return Bytecode::kTrap; 1319 return Bytecode::kTrap;
1254 } 1320 }
1255 } 1321 }
1256 1322
1257 1323
1324 static Bytecode::Opcode OpcodeForDoubleCondition(Token::Kind kind) {
1325 switch (kind) {
1326 case Token::kEQ: return Bytecode::kIfDEq;
1327 case Token::kNE: return Bytecode::kIfDNe;
1328 case Token::kLT: return Bytecode::kIfDLt;
1329 case Token::kGT: return Bytecode::kIfDGt;
1330 case Token::kLTE: return Bytecode::kIfDLe;
1331 case Token::kGTE: return Bytecode::kIfDGe;
1332 default:
1333 UNREACHABLE();
1334 return Bytecode::kTrap;
1335 }
1336 }
1337
1338
1258 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, 1339 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
1259 LocationSummary* locs, 1340 LocationSummary* locs,
1260 Token::Kind kind, 1341 Token::Kind kind,
1261 BranchLabels labels) { 1342 BranchLabels labels) {
1262 const Register left = locs->in(0).reg(); 1343 const Register left = locs->in(0).reg();
1263 const Register right = locs->in(1).reg(); 1344 const Register right = locs->in(1).reg();
1264 Token::Kind comparison = kind; 1345 Token::Kind comparison = kind;
1265 Condition condition = NEXT_IS_TRUE; 1346 Condition condition = NEXT_IS_TRUE;
1266 if (labels.fall_through != labels.false_label) { 1347 if (labels.fall_through != labels.false_label) {
1267 // If we aren't falling through to the false label, we can save a Jump 1348 // If we aren't falling through to the false label, we can save a Jump
1268 // instruction in the case that the true case is the fall through by 1349 // instruction in the case that the true case is the fall through by
1269 // flipping the sense of the test such that the instruction following the 1350 // flipping the sense of the test such that the instruction following the
1270 // test is the Jump to the false label. 1351 // test is the Jump to the false label.
1271 condition = NEXT_IS_FALSE; 1352 condition = NEXT_IS_FALSE;
1272 comparison = FlipCondition(kind); 1353 comparison = FlipCondition(kind);
1273 } 1354 }
1274 __ Emit(Bytecode::Encode(OpcodeForCondition(comparison), left, right)); 1355 __ Emit(Bytecode::Encode(OpcodeForSmiCondition(comparison), left, right));
1275 return condition; 1356 return condition;
1276 } 1357 }
1277 1358
1359
1360 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
1361 LocationSummary* locs,
1362 Token::Kind kind,
1363 BranchLabels labels) {
1364 const Register left = locs->in(0).reg();
1365 const Register right = locs->in(1).reg();
1366 Token::Kind comparison = kind;
1367 Condition condition = NEXT_IS_TRUE;
1368 if (labels.fall_through != labels.false_label) {
1369 // If we aren't falling through to the false label, we can save a Jump
1370 // instruction in the case that the true case is the fall through by
1371 // flipping the sense of the test such that the instruction following the
1372 // test is the Jump to the false label.
1373 condition = NEXT_IS_FALSE;
1374 comparison = FlipCondition(kind);
1375 }
1376 __ Emit(Bytecode::Encode(OpcodeForDoubleCondition(comparison), left, right));
1377 return condition;
1378 }
1379
1278 1380
1279 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 1381 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
1280 BranchLabels labels) { 1382 BranchLabels labels) {
1281 if (operation_cid() == kSmiCid) { 1383 if (operation_cid() == kSmiCid) {
1282 return EmitSmiComparisonOp(compiler, locs(), kind(), labels); 1384 return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
1283 } else { 1385 } else {
1284 ASSERT(operation_cid() == kDoubleCid); 1386 ASSERT(operation_cid() == kDoubleCid);
1285 Unsupported(compiler); 1387 return EmitDoubleComparisonOp(compiler, locs(), kind(), labels);
1286 UNREACHABLE();
1287 return NEXT_IS_FALSE;
1288 } 1388 }
1289 } 1389 }
1290 1390
1291 1391
1292 EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) { 1392 EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) {
1293 ASSERT(compiler->is_optimizing()); 1393 ASSERT(compiler->is_optimizing());
1294 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); 1394 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
1295 Label is_true, is_false; 1395 Label is_true, is_false;
1296 // These labels are not used. They are arranged so that EmitComparisonCode 1396 // These labels are not used. They are arranged so that EmitComparisonCode
1297 // emits a test that executes the following instruction when the test 1397 // emits a test that executes the following instruction when the test
(...skipping 15 matching lines...) Expand all
1313 EmitBranchOnCondition(compiler, true_condition, labels); 1413 EmitBranchOnCondition(compiler, true_condition, labels);
1314 } 1414 }
1315 1415
1316 1416
1317 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 1417 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
1318 BranchLabels labels) { 1418 BranchLabels labels) {
1319 if (operation_cid() == kSmiCid) { 1419 if (operation_cid() == kSmiCid) {
1320 return EmitSmiComparisonOp(compiler, locs(), kind(), labels); 1420 return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
1321 } else { 1421 } else {
1322 ASSERT(operation_cid() == kDoubleCid); 1422 ASSERT(operation_cid() == kDoubleCid);
1323 Unsupported(compiler); 1423 return EmitDoubleComparisonOp(compiler, locs(), kind(), labels);
1324 UNREACHABLE();
1325 return NEXT_IS_FALSE;
1326 } 1424 }
1327 } 1425 }
1328 1426
1329 1427
1330 EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) { 1428 EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) {
1331 ASSERT(compiler->is_optimizing()); 1429 ASSERT(compiler->is_optimizing());
1332 Label is_true, is_false; 1430 Label is_true, is_false;
1333 BranchLabels labels = { &is_true, &is_false, &is_false }; 1431 BranchLabels labels = { &is_true, &is_false, &is_false };
1334 const Register result = locs()->out(0).reg(); 1432 const Register result = locs()->out(0).reg();
1335 __ LoadConstant(result, Bool::False()); 1433 __ LoadConstant(result, Bool::False());
(...skipping 17 matching lines...) Expand all
1353 __ IfULe(length, index); 1451 __ IfULe(length, index);
1354 compiler->EmitDeopt(deopt_id(), 1452 compiler->EmitDeopt(deopt_id(),
1355 ICData::kDeoptCheckArrayBound, 1453 ICData::kDeoptCheckArrayBound,
1356 (generalized_ ? ICData::kGeneralized : 0) | 1454 (generalized_ ? ICData::kGeneralized : 0) |
1357 (licm_hoisted_ ? ICData::kHoisted : 0)); 1455 (licm_hoisted_ ? ICData::kHoisted : 0));
1358 } 1456 }
1359 1457
1360 } // namespace dart 1458 } // namespace dart
1361 1459
1362 #endif // defined TARGET_ARCH_DBC 1460 #endif // defined TARGET_ARCH_DBC
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698