OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1184 | 1184 |
1185 environment()->Push(elements); | 1185 environment()->Push(elements); |
1186 capacity_checker.End(); | 1186 capacity_checker.End(); |
1187 | 1187 |
1188 if (is_js_array) { | 1188 if (is_js_array) { |
1189 HValue* new_length = AddInstruction( | 1189 HValue* new_length = AddInstruction( |
1190 HAdd::New(zone, context, length, graph_->GetConstant1())); | 1190 HAdd::New(zone, context, length, graph_->GetConstant1())); |
1191 new_length->ChangeRepresentation(Representation::Integer32()); | 1191 new_length->ChangeRepresentation(Representation::Integer32()); |
1192 new_length->ClearFlag(HValue::kCanOverflow); | 1192 new_length->ClearFlag(HValue::kCanOverflow); |
1193 | 1193 |
1194 Factory* factory = isolate()->factory(); | 1194 AddStore(object, AccessArrayLength(), new_length, IsFastElementsKind(kind) |
1195 Representation representation = IsFastElementsKind(kind) | 1195 ? Representation::Smi() : Representation::Tagged()); |
1196 ? Representation::Smi() : Representation::Tagged(); | |
1197 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( | |
1198 object, | |
1199 factory->length_field_string(), | |
1200 new_length, true, | |
1201 representation, | |
1202 JSArray::kLengthOffset)); | |
1203 length_store->SetGVNFlag(kChangesArrayLengths); | |
1204 } | 1196 } |
1205 | 1197 |
1206 length_checker.Else(); | 1198 length_checker.Else(); |
1207 | 1199 |
1208 AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 1200 AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
1209 environment()->Push(elements); | 1201 environment()->Push(elements); |
1210 | 1202 |
1211 length_checker.End(); | 1203 length_checker.End(); |
1212 | 1204 |
1213 return environment()->Pop(); | 1205 return environment()->Pop(); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1275 AddInstruction(new(zone) HLoadElements(object, mapcheck)); | 1267 AddInstruction(new(zone) HLoadElements(object, mapcheck)); |
1276 if (is_store && (fast_elements || fast_smi_only_elements) && | 1268 if (is_store && (fast_elements || fast_smi_only_elements) && |
1277 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1269 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
1278 HCheckMaps* check_cow_map = HCheckMaps::New( | 1270 HCheckMaps* check_cow_map = HCheckMaps::New( |
1279 elements, isolate()->factory()->fixed_array_map(), zone); | 1271 elements, isolate()->factory()->fixed_array_map(), zone); |
1280 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1272 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1281 AddInstruction(check_cow_map); | 1273 AddInstruction(check_cow_map); |
1282 } | 1274 } |
1283 HInstruction* length = NULL; | 1275 HInstruction* length = NULL; |
1284 if (is_js_array) { | 1276 if (is_js_array) { |
1285 length = AddInstruction( | 1277 length = AddLoad(object, AccessArrayLength(), mapcheck); |
1286 HLoadNamedField::NewArrayLength(zone, object, mapcheck, HType::Smi())); | 1278 length->set_type(HType::Smi()); |
1287 } else { | 1279 } else { |
1288 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 1280 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
1289 } | 1281 } |
1290 HValue* checked_key = NULL; | 1282 HValue* checked_key = NULL; |
1291 if (IsExternalArrayElementsKind(elements_kind)) { | 1283 if (IsExternalArrayElementsKind(elements_kind)) { |
1292 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1284 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
1293 NoObservableSideEffectsScope no_effects(this); | 1285 NoObservableSideEffectsScope no_effects(this); |
1294 HLoadExternalArrayPointer* external_elements = | 1286 HLoadExternalArrayPointer* external_elements = |
1295 new(zone) HLoadExternalArrayPointer(elements); | 1287 new(zone) HLoadExternalArrayPointer(elements); |
1296 AddInstruction(external_elements); | 1288 AddInstruction(external_elements); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1402 HValue* elements = | 1394 HValue* elements = |
1403 AddInstruction(new(zone) HAllocate(context, total_size, | 1395 AddInstruction(new(zone) HAllocate(context, total_size, |
1404 HType::JSArray(), flags)); | 1396 HType::JSArray(), flags)); |
1405 return elements; | 1397 return elements; |
1406 } | 1398 } |
1407 | 1399 |
1408 | 1400 |
1409 void HGraphBuilder::BuildInitializeElements(HValue* elements, | 1401 void HGraphBuilder::BuildInitializeElements(HValue* elements, |
1410 ElementsKind kind, | 1402 ElementsKind kind, |
1411 HValue* capacity) { | 1403 HValue* capacity) { |
1412 Zone* zone = this->zone(); | |
1413 Factory* factory = isolate()->factory(); | 1404 Factory* factory = isolate()->factory(); |
1414 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1405 Handle<Map> map = IsFastDoubleElementsKind(kind) |
1415 ? factory->fixed_double_array_map() | 1406 ? factory->fixed_double_array_map() |
1416 : factory->fixed_array_map(); | 1407 : factory->fixed_array_map(); |
1417 BuildStoreMap(elements, map); | |
1418 | 1408 |
1419 Handle<String> fixed_array_length_field_name = factory->length_field_string(); | 1409 AddStoreMapConstant(elements, map); |
1420 Representation representation = IsFastElementsKind(kind) | 1410 AddStore(elements, AccessFixedArrayLength(), capacity, |
1421 ? Representation::Smi() : Representation::Tagged(); | 1411 IsFastElementsKind(kind) |
1422 HInstruction* store_length = | 1412 ? Representation::Smi() : Representation::Tagged()); |
1423 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, | |
1424 capacity, true, representation, | |
1425 FixedArray::kLengthOffset); | |
1426 AddInstruction(store_length); | |
1427 } | 1413 } |
1428 | 1414 |
1429 | 1415 |
1430 HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, | 1416 HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, |
1431 ElementsKind kind, | 1417 ElementsKind kind, |
1432 HValue* capacity) { | 1418 HValue* capacity) { |
1433 HValue* new_elements = BuildAllocateElements(context, kind, capacity); | 1419 HValue* new_elements = BuildAllocateElements(context, kind, capacity); |
1434 BuildInitializeElements(new_elements, kind, capacity); | 1420 BuildInitializeElements(new_elements, kind, capacity); |
1435 return new_elements; | 1421 return new_elements; |
1436 } | 1422 } |
1437 | 1423 |
1438 | 1424 |
1439 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 1425 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
1440 HValue* array_map, | 1426 HValue* array_map, |
1441 AllocationSiteMode mode, | 1427 AllocationSiteMode mode, |
1442 HValue* allocation_site_payload, | 1428 HValue* allocation_site_payload, |
1443 HValue* length_field) { | 1429 HValue* length_field) { |
1444 | 1430 |
1445 BuildStoreMap(array, array_map); | 1431 AddStore(array, AccessMap(), array_map); |
1446 | 1432 |
1447 HConstant* empty_fixed_array = | 1433 HConstant* empty_fixed_array = |
1448 new(zone()) HConstant( | 1434 new(zone()) HConstant( |
1449 Handle<FixedArray>(isolate()->heap()->empty_fixed_array()), | 1435 Handle<FixedArray>(isolate()->heap()->empty_fixed_array()), |
1450 Representation::Tagged()); | 1436 Representation::Tagged()); |
1451 AddInstruction(empty_fixed_array); | 1437 AddInstruction(empty_fixed_array); |
1452 | 1438 |
1453 AddInstruction(new(zone()) HStoreNamedField(array, | 1439 HObjectAccess *access = AccessInobject( |
1454 isolate()->factory()->properties_field_symbol(), | 1440 isolate()->factory()->properties_field_symbol(), |
1455 empty_fixed_array, | 1441 JSArray::kPropertiesOffset); |
1456 true, | 1442 AddStore(array, access, empty_fixed_array); |
1457 Representation::Tagged(), | 1443 AddStore(array, AccessArrayLength(), length_field); |
1458 JSArray::kPropertiesOffset)); | |
1459 | |
1460 HInstruction* length_store = AddInstruction( | |
1461 new(zone()) HStoreNamedField(array, | |
1462 isolate()->factory()->length_field_string(), | |
1463 length_field, | |
1464 true, | |
1465 Representation::Tagged(), | |
1466 JSArray::kLengthOffset)); | |
1467 length_store->SetGVNFlag(kChangesArrayLengths); | |
1468 | 1444 |
1469 if (mode == TRACK_ALLOCATION_SITE) { | 1445 if (mode == TRACK_ALLOCATION_SITE) { |
1470 BuildCreateAllocationSiteInfo(array, | 1446 BuildCreateAllocationSiteInfo(array, |
1471 JSArray::kSize, | 1447 JSArray::kSize, |
1472 allocation_site_payload); | 1448 allocation_site_payload); |
1473 } | 1449 } |
1474 | 1450 |
1475 int elements_location = JSArray::kSize; | 1451 int elements_location = JSArray::kSize; |
1476 if (mode == TRACK_ALLOCATION_SITE) { | 1452 if (mode == TRACK_ALLOCATION_SITE) { |
1477 elements_location += AllocationSiteInfo::kSize; | 1453 elements_location += AllocationSiteInfo::kSize; |
1478 } | 1454 } |
1479 | 1455 |
1480 HInnerAllocatedObject* elements = new(zone()) HInnerAllocatedObject( | 1456 HInnerAllocatedObject* elements = new(zone()) HInnerAllocatedObject( |
1481 array, | 1457 array, elements_location); |
1482 elements_location); | |
1483 AddInstruction(elements); | 1458 AddInstruction(elements); |
1484 | 1459 |
1485 HInstruction* elements_store = AddInstruction( | 1460 AddStore(array, AccessElements(), elements); |
1486 new(zone()) HStoreNamedField( | |
1487 array, | |
1488 isolate()->factory()->elements_field_string(), | |
1489 elements, | |
1490 true, | |
1491 Representation::Tagged(), | |
1492 JSArray::kElementsOffset)); | |
1493 elements_store->SetGVNFlag(kChangesElementsPointer); | |
1494 | |
1495 return elements; | 1461 return elements; |
1496 } | 1462 } |
1497 | 1463 |
1498 | 1464 |
1499 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | |
1500 HValue* map) { | |
1501 Zone* zone = this->zone(); | |
1502 Factory* factory = isolate()->factory(); | |
1503 Handle<String> map_field_name = factory->map_field_string(); | |
1504 HInstruction* store_map = | |
1505 new(zone) HStoreNamedField(object, map_field_name, map, | |
1506 true, Representation::Tagged(), | |
1507 JSObject::kMapOffset); | |
1508 store_map->ClearGVNFlag(kChangesInobjectFields); | |
1509 store_map->SetGVNFlag(kChangesMaps); | |
1510 AddInstruction(store_map); | |
1511 return store_map; | |
1512 } | |
1513 | |
1514 | |
1515 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | |
1516 Handle<Map> map) { | |
1517 Zone* zone = this->zone(); | |
1518 HValue* map_constant = | |
1519 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); | |
1520 return BuildStoreMap(object, map_constant); | |
1521 } | |
1522 | |
1523 | |
1524 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1465 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
1525 HValue* old_capacity) { | 1466 HValue* old_capacity) { |
1526 Zone* zone = this->zone(); | 1467 Zone* zone = this->zone(); |
1527 HValue* half_old_capacity = | 1468 HValue* half_old_capacity = |
1528 AddInstruction(HShr::New(zone, context, old_capacity, | 1469 AddInstruction(HShr::New(zone, context, old_capacity, |
1529 graph_->GetConstant1())); | 1470 graph_->GetConstant1())); |
1530 half_old_capacity->ChangeRepresentation(Representation::Integer32()); | 1471 half_old_capacity->ChangeRepresentation(Representation::Integer32()); |
1531 half_old_capacity->ClearFlag(HValue::kCanOverflow); | 1472 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
1532 | 1473 |
1533 HValue* new_capacity = AddInstruction( | 1474 HValue* new_capacity = AddInstruction( |
(...skipping 29 matching lines...) Expand all Loading... | |
1563 HBoundsCheck(length, max_size_constant, | 1504 HBoundsCheck(length, max_size_constant, |
1564 DONT_ALLOW_SMI_KEY, Representation::Integer32())); | 1505 DONT_ALLOW_SMI_KEY, Representation::Integer32())); |
1565 } | 1506 } |
1566 | 1507 |
1567 | 1508 |
1568 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 1509 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
1569 HValue* elements, | 1510 HValue* elements, |
1570 ElementsKind kind, | 1511 ElementsKind kind, |
1571 HValue* length, | 1512 HValue* length, |
1572 HValue* new_capacity) { | 1513 HValue* new_capacity) { |
1573 Zone* zone = this->zone(); | |
1574 HValue* context = environment()->LookupContext(); | 1514 HValue* context = environment()->LookupContext(); |
1575 | 1515 |
1576 BuildNewSpaceArrayCheck(new_capacity, kind); | 1516 BuildNewSpaceArrayCheck(new_capacity, kind); |
1577 | 1517 |
1578 HValue* new_elements = | 1518 HValue* new_elements = |
1579 BuildAllocateAndInitializeElements(context, kind, new_capacity); | 1519 BuildAllocateAndInitializeElements(context, kind, new_capacity); |
1580 | 1520 |
1581 BuildCopyElements(context, elements, kind, | 1521 BuildCopyElements(context, elements, kind, |
1582 new_elements, kind, | 1522 new_elements, kind, |
1583 length, new_capacity); | 1523 length, new_capacity); |
1584 | 1524 |
1585 Factory* factory = isolate()->factory(); | 1525 AddStore(object, AccessElements(), new_elements); |
1586 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( | |
1587 object, | |
1588 factory->elements_field_string(), | |
1589 new_elements, true, Representation::Tagged(), | |
1590 JSArray::kElementsOffset)); | |
1591 elements_store->SetGVNFlag(kChangesElementsPointer); | |
1592 | 1526 |
1593 return new_elements; | 1527 return new_elements; |
1594 } | 1528 } |
1595 | 1529 |
1596 | 1530 |
1597 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, | 1531 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, |
1598 HValue* elements, | 1532 HValue* elements, |
1599 ElementsKind elements_kind, | 1533 ElementsKind elements_kind, |
1600 HValue* from, | 1534 HValue* from, |
1601 HValue* to) { | 1535 HValue* to) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1716 AddInstruction(new(zone) HConstant(size, Representation::Integer32())); | 1650 AddInstruction(new(zone) HConstant(size, Representation::Integer32())); |
1717 HInstruction* object = | 1651 HInstruction* object = |
1718 AddInstruction(new(zone) HAllocate(context, | 1652 AddInstruction(new(zone) HAllocate(context, |
1719 size_in_bytes, | 1653 size_in_bytes, |
1720 HType::JSObject(), | 1654 HType::JSObject(), |
1721 allocate_flags)); | 1655 allocate_flags)); |
1722 | 1656 |
1723 // Copy the JS array part. | 1657 // Copy the JS array part. |
1724 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 1658 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
1725 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 1659 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
1726 HInstruction* value = AddInstruction(new(zone) HLoadNamedField( | 1660 HObjectAccess* access = AccessArrayHeader(i); |
1727 boilerplate, true, Representation::Tagged(), i)); | 1661 HInstruction* value = AddLoad(boilerplate, access); |
1728 if (i != JSArray::kMapOffset) { | 1662 AddStore(object, access, value); |
1729 AddInstruction(new(zone) HStoreNamedField(object, | |
1730 factory->empty_string(), | |
1731 value, true, | |
1732 Representation::Tagged(), i)); | |
1733 } else { | |
1734 BuildStoreMap(object, value); | |
1735 } | |
1736 } | 1663 } |
1737 } | 1664 } |
1738 | 1665 |
1739 // Create an allocation site info if requested. | 1666 // Create an allocation site info if requested. |
1740 if (mode == TRACK_ALLOCATION_SITE) { | 1667 if (mode == TRACK_ALLOCATION_SITE) { |
1741 BuildCreateAllocationSiteInfo(object, JSArray::kSize, boilerplate); | 1668 BuildCreateAllocationSiteInfo(object, JSArray::kSize, boilerplate); |
1742 } | 1669 } |
1743 | 1670 |
1744 if (length > 0) { | 1671 if (length > 0) { |
1745 // Get hold of the elements array of the boilerplate and setup the | 1672 // Get hold of the elements array of the boilerplate and setup the |
1746 // elements pointer in the resulting object. | 1673 // elements pointer in the resulting object. |
1747 HValue* boilerplate_elements = | 1674 HValue* boilerplate_elements = |
1748 AddInstruction(new(zone) HLoadElements(boilerplate, NULL)); | 1675 AddInstruction(new(zone) HLoadElements(boilerplate, NULL)); |
1749 HValue* object_elements = | 1676 HValue* object_elements = |
1750 AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset)); | 1677 AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset)); |
1751 AddInstruction(new(zone) HStoreNamedField(object, | 1678 AddStore(object, AccessElements(), object_elements); |
1752 factory->elements_field_string(), | |
1753 object_elements, true, | |
1754 Representation::Tagged(), | |
1755 JSObject::kElementsOffset)); | |
1756 | 1679 |
1757 // Copy the elements array header. | 1680 // Copy the elements array header. |
1758 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 1681 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
1759 HInstruction* value = | 1682 // TODO(titzer): AccessFixedArray? |
1760 AddInstruction(new(zone) HLoadNamedField( | 1683 HObjectAccess* access = AccessInobject(factory->empty_string(), i); |
1761 boilerplate_elements, true, Representation::Tagged(), i)); | 1684 HInstruction* value = AddLoad(boilerplate_elements, access); |
1762 AddInstruction(new(zone) HStoreNamedField(object_elements, | 1685 AddStore(object_elements, access, value); |
1763 factory->empty_string(), | |
1764 value, true, | |
1765 Representation::Tagged(), i)); | |
1766 } | 1686 } |
1767 | 1687 |
1768 // Copy the elements array contents. | 1688 // Copy the elements array contents. |
1769 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold | 1689 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold |
1770 // copying loops with constant length up to a given boundary and use this | 1690 // copying loops with constant length up to a given boundary and use this |
1771 // helper here instead. | 1691 // helper here instead. |
1772 for (int i = 0; i < length; i++) { | 1692 for (int i = 0; i < length; i++) { |
1773 HValue* key_constant = | 1693 HValue* key_constant = |
1774 AddInstruction(new(zone) HConstant(i, Representation::Integer32())); | 1694 AddInstruction(new(zone) HConstant(i, Representation::Integer32())); |
1775 HInstruction* value = | 1695 HInstruction* value = |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1835 } | 1755 } |
1836 | 1756 |
1837 | 1757 |
1838 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, | 1758 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, |
1839 int previous_object_size, | 1759 int previous_object_size, |
1840 HValue* payload) { | 1760 HValue* payload) { |
1841 HInnerAllocatedObject* alloc_site = new(zone()) | 1761 HInnerAllocatedObject* alloc_site = new(zone()) |
1842 HInnerAllocatedObject(previous_object, previous_object_size); | 1762 HInnerAllocatedObject(previous_object, previous_object_size); |
1843 AddInstruction(alloc_site); | 1763 AddInstruction(alloc_site); |
1844 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); | 1764 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); |
1845 BuildStoreMap(alloc_site, alloc_site_map); | 1765 AddStoreMapConstant(alloc_site, alloc_site_map); |
1846 AddInstruction(new(zone()) HStoreNamedField(alloc_site, | 1766 HObjectAccess* access = AccessInobject( |
1847 isolate()->factory()->payload_string(), | 1767 isolate()->factory()->payload_string(), |
1848 payload, | 1768 AllocationSiteInfo::kPayloadOffset); |
1849 true, | 1769 AddStore(alloc_site, access, payload); |
1850 Representation::Tagged(), | |
1851 AllocationSiteInfo::kPayloadOffset)); | |
1852 return alloc_site; | 1770 return alloc_site; |
1853 } | 1771 } |
1854 | 1772 |
1855 | 1773 |
1856 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 1774 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
1857 ElementsKind kind, | 1775 ElementsKind kind, |
1858 HValue* allocation_site_payload, | 1776 HValue* allocation_site_payload, |
1859 AllocationSiteMode mode) : | 1777 AllocationSiteMode mode) : |
1860 builder_(builder), | 1778 builder_(builder), |
1861 kind_(kind), | 1779 kind_(kind), |
1862 allocation_site_payload_(allocation_site_payload) { | 1780 allocation_site_payload_(allocation_site_payload) { |
1863 if (mode == DONT_TRACK_ALLOCATION_SITE) { | 1781 if (mode == DONT_TRACK_ALLOCATION_SITE) { |
1864 mode_ = mode; | 1782 mode_ = mode; |
1865 } else { | 1783 } else { |
1866 mode_ = AllocationSiteInfo::GetMode(kind); | 1784 mode_ = AllocationSiteInfo::GetMode(kind); |
1867 } | 1785 } |
1868 } | 1786 } |
1869 | 1787 |
1870 | 1788 |
1871 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 1789 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { |
1872 // Get the global context, the native context, the map array | 1790 // Get the global context, the native context, the map array |
1873 HInstruction* global_object = AddInstruction(new(zone()) | 1791 HInstruction* global_object = AddInstruction(new(zone()) |
1874 HGlobalObject(context)); | 1792 HGlobalObject(context)); |
1875 HInstruction* native_context = AddInstruction(new(zone()) | 1793 Handle<String> unknown = |
1876 HLoadNamedField(global_object, true, Representation::Tagged(), | 1794 builder()->isolate()->factory()->unknown_field_string(); |
1877 GlobalObject::kNativeContextOffset)); | 1795 HObjectAccess* access = builder()->AccessInobject(unknown, |
1796 GlobalObject::kNativeContextOffset); | |
1797 HInstruction* native_context = builder()->AddLoad(global_object, access); | |
1798 | |
1878 int offset = Context::kHeaderSize + | 1799 int offset = Context::kHeaderSize + |
1879 kPointerSize * Context::JS_ARRAY_MAPS_INDEX; | 1800 kPointerSize * Context::JS_ARRAY_MAPS_INDEX; |
1880 HInstruction* map_array = AddInstruction(new(zone()) | 1801 access = builder()->AccessInobject(unknown, offset); |
1881 HLoadNamedField(native_context, true, Representation::Tagged(), offset)); | 1802 HInstruction* map_array = builder()->AddLoad(native_context, access); |
1803 | |
1882 offset = kind_ * kPointerSize + FixedArrayBase::kHeaderSize; | 1804 offset = kind_ * kPointerSize + FixedArrayBase::kHeaderSize; |
1883 return AddInstruction(new(zone()) HLoadNamedField( | 1805 access = builder()->AccessInobject(unknown, offset); |
1884 map_array, true, Representation::Tagged(), offset)); | 1806 return builder()->AddLoad(map_array, access); |
1885 } | 1807 } |
1886 | 1808 |
1887 | 1809 |
1888 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1810 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
1889 HValue* length_node) { | 1811 HValue* length_node) { |
1890 HValue* context = builder()->environment()->LookupContext(); | 1812 HValue* context = builder()->environment()->LookupContext(); |
1891 ASSERT(length_node != NULL); | 1813 ASSERT(length_node != NULL); |
1892 | 1814 |
1893 int base_size = JSArray::kSize; | 1815 int base_size = JSArray::kSize; |
1894 if (mode_ == TRACK_ALLOCATION_SITE) { | 1816 if (mode_ == TRACK_ALLOCATION_SITE) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1983 | 1905 |
1984 if (fill_with_hole) { | 1906 if (fill_with_hole) { |
1985 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, | 1907 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, |
1986 graph()->GetConstant0(), capacity); | 1908 graph()->GetConstant0(), capacity); |
1987 } | 1909 } |
1988 | 1910 |
1989 return new_object; | 1911 return new_object; |
1990 } | 1912 } |
1991 | 1913 |
1992 | 1914 |
1915 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, HObjectAccess* access, | |
1916 HValue *val, Representation representation) { | |
1917 HStoreNamedField *instr = new(zone()) HStoreNamedField(object, access, val); | |
1918 AddInstruction(instr); | |
1919 instr->set_field_representation(representation); | |
1920 return instr; | |
1921 } | |
1922 | |
1923 | |
1924 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, HObjectAccess* access, | |
1925 HValue *typecheck) { | |
1926 HLoadNamedField *instr = new(zone()) | |
1927 HLoadNamedField(object, access, typecheck); | |
1928 AddInstruction(instr); | |
1929 return instr; | |
1930 } | |
1931 | |
1932 | |
1933 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | |
1934 Handle<Map> map) { | |
1935 HValue* constant = AddInstruction(new(zone()) | |
1936 HConstant(map, Representation::Tagged())); | |
1937 HStoreNamedField *instr = new(zone()) | |
1938 HStoreNamedField(object, AccessMap(), constant); | |
1939 AddInstruction(instr); | |
1940 return instr; | |
1941 } | |
1942 | |
1943 | |
1944 HObjectAccess* HGraphBuilder::AccessArrayHeader(int offset) { | |
danno
2013/05/02 14:16:47
I am not convinced this should be separate method.
titzer
2013/05/03 09:18:41
I've moved this and other constructor methods to H
| |
1945 ASSERT(offset >= 0 && offset <= JSArray::kSize); | |
1946 Factory *factory = isolate()->factory(); | |
1947 HObjectAccess::Portion portion = HObjectAccess::kInobject; | |
1948 Handle<String> name = factory->empty_string(); | |
1949 if (offset == JSObject::kElementsOffset) { | |
1950 portion = HObjectAccess::kElementsPointer; | |
1951 name = factory->elements_field_string(); | |
1952 } else if (offset == JSArray::kLengthOffset) { | |
1953 portion = HObjectAccess::kArrayLengths; | |
1954 name = factory->length_field_string(); | |
1955 } else if (offset == JSArray::kMapOffset) { | |
1956 portion = HObjectAccess::kMaps; | |
1957 name = factory->map_field_string(); | |
1958 } | |
1959 return new(zone()) HObjectAccess(portion, offset, name); | |
1960 } | |
1961 | |
1962 | |
1963 HObjectAccess* HGraphBuilder::AccessArrayLength() { | |
1964 return new (zone()) HObjectAccess(HObjectAccess::kArrayLengths, | |
danno
2013/05/02 14:16:47
This method and the methods below should return th
titzer
2013/05/03 09:18:41
Done (in HObjectAccess).
| |
1965 JSArray::kLengthOffset, isolate()->factory()->length_field_string()); | |
1966 } | |
1967 | |
1968 | |
1969 HObjectAccess* HGraphBuilder::AccessFixedArrayLength() { | |
1970 return new(zone()) HObjectAccess(HObjectAccess::kInobject, | |
1971 FixedArray::kLengthOffset, isolate()->factory()->length_field_string()); | |
1972 } | |
1973 | |
1974 | |
1975 HObjectAccess* HGraphBuilder::AccessElements() { | |
1976 return new(zone()) HObjectAccess(HObjectAccess::kElementsPointer, | |
1977 JSObject::kElementsOffset, isolate()->factory()->elements_field_string()); | |
1978 } | |
1979 | |
1980 | |
1981 HObjectAccess* HGraphBuilder::AccessMap() { | |
1982 return new(zone()) HObjectAccess(HObjectAccess::kMaps, JSObject::kMapOffset, | |
1983 isolate()->factory()->map_field_string()); | |
1984 } | |
1985 | |
1986 | |
1987 HObjectAccess* HGraphBuilder::AccessField(Handle<Map> map, Handle<String> name, | |
1988 LookupResult* lookup) { | |
1989 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*map)); | |
1990 int index; | |
1991 if (lookup->IsField()) { | |
1992 index = lookup->GetLocalFieldIndexFromMap(*map); | |
1993 } else { | |
1994 Map* transition = lookup->GetTransitionMapFromMap(*map); | |
1995 int descriptor = transition->LastAdded(); | |
1996 index = transition->instance_descriptors()->GetFieldIndex(descriptor) - | |
1997 map->inobject_properties(); | |
1998 } | |
1999 if (index < 0) { | |
2000 // Negative property indices are in-object properties, indexed | |
2001 // from the end of the fixed part of the object. | |
2002 int offset = (index * kPointerSize) + map->instance_size(); | |
2003 return new(zone()) HObjectAccess(HObjectAccess::kInobject, offset); | |
2004 } else { | |
2005 // Non-negative property indices are in the properties array. | |
2006 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | |
2007 return new(zone()) | |
2008 HObjectAccess(HObjectAccess::kBackingStore, offset, name); | |
danno
2013/05/02 14:16:47
Seems like a wast of memory, these can be stack al
titzer
2013/05/03 09:18:41
Can't do that, since a pointer to them is retained
| |
2009 } | |
2010 } | |
2011 | |
2012 HObjectAccess* HGraphBuilder::AccessInobject(Handle<String> name, int offset) { | |
2013 return new(zone()) HObjectAccess(HObjectAccess::kInobject, offset, name); | |
danno
2013/05/02 14:16:47
Same here...
| |
2014 } | |
2015 | |
2016 | |
1993 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 2017 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, |
1994 TypeFeedbackOracle* oracle) | 2018 TypeFeedbackOracle* oracle) |
1995 : HGraphBuilder(info), | 2019 : HGraphBuilder(info), |
1996 function_state_(NULL), | 2020 function_state_(NULL), |
1997 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 2021 initial_function_state_(this, info, oracle, NORMAL_RETURN), |
1998 ast_context_(NULL), | 2022 ast_context_(NULL), |
1999 break_scope_(NULL), | 2023 break_scope_(NULL), |
2000 inlined_count_(0), | 2024 inlined_count_(0), |
2001 globals_(10, info->zone()), | 2025 globals_(10, info->zone()), |
2002 inline_bailout_(false) { | 2026 inline_bailout_(false) { |
(...skipping 4892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6895 if (!is_store) return false; | 6919 if (!is_store) return false; |
6896 | 6920 |
6897 // 2nd chance: A store into a non-existent field can still be inlined if we | 6921 // 2nd chance: A store into a non-existent field can still be inlined if we |
6898 // have a matching transition and some room left in the object. | 6922 // have a matching transition and some room left in the object. |
6899 type->LookupTransition(NULL, *name, lookup); | 6923 type->LookupTransition(NULL, *name, lookup); |
6900 return lookup->IsTransitionToField(*type) && | 6924 return lookup->IsTransitionToField(*type) && |
6901 (type->unused_property_fields() > 0); | 6925 (type->unused_property_fields() > 0); |
6902 } | 6926 } |
6903 | 6927 |
6904 | 6928 |
6905 static int ComputeLoadStoreFieldIndex(Handle<Map> type, | |
6906 LookupResult* lookup) { | |
6907 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); | |
6908 if (lookup->IsField()) { | |
6909 return lookup->GetLocalFieldIndexFromMap(*type); | |
6910 } else { | |
6911 Map* transition = lookup->GetTransitionMapFromMap(*type); | |
6912 int descriptor = transition->LastAdded(); | |
6913 int index = transition->instance_descriptors()->GetFieldIndex(descriptor); | |
6914 return index - type->inobject_properties(); | |
6915 } | |
6916 } | |
6917 | |
6918 | |
6919 static Representation ComputeLoadStoreRepresentation(Handle<Map> type, | 6929 static Representation ComputeLoadStoreRepresentation(Handle<Map> type, |
6920 LookupResult* lookup) { | 6930 LookupResult* lookup) { |
6921 if (lookup->IsField()) { | 6931 if (lookup->IsField()) { |
6922 return lookup->representation(); | 6932 return lookup->representation(); |
6923 } else { | 6933 } else { |
6924 Map* transition = lookup->GetTransitionMapFromMap(*type); | 6934 Map* transition = lookup->GetTransitionMapFromMap(*type); |
6925 int descriptor = transition->LastAdded(); | 6935 int descriptor = transition->LastAdded(); |
6926 PropertyDetails details = | 6936 PropertyDetails details = |
6927 transition->instance_descriptors()->GetDetails(descriptor); | 6937 transition->instance_descriptors()->GetDetails(descriptor); |
6928 return details.representation(); | 6938 return details.representation(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6973 } | 6983 } |
6974 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 6984 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
6975 } | 6985 } |
6976 ASSERT(proto->IsJSObject()); | 6986 ASSERT(proto->IsJSObject()); |
6977 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6987 AddInstruction(new(zone()) HCheckPrototypeMaps( |
6978 Handle<JSObject>(JSObject::cast(map->prototype())), | 6988 Handle<JSObject>(JSObject::cast(map->prototype())), |
6979 Handle<JSObject>(JSObject::cast(proto)), | 6989 Handle<JSObject>(JSObject::cast(proto)), |
6980 zone())); | 6990 zone())); |
6981 } | 6991 } |
6982 | 6992 |
6983 int index = ComputeLoadStoreFieldIndex(map, lookup); | 6993 HObjectAccess* access = AccessField(map, name, lookup); |
6984 bool is_in_object = index < 0; | 6994 HStoreNamedField* instr = new(zone()) HStoreNamedField(object, access, value); |
6985 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | 6995 instr->set_field_representation(ComputeLoadStoreRepresentation(map, lookup)); |
6986 int offset = index * kPointerSize; | 6996 |
6987 if (index < 0) { | |
6988 // Negative property indices are in-object properties, indexed | |
6989 // from the end of the fixed part of the object. | |
6990 offset += map->instance_size(); | |
6991 } else { | |
6992 offset += FixedArray::kHeaderSize; | |
6993 } | |
6994 HStoreNamedField* instr = new(zone()) HStoreNamedField( | |
6995 object, name, value, is_in_object, representation, offset); | |
6996 if (lookup->IsTransitionToField(*map)) { | 6997 if (lookup->IsTransitionToField(*map)) { |
6997 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 6998 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
6998 instr->set_transition(transition); | 6999 instr->set_transition(transition); |
6999 // TODO(fschneider): Record the new map type of the object in the IR to | 7000 // TODO(fschneider): Record the new map type of the object in the IR to |
7000 // enable elimination of redundant checks after the transition store. | 7001 // enable elimination of redundant checks after the transition store. |
7001 instr->SetGVNFlag(kChangesMaps); | 7002 instr->SetGVNFlag(kChangesMaps); |
7002 } | 7003 } |
7003 return instr; | 7004 return instr; |
7004 } | 7005 } |
7005 | 7006 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7055 Handle<String> name) { | 7056 Handle<String> name) { |
7056 if (!name->Equals(isolate()->heap()->length_string())) return false; | 7057 if (!name->Equals(isolate()->heap()->length_string())) return false; |
7057 | 7058 |
7058 for (int i = 0; i < types->length(); i++) { | 7059 for (int i = 0; i < types->length(); i++) { |
7059 if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false; | 7060 if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false; |
7060 } | 7061 } |
7061 | 7062 |
7062 AddInstruction(new(zone()) HCheckNonSmi(object)); | 7063 AddInstruction(new(zone()) HCheckNonSmi(object)); |
7063 | 7064 |
7064 HInstruction* typecheck = | 7065 HInstruction* typecheck = |
7065 AddInstruction(HCheckMaps::New(object, types, zone())); | 7066 AddInstruction(HCheckMaps::New(object, types, zone())); |
7066 HInstruction* instr = | 7067 HInstruction* instr = new(zone()) |
7067 HLoadNamedField::NewArrayLength(zone(), object, typecheck); | 7068 HLoadNamedField(object, AccessArrayLength(), typecheck); |
7069 | |
7068 instr->set_position(expr->position()); | 7070 instr->set_position(expr->position()); |
7069 ast_context()->ReturnInstruction(instr, expr->id()); | 7071 ast_context()->ReturnInstruction(instr, expr->id()); |
7070 return true; | 7072 return true; |
7071 } | 7073 } |
7072 | 7074 |
7073 | 7075 |
7074 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 7076 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
7075 HValue* object, | 7077 HValue* object, |
7076 SmallMapList* types, | 7078 SmallMapList* types, |
7077 Handle<String> name) { | 7079 Handle<String> name) { |
7078 int count = 0; | 7080 int count = 0; |
7079 int previous_field_offset = 0; | 7081 int previous_field_offset = 0; |
7080 bool previous_field_is_in_object = false; | 7082 bool previous_field_is_in_object = false; |
7081 bool is_monomorphic_field = true; | 7083 bool is_monomorphic_field = true; |
7082 | 7084 |
7083 if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) | 7085 if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) |
7084 return; | 7086 return; |
7085 | 7087 |
7086 Handle<Map> map; | 7088 Handle<Map> map; |
7087 LookupResult lookup(isolate()); | 7089 LookupResult lookup(isolate()); |
7088 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 7090 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
7089 map = types->at(i); | 7091 map = types->at(i); |
7090 if (ComputeLoadStoreField(map, name, &lookup, false)) { | 7092 if (ComputeLoadStoreField(map, name, &lookup, false)) { |
7091 int index = ComputeLoadStoreFieldIndex(map, &lookup); | 7093 HObjectAccess* access = AccessField(map, name, &lookup); |
7092 bool is_in_object = index < 0; | |
7093 int offset = index * kPointerSize; | |
7094 if (index < 0) { | |
7095 // Negative property indices are in-object properties, indexed | |
7096 // from the end of the fixed part of the object. | |
7097 offset += map->instance_size(); | |
7098 } else { | |
7099 offset += FixedArray::kHeaderSize; | |
7100 } | |
7101 if (count == 0) { | 7094 if (count == 0) { |
7102 previous_field_offset = offset; | 7095 previous_field_offset = access->offset(); |
7103 previous_field_is_in_object = is_in_object; | 7096 previous_field_is_in_object = access->IsInobject(); |
7104 } else if (is_monomorphic_field) { | 7097 } else if (is_monomorphic_field) { |
7105 is_monomorphic_field = (offset == previous_field_offset) && | 7098 // TODO(titzer): just break out of this loop if not the same |
7106 (is_in_object == previous_field_is_in_object); | 7099 is_monomorphic_field = |
7100 (access->offset() == previous_field_offset) && | |
7101 (access->IsInobject() == previous_field_is_in_object); | |
7107 } | 7102 } |
7108 ++count; | 7103 ++count; |
7109 } | 7104 } |
7110 } | 7105 } |
7111 | 7106 |
7112 // Use monomorphic load if property lookup results in the same field index | 7107 // Use monomorphic load if property lookup results in the same field index |
7113 // for all maps. Requires special map check on the set of all handled maps. | 7108 // for all maps. Requires special map check on the set of all handled maps. |
7114 AddInstruction(new(zone()) HCheckNonSmi(object)); | 7109 AddInstruction(new(zone()) HCheckNonSmi(object)); |
7115 HInstruction* instr; | 7110 HInstruction* instr; |
7116 if (count == types->length() && is_monomorphic_field) { | 7111 if (count == types->length() && is_monomorphic_field) { |
7117 AddInstruction(HCheckMaps::New(object, types, zone())); | 7112 AddInstruction(HCheckMaps::New(object, types, zone())); |
7118 instr = BuildLoadNamedField(object, map, &lookup); | 7113 instr = new(zone()) |
7114 HLoadNamedField(object, AccessField(map, name, &lookup)); | |
7115 // TODO(titzer): ensure the representation is the same for all maps | |
7119 } else { | 7116 } else { |
7120 HValue* context = environment()->LookupContext(); | 7117 HValue* context = environment()->LookupContext(); |
7121 instr = new(zone()) HLoadNamedFieldPolymorphic(context, | 7118 instr = new(zone()) |
7122 object, | 7119 HLoadNamedFieldPolymorphic(context, object, types, name, zone()); |
7123 types, | |
7124 name, | |
7125 zone()); | |
7126 } | 7120 } |
7127 | 7121 |
7128 instr->set_position(expr->position()); | 7122 instr->set_position(expr->position()); |
7129 return ast_context()->ReturnInstruction(instr, expr->id()); | 7123 return ast_context()->ReturnInstruction(instr, expr->id()); |
7130 } | 7124 } |
7131 | 7125 |
7132 | 7126 |
7133 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 7127 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
7134 Assignment* expr, | 7128 Assignment* expr, |
7135 HValue* object, | 7129 HValue* object, |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7668 HValue* value = environment()->Pop(); | 7662 HValue* value = environment()->Pop(); |
7669 HThrow* instr = new(zone()) HThrow(context, value); | 7663 HThrow* instr = new(zone()) HThrow(context, value); |
7670 instr->set_position(expr->position()); | 7664 instr->set_position(expr->position()); |
7671 AddInstruction(instr); | 7665 AddInstruction(instr); |
7672 AddSimulate(expr->id()); | 7666 AddSimulate(expr->id()); |
7673 current_block()->FinishExit(new(zone()) HAbnormalExit); | 7667 current_block()->FinishExit(new(zone()) HAbnormalExit); |
7674 set_current_block(NULL); | 7668 set_current_block(NULL); |
7675 } | 7669 } |
7676 | 7670 |
7677 | 7671 |
7678 HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField( | |
7679 HValue* object, | |
7680 Handle<Map> map, | |
7681 LookupResult* lookup) { | |
7682 Representation representation = lookup->representation(); | |
7683 int index = lookup->GetLocalFieldIndexFromMap(*map); | |
7684 if (index < 0) { | |
7685 // Negative property indices are in-object properties, indexed | |
7686 // from the end of the fixed part of the object. | |
7687 int offset = (index * kPointerSize) + map->instance_size(); | |
7688 return new(zone()) HLoadNamedField(object, true, representation, offset); | |
7689 } else { | |
7690 // Non-negative property indices are in the properties array. | |
7691 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | |
7692 return new(zone()) HLoadNamedField(object, false, representation, offset); | |
7693 } | |
7694 } | |
7695 | |
7696 | |
7697 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 7672 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
7698 HValue* object, | 7673 HValue* object, |
7699 Handle<String> name, | 7674 Handle<String> name, |
7700 Property* expr) { | 7675 Property* expr) { |
7701 if (expr->IsUninitialized()) { | 7676 if (expr->IsUninitialized()) { |
7702 AddSoftDeoptimize(); | 7677 AddSoftDeoptimize(); |
7703 } | 7678 } |
7704 HValue* context = environment()->LookupContext(); | 7679 HValue* context = environment()->LookupContext(); |
7705 return new(zone()) HLoadNamedGeneric(context, object, name); | 7680 return new(zone()) HLoadNamedGeneric(context, object, name); |
7706 } | 7681 } |
(...skipping 15 matching lines...) Expand all Loading... | |
7722 Handle<String> name, | 7697 Handle<String> name, |
7723 Property* expr, | 7698 Property* expr, |
7724 Handle<Map> map) { | 7699 Handle<Map> map) { |
7725 // Handle a load from a known field. | 7700 // Handle a load from a known field. |
7726 ASSERT(!map->is_dictionary_map()); | 7701 ASSERT(!map->is_dictionary_map()); |
7727 | 7702 |
7728 // Handle access to various length properties | 7703 // Handle access to various length properties |
7729 if (name->Equals(isolate()->heap()->length_string())) { | 7704 if (name->Equals(isolate()->heap()->length_string())) { |
7730 if (map->instance_type() == JS_ARRAY_TYPE) { | 7705 if (map->instance_type() == JS_ARRAY_TYPE) { |
7731 AddCheckMapsWithTransitions(object, map); | 7706 AddCheckMapsWithTransitions(object, map); |
7732 return HLoadNamedField::NewArrayLength(zone(), object, object); | 7707 return new(zone()) HLoadNamedField(object, AccessArrayLength()); |
7733 } | 7708 } |
7734 } | 7709 } |
7735 | 7710 |
7736 LookupResult lookup(isolate()); | 7711 LookupResult lookup(isolate()); |
7737 map->LookupDescriptor(NULL, *name, &lookup); | 7712 map->LookupDescriptor(NULL, *name, &lookup); |
7738 if (lookup.IsField()) { | 7713 if (lookup.IsField()) { |
7739 AddCheckMap(object, map); | 7714 AddCheckMap(object, map); |
7740 return BuildLoadNamedField(object, map, &lookup); | 7715 HLoadNamedField* load = new(zone()) |
7716 HLoadNamedField(object, AccessField(map, name, &lookup)); | |
7717 load->set_field_representation( | |
7718 ComputeLoadStoreRepresentation(map, &lookup)); | |
7719 return load; | |
7741 } | 7720 } |
7742 | 7721 |
7743 // Handle a load of a constant known function. | 7722 // Handle a load of a constant known function. |
7744 if (lookup.IsConstantFunction()) { | 7723 if (lookup.IsConstantFunction()) { |
7745 AddCheckMap(object, map); | 7724 AddCheckMap(object, map); |
7746 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 7725 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
7747 return new(zone()) HConstant(function, Representation::Tagged()); | 7726 return new(zone()) HConstant(function, Representation::Tagged()); |
7748 } | 7727 } |
7749 | 7728 |
7750 // Handle a load from a known field somewhere in the prototype chain. | 7729 // Handle a load from a known field somewhere in the prototype chain. |
7751 LookupInPrototypes(map, name, &lookup); | 7730 LookupInPrototypes(map, name, &lookup); |
7752 if (lookup.IsField()) { | 7731 if (lookup.IsField()) { |
7753 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7732 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
7754 Handle<JSObject> holder(lookup.holder()); | 7733 Handle<JSObject> holder(lookup.holder()); |
7755 Handle<Map> holder_map(holder->map()); | 7734 Handle<Map> holder_map(holder->map()); |
7756 AddCheckMap(object, map); | 7735 AddCheckMap(object, map); |
7757 AddInstruction( | 7736 AddInstruction(new(zone()) |
7758 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7737 HCheckPrototypeMaps(prototype, holder, zone())); |
7759 HValue* holder_value = AddInstruction( | 7738 HValue* holder_value = AddInstruction(new(zone()) |
7760 new(zone()) HConstant(holder, Representation::Tagged())); | 7739 HConstant(holder, Representation::Tagged())); |
7761 return BuildLoadNamedField(holder_value, holder_map, &lookup); | 7740 HLoadNamedField* load = new(zone()) |
7741 HLoadNamedField(holder_value, AccessField(holder_map, name, &lookup)); | |
7742 load->set_field_representation( | |
7743 ComputeLoadStoreRepresentation(map, &lookup)); | |
7744 return load; | |
7762 } | 7745 } |
7763 | 7746 |
7764 // Handle a load of a constant function somewhere in the prototype chain. | 7747 // Handle a load of a constant function somewhere in the prototype chain. |
7765 if (lookup.IsConstantFunction()) { | 7748 if (lookup.IsConstantFunction()) { |
7766 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7749 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
7767 Handle<JSObject> holder(lookup.holder()); | 7750 Handle<JSObject> holder(lookup.holder()); |
7768 Handle<Map> holder_map(holder->map()); | 7751 Handle<Map> holder_map(holder->map()); |
7769 AddCheckMap(object, map); | 7752 AddCheckMap(object, map); |
7770 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7753 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); |
7771 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 7754 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8015 // it's a keyed property) and registered in the full codegen. | 7998 // it's a keyed property) and registered in the full codegen. |
8016 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 7999 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
8017 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 8000 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
8018 HHasInstanceTypeAndBranch* typecheck = | 8001 HHasInstanceTypeAndBranch* typecheck = |
8019 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 8002 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
8020 typecheck->SetSuccessorAt(0, if_jsarray); | 8003 typecheck->SetSuccessorAt(0, if_jsarray); |
8021 typecheck->SetSuccessorAt(1, if_fastobject); | 8004 typecheck->SetSuccessorAt(1, if_fastobject); |
8022 current_block()->Finish(typecheck); | 8005 current_block()->Finish(typecheck); |
8023 | 8006 |
8024 set_current_block(if_jsarray); | 8007 set_current_block(if_jsarray); |
8025 HInstruction* length; | 8008 HInstruction* length = AddLoad(object, AccessArrayLength(), typecheck); |
8026 length = AddInstruction( | 8009 length->set_type(HType::Smi()); |
8027 HLoadNamedField::NewArrayLength(zone(), object, typecheck, | 8010 // TODO(titzer): length->set_field_representation(Representation::Smi()) |
8028 HType::Smi())); | 8011 |
8029 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 8012 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
8030 access = AddInstruction(BuildFastElementAccess( | 8013 access = AddInstruction(BuildFastElementAccess( |
8031 elements, checked_key, val, elements_kind_branch, | 8014 elements, checked_key, val, elements_kind_branch, |
8032 elements_kind, is_store, STANDARD_STORE)); | 8015 elements_kind, is_store, STANDARD_STORE)); |
8033 if (!is_store) { | 8016 if (!is_store) { |
8034 Push(access); | 8017 Push(access); |
8035 } | 8018 } |
8036 | 8019 |
8037 *has_side_effects |= access->HasObservableSideEffects(); | 8020 *has_side_effects |= access->HasObservableSideEffects(); |
8038 // The caller will use has_side_effects and add correct Simulate. | 8021 // The caller will use has_side_effects and add correct Simulate. |
(...skipping 2672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10711 Handle<Object> value = | 10694 Handle<Object> value = |
10712 Handle<Object>(boilerplate_object->InObjectPropertyAt(i), | 10695 Handle<Object>(boilerplate_object->InObjectPropertyAt(i), |
10713 isolate()); | 10696 isolate()); |
10714 if (value->IsJSObject()) { | 10697 if (value->IsJSObject()) { |
10715 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 10698 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
10716 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 10699 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
10717 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(i), | 10700 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(i), |
10718 isolate())); | 10701 isolate())); |
10719 HInstruction* value_instruction = | 10702 HInstruction* value_instruction = |
10720 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 10703 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); |
10704 | |
10721 // TODO(verwaest): choose correct storage. | 10705 // TODO(verwaest): choose correct storage. |
10722 AddInstruction(new(zone) HStoreNamedField( | 10706 HObjectAccess* access = AccessInobject(factory->unknown_field_string(), |
10723 object_properties, factory->unknown_field_string(), value_instruction, | 10707 boilerplate_object->GetInObjectPropertyOffset(i)); |
10724 true, Representation::Tagged(), | 10708 AddStore(object_properties, access, value_instruction); |
10725 boilerplate_object->GetInObjectPropertyOffset(i))); | 10709 |
10726 BuildEmitDeepCopy(value_object, original_value_object, target, | 10710 BuildEmitDeepCopy(value_object, original_value_object, target, |
10727 offset, DONT_TRACK_ALLOCATION_SITE); | 10711 offset, DONT_TRACK_ALLOCATION_SITE); |
10728 } else { | 10712 } else { |
10729 // TODO(verwaest): choose correct storage. | 10713 // TODO(verwaest): choose correct storage. |
10730 HInstruction* value_instruction = AddInstruction(new(zone) HConstant( | 10714 HInstruction* value_instruction = AddInstruction(new(zone) HConstant( |
10731 value, Representation::Tagged())); | 10715 value, Representation::Tagged())); |
10732 AddInstruction(new(zone) HStoreNamedField( | 10716 |
10733 object_properties, factory->unknown_field_string(), value_instruction, | 10717 HObjectAccess* access = AccessInobject(factory->unknown_field_string(), |
10734 true, Representation::Tagged(), | 10718 boilerplate_object->GetInObjectPropertyOffset(i)); |
10735 boilerplate_object->GetInObjectPropertyOffset(i))); | 10719 AddStore(object_properties, access, value_instruction); |
10736 } | 10720 } |
10737 } | 10721 } |
10738 | 10722 |
10739 // Build Allocation Site Info if desired | 10723 // Build Allocation Site Info if desired |
10740 if (create_allocation_site_info) { | 10724 if (create_allocation_site_info) { |
10741 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate); | 10725 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate); |
10742 } | 10726 } |
10743 | 10727 |
10744 if (object_elements != NULL) { | 10728 if (object_elements != NULL) { |
10745 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( | 10729 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10803 int elements_offset, | 10787 int elements_offset, |
10804 int elements_size) { | 10788 int elements_size) { |
10805 ASSERT(boilerplate_object->properties()->length() == 0); | 10789 ASSERT(boilerplate_object->properties()->length() == 0); |
10806 Zone* zone = this->zone(); | 10790 Zone* zone = this->zone(); |
10807 Factory* factory = isolate()->factory(); | 10791 Factory* factory = isolate()->factory(); |
10808 HValue* result = NULL; | 10792 HValue* result = NULL; |
10809 | 10793 |
10810 HValue* object_header = | 10794 HValue* object_header = |
10811 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); | 10795 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); |
10812 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 10796 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
10813 BuildStoreMap(object_header, boilerplate_object_map); | 10797 AddStoreMapConstant(object_header, boilerplate_object_map); |
10814 | 10798 |
10815 HInstruction* elements; | 10799 HInstruction* elements; |
10816 if (elements_size == 0) { | 10800 if (elements_size == 0) { |
10817 Handle<Object> elements_field = | 10801 Handle<Object> elements_field = |
10818 Handle<Object>(boilerplate_object->elements(), isolate()); | 10802 Handle<Object>(boilerplate_object->elements(), isolate()); |
10819 elements = AddInstruction(new(zone) HConstant( | 10803 elements = AddInstruction(new(zone) HConstant( |
10820 elements_field, Representation::Tagged())); | 10804 elements_field, Representation::Tagged())); |
10821 } else { | 10805 } else { |
10822 elements = AddInstruction(new(zone) HInnerAllocatedObject( | 10806 elements = AddInstruction(new(zone) HInnerAllocatedObject( |
10823 target, elements_offset)); | 10807 target, elements_offset)); |
10824 result = elements; | 10808 result = elements; |
10825 } | 10809 } |
10826 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( | 10810 AddStore(object_header, AccessElements(), elements); |
10827 object_header, | |
10828 factory->elements_field_string(), | |
10829 elements, | |
10830 true, Representation::Tagged(), JSObject::kElementsOffset)); | |
10831 elements_store->SetGVNFlag(kChangesElementsPointer); | |
10832 | 10811 |
10833 Handle<Object> properties_field = | 10812 Handle<Object> properties_field = |
10834 Handle<Object>(boilerplate_object->properties(), isolate()); | 10813 Handle<Object>(boilerplate_object->properties(), isolate()); |
10835 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 10814 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
10836 HInstruction* properties = AddInstruction(new(zone) HConstant( | 10815 HInstruction* properties = AddInstruction(new(zone) HConstant( |
10837 properties_field, Representation::None())); | 10816 properties_field, Representation::None())); |
10838 AddInstruction(new(zone) HStoreNamedField(object_header, | 10817 HObjectAccess* access = AccessInobject( |
10839 factory->empty_string(), | 10818 factory->empty_string(), JSObject::kPropertiesOffset); |
10840 properties, true, | 10819 AddStore(object_header, access, properties); |
10841 Representation::Tagged(), | |
10842 JSObject::kPropertiesOffset)); | |
10843 | 10820 |
10844 if (boilerplate_object->IsJSArray()) { | 10821 if (boilerplate_object->IsJSArray()) { |
10845 Handle<JSArray> boilerplate_array = | 10822 Handle<JSArray> boilerplate_array = |
10846 Handle<JSArray>::cast(boilerplate_object); | 10823 Handle<JSArray>::cast(boilerplate_object); |
10847 Handle<Object> length_field = | 10824 Handle<Object> length_field = |
10848 Handle<Object>(boilerplate_array->length(), isolate()); | 10825 Handle<Object>(boilerplate_array->length(), isolate()); |
10849 HInstruction* length = AddInstruction(new(zone) HConstant( | 10826 HInstruction* length = AddInstruction(new(zone) HConstant( |
10850 length_field, Representation::None())); | 10827 length_field, Representation::None())); |
10828 | |
10851 ASSERT(boilerplate_array->length()->IsSmi()); | 10829 ASSERT(boilerplate_array->length()->IsSmi()); |
10852 Representation representation = | 10830 Representation representation = |
10853 IsFastElementsKind(boilerplate_array->GetElementsKind()) | 10831 IsFastElementsKind(boilerplate_array->GetElementsKind()) |
10854 ? Representation::Smi() : Representation::Tagged(); | 10832 ? Representation::Smi() : Representation::Tagged(); |
10855 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( | 10833 AddStore(object_header, AccessArrayLength(), length, representation); |
10856 object_header, | |
10857 factory->length_field_string(), | |
10858 length, | |
10859 true, representation, JSArray::kLengthOffset)); | |
10860 length_store->SetGVNFlag(kChangesArrayLengths); | |
10861 } | 10834 } |
10862 | 10835 |
10863 return result; | 10836 return result; |
10864 } | 10837 } |
10865 | 10838 |
10866 | 10839 |
10867 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 10840 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
10868 ASSERT(!HasStackOverflow()); | 10841 ASSERT(!HasStackOverflow()); |
10869 ASSERT(current_block() != NULL); | 10842 ASSERT(current_block() != NULL); |
10870 ASSERT(current_block()->HasPredecessor()); | 10843 ASSERT(current_block()->HasPredecessor()); |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11238 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); | 11211 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); |
11239 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); | 11212 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); |
11240 typecheck->SetSuccessorAt(0, if_js_value); | 11213 typecheck->SetSuccessorAt(0, if_js_value); |
11241 typecheck->SetSuccessorAt(1, not_js_value); | 11214 typecheck->SetSuccessorAt(1, not_js_value); |
11242 current_block()->Finish(typecheck); | 11215 current_block()->Finish(typecheck); |
11243 not_js_value->Goto(join); | 11216 not_js_value->Goto(join); |
11244 | 11217 |
11245 // Create in-object property store to kValueOffset. | 11218 // Create in-object property store to kValueOffset. |
11246 set_current_block(if_js_value); | 11219 set_current_block(if_js_value); |
11247 Handle<String> name = isolate()->factory()->undefined_string(); | 11220 Handle<String> name = isolate()->factory()->undefined_string(); |
11248 AddInstruction(new(zone()) HStoreNamedField(object, | 11221 AddStore(object, AccessInobject(name, JSValue::kValueOffset), value); |
11249 name, | |
11250 value, | |
11251 true, // in-object store. | |
11252 Representation::Tagged(), | |
11253 JSValue::kValueOffset)); | |
11254 if_js_value->Goto(join); | 11222 if_js_value->Goto(join); |
11255 join->SetJoinId(call->id()); | 11223 join->SetJoinId(call->id()); |
11256 set_current_block(join); | 11224 set_current_block(join); |
11257 return ast_context()->ReturnValue(value); | 11225 return ast_context()->ReturnValue(value); |
11258 } | 11226 } |
11259 | 11227 |
11260 | 11228 |
11261 // Fast support for charCodeAt(n). | 11229 // Fast support for charCodeAt(n). |
11262 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 11230 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
11263 ASSERT(call->arguments()->length() == 2); | 11231 ASSERT(call->arguments()->length() == 2); |
(...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12218 } | 12186 } |
12219 } | 12187 } |
12220 | 12188 |
12221 #ifdef DEBUG | 12189 #ifdef DEBUG |
12222 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 12190 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
12223 if (allocator_ != NULL) allocator_->Verify(); | 12191 if (allocator_ != NULL) allocator_->Verify(); |
12224 #endif | 12192 #endif |
12225 } | 12193 } |
12226 | 12194 |
12227 } } // namespace v8::internal | 12195 } } // namespace v8::internal |
OLD | NEW |