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

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

Issue 12529008: Collect type feedback for fields. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 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 | Annotate | Revision Log
OLDNEW
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
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 LeftT, typename RightT>
1418 static void CompareJump(FlowGraphCompiler* compiler,
1419 Condition cond,
1420 LeftT left,
1421 RightT 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, &not_smi, Assembler::kNearJump);
1494 __ movq(value_cid_reg, Immediate(kSmiCid));
1495 __ jmp(&cid_loaded);
1496 __ Bind(&not_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 value_cid = value()->Type()->ToCid();
1524 const intptr_t field_cid = field().guarded_cid();
1525 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1526
1527 Register value_reg = locs()->in(0).reg();
1528
1529 Register value_cid_reg = (value_cid == kDynamicCid) ?
1530 locs()->temp(0).reg() : kNoRegister;
1531
1532 Label* deopt = compiler->is_optimizing() && CanDeoptimize() ?
1533 compiler->AddDeoptStub(deopt_id(), kDeoptStoreInstanceField) : NULL;
1534
1535 if ((deopt != NULL) && (field_cid != kIllegalCid)) {
1536 if (value_cid != kDynamicCid) {
1537 ASSERT(field_cid != value_cid);
1538 __ jmp(deopt);
1539 return;
1540 }
1541
1542 if (field_cid == kSmiCid) {
1543 __ testq(value_reg, Immediate(kSmiTagMask));
1544 } else {
1545 ASSERT(value_cid_reg != kNoRegister);
1546 __ testq(value_reg, Immediate(kSmiTagMask));
1547 __ j(ZERO, deopt);
1548 __ LoadClassId(value_cid_reg, value_reg);
1549 __ cmpq(value_cid_reg, Immediate(field_cid));
1550 }
1551
1552 if (field().is_nullable()) {
1553 Label ok;
1554 __ j(EQUAL, &ok);
1555 const Immediate& raw_null =
1556 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1557 __ cmpq(value_reg, raw_null);
1558 __ j(NOT_EQUAL, deopt);
1559 __ Bind(&ok);
1560 } else {
1561 __ j(NOT_EQUAL, deopt);
1562 }
1563
1564 return;
1565 }
1566
1567 Register field_reg = (field_cid == kIllegalCid) ?
1568 locs()->temp(1).reg() : kNoRegister;
1569
1570 EmitFieldGuard(compiler,
1571 value_reg,
1572 field(),
1573 value_cid, value_cid_reg,
1574 field_cid, nullability, field_reg,
1575 deopt);
1576 }
1577
1578
1335 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { 1579 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
1336 const intptr_t kNumInputs = 2; 1580 const intptr_t kNumInputs = 2;
1337 const intptr_t num_temps = 0; 1581 const intptr_t num_temps = 0;
1338 LocationSummary* summary = 1582 LocationSummary* summary =
1339 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); 1583 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall);
1340 summary->set_in(0, Location::RequiresRegister()); 1584 summary->set_in(0, Location::RequiresRegister());
1341 summary->set_in(1, ShouldEmitStoreBarrier() 1585 summary->set_in(1, (ShouldEmitStoreBarrier() || should_emit_field_guard())
1342 ? Location::WritableRegister() 1586 ? Location::WritableRegister()
1343 : Location::RegisterOrConstant(value())); 1587 : Location::RegisterOrConstant(value()));
1588
1589 if (should_emit_field_guard()) {
1590 summary->AddTemp(Location::RequiresRegister());
1591 summary->AddTemp(Location::RequiresRegister());
1592 }
1593
1344 return summary; 1594 return summary;
1345 } 1595 }
1346 1596
1347 1597
1348 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1598 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1349 Register instance_reg = locs()->in(0).reg(); 1599 Register instance_reg = locs()->in(0).reg();
1600
1601
1602 if (should_emit_field_guard()) {
1603 ASSERT(!compiler->is_optimizing());
1604 Register value_reg = locs()->in(1).reg();
1605 Register value_cid_reg = locs()->temp(0).reg();
1606 Register field_reg = locs()->temp(1).reg();
1607
1608 __ pushq(instance_reg);
1609 __ pushq(value_reg);
1610 EmitFieldGuard(compiler,
1611 value_reg,
1612 field(),
1613 kDynamicCid,
1614 value_cid_reg,
1615 kIllegalCid,
1616 kIllegalCid,
1617 field_reg,
1618 NULL);
1619 __ popq(value_reg);
1620 __ popq(instance_reg);
1621 }
1622
1350 if (ShouldEmitStoreBarrier()) { 1623 if (ShouldEmitStoreBarrier()) {
1351 Register value_reg = locs()->in(1).reg(); 1624 Register value_reg = locs()->in(1).reg();
1352 __ StoreIntoObject(instance_reg, 1625 __ StoreIntoObject(instance_reg,
1353 FieldAddress(instance_reg, field().Offset()), value_reg); 1626 FieldAddress(instance_reg, field().Offset()), value_reg);
1354 } else { 1627 } else {
1355 if (locs()->in(1).IsConstant()) { 1628 if (locs()->in(1).IsConstant()) {
1356 __ StoreObject(FieldAddress(instance_reg, field().Offset()), 1629 __ StoreObject(FieldAddress(instance_reg, field().Offset()),
1357 locs()->in(1).constant()); 1630 locs()->in(1).constant());
1358 } else { 1631 } else {
1359 Register value_reg = locs()->in(1).reg(); 1632 Register value_reg = locs()->in(1).reg();
(...skipping 1313 matching lines...) Expand 10 before | Expand all | Expand 10 after
2673 } 2946 }
2674 2947
2675 2948
2676 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2949 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2677 comparison()->EmitBranchCode(compiler, this); 2950 comparison()->EmitBranchCode(compiler, this);
2678 } 2951 }
2679 2952
2680 2953
2681 LocationSummary* CheckClassInstr::MakeLocationSummary() const { 2954 LocationSummary* CheckClassInstr::MakeLocationSummary() const {
2682 const intptr_t kNumInputs = 1; 2955 const intptr_t kNumInputs = 1;
2683 const intptr_t kNumTemps = 1; 2956 const intptr_t kNumTemps = 0;
2684 LocationSummary* summary = 2957 LocationSummary* summary =
2685 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2958 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2686 summary->set_in(0, Location::RequiresRegister()); 2959 summary->set_in(0, Location::RequiresRegister());
2687 summary->set_temp(0, Location::RequiresRegister()); 2960 if (!null_check()) {
2961 summary->AddTemp(Location::RequiresRegister());
2962 }
2688 return summary; 2963 return summary;
2689 } 2964 }
2690 2965
2691 2966
2692 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2967 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2968 if (null_check()) {
2969 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2970 kDeoptCheckClass);
2971 const Immediate& raw_null =
2972 Immediate(reinterpret_cast<intptr_t>(Object::null()));
2973 __ cmpq(locs()->in(0).reg(), raw_null);
2974 __ j(EQUAL, deopt);
2975 return;
2976 }
2977
2693 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || 2978 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) ||
2694 (unary_checks().NumberOfChecks() > 1)); 2979 (unary_checks().NumberOfChecks() > 1));
2695 Register value = locs()->in(0).reg(); 2980 Register value = locs()->in(0).reg();
2696 Register temp = locs()->temp(0).reg(); 2981 Register temp = locs()->temp(0).reg();
2697 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2982 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2698 kDeoptCheckClass); 2983 kDeoptCheckClass);
2699 Label is_ok; 2984 Label is_ok;
2700 intptr_t cix = 0; 2985 intptr_t cix = 0;
2701 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { 2986 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
2702 __ testq(value, Immediate(kSmiTagMask)); 2987 __ testq(value, Immediate(kSmiTagMask));
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
3158 PcDescriptors::kOther, 3443 PcDescriptors::kOther,
3159 locs()); 3444 locs());
3160 __ Drop(2); // Discard type arguments and receiver. 3445 __ Drop(2); // Discard type arguments and receiver.
3161 } 3446 }
3162 3447
3163 } // namespace dart 3448 } // namespace dart
3164 3449
3165 #undef __ 3450 #undef __
3166 3451
3167 #endif // defined TARGET_ARCH_X64 3452 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698