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

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

Issue 304703002: Split GuardField into GuardFieldType and GuardFieldLength instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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) 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 "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 case kTypedDataFloat64x2ArrayCid: 1296 case kTypedDataFloat64x2ArrayCid:
1297 case kTypedDataFloat32x4ArrayCid: 1297 case kTypedDataFloat32x4ArrayCid:
1298 __ movups(element_address, locs()->in(2).fpu_reg()); 1298 __ movups(element_address, locs()->in(2).fpu_reg());
1299 break; 1299 break;
1300 default: 1300 default:
1301 UNREACHABLE(); 1301 UNREACHABLE();
1302 } 1302 }
1303 } 1303 }
1304 1304
1305 1305
1306 LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate, 1306 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
1307 bool opt) const { 1307 bool opt) const {
1308 const intptr_t kNumInputs = 1; 1308 const intptr_t kNumInputs = 1;
1309 LocationSummary* summary = new(isolate) LocationSummary( 1309 LocationSummary* summary = new(isolate) LocationSummary(
1310 isolate, kNumInputs, 0, LocationSummary::kNoCall); 1310 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1311 summary->set_in(0, Location::RequiresRegister()); 1311 summary->set_in(0, Location::RequiresRegister());
1312 const bool field_has_length = field().needs_length_check(); 1312
1313 const bool need_value_temp_reg = 1313 const intptr_t value_cid = value()->Type()->ToCid();
1314 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) && 1314 const intptr_t field_cid = field().guarded_cid();
1315 (field().guarded_cid() != kSmiCid))); 1315
1316 if (need_value_temp_reg) { 1316 const bool emit_full_guard = !opt || (field_cid == kIllegalCid);
1317 const bool needs_value_cid_temp_reg =
1318 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1319 const bool needs_field_temp_reg = emit_full_guard;
1320
1321 if (needs_value_cid_temp_reg) {
1317 summary->AddTemp(Location::RequiresRegister()); 1322 summary->AddTemp(Location::RequiresRegister());
1318 } 1323 }
1319 const bool need_field_temp_reg = 1324
1320 field_has_length || (field().guarded_cid() == kIllegalCid); 1325 if (needs_field_temp_reg) {
1321 if (need_field_temp_reg) {
1322 summary->AddTemp(Location::RequiresRegister()); 1326 summary->AddTemp(Location::RequiresRegister());
1323 } 1327 }
1328
1324 return summary; 1329 return summary;
1325 } 1330 }
1326 1331
1327 1332
1328 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1333 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1334 const intptr_t value_cid = value()->Type()->ToCid();
1329 const intptr_t field_cid = field().guarded_cid(); 1335 const intptr_t field_cid = field().guarded_cid();
1330 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; 1336 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1331 const intptr_t field_length = field().guarded_list_length();
1332 const bool field_has_length = field().needs_length_check();
1333 const bool needs_value_temp_reg =
1334 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
1335 (field().guarded_cid() != kSmiCid)));
1336 const bool needs_field_temp_reg =
1337 field_has_length || (field().guarded_cid() == kIllegalCid);
1338 if (field_has_length) {
1339 // Currently, we should only see final fields that remember length.
1340 ASSERT(field().is_final());
1341 }
1342 1337
1343 if (field_cid == kDynamicCid) { 1338 if (field_cid == kDynamicCid) {
1344 ASSERT(!compiler->is_optimizing()); 1339 ASSERT(!compiler->is_optimizing());
1345 return; // Nothing to emit. 1340 return; // Nothing to emit.
1346 } 1341 }
1347 1342
1348 const intptr_t value_cid = value()->Type()->ToCid(); 1343 const bool emit_full_guard =
1344 !compiler->is_optimizing() || (field_cid == kIllegalCid);
1345
1346 const bool needs_value_cid_temp_reg =
1347 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1348
1349 const bool needs_field_temp_reg = emit_full_guard;
1349 1350
1350 Register value_reg = locs()->in(0).reg(); 1351 Register value_reg = locs()->in(0).reg();
1351 1352
1352 Register value_cid_reg = needs_value_temp_reg ? 1353 Register value_cid_reg = needs_value_cid_temp_reg ?
1353 locs()->temp(0).reg() : kNoRegister; 1354 locs()->temp(0).reg() : kNoRegister;
1354 1355
1355 Register field_reg = needs_field_temp_reg ? 1356 Register field_reg = needs_field_temp_reg ?
1356 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; 1357 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
1357 1358
1358 Label ok, fail_label; 1359 Label ok, fail_label;
1359 1360
1360 Label* deopt = compiler->is_optimizing() ? 1361 Label* deopt = compiler->is_optimizing() ?
1361 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; 1362 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
1362 1363
1363 Label* fail = (deopt != NULL) ? deopt : &fail_label; 1364 Label* fail = (deopt != NULL) ? deopt : &fail_label;
1364 1365
1365 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { 1366 if (emit_full_guard) {
1366 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
1367 // Currently we can't have different location summaries for optimized
1368 // and non-optimized code. So instead we manually pick up a register
1369 // that is known to be free because we know how non-optimizing compiler
1370 // allocates registers.
1371 field_reg = RBX;
1372 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
1373 }
1374
1375 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP); 1367 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
1376 1368
1377 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); 1369 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
1378 FieldAddress field_nullability_operand( 1370 FieldAddress field_nullability_operand(
1379 field_reg, Field::is_nullable_offset()); 1371 field_reg, Field::is_nullable_offset());
1380 FieldAddress field_length_operand(
1381 field_reg, Field::guarded_list_length_offset());
1382 1372
1383 if (value_cid == kDynamicCid) { 1373 if (value_cid == kDynamicCid) {
1384 if (value_cid_reg == kNoRegister) {
1385 ASSERT(!compiler->is_optimizing());
1386 value_cid_reg = RDX;
1387 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1388 }
1389
1390 LoadValueCid(compiler, value_cid_reg, value_reg); 1374 LoadValueCid(compiler, value_cid_reg, value_reg);
1391 1375
1392 Label skip_length_check;
1393 __ cmpq(value_cid_reg, field_cid_operand); 1376 __ cmpq(value_cid_reg, field_cid_operand);
1394 __ j(NOT_EQUAL, &skip_length_check); 1377 __ j(EQUAL, &ok);
1395 if (field_has_length) {
1396 // Field guard may have remembered list length, check it.
1397 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1398 __ pushq(value_cid_reg);
1399 __ movq(value_cid_reg,
1400 FieldAddress(value_reg, Array::length_offset()));
1401 __ CompareImmediate(
1402 value_cid_reg, Immediate(Smi::RawValue(field_length)), PP);
1403 __ popq(value_cid_reg);
1404 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1405 __ pushq(value_cid_reg);
1406 __ movq(value_cid_reg,
1407 FieldAddress(value_reg, TypedData::length_offset()));
1408 __ CompareImmediate(
1409 value_cid_reg, Immediate(Smi::RawValue(field_length)), PP);
1410 __ popq(value_cid_reg);
1411 } else {
1412 ASSERT(field_cid == kIllegalCid);
1413 ASSERT(field_length == Field::kUnknownFixedLength);
1414 // At compile time we do not know the type of the field nor its
1415 // length. At execution time we may have set the class id and
1416 // list length so we compare the guarded length with the
1417 // list length here, without this check the list length could change
1418 // without triggering a deoptimization.
1419 Label check_array, length_compared, no_fixed_length;
1420 // If length is negative the length guard is either disabled or
1421 // has not been initialized, either way it is safe to skip the
1422 // length check.
1423 __ CompareImmediate(
1424 field_length_operand, Immediate(Smi::RawValue(0)), PP);
1425 __ j(LESS, &skip_length_check);
1426 __ CompareImmediate(value_cid_reg, Immediate(kNullCid), PP);
1427 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
1428 // Check for typed data array.
1429 __ CompareImmediate(
1430 value_cid_reg, Immediate(kTypedDataInt32x4ArrayCid), PP);
1431 // Not a typed array or a regular array.
1432 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1433 __ CompareImmediate(
1434 value_cid_reg, Immediate(kTypedDataInt8ArrayCid), PP);
1435 // Could still be a regular array.
1436 __ j(LESS, &check_array, Assembler::kNearJump);
1437 __ pushq(value_cid_reg);
1438 __ movq(value_cid_reg,
1439 FieldAddress(value_reg, TypedData::length_offset()));
1440 __ cmpq(field_length_operand, value_cid_reg);
1441 __ popq(value_cid_reg);
1442 __ jmp(&length_compared, Assembler::kNearJump);
1443 // Check for regular array.
1444 __ Bind(&check_array);
1445 __ CompareImmediate(value_cid_reg, Immediate(kImmutableArrayCid), PP);
1446 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1447 __ CompareImmediate(value_cid_reg, Immediate(kArrayCid), PP);
1448 __ j(LESS, &no_fixed_length, Assembler::kNearJump);
1449 __ pushq(value_cid_reg);
1450 __ movq(value_cid_reg,
1451 FieldAddress(value_reg, Array::length_offset()));
1452 __ cmpq(field_length_operand, value_cid_reg);
1453 __ popq(value_cid_reg);
1454 __ jmp(&length_compared, Assembler::kNearJump);
1455 __ Bind(&no_fixed_length);
1456 __ jmp(fail);
1457 __ Bind(&length_compared);
1458 }
1459 __ j(NOT_EQUAL, fail);
1460 }
1461 __ Bind(&skip_length_check);
1462 __ cmpq(value_cid_reg, field_nullability_operand); 1378 __ cmpq(value_cid_reg, field_nullability_operand);
1463 } else if (value_cid == kNullCid) { 1379 } else if (value_cid == kNullCid) {
1464 __ CompareImmediate(field_nullability_operand, Immediate(value_cid), PP); 1380 __ CompareImmediate(field_nullability_operand, Immediate(value_cid), PP);
1465 } else { 1381 } else {
1466 Label skip_length_check;
1467 __ CompareImmediate(field_cid_operand, Immediate(value_cid), PP); 1382 __ CompareImmediate(field_cid_operand, Immediate(value_cid), PP);
1468 // If not equal, skip over length check.
1469 __ j(NOT_EQUAL, &skip_length_check);
1470 // Insert length check.
1471 if (field_has_length) {
1472 ASSERT(value_cid_reg != kNoRegister);
1473 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1474 __ CompareImmediate(FieldAddress(value_reg, Array::length_offset()),
1475 Immediate(Smi::RawValue(field_length)), PP);
1476 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1477 __ CompareImmediate(
1478 FieldAddress(value_reg, TypedData::length_offset()),
1479 Immediate(Smi::RawValue(field_length)), PP);
1480 } else if (field_cid != kIllegalCid) {
1481 ASSERT(field_cid != value_cid);
1482 ASSERT(field_length >= 0);
1483 // Field has a known class id and length. At compile time it is
1484 // known that the value's class id is not a fixed length list.
1485 __ jmp(fail);
1486 } else {
1487 ASSERT(field_cid == kIllegalCid);
1488 ASSERT(field_length == Field::kUnknownFixedLength);
1489 // Following jump cannot not occur, fall through.
1490 }
1491 __ j(NOT_EQUAL, fail);
1492 }
1493 // Not identical, possibly null.
1494 __ Bind(&skip_length_check);
1495 } 1383 }
1496 __ j(EQUAL, &ok); 1384 __ j(EQUAL, &ok);
1497 1385
1498 __ CompareImmediate(field_cid_operand, Immediate(kIllegalCid), PP); 1386 // Check if the tracked state of the guarded field can be initialized
1499 __ j(NOT_EQUAL, fail); 1387 // inline. If the field needs length check we fall through to runtime
1388 // which is responsible for computing offset of the length field
1389 // based on the class id.
1390 if (!field().needs_length_check()) {
1391 // Uninitialized field can be handled inline. Check if the
1392 // field is still unitialized.
1393 __ CompareImmediate(field_cid_operand, Immediate(kIllegalCid), PP);
1394 __ j(NOT_EQUAL, fail);
1500 1395
1501 if (value_cid == kDynamicCid) { 1396 if (value_cid == kDynamicCid) {
1502 __ movq(field_cid_operand, value_cid_reg); 1397 __ movq(field_cid_operand, value_cid_reg);
1503 __ movq(field_nullability_operand, value_cid_reg); 1398 __ movq(field_nullability_operand, value_cid_reg);
1504 if (field_has_length) { 1399 } else {
1505 Label check_array, length_set, no_fixed_length; 1400 ASSERT(field_reg != kNoRegister);
1506 __ CompareImmediate(value_cid_reg, Immediate(kNullCid), PP); 1401 __ LoadImmediate(field_cid_operand, Immediate(value_cid), PP);
1507 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump); 1402 __ LoadImmediate(field_nullability_operand, Immediate(value_cid), PP);
1508 // Check for typed data array.
1509 __ CompareImmediate(value_cid_reg,
1510 Immediate(kTypedDataInt32x4ArrayCid), PP);
1511 // Not a typed array or a regular array.
1512 __ j(GREATER, &no_fixed_length);
1513 __ CompareImmediate(
1514 value_cid_reg, Immediate(kTypedDataInt8ArrayCid), PP);
1515 // Could still be a regular array.
1516 __ j(LESS, &check_array, Assembler::kNearJump);
1517 // Destroy value_cid_reg (safe because we are finished with it).
1518 __ movq(value_cid_reg,
1519 FieldAddress(value_reg, TypedData::length_offset()));
1520 __ movq(field_length_operand, value_cid_reg);
1521 // Updated field length typed data array.
1522 __ jmp(&length_set);
1523 // Check for regular array.
1524 __ Bind(&check_array);
1525 __ CompareImmediate(value_cid_reg, Immediate(kImmutableArrayCid), PP);
1526 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1527 __ CompareImmediate(value_cid_reg, Immediate(kArrayCid), PP);
1528 __ j(LESS, &no_fixed_length, Assembler::kNearJump);
1529 // Destroy value_cid_reg (safe because we are finished with it).
1530 __ movq(value_cid_reg,
1531 FieldAddress(value_reg, Array::length_offset()));
1532 __ movq(field_length_operand, value_cid_reg);
1533 // Updated field length from regular array.
1534 __ jmp(&length_set, Assembler::kNearJump);
1535 __ Bind(&no_fixed_length);
1536 __ LoadImmediate(field_length_operand,
1537 Immediate(Smi::RawValue(Field::kNoFixedLength)), PP);
1538 __ Bind(&length_set);
1539 } 1403 }
1540 } else { 1404
1541 ASSERT(field_reg != kNoRegister); 1405 if (deopt == NULL) {
1542 __ LoadImmediate(field_cid_operand, Immediate(value_cid), PP); 1406 ASSERT(!compiler->is_optimizing());
1543 __ LoadImmediate(field_nullability_operand, Immediate(value_cid), PP); 1407 __ jmp(&ok);
1544 if (field_has_length) {
1545 ASSERT(value_cid_reg != kNoRegister);
1546 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1547 // Destroy value_cid_reg (safe because we are finished with it).
1548 __ movq(value_cid_reg,
1549 FieldAddress(value_reg, Array::length_offset()));
1550 __ movq(field_length_operand, value_cid_reg);
1551 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1552 // Destroy value_cid_reg (safe because we are finished with it).
1553 __ movq(value_cid_reg,
1554 FieldAddress(value_reg, TypedData::length_offset()));
1555 __ movq(field_length_operand, value_cid_reg);
1556 } else {
1557 __ LoadImmediate(field_length_operand,
1558 Immediate(Smi::RawValue(Field::kNoFixedLength)), PP);
1559 }
1560 } 1408 }
1561 } 1409 }
1562 1410
1563 if (deopt == NULL) { 1411 if (deopt == NULL) {
1564 ASSERT(!compiler->is_optimizing()); 1412 ASSERT(!compiler->is_optimizing());
1565 __ jmp(&ok);
1566 __ Bind(fail); 1413 __ Bind(fail);
1567 1414
1568 __ CompareImmediate(FieldAddress(field_reg, Field::guarded_cid_offset()), 1415 __ CompareImmediate(FieldAddress(field_reg, Field::guarded_cid_offset()),
1569 Immediate(kDynamicCid), PP); 1416 Immediate(kDynamicCid), PP);
1570 __ j(EQUAL, &ok); 1417 __ j(EQUAL, &ok);
1571 1418
1572 __ pushq(field_reg); 1419 __ pushq(field_reg);
1573 __ pushq(value_reg); 1420 __ pushq(value_reg);
1574 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); 1421 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1575 __ Drop(2); // Drop the field and the value. 1422 __ Drop(2); // Drop the field and the value.
1576 } 1423 }
1577 } else { 1424 } else {
1578 ASSERT(compiler->is_optimizing()); 1425 ASSERT(compiler->is_optimizing());
1579 ASSERT(deopt != NULL); 1426 ASSERT(deopt != NULL);
1427
1580 // Field guard class has been initialized and is known. 1428 // Field guard class has been initialized and is known.
1581 if (field_reg != kNoRegister) {
1582 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
1583 }
1584
1585 if (value_cid == kDynamicCid) { 1429 if (value_cid == kDynamicCid) {
1586 // Field's guarded class id is fixed but value's class id is not known. 1430 // Value's class id is not known.
1587 __ testq(value_reg, Immediate(kSmiTagMask)); 1431 __ testq(value_reg, Immediate(kSmiTagMask));
1588 1432
1589 if (field_cid != kSmiCid) { 1433 if (field_cid != kSmiCid) {
1590 __ j(ZERO, fail); 1434 __ j(ZERO, fail);
1591 __ LoadClassId(value_cid_reg, value_reg); 1435 __ LoadClassId(value_cid_reg, value_reg);
1592 __ CompareImmediate(value_cid_reg, Immediate(field_cid), PP); 1436 __ CompareImmediate(value_cid_reg, Immediate(field_cid), PP);
1593 } 1437 }
1594 1438
1595 if (field_has_length) {
1596 // Jump when Value CID != Field guard CID
1597 __ j(NOT_EQUAL, fail);
1598
1599 // Classes are same, perform guarded list length check.
1600 ASSERT(field_reg != kNoRegister);
1601 ASSERT(value_cid_reg != kNoRegister);
1602 FieldAddress field_length_operand(
1603 field_reg, Field::guarded_list_length_offset());
1604 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1605 // Destroy value_cid_reg (safe because we are finished with it).
1606 __ movq(value_cid_reg,
1607 FieldAddress(value_reg, Array::length_offset()));
1608 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1609 // Destroy value_cid_reg (safe because we are finished with it).
1610 __ movq(value_cid_reg,
1611 FieldAddress(value_reg, TypedData::length_offset()));
1612 }
1613 __ cmpq(value_cid_reg, field_length_operand);
1614 }
1615
1616 if (field().is_nullable() && (field_cid != kNullCid)) { 1439 if (field().is_nullable() && (field_cid != kNullCid)) {
1617 __ j(EQUAL, &ok); 1440 __ j(EQUAL, &ok);
1618 __ CompareObject(value_reg, Object::null_object(), PP); 1441 __ CompareObject(value_reg, Object::null_object(), PP);
1619 } 1442 }
1443
1620 __ j(NOT_EQUAL, fail); 1444 __ j(NOT_EQUAL, fail);
1621 } else { 1445 } else {
1622 // Both value's and field's class id is known. 1446 // Both value's and field's class id is known.
1623 if ((value_cid != field_cid) && (value_cid != nullability)) { 1447 ASSERT((value_cid != field_cid) && (value_cid != nullability));
1624 __ jmp(fail); 1448 __ jmp(fail);
1625 } else if (field_has_length && (value_cid == field_cid)) {
1626 ASSERT(value_cid_reg != kNoRegister);
1627 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1628 // Destroy value_cid_reg (safe because we are finished with it).
1629 __ movq(value_cid_reg,
1630 FieldAddress(value_reg, Array::length_offset()));
1631 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1632 // Destroy value_cid_reg (safe because we are finished with it).
1633 __ movq(value_cid_reg,
1634 FieldAddress(value_reg, TypedData::length_offset()));
1635 }
1636 __ CompareImmediate(
1637 value_cid_reg, Immediate(Smi::RawValue(field_length)), PP);
1638 __ j(NOT_EQUAL, fail);
1639 } else {
1640 UNREACHABLE();
1641 }
1642 } 1449 }
1643 } 1450 }
1644 __ Bind(&ok); 1451 __ Bind(&ok);
1645 } 1452 }
1646 1453
1647 1454
1455 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
1456 bool opt) const {
1457 const intptr_t kNumInputs = 1;
1458 LocationSummary* summary = new(isolate) LocationSummary(
1459 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1460 summary->set_in(0, Location::RequiresRegister());
1461
1462 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1463 // We need temporaries for field object, length offset and expected length.
1464 summary->AddTemp(Location::RequiresRegister());
1465 summary->AddTemp(Location::RequiresRegister());
1466 summary->AddTemp(Location::RequiresRegister());
1467 }
1468
1469 return summary;
1470 }
1471
1472
1473 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1474 if (field().guarded_list_length() == Field::kNoFixedLength) {
1475 ASSERT(!compiler->is_optimizing());
1476 return; // Nothing to emit.
1477 }
1478
1479 Register value_reg = locs()->in(0).reg();
1480
1481 if (!compiler->is_optimizing() ||
1482 (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1483 Register field_reg = locs()->temp(0).reg();
1484 Register offset_reg = locs()->temp(1).reg();
1485 Register length_reg = locs()->temp(2).reg();
1486
1487 Label ok;
1488
1489 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
1490
1491 __ movsxb(offset_reg, FieldAddress(field_reg,
1492 Field::guarded_list_length_in_object_offset_offset()));
1493 __ movq(length_reg, FieldAddress(field_reg,
1494 Field::guarded_list_length_offset()));
1495
1496 __ cmpq(offset_reg, Immediate(0));
1497 __ j(NEGATIVE, &ok);
1498
1499 // Load the length from the value. GuardFieldClass already verified that
1500 // value's class matches guarded class id of the field.
1501 // offset_reg contains offset already corrected by -kHeapObjectTag that is
1502 // why we use Address instead of FieldAddress.
1503 __ cmpq(length_reg, Address(value_reg, offset_reg, TIMES_1, 0));
1504 __ j(EQUAL, &ok);
1505
1506 __ pushq(field_reg);
1507 __ pushq(value_reg);
1508 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1509 __ Drop(2); // Drop the field and the value.
1510
1511 __ Bind(&ok);
1512 } else {
1513 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField);
1514
1515 ASSERT(compiler->is_optimizing());
1516 ASSERT(field().guarded_list_length() >= 0);
1517 ASSERT(field().guarded_list_length_in_object_offset() !=
1518 Field::kUnknownLengthOffset);
1519
1520 __ CompareImmediate(
1521 FieldAddress(value_reg,
1522 field().guarded_list_length_in_object_offset()),
1523 Immediate(Smi::RawValue(field().guarded_list_length())),
1524 PP);
1525 __ j(NOT_EQUAL, deopt);
1526 }
1527 }
1528
1529
1648 class StoreInstanceFieldSlowPath : public SlowPathCode { 1530 class StoreInstanceFieldSlowPath : public SlowPathCode {
1649 public: 1531 public:
1650 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, 1532 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
1651 const Class& cls) 1533 const Class& cls)
1652 : instruction_(instruction), cls_(cls) { } 1534 : instruction_(instruction), cls_(cls) { }
1653 1535
1654 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 1536 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
1655 __ Comment("StoreInstanceFieldSlowPath"); 1537 __ Comment("StoreInstanceFieldSlowPath");
1656 __ Bind(entry_label()); 1538 __ Bind(entry_label());
1657 const Code& stub = 1539 const Code& stub =
(...skipping 4264 matching lines...) Expand 10 before | Expand all | Expand 10 after
5922 PcDescriptors::kOther, 5804 PcDescriptors::kOther,
5923 locs()); 5805 locs());
5924 __ Drop(ArgumentCount()); // Discard arguments. 5806 __ Drop(ArgumentCount()); // Discard arguments.
5925 } 5807 }
5926 5808
5927 } // namespace dart 5809 } // namespace dart
5928 5810
5929 #undef __ 5811 #undef __
5930 5812
5931 #endif // defined TARGET_ARCH_X64 5813 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698