| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/locations.h" | 13 #include "vm/locations.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/parser.h" | 15 #include "vm/parser.h" |
| 16 #include "vm/stack_frame.h" |
| 16 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 17 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 18 | 19 |
| 19 #define __ compiler->assembler()-> | 20 #define __ compiler->assembler()-> |
| 20 | 21 |
| 21 namespace dart { | 22 namespace dart { |
| 22 | 23 |
| 23 DECLARE_FLAG(int, optimization_counter_threshold); | 24 DECLARE_FLAG(int, optimization_counter_threshold); |
| 24 DECLARE_FLAG(bool, propagate_ic_data); | 25 DECLARE_FLAG(bool, propagate_ic_data); |
| 25 | 26 |
| (...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1325 break; | 1326 break; |
| 1326 case kFloat64ArrayCid: | 1327 case kFloat64ArrayCid: |
| 1327 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1328 __ movsd(element_address, locs()->in(2).fpu_reg()); |
| 1328 break; | 1329 break; |
| 1329 default: | 1330 default: |
| 1330 UNREACHABLE(); | 1331 UNREACHABLE(); |
| 1331 } | 1332 } |
| 1332 } | 1333 } |
| 1333 | 1334 |
| 1334 | 1335 |
| 1336 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { |
| 1337 const intptr_t kNumInputs = 1; |
| 1338 LocationSummary* summary = |
| 1339 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); |
| 1340 summary->set_in(0, Location::RequiresRegister()); |
| 1341 if (value()->Type()->ToCid() == kDynamicCid) { |
| 1342 summary->AddTemp(Location::RequiresRegister()); |
| 1343 } |
| 1344 if (field().guarded_cid() == kIllegalCid) { |
| 1345 summary->AddTemp(Location::RequiresRegister()); |
| 1346 } |
| 1347 return summary; |
| 1348 } |
| 1349 |
| 1350 |
| 1351 static void PushCid(FlowGraphCompiler* compiler, const Immediate& imm) { |
| 1352 __ pushq(Immediate(Smi::RawValue(imm.value()))); |
| 1353 } |
| 1354 |
| 1355 |
| 1356 static void PushCid(FlowGraphCompiler* compiler, Register reg) { |
| 1357 __ SmiTag(reg); |
| 1358 __ pushq(reg); |
| 1359 } |
| 1360 |
| 1361 |
| 1362 template<typename ValueCidOperandType> |
| 1363 static void EmitCidGuardInit(FlowGraphCompiler* compiler, |
| 1364 ValueCidOperandType value_cid, |
| 1365 const Immediate& field_cid, |
| 1366 const Immediate& nullability, |
| 1367 Label* deopt, |
| 1368 Label* ok) { |
| 1369 // nothing to do. |
| 1370 } |
| 1371 |
| 1372 |
| 1373 template<typename ValueCidOperandType> |
| 1374 static void EmitCidGuardInit(FlowGraphCompiler* compiler, |
| 1375 ValueCidOperandType value_cid, |
| 1376 const FieldAddress& field_cid, |
| 1377 const FieldAddress& nullability, |
| 1378 Label* deopt, |
| 1379 Label* ok) { |
| 1380 // Check if field is initialized for the first time. |
| 1381 Label fail; |
| 1382 __ cmpq(field_cid, Immediate(kIllegalCid)); |
| 1383 __ j(NOT_EQUAL, (deopt != NULL) ? deopt : &fail); |
| 1384 __ movq(field_cid, value_cid); |
| 1385 __ movq(nullability, value_cid); |
| 1386 __ jmp(ok); |
| 1387 if (deopt == NULL) { |
| 1388 __ Bind(&fail); |
| 1389 } |
| 1390 } |
| 1391 |
| 1392 |
| 1393 static void CompareJump(FlowGraphCompiler* compiler, |
| 1394 Condition cond, |
| 1395 const Immediate& left, |
| 1396 const Immediate& right, |
| 1397 Label* target) { |
| 1398 if ((left.value() == right.value()) && (cond == EQUAL)) { |
| 1399 __ jmp(target); |
| 1400 } else if ((left.value() != right.value()) && cond == NOT_EQUAL) { |
| 1401 __ jmp(target); |
| 1402 } |
| 1403 } |
| 1404 |
| 1405 |
| 1406 static void CompareJump(FlowGraphCompiler* compiler, |
| 1407 Condition cond, |
| 1408 Immediate left, |
| 1409 Register right, |
| 1410 Label* target) { |
| 1411 ASSERT((cond == EQUAL) || (cond == NOT_EQUAL)); |
| 1412 __ cmpq(right, left); |
| 1413 __ j(cond, target); |
| 1414 } |
| 1415 |
| 1416 |
| 1417 template<typename LeftOperandType, typename RightOperandType> |
| 1418 static void CompareJump(FlowGraphCompiler* compiler, |
| 1419 Condition cond, |
| 1420 LeftOperandType left, |
| 1421 RightOperandType right, |
| 1422 Label* target) { |
| 1423 __ cmpq(left, right); |
| 1424 __ j(cond, target); |
| 1425 } |
| 1426 |
| 1427 |
| 1428 template<typename ValueCidOperandType, |
| 1429 typename FieldCidOperandType, |
| 1430 typename FieldNullabilityOperandType> |
| 1431 static void EmitCidGuard(FlowGraphCompiler* compiler, |
| 1432 const Field& field, |
| 1433 ValueCidOperandType value_cid, |
| 1434 FieldCidOperandType field_cid, |
| 1435 FieldNullabilityOperandType nullability, |
| 1436 Label* deopt) { |
| 1437 Label ok, update; |
| 1438 CompareJump(compiler, EQUAL, field_cid, value_cid, &ok); |
| 1439 if ((deopt != NULL) && (field.guarded_cid() != kIllegalCid)) { |
| 1440 CompareJump(compiler, NOT_EQUAL, nullability, value_cid, deopt); |
| 1441 } else { |
| 1442 CompareJump(compiler, EQUAL, nullability, value_cid, &ok); |
| 1443 } |
| 1444 |
| 1445 EmitCidGuardInit(compiler, value_cid, field_cid, nullability, deopt, &ok); |
| 1446 |
| 1447 if (deopt == NULL) { |
| 1448 // Switch field's cid to dynamic and notify runtime. |
| 1449 CompareJump(compiler, EQUAL, field_cid, Immediate(kDynamicCid), &ok); |
| 1450 __ PushObject(field); |
| 1451 PushCid(compiler, value_cid); |
| 1452 __ CallRuntime(kUpdateFieldCidRuntimeEntry); |
| 1453 __ Drop(2); |
| 1454 } |
| 1455 |
| 1456 __ Bind(&ok); |
| 1457 } |
| 1458 |
| 1459 |
| 1460 template<typename FieldCidOperandType, typename FieldNullabilityOperandType> |
| 1461 static void EmitCidGuard(FlowGraphCompiler* compiler, |
| 1462 const Field& field, |
| 1463 intptr_t value_cid, |
| 1464 Register value_cid_reg, |
| 1465 FieldCidOperandType field_cid, |
| 1466 FieldNullabilityOperandType nullability, |
| 1467 Label* deopt) { |
| 1468 if (value_cid == kDynamicCid) { |
| 1469 EmitCidGuard(compiler, field, value_cid_reg, field_cid, nullability, deopt); |
| 1470 } else { |
| 1471 EmitCidGuard(compiler, |
| 1472 field, |
| 1473 Immediate(value_cid), |
| 1474 field_cid, |
| 1475 nullability, |
| 1476 deopt); |
| 1477 } |
| 1478 } |
| 1479 |
| 1480 |
| 1481 static void EmitFieldGuard(FlowGraphCompiler* compiler, |
| 1482 Register value_reg, |
| 1483 const Field& field, |
| 1484 intptr_t value_cid, |
| 1485 Register value_cid_reg, |
| 1486 intptr_t field_cid, |
| 1487 intptr_t nullability, |
| 1488 Register field_reg, |
| 1489 Label* deopt) { |
| 1490 if (value_cid == kDynamicCid) { |
| 1491 Label not_smi, cid_loaded; |
| 1492 __ testq(value_reg, Immediate(kSmiTagMask)); |
| 1493 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 1494 __ movq(value_cid_reg, Immediate(kSmiCid)); |
| 1495 __ jmp(&cid_loaded); |
| 1496 __ Bind(¬_smi); |
| 1497 __ LoadClassId(value_cid_reg, value_reg); |
| 1498 __ Bind(&cid_loaded); |
| 1499 } |
| 1500 |
| 1501 if (field_cid == kIllegalCid) { |
| 1502 __ LoadObject(field_reg, Field::ZoneHandle(field.raw())); |
| 1503 EmitCidGuard(compiler, |
| 1504 field, |
| 1505 value_cid, |
| 1506 value_cid_reg, |
| 1507 FieldAddress(field_reg, Field::guarded_cid_offset()), |
| 1508 FieldAddress(field_reg, Field::is_nullable_offset()), |
| 1509 deopt); |
| 1510 } else { |
| 1511 EmitCidGuard(compiler, |
| 1512 field, |
| 1513 value_cid, |
| 1514 value_cid_reg, |
| 1515 Immediate(field_cid), |
| 1516 Immediate(nullability), |
| 1517 deopt); |
| 1518 } |
| 1519 } |
| 1520 |
| 1521 |
| 1522 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1523 const intptr_t field_cid = field().guarded_cid(); |
| 1524 |
| 1525 if (field_cid == kDynamicCid) { |
| 1526 ASSERT(!compiler->is_optimizing()); |
| 1527 return; // Nothing to emit. |
| 1528 } |
| 1529 |
| 1530 |
| 1531 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1532 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1533 |
| 1534 Register value_reg = locs()->in(0).reg(); |
| 1535 |
| 1536 Register value_cid_reg = (value_cid == kDynamicCid) ? |
| 1537 locs()->temp(0).reg() : kNoRegister; |
| 1538 |
| 1539 Label* deopt = compiler->is_optimizing() && CanDeoptimize() ? |
| 1540 compiler->AddDeoptStub(deopt_id(), kDeoptStoreInstanceField) : NULL; |
| 1541 |
| 1542 if ((deopt != NULL) && (field_cid != kIllegalCid)) { |
| 1543 if (value_cid != kDynamicCid) { |
| 1544 ASSERT(field_cid != value_cid); |
| 1545 __ jmp(deopt); |
| 1546 return; |
| 1547 } |
| 1548 |
| 1549 if (field_cid == kSmiCid) { |
| 1550 __ testq(value_reg, Immediate(kSmiTagMask)); |
| 1551 } else { |
| 1552 ASSERT(value_cid_reg != kNoRegister); |
| 1553 __ testq(value_reg, Immediate(kSmiTagMask)); |
| 1554 __ j(ZERO, deopt); |
| 1555 __ LoadClassId(value_cid_reg, value_reg); |
| 1556 __ cmpq(value_cid_reg, Immediate(field_cid)); |
| 1557 } |
| 1558 |
| 1559 if (field().is_nullable()) { |
| 1560 Label ok; |
| 1561 __ j(EQUAL, &ok); |
| 1562 const Immediate& raw_null = |
| 1563 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1564 __ cmpq(value_reg, raw_null); |
| 1565 __ j(NOT_EQUAL, deopt); |
| 1566 __ Bind(&ok); |
| 1567 } else { |
| 1568 __ j(NOT_EQUAL, deopt); |
| 1569 } |
| 1570 |
| 1571 return; |
| 1572 } |
| 1573 |
| 1574 Register field_reg = (field_cid == kIllegalCid) ? |
| 1575 locs()->temp(value_cid_reg == kNoRegister ? 0 : 1).reg() : kNoRegister; |
| 1576 |
| 1577 EmitFieldGuard(compiler, |
| 1578 value_reg, |
| 1579 field(), |
| 1580 value_cid, value_cid_reg, |
| 1581 field_cid, nullability, field_reg, |
| 1582 deopt); |
| 1583 } |
| 1584 |
| 1585 |
| 1335 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1586 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
| 1336 const intptr_t kNumInputs = 2; | 1587 const intptr_t kNumInputs = 2; |
| 1337 const intptr_t num_temps = 0; | 1588 const intptr_t num_temps = 0; |
| 1338 LocationSummary* summary = | 1589 LocationSummary* summary = |
| 1339 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); | 1590 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1340 summary->set_in(0, Location::RequiresRegister()); | 1591 summary->set_in(0, Location::RequiresRegister()); |
| 1341 summary->set_in(1, ShouldEmitStoreBarrier() | 1592 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1342 ? Location::WritableRegister() | 1593 ? Location::WritableRegister() |
| 1343 : Location::RegisterOrConstant(value())); | 1594 : Location::RegisterOrConstant(value())); |
| 1344 return summary; | 1595 return summary; |
| (...skipping 1328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2673 } | 2924 } |
| 2674 | 2925 |
| 2675 | 2926 |
| 2676 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2927 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2677 comparison()->EmitBranchCode(compiler, this); | 2928 comparison()->EmitBranchCode(compiler, this); |
| 2678 } | 2929 } |
| 2679 | 2930 |
| 2680 | 2931 |
| 2681 LocationSummary* CheckClassInstr::MakeLocationSummary() const { | 2932 LocationSummary* CheckClassInstr::MakeLocationSummary() const { |
| 2682 const intptr_t kNumInputs = 1; | 2933 const intptr_t kNumInputs = 1; |
| 2683 const intptr_t kNumTemps = 1; | 2934 const intptr_t kNumTemps = 0; |
| 2684 LocationSummary* summary = | 2935 LocationSummary* summary = |
| 2685 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2936 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2686 summary->set_in(0, Location::RequiresRegister()); | 2937 summary->set_in(0, Location::RequiresRegister()); |
| 2687 summary->set_temp(0, Location::RequiresRegister()); | 2938 if (!null_check()) { |
| 2939 summary->AddTemp(Location::RequiresRegister()); |
| 2940 } |
| 2688 return summary; | 2941 return summary; |
| 2689 } | 2942 } |
| 2690 | 2943 |
| 2691 | 2944 |
| 2692 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2945 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2946 if (null_check()) { |
| 2947 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2948 kDeoptCheckClass); |
| 2949 const Immediate& raw_null = |
| 2950 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2951 __ cmpq(locs()->in(0).reg(), raw_null); |
| 2952 __ j(EQUAL, deopt); |
| 2953 return; |
| 2954 } |
| 2955 |
| 2693 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 2956 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| 2694 (unary_checks().NumberOfChecks() > 1)); | 2957 (unary_checks().NumberOfChecks() > 1)); |
| 2695 Register value = locs()->in(0).reg(); | 2958 Register value = locs()->in(0).reg(); |
| 2696 Register temp = locs()->temp(0).reg(); | 2959 Register temp = locs()->temp(0).reg(); |
| 2697 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2960 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2698 kDeoptCheckClass); | 2961 kDeoptCheckClass); |
| 2699 Label is_ok; | 2962 Label is_ok; |
| 2700 intptr_t cix = 0; | 2963 intptr_t cix = 0; |
| 2701 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { | 2964 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { |
| 2702 __ testq(value, Immediate(kSmiTagMask)); | 2965 __ testq(value, Immediate(kSmiTagMask)); |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3158 PcDescriptors::kOther, | 3421 PcDescriptors::kOther, |
| 3159 locs()); | 3422 locs()); |
| 3160 __ Drop(2); // Discard type arguments and receiver. | 3423 __ Drop(2); // Discard type arguments and receiver. |
| 3161 } | 3424 } |
| 3162 | 3425 |
| 3163 } // namespace dart | 3426 } // namespace dart |
| 3164 | 3427 |
| 3165 #undef __ | 3428 #undef __ |
| 3166 | 3429 |
| 3167 #endif // defined TARGET_ARCH_X64 | 3430 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |