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

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

Issue 304703002: Split GuardField into GuardFieldType and GuardFieldLength instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address comments Created 6 years, 6 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 1340 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 if (value_is_smi == NULL) { 1351 if (value_is_smi == NULL) {
1352 __ b(&done, EQ); 1352 __ b(&done, EQ);
1353 } else { 1353 } else {
1354 __ b(value_is_smi, EQ); 1354 __ b(value_is_smi, EQ);
1355 } 1355 }
1356 __ LoadClassId(value_cid_reg, value_reg, PP); 1356 __ LoadClassId(value_cid_reg, value_reg, PP);
1357 __ Bind(&done); 1357 __ Bind(&done);
1358 } 1358 }
1359 1359
1360 1360
1361 LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate, 1361 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
1362 bool opt) const { 1362 bool opt) const {
1363 const intptr_t kNumInputs = 1; 1363 const intptr_t kNumInputs = 1;
1364 LocationSummary* summary = new(isolate) LocationSummary( 1364 LocationSummary* summary = new(isolate) LocationSummary(
1365 isolate, kNumInputs, 0, LocationSummary::kNoCall); 1365 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1366 summary->set_in(0, Location::RequiresRegister()); 1366 summary->set_in(0, Location::RequiresRegister());
1367 const bool field_has_length = field().needs_length_check(); 1367
1368 summary->AddTemp(Location::RequiresRegister()); 1368 const intptr_t value_cid = value()->Type()->ToCid();
1369 summary->AddTemp(Location::RequiresRegister()); 1369 const intptr_t field_cid = field().guarded_cid();
1370 const bool need_field_temp_reg = 1370
1371 field_has_length || (field().guarded_cid() == kIllegalCid); 1371 const bool emit_full_guard =
1372 if (need_field_temp_reg) { 1372 !opt || (field_cid == kIllegalCid);
1373
1374 const bool needs_value_cid_temp_reg = emit_full_guard ||
1375 ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
1376
1377 const bool needs_field_temp_reg = emit_full_guard;
1378
1379 if (needs_value_cid_temp_reg) {
1373 summary->AddTemp(Location::RequiresRegister()); 1380 summary->AddTemp(Location::RequiresRegister());
1374 } 1381 }
1382
1383 if (needs_field_temp_reg) {
1384 summary->AddTemp(Location::RequiresRegister());
1385 }
1386
1375 return summary; 1387 return summary;
1376 } 1388 }
1377 1389
1378 1390
1379 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1391 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1392 const intptr_t value_cid = value()->Type()->ToCid();
1380 const intptr_t field_cid = field().guarded_cid(); 1393 const intptr_t field_cid = field().guarded_cid();
1381 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; 1394 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1382 const intptr_t field_length = field().guarded_list_length();
1383 const bool field_has_length = field().needs_length_check();
1384 const bool needs_field_temp_reg =
1385 field_has_length || (field().guarded_cid() == kIllegalCid);
1386 if (field_has_length) {
1387 // Currently, we should only see final fields that remember length.
1388 ASSERT(field().is_final());
1389 }
1390 1395
1391 if (field_cid == kDynamicCid) { 1396 if (field_cid == kDynamicCid) {
1392 ASSERT(!compiler->is_optimizing()); 1397 ASSERT(!compiler->is_optimizing());
1393 return; // Nothing to emit. 1398 return; // Nothing to emit.
1394 } 1399 }
1395 1400
1396 const intptr_t value_cid = value()->Type()->ToCid(); 1401 const bool emit_full_guard =
1402 !compiler->is_optimizing() || (field_cid == kIllegalCid);
1403
1404 const bool needs_value_cid_temp_reg = emit_full_guard ||
1405 ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
1406
1407 const bool needs_field_temp_reg = emit_full_guard;
1397 1408
1398 const Register value_reg = locs()->in(0).reg(); 1409 const Register value_reg = locs()->in(0).reg();
1399 1410
1400 const Register value_cid_reg = locs()->temp(0).reg(); 1411 const Register value_cid_reg = needs_value_cid_temp_reg ?
1412 locs()->temp(0).reg() : kNoRegister;
1401 1413
1402 const Register temp_reg = locs()->temp(1).reg(); 1414 const Register field_reg = needs_field_temp_reg ?
1403
1404 Register field_reg = needs_field_temp_reg ?
1405 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; 1415 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
1406 1416
1407 Label ok, fail_label; 1417 Label ok, fail_label;
1408 1418
1409 Label* deopt = compiler->is_optimizing() ? 1419 Label* deopt = compiler->is_optimizing() ?
1410 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; 1420 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
1411 1421
1412 Label* fail = (deopt != NULL) ? deopt : &fail_label; 1422 Label* fail = (deopt != NULL) ? deopt : &fail_label;
1413 1423
1414 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { 1424 if (emit_full_guard) {
1415 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
1416 // Currently we can't have different location summaries for optimized
1417 // and non-optimized code. So instead we manually pick up a register
1418 // that is known to be free because we know how non-optimizing compiler
1419 // allocates registers.
1420 field_reg = R2;
1421 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
1422 }
1423
1424 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP); 1425 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
1425 1426
1426 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); 1427 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
1427 FieldAddress field_nullability_operand( 1428 FieldAddress field_nullability_operand(
1428 field_reg, Field::is_nullable_offset()); 1429 field_reg, Field::is_nullable_offset());
1429 FieldAddress field_length_operand(
1430 field_reg, Field::guarded_list_length_offset());
1431
1432 ASSERT(value_cid_reg != kNoRegister);
1433 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1434 1430
1435 if (value_cid == kDynamicCid) { 1431 if (value_cid == kDynamicCid) {
1436 LoadValueCid(compiler, value_cid_reg, value_reg); 1432 LoadValueCid(compiler, value_cid_reg, value_reg);
1437 Label skip_length_check; 1433 Label skip_length_check;
1438 __ ldr(TMP, field_cid_operand); 1434 __ ldr(TMP, field_cid_operand);
1439 __ CompareRegisters(value_cid_reg, TMP); 1435 __ CompareRegisters(value_cid_reg, TMP);
1440 __ b(&skip_length_check, NE); 1436 __ b(&ok, EQ);
1441 if (field_has_length) {
1442 ASSERT(temp_reg != kNoRegister);
1443 // Field guard may have remembered list length, check it.
1444 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1445 __ LoadFieldFromOffset(
1446 temp_reg, value_reg, Array::length_offset(), PP);
1447 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
1448 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1449 __ LoadFieldFromOffset(
1450 temp_reg, value_reg, TypedData::length_offset(), PP);
1451 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
1452 } else {
1453 ASSERT(field_cid == kIllegalCid);
1454 ASSERT(field_length == Field::kUnknownFixedLength);
1455 // At compile time we do not know the type of the field nor its
1456 // length. At execution time we may have set the class id and
1457 // list length so we compare the guarded length with the
1458 // list length here, without this check the list length could change
1459 // without triggering a deoptimization.
1460 Label check_array, length_compared, no_fixed_length;
1461 // If length is negative the length guard is either disabled or
1462 // has not been initialized, either way it is safe to skip the
1463 // length check.
1464 __ ldr(TMP, field_length_operand);
1465 __ CompareImmediate(TMP, 0, PP);
1466 __ b(&skip_length_check, LT);
1467 __ CompareImmediate(value_cid_reg, kNullCid, PP);
1468 __ b(&no_fixed_length, EQ);
1469 // Check for typed data array.
1470 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP);
1471 __ b(&no_fixed_length, GT);
1472 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP);
1473 // Could still be a regular array.
1474 __ b(&check_array, LT);
1475 __ LoadFieldFromOffset(
1476 temp_reg, value_reg, TypedData::length_offset(), PP);
1477 __ ldr(TMP, field_length_operand);
1478 __ CompareRegisters(temp_reg, TMP);
1479 __ b(&length_compared);
1480 // Check for regular array.
1481 __ Bind(&check_array);
1482 __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP);
1483 __ b(&no_fixed_length, GT);
1484 __ CompareImmediate(value_cid_reg, kArrayCid, PP);
1485 __ b(&no_fixed_length, LT);
1486 __ LoadFieldFromOffset(
1487 temp_reg, value_reg, Array::length_offset(), PP);
1488 __ ldr(TMP, field_length_operand);
1489 __ CompareRegisters(temp_reg, TMP);
1490 __ b(&length_compared);
1491 __ Bind(&no_fixed_length);
1492 __ b(fail);
1493 __ Bind(&length_compared);
1494 // Following branch cannot not occur, fall through.
1495 }
1496 __ b(fail, NE);
1497 }
1498 __ Bind(&skip_length_check);
1499 __ ldr(TMP, field_nullability_operand); 1437 __ ldr(TMP, field_nullability_operand);
1500 __ CompareRegisters(value_cid_reg, TMP); 1438 __ CompareRegisters(value_cid_reg, TMP);
1501 } else if (value_cid == kNullCid) { 1439 } else if (value_cid == kNullCid) {
1502 __ ldr(value_cid_reg, field_nullability_operand); 1440 __ ldr(value_cid_reg, field_nullability_operand);
1503 __ CompareImmediate(value_cid_reg, value_cid, PP); 1441 __ CompareImmediate(value_cid_reg, value_cid, PP);
1504 } else { 1442 } else {
1505 Label skip_length_check; 1443 Label skip_length_check;
1506 __ ldr(value_cid_reg, field_cid_operand); 1444 __ ldr(value_cid_reg, field_cid_operand);
1507 __ CompareImmediate(value_cid_reg, value_cid, PP); 1445 __ CompareImmediate(value_cid_reg, value_cid, PP);
1508 __ b(&skip_length_check, NE);
1509 if (field_has_length) {
1510 ASSERT(value_cid_reg != kNoRegister);
1511 ASSERT(temp_reg != kNoRegister);
1512 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1513 __ LoadFieldFromOffset(
1514 temp_reg, value_reg, Array::length_offset(), PP);
1515 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
1516 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1517 __ LoadFieldFromOffset(
1518 temp_reg, value_reg, TypedData::length_offset(), PP);
1519 __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
1520 } else if (field_cid != kIllegalCid) {
1521 ASSERT(field_cid != value_cid);
1522 ASSERT(field_length >= 0);
1523 // Field has a known class id and length. At compile time it is
1524 // known that the value's class id is not a fixed length list.
1525 __ b(fail);
1526 } else {
1527 ASSERT(field_cid == kIllegalCid);
1528 ASSERT(field_length == Field::kUnknownFixedLength);
1529 // Following jump cannot not occur, fall through.
1530 }
1531 __ b(fail, NE);
1532 }
1533 // Not identical, possibly null.
1534 __ Bind(&skip_length_check);
1535 } 1446 }
1536 __ b(&ok, EQ); 1447 __ b(&ok, EQ);
1537 1448
1538 __ ldr(TMP, field_cid_operand); 1449 // Check if the tracked state of the guarded field can be initialized
1539 __ CompareImmediate(TMP, kIllegalCid, PP); 1450 // inline. If the field needs length check we fall through to runtime
1540 __ b(fail, NE); 1451 // which is responsible for computing offset of the length field
1452 // based on the class id.
1453 // Length guard will be emitted separately when needed via GuardFieldLength
1454 // instruction after GuardFieldClass.
1455 if (!field().needs_length_check()) {
1456 // Uninitialized field can be handled inline. Check if the
1457 // field is still unitialized.
1458 __ ldr(TMP, field_cid_operand);
Florian Schneider 2014/06/02 11:37:01 General suggestion for ARM/ARM64/MIPS code (You do
Vyacheslav Egorov (Google) 2014/06/02 12:09:47 I second this. The stuff we are writing now is ver
1459 __ CompareImmediate(TMP, kIllegalCid, PP);
1460 __ b(fail, NE);
1541 1461
1542 if (value_cid == kDynamicCid) { 1462 if (value_cid == kDynamicCid) {
1543 __ str(value_cid_reg, field_cid_operand); 1463 __ str(value_cid_reg, field_cid_operand);
1544 __ str(value_cid_reg, field_nullability_operand); 1464 __ str(value_cid_reg, field_nullability_operand);
1545 if (field_has_length) { 1465 } else {
1546 Label check_array, length_set, no_fixed_length; 1466 __ LoadImmediate(TMP, value_cid, PP);
1547 __ CompareImmediate(value_cid_reg, kNullCid, PP); 1467 __ str(TMP, field_cid_operand);
1548 __ b(&no_fixed_length, EQ); 1468 __ str(TMP, field_nullability_operand);
1549 // Check for typed data array.
1550 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP);
1551 __ b(&no_fixed_length, GT);
1552 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP);
1553 // Could still be a regular array.
1554 __ b(&check_array, LT);
1555 // Destroy value_cid_reg (safe because we are finished with it).
1556 __ LoadFieldFromOffset(
1557 value_cid_reg, value_reg, TypedData::length_offset(), PP);
1558 __ str(value_cid_reg, field_length_operand);
1559 __ b(&length_set); // Updated field length typed data array.
1560 // Check for regular array.
1561 __ Bind(&check_array);
1562 __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP);
1563 __ b(&no_fixed_length, GT);
1564 __ CompareImmediate(value_cid_reg, kArrayCid, PP);
1565 __ b(&no_fixed_length, LT);
1566 // Destroy value_cid_reg (safe because we are finished with it).
1567 __ LoadFieldFromOffset(
1568 value_cid_reg, value_reg, Array::length_offset(), PP);
1569 __ str(value_cid_reg, field_length_operand);
1570 // Updated field length from regular array.
1571 __ b(&length_set);
1572 __ Bind(&no_fixed_length);
1573 __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength), PP);
1574 __ str(TMP, field_length_operand);
1575 __ Bind(&length_set);
1576 } 1469 }
1577 } else { 1470
1578 __ LoadImmediate(TMP, value_cid, PP); 1471 if (deopt == NULL) {
1579 __ str(TMP, field_cid_operand); 1472 ASSERT(!compiler->is_optimizing());
1580 __ str(TMP, field_nullability_operand); 1473 __ b(&ok);
1581 if (field_has_length) {
1582 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1583 // Destroy value_cid_reg (safe because we are finished with it).
1584 __ LoadFieldFromOffset(
1585 value_cid_reg, value_reg, Array::length_offset(), PP);
1586 __ str(value_cid_reg, field_length_operand);
1587 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1588 // Destroy value_cid_reg (safe because we are finished with it).
1589 __ LoadFieldFromOffset(
1590 value_cid_reg, value_reg, TypedData::length_offset(), PP);
1591 __ str(value_cid_reg, field_length_operand);
1592 } else {
1593 __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength), PP);
1594 __ str(TMP, field_length_operand);
1595 }
1596 } 1474 }
1597 } 1475 }
1598 1476
1599 if (deopt == NULL) { 1477 if (deopt == NULL) {
1600 ASSERT(!compiler->is_optimizing()); 1478 ASSERT(!compiler->is_optimizing());
1601 __ b(&ok);
1602 __ Bind(fail); 1479 __ Bind(fail);
1603 1480
1604 __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), PP); 1481 __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), PP);
1605 __ CompareImmediate(TMP, kDynamicCid, PP); 1482 __ CompareImmediate(TMP, kDynamicCid, PP);
1606 __ b(&ok, EQ); 1483 __ b(&ok, EQ);
1607 1484
1608 __ Push(field_reg); 1485 __ Push(field_reg);
1609 __ Push(value_reg); 1486 __ Push(value_reg);
1610 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); 1487 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1611 __ Drop(2); // Drop the field and the value. 1488 __ Drop(2); // Drop the field and the value.
1612 } 1489 }
1613 } else { 1490 } else {
1614 ASSERT(compiler->is_optimizing()); 1491 ASSERT(compiler->is_optimizing());
1615 ASSERT(deopt != NULL); 1492 ASSERT(deopt != NULL);
1493
1616 // Field guard class has been initialized and is known. 1494 // Field guard class has been initialized and is known.
1617 if (field_reg != kNoRegister) {
1618 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
1619 }
1620 if (value_cid == kDynamicCid) { 1495 if (value_cid == kDynamicCid) {
1621 // Field's guarded class id is fixed by value's class id is not known. 1496 // Value's class id is not known.
1622 __ tsti(value_reg, kSmiTagMask); 1497 __ tsti(value_reg, kSmiTagMask);
1623 1498
1624 if (field_cid != kSmiCid) { 1499 if (field_cid != kSmiCid) {
1625 __ b(fail, EQ); 1500 __ b(fail, EQ);
1626 __ LoadClassId(value_cid_reg, value_reg, PP); 1501 __ LoadClassId(value_cid_reg, value_reg, PP);
1627 __ CompareImmediate(value_cid_reg, field_cid, PP); 1502 __ CompareImmediate(value_cid_reg, field_cid, PP);
1628 } 1503 }
1629 1504
1630 if (field_has_length) {
1631 __ b(fail, NE);
1632 // Classes are same, perform guarded list length check.
1633 ASSERT(field_reg != kNoRegister);
1634 ASSERT(value_cid_reg != kNoRegister);
1635 FieldAddress field_length_operand(
1636 field_reg, Field::guarded_list_length_offset());
1637 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1638 // Destroy value_cid_reg (safe because we are finished with it).
1639 __ LoadFieldFromOffset(
1640 value_cid_reg, value_reg, Array::length_offset(), PP);
1641 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1642 // Destroy value_cid_reg (safe because we are finished with it).
1643 __ LoadFieldFromOffset(
1644 value_cid_reg, value_reg, TypedData::length_offset(), PP);
1645 }
1646 __ ldr(TMP, field_length_operand);
1647 __ CompareRegisters(value_cid_reg, TMP);
1648 }
1649
1650 if (field().is_nullable() && (field_cid != kNullCid)) { 1505 if (field().is_nullable() && (field_cid != kNullCid)) {
1651 __ b(&ok, EQ); 1506 __ b(&ok, EQ);
1652 __ CompareObject(value_reg, Object::null_object(), PP); 1507 __ CompareObject(value_reg, Object::null_object(), PP);
1653 } 1508 }
1509
1654 __ b(fail, NE); 1510 __ b(fail, NE);
1655 } else { 1511 } else {
1656 // Both value's and field's class id is known. 1512 // Both value's and field's class id is known.
1657 if ((value_cid != field_cid) && (value_cid != nullability)) { 1513 ASSERT((value_cid != field_cid) && (value_cid != nullability));
1658 __ b(fail); 1514 __ b(fail);
1659 } else if (field_has_length && (value_cid == field_cid)) {
1660 ASSERT(value_cid_reg != kNoRegister);
1661 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1662 // Destroy value_cid_reg (safe because we are finished with it).
1663 __ LoadFieldFromOffset(
1664 value_cid_reg, value_reg, Array::length_offset(), PP);
1665 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1666 // Destroy value_cid_reg (safe because we are finished with it).
1667 __ LoadFieldFromOffset(
1668 value_cid_reg, value_reg, TypedData::length_offset(), PP);
1669 }
1670 __ CompareImmediate(value_cid_reg, field_length, PP);
1671 __ b(fail, NE);
1672 } else {
1673 UNREACHABLE();
1674 }
1675 } 1515 }
1676 } 1516 }
1677 __ Bind(&ok); 1517 __ Bind(&ok);
1678 } 1518 }
1679 1519
1680 1520
1521 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
1522 bool opt) const {
1523 const intptr_t kNumInputs = 1;
1524 LocationSummary* summary = new(isolate) LocationSummary(
1525 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1526 summary->set_in(0, Location::RequiresRegister());
1527
1528 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1529 // We need temporaries for field object, length offset and expected length.
1530 summary->AddTemp(Location::RequiresRegister());
1531 summary->AddTemp(Location::RequiresRegister());
1532 summary->AddTemp(Location::RequiresRegister());
1533 }
1534
1535 return summary;
1536 }
1537
1538
1539 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1540 if (field().guarded_list_length() == Field::kNoFixedLength) {
1541 ASSERT(!compiler->is_optimizing());
1542 return; // Nothing to emit.
1543 }
1544
1545 Label* deopt = compiler->is_optimizing() ?
1546 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
1547
1548 const Register value_reg = locs()->in(0).reg();
1549
1550 if (!compiler->is_optimizing() ||
1551 (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1552 const Register field_reg = locs()->temp(0).reg();
1553 const Register offset_reg = locs()->temp(1).reg();
1554 const Register length_reg = locs()->temp(2).reg();
1555
1556 Label ok;
1557
1558 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
1559
1560 __ ldrsb(offset_reg, FieldAddress(field_reg,
1561 Field::guarded_list_length_in_object_offset_offset()));
1562 __ ldr(length_reg, FieldAddress(field_reg,
1563 Field::guarded_list_length_offset()));
1564
1565 __ tst(offset_reg, Operand(offset_reg));
1566 __ b(&ok, MI);
1567
1568 // Load the length from the value. GuardFieldClass already verified that
1569 // value's class matches guarded class id of the field.
1570 // offset_reg contains offset already corrected by -kHeapObjectTag that is
1571 // why we use Address instead of FieldAddress.
1572 __ ldr(TMP, Address(value_reg, offset_reg));
1573 __ CompareRegisters(length_reg, TMP);
1574
1575 if (deopt == NULL) {
1576 __ b(&ok, EQ);
1577
1578 __ Push(field_reg);
1579 __ Push(value_reg);
1580 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1581 __ Drop(2); // Drop the field and the value.
1582 } else {
1583 __ b(deopt, NE);
1584 }
1585
1586 __ Bind(&ok);
1587 } else {
1588 ASSERT(compiler->is_optimizing());
1589 ASSERT(field().guarded_list_length() >= 0);
1590 ASSERT(field().guarded_list_length_in_object_offset() !=
1591 Field::kUnknownLengthOffset);
1592
1593 __ ldr(TMP, FieldAddress(value_reg,
1594 field().guarded_list_length_in_object_offset()));
1595 __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length()), PP);
1596 __ b(deopt, NE);
1597 }
1598 }
1599
1600
1681 class StoreInstanceFieldSlowPath : public SlowPathCode { 1601 class StoreInstanceFieldSlowPath : public SlowPathCode {
1682 public: 1602 public:
1683 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, 1603 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
1684 const Class& cls) 1604 const Class& cls)
1685 : instruction_(instruction), cls_(cls) { } 1605 : instruction_(instruction), cls_(cls) { }
1686 1606
1687 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 1607 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
1688 __ Comment("StoreInstanceFieldSlowPath"); 1608 __ Comment("StoreInstanceFieldSlowPath");
1689 __ Bind(entry_label()); 1609 __ Bind(entry_label());
1690 1610
(...skipping 3710 matching lines...) Expand 10 before | Expand all | Expand 10 after
5401 compiler->GenerateCall(token_pos(), 5321 compiler->GenerateCall(token_pos(),
5402 &label, 5322 &label,
5403 PcDescriptors::kOther, 5323 PcDescriptors::kOther,
5404 locs()); 5324 locs());
5405 __ Drop(ArgumentCount()); // Discard arguments. 5325 __ Drop(ArgumentCount()); // Discard arguments.
5406 } 5326 }
5407 5327
5408 } // namespace dart 5328 } // namespace dart
5409 5329
5410 #endif // defined TARGET_ARCH_ARM64 5330 #endif // defined TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698