Chromium Code Reviews| 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 1171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1182 | 1182 |
| 1183 environment()->Push(elements); | 1183 environment()->Push(elements); |
| 1184 capacity_checker.End(); | 1184 capacity_checker.End(); |
| 1185 | 1185 |
| 1186 if (is_js_array) { | 1186 if (is_js_array) { |
| 1187 HValue* new_length = AddInstruction( | 1187 HValue* new_length = AddInstruction( |
| 1188 HAdd::New(zone, context, length, graph_->GetConstant1())); | 1188 HAdd::New(zone, context, length, graph_->GetConstant1())); |
| 1189 new_length->ChangeRepresentation(Representation::Integer32()); | 1189 new_length->ChangeRepresentation(Representation::Integer32()); |
| 1190 new_length->ClearFlag(HValue::kCanOverflow); | 1190 new_length->ClearFlag(HValue::kCanOverflow); |
| 1191 | 1191 |
| 1192 Factory* factory = isolate()->factory(); | 1192 AddStore(object, AccessArrayLength(), new_length); |
| 1193 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( | |
| 1194 object, | |
| 1195 factory->length_field_string(), | |
| 1196 new_length, true, | |
| 1197 JSArray::kLengthOffset)); | |
| 1198 length_store->SetGVNFlag(kChangesArrayLengths); | |
| 1199 } | 1193 } |
| 1200 | 1194 |
| 1201 length_checker.Else(); | 1195 length_checker.Else(); |
| 1202 | 1196 |
| 1203 AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 1197 AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
| 1204 environment()->Push(elements); | 1198 environment()->Push(elements); |
| 1205 | 1199 |
| 1206 length_checker.End(); | 1200 length_checker.End(); |
| 1207 | 1201 |
| 1208 return environment()->Pop(); | 1202 return environment()->Pop(); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1270 AddInstruction(new(zone) HLoadElements(object, mapcheck)); | 1264 AddInstruction(new(zone) HLoadElements(object, mapcheck)); |
| 1271 if (is_store && (fast_elements || fast_smi_only_elements) && | 1265 if (is_store && (fast_elements || fast_smi_only_elements) && |
| 1272 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1266 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 1273 HCheckMaps* check_cow_map = HCheckMaps::New( | 1267 HCheckMaps* check_cow_map = HCheckMaps::New( |
| 1274 elements, isolate()->factory()->fixed_array_map(), zone); | 1268 elements, isolate()->factory()->fixed_array_map(), zone); |
| 1275 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1269 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1276 AddInstruction(check_cow_map); | 1270 AddInstruction(check_cow_map); |
| 1277 } | 1271 } |
| 1278 HInstruction* length = NULL; | 1272 HInstruction* length = NULL; |
| 1279 if (is_js_array) { | 1273 if (is_js_array) { |
| 1280 length = AddInstruction( | 1274 length = AddInstruction( |
|
danno
2013/04/26 09:39:38
while your here, and you add a AddLoad (like your
| |
| 1281 HLoadNamedField::NewArrayLength(zone, object, mapcheck, HType::Smi())); | 1275 new(zone) HLoadNamedField(object, AccessArrayLength(), mapcheck)); |
| 1276 length->set_type(HType::Smi()); | |
| 1282 } else { | 1277 } else { |
| 1283 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 1278 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
| 1284 } | 1279 } |
| 1285 HValue* checked_key = NULL; | 1280 HValue* checked_key = NULL; |
| 1286 if (IsExternalArrayElementsKind(elements_kind)) { | 1281 if (IsExternalArrayElementsKind(elements_kind)) { |
| 1287 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1282 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 1288 NoObservableSideEffectsScope no_effects(this); | 1283 NoObservableSideEffectsScope no_effects(this); |
| 1289 HLoadExternalArrayPointer* external_elements = | 1284 HLoadExternalArrayPointer* external_elements = |
| 1290 new(zone) HLoadExternalArrayPointer(elements); | 1285 new(zone) HLoadExternalArrayPointer(elements); |
| 1291 AddInstruction(external_elements); | 1286 AddInstruction(external_elements); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1404 | 1399 |
| 1405 | 1400 |
| 1406 void HGraphBuilder::BuildInitializeElements(HValue* elements, | 1401 void HGraphBuilder::BuildInitializeElements(HValue* elements, |
| 1407 ElementsKind kind, | 1402 ElementsKind kind, |
| 1408 HValue* capacity) { | 1403 HValue* capacity) { |
| 1409 Zone* zone = this->zone(); | 1404 Zone* zone = this->zone(); |
| 1410 Factory* factory = isolate()->factory(); | 1405 Factory* factory = isolate()->factory(); |
| 1411 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1406 Handle<Map> map = IsFastDoubleElementsKind(kind) |
| 1412 ? factory->fixed_double_array_map() | 1407 ? factory->fixed_double_array_map() |
| 1413 : factory->fixed_array_map(); | 1408 : factory->fixed_array_map(); |
| 1414 BuildStoreMap(elements, map); | |
| 1415 | 1409 |
| 1416 Handle<String> fixed_array_length_field_name = factory->length_field_string(); | 1410 HValue* map_constant = |
| 1417 HInstruction* store_length = | 1411 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); |
| 1418 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, | 1412 AddStore(elements, AccessMap(), map_constant); |
| 1419 capacity, true, FixedArray::kLengthOffset); | 1413 AddStore(elements, AccessFixedArrayLength(), capacity); |
| 1420 AddInstruction(store_length); | |
| 1421 } | 1414 } |
| 1422 | 1415 |
| 1423 | 1416 |
| 1424 HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, | 1417 HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, |
| 1425 ElementsKind kind, | 1418 ElementsKind kind, |
| 1426 HValue* capacity) { | 1419 HValue* capacity) { |
| 1427 HValue* new_elements = BuildAllocateElements(context, kind, capacity); | 1420 HValue* new_elements = BuildAllocateElements(context, kind, capacity); |
| 1428 BuildInitializeElements(new_elements, kind, capacity); | 1421 BuildInitializeElements(new_elements, kind, capacity); |
| 1429 return new_elements; | 1422 return new_elements; |
| 1430 } | 1423 } |
| 1431 | 1424 |
| 1432 | 1425 |
| 1433 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | |
| 1434 HValue* map) { | |
| 1435 Zone* zone = this->zone(); | |
| 1436 Factory* factory = isolate()->factory(); | |
| 1437 Handle<String> map_field_name = factory->map_field_string(); | |
| 1438 HInstruction* store_map = | |
| 1439 new(zone) HStoreNamedField(object, map_field_name, map, | |
| 1440 true, JSObject::kMapOffset); | |
| 1441 store_map->SetGVNFlag(kChangesMaps); | |
| 1442 AddInstruction(store_map); | |
| 1443 return store_map; | |
| 1444 } | |
| 1445 | |
| 1446 | |
| 1447 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | |
| 1448 Handle<Map> map) { | |
| 1449 Zone* zone = this->zone(); | |
| 1450 HValue* map_constant = | |
| 1451 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); | |
| 1452 return BuildStoreMap(object, map_constant); | |
| 1453 } | |
| 1454 | |
| 1455 | |
| 1456 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1426 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
| 1457 HValue* old_capacity) { | 1427 HValue* old_capacity) { |
| 1458 Zone* zone = this->zone(); | 1428 Zone* zone = this->zone(); |
| 1459 HValue* half_old_capacity = | 1429 HValue* half_old_capacity = |
| 1460 AddInstruction(HShr::New(zone, context, old_capacity, | 1430 AddInstruction(HShr::New(zone, context, old_capacity, |
| 1461 graph_->GetConstant1())); | 1431 graph_->GetConstant1())); |
| 1462 half_old_capacity->ChangeRepresentation(Representation::Integer32()); | 1432 half_old_capacity->ChangeRepresentation(Representation::Integer32()); |
| 1463 half_old_capacity->ClearFlag(HValue::kCanOverflow); | 1433 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
| 1464 | 1434 |
| 1465 HValue* new_capacity = AddInstruction( | 1435 HValue* new_capacity = AddInstruction( |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1495 HBoundsCheck(length, max_size_constant, | 1465 HBoundsCheck(length, max_size_constant, |
| 1496 DONT_ALLOW_SMI_KEY, Representation::Integer32())); | 1466 DONT_ALLOW_SMI_KEY, Representation::Integer32())); |
| 1497 } | 1467 } |
| 1498 | 1468 |
| 1499 | 1469 |
| 1500 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 1470 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
| 1501 HValue* elements, | 1471 HValue* elements, |
| 1502 ElementsKind kind, | 1472 ElementsKind kind, |
| 1503 HValue* length, | 1473 HValue* length, |
| 1504 HValue* new_capacity) { | 1474 HValue* new_capacity) { |
| 1505 Zone* zone = this->zone(); | |
| 1506 HValue* context = environment()->LookupContext(); | 1475 HValue* context = environment()->LookupContext(); |
| 1507 | 1476 |
| 1508 BuildNewSpaceArrayCheck(new_capacity, kind); | 1477 BuildNewSpaceArrayCheck(new_capacity, kind); |
| 1509 | 1478 |
| 1510 HValue* new_elements = | 1479 HValue* new_elements = |
| 1511 BuildAllocateAndInitializeElements(context, kind, new_capacity); | 1480 BuildAllocateAndInitializeElements(context, kind, new_capacity); |
| 1512 | 1481 |
| 1513 BuildCopyElements(context, elements, kind, | 1482 BuildCopyElements(context, elements, kind, |
| 1514 new_elements, kind, | 1483 new_elements, kind, |
| 1515 length, new_capacity); | 1484 length, new_capacity); |
| 1516 | 1485 |
| 1517 Factory* factory = isolate()->factory(); | 1486 AddStore(object, AccessElements(), new_elements); |
| 1518 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( | |
| 1519 object, | |
| 1520 factory->elements_field_string(), | |
| 1521 new_elements, true, | |
| 1522 JSArray::kElementsOffset)); | |
| 1523 elements_store->SetGVNFlag(kChangesElementsPointer); | |
| 1524 | 1487 |
| 1525 return new_elements; | 1488 return new_elements; |
| 1526 } | 1489 } |
| 1527 | 1490 |
| 1528 | 1491 |
| 1529 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, | 1492 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, |
| 1530 HValue* elements, | 1493 HValue* elements, |
| 1531 ElementsKind elements_kind, | 1494 ElementsKind elements_kind, |
| 1532 HValue* from, | 1495 HValue* from, |
| 1533 HValue* to) { | 1496 HValue* to) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1628 AddInstruction(new(zone) HConstant(size, Representation::Integer32())); | 1591 AddInstruction(new(zone) HConstant(size, Representation::Integer32())); |
| 1629 HInstruction* object = | 1592 HInstruction* object = |
| 1630 AddInstruction(new(zone) HAllocate(context, | 1593 AddInstruction(new(zone) HAllocate(context, |
| 1631 size_in_bytes, | 1594 size_in_bytes, |
| 1632 HType::JSObject(), | 1595 HType::JSObject(), |
| 1633 allocate_flags)); | 1596 allocate_flags)); |
| 1634 | 1597 |
| 1635 // Copy the JS array part. | 1598 // Copy the JS array part. |
| 1636 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 1599 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 1637 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 1600 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
| 1601 ObjectAccess access = AccessArray(i); | |
|
danno
2013/04/26 09:39:38
Careful, this isn't what you think. This loop does
| |
| 1638 HInstruction* value = | 1602 HInstruction* value = |
| 1639 AddInstruction(new(zone) HLoadNamedField(boilerplate, true, i)); | 1603 AddInstruction(new(zone) HLoadNamedField(boilerplate, access)); |
| 1640 if (i != JSArray::kMapOffset) { | 1604 AddStore(object, access, value); |
| 1641 AddInstruction(new(zone) HStoreNamedField(object, | |
| 1642 factory->empty_string(), | |
| 1643 value, | |
| 1644 true, i)); | |
| 1645 } else { | |
| 1646 BuildStoreMap(object, value); | |
| 1647 } | |
| 1648 } | 1605 } |
| 1649 } | 1606 } |
| 1650 | 1607 |
| 1651 // Create an allocation site info if requested. | 1608 // Create an allocation site info if requested. |
| 1652 if (mode == TRACK_ALLOCATION_SITE) { | 1609 if (mode == TRACK_ALLOCATION_SITE) { |
| 1653 HValue* alloc_site = | 1610 HValue* alloc_site = |
| 1654 AddInstruction(new(zone) HInnerAllocatedObject(object, JSArray::kSize)); | 1611 AddInstruction(new(zone) HInnerAllocatedObject(object, JSArray::kSize)); |
| 1655 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); | 1612 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); |
| 1656 BuildStoreMap(alloc_site, alloc_site_map); | 1613 HValue* alloc_site_map_constant = AddInstruction(new(zone) |
| 1657 int alloc_payload_offset = AllocationSiteInfo::kPayloadOffset; | 1614 HConstant(alloc_site_map, Representation::Tagged())); |
| 1658 AddInstruction(new(zone) HStoreNamedField(alloc_site, | 1615 AddStore(alloc_site, AccessMap(), alloc_site_map_constant); |
|
danno
2013/04/26 09:39:38
I still think a wrapper utility BuildStoreMap woul
| |
| 1659 factory->empty_string(), | 1616 ObjectAccess access = AccessInobject( |
| 1660 boilerplate, | 1617 factory->payload_string(), AllocationSiteInfo::kPayloadOffset); |
| 1661 true, alloc_payload_offset)); | 1618 AddStore(alloc_site, access, boilerplate); |
| 1662 } | 1619 } |
| 1663 | 1620 |
| 1664 if (length > 0) { | 1621 if (length > 0) { |
| 1665 // Get hold of the elements array of the boilerplate and setup the | 1622 // Get hold of the elements array of the boilerplate and setup the |
| 1666 // elements pointer in the resulting object. | 1623 // elements pointer in the resulting object. |
| 1667 HValue* boilerplate_elements = | 1624 HValue* boilerplate_elements = |
| 1668 AddInstruction(new(zone) HLoadElements(boilerplate, NULL)); | 1625 AddInstruction(new(zone) HLoadElements(boilerplate, NULL)); |
| 1669 HValue* object_elements = | 1626 HValue* object_elements = |
| 1670 AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset)); | 1627 AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset)); |
| 1671 AddInstruction(new(zone) HStoreNamedField(object, | 1628 AddStore(object, AccessElements(), object_elements); |
| 1672 factory->elements_field_string(), | |
| 1673 object_elements, | |
| 1674 true, JSObject::kElementsOffset)); | |
| 1675 | 1629 |
| 1676 // Copy the elements array header. | 1630 // Copy the elements array header. |
| 1677 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 1631 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
| 1678 HInstruction* value = | 1632 // TODO(titzer): AccessFixedArray? |
| 1679 AddInstruction(new(zone) HLoadNamedField(boilerplate_elements, | 1633 ObjectAccess access = AccessInobject(factory->empty_string(), i); |
| 1680 true, i)); | 1634 HInstruction* value = AddInstruction(new(zone) |
| 1681 AddInstruction(new(zone) HStoreNamedField(object_elements, | 1635 HLoadNamedField(boilerplate_elements, access)); |
| 1682 factory->empty_string(), | 1636 AddStore(object_elements, access, value); |
| 1683 value, | |
| 1684 true, i)); | |
| 1685 } | 1637 } |
| 1686 | 1638 |
| 1687 // Copy the elements array contents. | 1639 // Copy the elements array contents. |
| 1688 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold | 1640 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold |
| 1689 // copying loops with constant length up to a given boundary and use this | 1641 // copying loops with constant length up to a given boundary and use this |
| 1690 // helper here instead. | 1642 // helper here instead. |
| 1691 for (int i = 0; i < length; i++) { | 1643 for (int i = 0; i < length; i++) { |
| 1692 HValue* key_constant = | 1644 HValue* key_constant = |
| 1693 AddInstruction(new(zone) HConstant(i, Representation::Integer32())); | 1645 AddInstruction(new(zone) HConstant(i, Representation::Integer32())); |
| 1694 HInstruction* value = | 1646 HInstruction* value = |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1747 if (kind == kNonStrictEquality) { | 1699 if (kind == kNonStrictEquality) { |
| 1748 if_nil.Deopt(); | 1700 if_nil.Deopt(); |
| 1749 } | 1701 } |
| 1750 } | 1702 } |
| 1751 } | 1703 } |
| 1752 | 1704 |
| 1753 if_nil.CaptureContinuation(continuation); | 1705 if_nil.CaptureContinuation(continuation); |
| 1754 } | 1706 } |
| 1755 | 1707 |
| 1756 | 1708 |
| 1709 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, ObjectAccess access, | |
| 1710 HValue *val) { | |
| 1711 HStoreNamedField *instr = new(zone()) HStoreNamedField(object, access, val); | |
| 1712 AddInstruction(instr); | |
| 1713 return instr; | |
| 1714 } | |
| 1715 | |
| 1716 | |
| 1717 ObjectAccess HGraphBuilder::AccessArray(int offset) { | |
| 1718 Factory *factory = isolate()->factory(); | |
| 1719 ObjectAccess::Portion portion = ObjectAccess::kInobject; | |
| 1720 Handle<String> name = factory->empty_string(); | |
| 1721 if (offset == JSObject::kElementsOffset) { | |
| 1722 portion = ObjectAccess::kElementsPointer; | |
| 1723 name = factory->elements_field_string(); | |
| 1724 } else if (offset == JSArray::kLengthOffset) { | |
| 1725 portion = ObjectAccess::kArrayLengths; | |
| 1726 name = factory->length_field_string(); | |
| 1727 } else if (offset == JSArray::kMapOffset) { | |
| 1728 portion = ObjectAccess::kMaps; | |
| 1729 name = factory->map_field_string(); | |
|
danno
2013/04/26 09:39:38
See my other comments about consolidating this log
| |
| 1730 } | |
| 1731 return ObjectAccess(portion, offset, false, name); | |
| 1732 } | |
| 1733 | |
| 1734 | |
| 1735 ObjectAccess HGraphBuilder::AccessArrayLength() { | |
| 1736 return ObjectAccess(ObjectAccess::kArrayLengths, JSArray::kLengthOffset, | |
| 1737 false, isolate()->factory()->length_field_string()); | |
| 1738 } | |
| 1739 | |
| 1740 | |
| 1741 ObjectAccess HGraphBuilder::AccessFixedArrayLength() { | |
| 1742 return ObjectAccess(ObjectAccess::kInobject, FixedArray::kLengthOffset, | |
| 1743 false, isolate()->factory()->length_field_string()); | |
| 1744 } | |
| 1745 | |
| 1746 | |
| 1747 ObjectAccess HGraphBuilder::AccessElements() { | |
| 1748 return ObjectAccess(ObjectAccess::kElementsPointer, JSObject::kElementsOffset, | |
| 1749 false, isolate()->factory()->elements_field_string()); | |
| 1750 } | |
| 1751 | |
| 1752 | |
| 1753 ObjectAccess HGraphBuilder::AccessMap() { | |
| 1754 return ObjectAccess(ObjectAccess::kMaps, JSObject::kMapOffset, | |
| 1755 false, isolate()->factory()->map_field_string()); | |
| 1756 } | |
| 1757 | |
| 1758 | |
| 1759 ObjectAccess HGraphBuilder::AccessField(Handle<Map> map, Handle<String> name, | |
| 1760 LookupResult* lookup) { | |
| 1761 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*map)); | |
| 1762 int index; | |
| 1763 if (lookup->IsField()) { | |
| 1764 index = lookup->GetLocalFieldIndexFromMap(*map); | |
| 1765 } else { | |
| 1766 Map* transition = lookup->GetTransitionMapFromMap(*map); | |
| 1767 index = transition->PropertyIndexFor(*name) - map->inobject_properties(); | |
| 1768 } | |
| 1769 if (index < 0) { | |
| 1770 // Negative property indices are in-object properties, indexed | |
| 1771 // from the end of the fixed part of the object. | |
| 1772 int offset = (index * kPointerSize) + map->instance_size(); | |
| 1773 return ObjectAccess(ObjectAccess::kInobject, offset, false); | |
| 1774 } else { | |
| 1775 // Non-negative property indices are in the properties array. | |
| 1776 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | |
| 1777 return ObjectAccess(ObjectAccess::kBackingStore, offset, false, name); | |
| 1778 } | |
| 1779 } | |
| 1780 | |
| 1781 ObjectAccess HGraphBuilder::AccessInobject(Handle<String> name, int offset) { | |
| 1782 return ObjectAccess(ObjectAccess::kInobject, offset, false, name); | |
| 1783 } | |
| 1784 | |
| 1785 | |
| 1757 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 1786 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, |
| 1758 TypeFeedbackOracle* oracle) | 1787 TypeFeedbackOracle* oracle) |
| 1759 : HGraphBuilder(info), | 1788 : HGraphBuilder(info), |
| 1760 function_state_(NULL), | 1789 function_state_(NULL), |
| 1761 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 1790 initial_function_state_(this, info, oracle, NORMAL_RETURN), |
| 1762 ast_context_(NULL), | 1791 ast_context_(NULL), |
| 1763 break_scope_(NULL), | 1792 break_scope_(NULL), |
| 1764 inlined_count_(0), | 1793 inlined_count_(0), |
| 1765 globals_(10, info->zone()), | 1794 globals_(10, info->zone()), |
| 1766 inline_bailout_(false) { | 1795 inline_bailout_(false) { |
| (...skipping 4887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6654 if (!is_store) return false; | 6683 if (!is_store) return false; |
| 6655 | 6684 |
| 6656 // 2nd chance: A store into a non-existent field can still be inlined if we | 6685 // 2nd chance: A store into a non-existent field can still be inlined if we |
| 6657 // have a matching transition and some room left in the object. | 6686 // have a matching transition and some room left in the object. |
| 6658 type->LookupTransition(NULL, *name, lookup); | 6687 type->LookupTransition(NULL, *name, lookup); |
| 6659 return lookup->IsTransitionToField(*type) && | 6688 return lookup->IsTransitionToField(*type) && |
| 6660 (type->unused_property_fields() > 0); | 6689 (type->unused_property_fields() > 0); |
| 6661 } | 6690 } |
| 6662 | 6691 |
| 6663 | 6692 |
| 6664 static int ComputeLoadStoreFieldIndex(Handle<Map> type, | |
| 6665 Handle<String> name, | |
| 6666 LookupResult* lookup) { | |
| 6667 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); | |
| 6668 if (lookup->IsField()) { | |
| 6669 return lookup->GetLocalFieldIndexFromMap(*type); | |
| 6670 } else { | |
| 6671 Map* transition = lookup->GetTransitionMapFromMap(*type); | |
| 6672 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | |
| 6673 } | |
| 6674 } | |
| 6675 | |
| 6676 | |
| 6677 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { | 6693 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { |
| 6678 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6694 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 6679 AddInstruction(HCheckMaps::New(object, map, zone())); | 6695 AddInstruction(HCheckMaps::New(object, map, zone())); |
| 6680 } | 6696 } |
| 6681 | 6697 |
| 6682 | 6698 |
| 6683 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, | 6699 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
| 6684 Handle<Map> map) { | 6700 Handle<Map> map) { |
| 6685 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6701 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 6686 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | 6702 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 6717 } | 6733 } |
| 6718 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 6734 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
| 6719 } | 6735 } |
| 6720 ASSERT(proto->IsJSObject()); | 6736 ASSERT(proto->IsJSObject()); |
| 6721 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6737 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 6722 Handle<JSObject>(JSObject::cast(map->prototype())), | 6738 Handle<JSObject>(JSObject::cast(map->prototype())), |
| 6723 Handle<JSObject>(JSObject::cast(proto)), | 6739 Handle<JSObject>(JSObject::cast(proto)), |
| 6724 zone())); | 6740 zone())); |
| 6725 } | 6741 } |
| 6726 | 6742 |
| 6727 int index = ComputeLoadStoreFieldIndex(map, name, lookup); | 6743 ObjectAccess access = AccessField(map, name, lookup); |
| 6728 bool is_in_object = index < 0; | 6744 HStoreNamedField* instr = new(zone()) HStoreNamedField(object, access, value); |
| 6729 int offset = index * kPointerSize; | |
| 6730 if (index < 0) { | |
| 6731 // Negative property indices are in-object properties, indexed | |
| 6732 // from the end of the fixed part of the object. | |
| 6733 offset += map->instance_size(); | |
| 6734 } else { | |
| 6735 offset += FixedArray::kHeaderSize; | |
| 6736 } | |
| 6737 HStoreNamedField* instr = | |
| 6738 new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); | |
| 6739 if (lookup->IsTransitionToField(*map)) { | 6745 if (lookup->IsTransitionToField(*map)) { |
| 6740 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 6746 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 6741 instr->set_transition(transition); | 6747 instr->set_transition(transition); |
| 6742 // TODO(fschneider): Record the new map type of the object in the IR to | 6748 // TODO(fschneider): Record the new map type of the object in the IR to |
| 6743 // enable elimination of redundant checks after the transition store. | 6749 // enable elimination of redundant checks after the transition store. |
| 6744 instr->SetGVNFlag(kChangesMaps); | 6750 instr->SetGVNFlag(kChangesMaps); |
| 6745 } | 6751 } |
| 6746 return instr; | 6752 return instr; |
| 6747 } | 6753 } |
| 6748 | 6754 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6800 | 6806 |
| 6801 for (int i = 0; i < types->length(); i++) { | 6807 for (int i = 0; i < types->length(); i++) { |
| 6802 if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false; | 6808 if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false; |
| 6803 } | 6809 } |
| 6804 | 6810 |
| 6805 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6811 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 6806 | 6812 |
| 6807 HInstruction* typecheck = | 6813 HInstruction* typecheck = |
| 6808 AddInstruction(HCheckMaps::New(object, types, zone())); | 6814 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 6809 HInstruction* instr = | 6815 HInstruction* instr = |
| 6810 HLoadNamedField::NewArrayLength(zone(), object, typecheck); | 6816 new(zone()) HLoadNamedField(object, AccessArrayLength(), typecheck); |
| 6817 | |
| 6811 instr->set_position(expr->position()); | 6818 instr->set_position(expr->position()); |
| 6812 ast_context()->ReturnInstruction(instr, expr->id()); | 6819 ast_context()->ReturnInstruction(instr, expr->id()); |
| 6813 return true; | 6820 return true; |
| 6814 } | 6821 } |
| 6815 | 6822 |
| 6816 | 6823 |
| 6817 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 6824 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
| 6818 HValue* object, | 6825 HValue* object, |
| 6819 SmallMapList* types, | 6826 SmallMapList* types, |
| 6820 Handle<String> name) { | 6827 Handle<String> name) { |
| 6821 int count = 0; | 6828 int count = 0; |
| 6822 int previous_field_offset = 0; | 6829 int previous_field_offset = 0; |
| 6823 bool previous_field_is_in_object = false; | 6830 bool previous_field_is_in_object = false; |
| 6824 bool is_monomorphic_field = true; | 6831 bool is_monomorphic_field = true; |
| 6825 | 6832 |
| 6826 if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) | 6833 if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) |
| 6827 return; | 6834 return; |
| 6828 | 6835 |
| 6829 Handle<Map> map; | 6836 Handle<Map> map; |
| 6830 LookupResult lookup(isolate()); | 6837 LookupResult lookup(isolate()); |
| 6831 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 6838 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 6832 map = types->at(i); | 6839 map = types->at(i); |
| 6833 if (ComputeLoadStoreField(map, name, &lookup, false)) { | 6840 if (ComputeLoadStoreField(map, name, &lookup, false)) { |
| 6834 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); | 6841 ObjectAccess access = AccessField(map, name, &lookup); |
| 6835 bool is_in_object = index < 0; | |
| 6836 int offset = index * kPointerSize; | |
| 6837 if (index < 0) { | |
| 6838 // Negative property indices are in-object properties, indexed | |
| 6839 // from the end of the fixed part of the object. | |
| 6840 offset += map->instance_size(); | |
| 6841 } else { | |
| 6842 offset += FixedArray::kHeaderSize; | |
| 6843 } | |
| 6844 if (count == 0) { | 6842 if (count == 0) { |
| 6845 previous_field_offset = offset; | 6843 previous_field_offset = access.offset(); |
| 6846 previous_field_is_in_object = is_in_object; | 6844 previous_field_is_in_object = access.IsInobject(); |
| 6847 } else if (is_monomorphic_field) { | 6845 } else if (is_monomorphic_field) { |
| 6848 is_monomorphic_field = (offset == previous_field_offset) && | 6846 // TODO(titzer): just break out of this loop if not the same |
| 6849 (is_in_object == previous_field_is_in_object); | 6847 is_monomorphic_field = |
| 6848 (access.offset() == previous_field_offset) && | |
| 6849 (access.IsInobject() == previous_field_is_in_object); | |
| 6850 } | 6850 } |
| 6851 ++count; | 6851 ++count; |
| 6852 } | 6852 } |
| 6853 } | 6853 } |
| 6854 | 6854 |
| 6855 // Use monomorphic load if property lookup results in the same field index | 6855 // Use monomorphic load if property lookup results in the same field index |
| 6856 // for all maps. Requires special map check on the set of all handled maps. | 6856 // for all maps. Requires special map check on the set of all handled maps. |
| 6857 AddInstruction(new(zone()) HCheckNonSmi(object)); | 6857 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 6858 HInstruction* instr; | 6858 HInstruction* instr; |
| 6859 if (count == types->length() && is_monomorphic_field) { | 6859 if (count == types->length() && is_monomorphic_field) { |
| 6860 AddInstruction(HCheckMaps::New(object, types, zone())); | 6860 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 6861 instr = BuildLoadNamedField(object, map, &lookup); | 6861 instr = new(zone()) |
| 6862 HLoadNamedField(object, AccessField(map, name, &lookup)); | |
| 6862 } else { | 6863 } else { |
| 6863 HValue* context = environment()->LookupContext(); | 6864 HValue* context = environment()->LookupContext(); |
| 6864 instr = new(zone()) HLoadNamedFieldPolymorphic(context, | 6865 instr = new(zone()) |
| 6865 object, | 6866 HLoadNamedFieldPolymorphic(context, object, types, name, zone()); |
| 6866 types, | |
| 6867 name, | |
| 6868 zone()); | |
| 6869 } | 6867 } |
| 6870 | 6868 |
| 6871 instr->set_position(expr->position()); | 6869 instr->set_position(expr->position()); |
| 6872 return ast_context()->ReturnInstruction(instr, expr->id()); | 6870 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 6873 } | 6871 } |
| 6874 | 6872 |
| 6875 | 6873 |
| 6876 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 6874 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 6877 Assignment* expr, | 6875 Assignment* expr, |
| 6878 HValue* object, | 6876 HValue* object, |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7411 HValue* value = environment()->Pop(); | 7409 HValue* value = environment()->Pop(); |
| 7412 HThrow* instr = new(zone()) HThrow(context, value); | 7410 HThrow* instr = new(zone()) HThrow(context, value); |
| 7413 instr->set_position(expr->position()); | 7411 instr->set_position(expr->position()); |
| 7414 AddInstruction(instr); | 7412 AddInstruction(instr); |
| 7415 AddSimulate(expr->id()); | 7413 AddSimulate(expr->id()); |
| 7416 current_block()->FinishExit(new(zone()) HAbnormalExit); | 7414 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 7417 set_current_block(NULL); | 7415 set_current_block(NULL); |
| 7418 } | 7416 } |
| 7419 | 7417 |
| 7420 | 7418 |
| 7421 HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField( | |
| 7422 HValue* object, | |
| 7423 Handle<Map> map, | |
| 7424 LookupResult* lookup) { | |
| 7425 int index = lookup->GetLocalFieldIndexFromMap(*map); | |
| 7426 if (index < 0) { | |
| 7427 // Negative property indices are in-object properties, indexed | |
| 7428 // from the end of the fixed part of the object. | |
| 7429 int offset = (index * kPointerSize) + map->instance_size(); | |
| 7430 return new(zone()) HLoadNamedField(object, true, offset); | |
| 7431 } else { | |
| 7432 // Non-negative property indices are in the properties array. | |
| 7433 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | |
| 7434 return new(zone()) HLoadNamedField(object, false, offset); | |
| 7435 } | |
| 7436 } | |
| 7437 | |
| 7438 | |
| 7439 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 7419 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 7440 HValue* object, | 7420 HValue* object, |
| 7441 Handle<String> name, | 7421 Handle<String> name, |
| 7442 Property* expr) { | 7422 Property* expr) { |
| 7443 if (expr->IsUninitialized()) { | 7423 if (expr->IsUninitialized()) { |
| 7444 AddSoftDeoptimize(); | 7424 AddSoftDeoptimize(); |
| 7445 } | 7425 } |
| 7446 HValue* context = environment()->LookupContext(); | 7426 HValue* context = environment()->LookupContext(); |
| 7447 return new(zone()) HLoadNamedGeneric(context, object, name); | 7427 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 7448 } | 7428 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 7464 Handle<String> name, | 7444 Handle<String> name, |
| 7465 Property* expr, | 7445 Property* expr, |
| 7466 Handle<Map> map) { | 7446 Handle<Map> map) { |
| 7467 // Handle a load from a known field. | 7447 // Handle a load from a known field. |
| 7468 ASSERT(!map->is_dictionary_map()); | 7448 ASSERT(!map->is_dictionary_map()); |
| 7469 | 7449 |
| 7470 // Handle access to various length properties | 7450 // Handle access to various length properties |
| 7471 if (name->Equals(isolate()->heap()->length_string())) { | 7451 if (name->Equals(isolate()->heap()->length_string())) { |
| 7472 if (map->instance_type() == JS_ARRAY_TYPE) { | 7452 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 7473 AddCheckMapsWithTransitions(object, map); | 7453 AddCheckMapsWithTransitions(object, map); |
| 7474 return HLoadNamedField::NewArrayLength(zone(), object, object); | 7454 return new(zone()) HLoadNamedField(object, AccessArrayLength()); |
| 7475 } | 7455 } |
| 7476 } | 7456 } |
| 7477 | 7457 |
| 7478 LookupResult lookup(isolate()); | 7458 LookupResult lookup(isolate()); |
| 7479 map->LookupDescriptor(NULL, *name, &lookup); | 7459 map->LookupDescriptor(NULL, *name, &lookup); |
| 7480 if (lookup.IsField()) { | 7460 if (lookup.IsField()) { |
| 7481 AddCheckMap(object, map); | 7461 AddCheckMap(object, map); |
| 7482 return BuildLoadNamedField(object, map, &lookup); | 7462 return new(zone()) HLoadNamedField(object, AccessField(map, name, &lookup)); |
| 7483 } | 7463 } |
| 7484 | 7464 |
| 7485 // Handle a load of a constant known function. | 7465 // Handle a load of a constant known function. |
| 7486 if (lookup.IsConstantFunction()) { | 7466 if (lookup.IsConstantFunction()) { |
| 7487 AddCheckMap(object, map); | 7467 AddCheckMap(object, map); |
| 7488 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 7468 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
| 7489 return new(zone()) HConstant(function, Representation::Tagged()); | 7469 return new(zone()) HConstant(function, Representation::Tagged()); |
| 7490 } | 7470 } |
| 7491 | 7471 |
| 7492 // Handle a load from a known field somewhere in the prototype chain. | 7472 // Handle a load from a known field somewhere in the prototype chain. |
| 7493 LookupInPrototypes(map, name, &lookup); | 7473 LookupInPrototypes(map, name, &lookup); |
| 7494 if (lookup.IsField()) { | 7474 if (lookup.IsField()) { |
| 7495 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7475 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7496 Handle<JSObject> holder(lookup.holder()); | 7476 Handle<JSObject> holder(lookup.holder()); |
| 7497 Handle<Map> holder_map(holder->map()); | 7477 Handle<Map> holder_map(holder->map()); |
| 7498 AddCheckMap(object, map); | 7478 AddCheckMap(object, map); |
| 7499 AddInstruction( | 7479 AddInstruction(new(zone()) |
| 7500 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7480 HCheckPrototypeMaps(prototype, holder, zone())); |
| 7501 HValue* holder_value = AddInstruction( | 7481 HValue* holder_value = AddInstruction(new(zone()) |
| 7502 new(zone()) HConstant(holder, Representation::Tagged())); | 7482 HConstant(holder, Representation::Tagged())); |
| 7503 return BuildLoadNamedField(holder_value, holder_map, &lookup); | 7483 return new(zone()) |
| 7484 HLoadNamedField(holder_value, AccessField(holder_map, name, &lookup)); | |
| 7504 } | 7485 } |
| 7505 | 7486 |
| 7506 // Handle a load of a constant function somewhere in the prototype chain. | 7487 // Handle a load of a constant function somewhere in the prototype chain. |
| 7507 if (lookup.IsConstantFunction()) { | 7488 if (lookup.IsConstantFunction()) { |
| 7508 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7489 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7509 Handle<JSObject> holder(lookup.holder()); | 7490 Handle<JSObject> holder(lookup.holder()); |
| 7510 Handle<Map> holder_map(holder->map()); | 7491 Handle<Map> holder_map(holder->map()); |
| 7511 AddCheckMap(object, map); | 7492 AddCheckMap(object, map); |
| 7512 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7493 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); |
| 7513 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 7494 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7757 // it's a keyed property) and registered in the full codegen. | 7738 // it's a keyed property) and registered in the full codegen. |
| 7758 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 7739 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
| 7759 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 7740 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
| 7760 HHasInstanceTypeAndBranch* typecheck = | 7741 HHasInstanceTypeAndBranch* typecheck = |
| 7761 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 7742 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
| 7762 typecheck->SetSuccessorAt(0, if_jsarray); | 7743 typecheck->SetSuccessorAt(0, if_jsarray); |
| 7763 typecheck->SetSuccessorAt(1, if_fastobject); | 7744 typecheck->SetSuccessorAt(1, if_fastobject); |
| 7764 current_block()->Finish(typecheck); | 7745 current_block()->Finish(typecheck); |
| 7765 | 7746 |
| 7766 set_current_block(if_jsarray); | 7747 set_current_block(if_jsarray); |
| 7767 HInstruction* length; | 7748 HInstruction* length = AddInstruction(new(zone()) |
| 7768 length = AddInstruction( | 7749 HLoadNamedField(object, AccessArrayLength(), typecheck)); |
| 7769 HLoadNamedField::NewArrayLength(zone(), object, typecheck, | 7750 length->set_type(HType::Smi()); |
| 7770 HType::Smi())); | 7751 |
| 7771 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 7752 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
| 7772 access = AddInstruction(BuildFastElementAccess( | 7753 access = AddInstruction(BuildFastElementAccess( |
| 7773 elements, checked_key, val, elements_kind_branch, | 7754 elements, checked_key, val, elements_kind_branch, |
| 7774 elements_kind, is_store, STANDARD_STORE)); | 7755 elements_kind, is_store, STANDARD_STORE)); |
| 7775 if (!is_store) { | 7756 if (!is_store) { |
| 7776 Push(access); | 7757 Push(access); |
| 7777 } | 7758 } |
| 7778 | 7759 |
| 7779 *has_side_effects |= access->HasObservableSideEffects(); | 7760 *has_side_effects |= access->HasObservableSideEffects(); |
| 7780 // The caller will use has_side_effects and add correct Simulate. | 7761 // The caller will use has_side_effects and add correct Simulate. |
| (...skipping 2633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10414 Handle<Object> value = | 10395 Handle<Object> value = |
| 10415 Handle<Object>(boilerplate_object->InObjectPropertyAt(i), | 10396 Handle<Object>(boilerplate_object->InObjectPropertyAt(i), |
| 10416 isolate()); | 10397 isolate()); |
| 10417 if (value->IsJSObject()) { | 10398 if (value->IsJSObject()) { |
| 10418 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 10399 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 10419 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 10400 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
| 10420 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(i), | 10401 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(i), |
| 10421 isolate())); | 10402 isolate())); |
| 10422 HInstruction* value_instruction = | 10403 HInstruction* value_instruction = |
| 10423 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 10404 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); |
| 10424 AddInstruction(new(zone) HStoreNamedField( | 10405 |
| 10425 object_properties, factory->unknown_field_string(), value_instruction, | 10406 ObjectAccess access = AccessInobject(factory->unknown_field_string(), |
| 10426 true, boilerplate_object->GetInObjectPropertyOffset(i))); | 10407 boilerplate_object->GetInObjectPropertyOffset(i)); |
| 10408 AddStore(object_properties, access, value_instruction); | |
| 10409 | |
| 10427 BuildEmitDeepCopy(value_object, original_value_object, target, | 10410 BuildEmitDeepCopy(value_object, original_value_object, target, |
| 10428 offset, DONT_TRACK_ALLOCATION_SITE); | 10411 offset, DONT_TRACK_ALLOCATION_SITE); |
| 10429 } else { | 10412 } else { |
| 10430 HInstruction* value_instruction = AddInstruction(new(zone) HConstant( | 10413 HInstruction* value_instruction = AddInstruction(new(zone) HConstant( |
| 10431 value, Representation::Tagged())); | 10414 value, Representation::Tagged())); |
| 10432 AddInstruction(new(zone) HStoreNamedField( | 10415 |
| 10433 object_properties, factory->unknown_field_string(), value_instruction, | 10416 ObjectAccess access = AccessInobject(factory->unknown_field_string(), |
| 10434 true, boilerplate_object->GetInObjectPropertyOffset(i))); | 10417 boilerplate_object->GetInObjectPropertyOffset(i)); |
| 10418 AddStore(object_properties, access, value_instruction); | |
| 10435 } | 10419 } |
| 10436 } | 10420 } |
| 10437 | 10421 |
| 10438 // Build Allocation Site Info if desired | 10422 // Build Allocation Site Info if desired |
| 10439 if (create_allocation_site_info) { | 10423 if (create_allocation_site_info) { |
| 10440 HValue* alloc_site = | 10424 HValue* alloc_site = |
| 10441 AddInstruction(new(zone) HInnerAllocatedObject(target, JSArray::kSize)); | 10425 AddInstruction(new(zone) HInnerAllocatedObject(target, JSArray::kSize)); |
| 10442 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); | 10426 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); |
| 10443 BuildStoreMap(alloc_site, alloc_site_map); | 10427 HValue* alloc_site_map_constant = AddInstruction(new(zone) |
| 10444 int alloc_payload_offset = AllocationSiteInfo::kPayloadOffset; | 10428 HConstant(alloc_site_map, Representation::Tagged())); |
| 10445 AddInstruction(new(zone) HStoreNamedField(alloc_site, | 10429 AddStore(alloc_site, AccessMap(), alloc_site_map_constant); |
| 10446 factory->payload_string(), | 10430 ObjectAccess access = AccessInobject( |
| 10447 original_boilerplate, | 10431 factory->payload_string(), AllocationSiteInfo::kPayloadOffset); |
| 10448 true, alloc_payload_offset)); | 10432 AddStore(alloc_site, access, original_boilerplate); |
| 10449 } | 10433 } |
| 10450 | 10434 |
| 10451 if (object_elements != NULL) { | 10435 if (object_elements != NULL) { |
| 10452 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( | 10436 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( |
| 10453 elements, Representation::Tagged())); | 10437 elements, Representation::Tagged())); |
| 10454 | 10438 |
| 10455 int elements_length = elements->length(); | 10439 int elements_length = elements->length(); |
| 10456 HValue* object_elements_length = | 10440 HValue* object_elements_length = |
| 10457 AddInstruction(new(zone) HConstant( | 10441 AddInstruction(new(zone) HConstant( |
| 10458 elements_length, Representation::Integer32())); | 10442 elements_length, Representation::Integer32())); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10510 int elements_offset, | 10494 int elements_offset, |
| 10511 int elements_size) { | 10495 int elements_size) { |
| 10512 ASSERT(boilerplate_object->properties()->length() == 0); | 10496 ASSERT(boilerplate_object->properties()->length() == 0); |
| 10513 Zone* zone = this->zone(); | 10497 Zone* zone = this->zone(); |
| 10514 Factory* factory = isolate()->factory(); | 10498 Factory* factory = isolate()->factory(); |
| 10515 HValue* result = NULL; | 10499 HValue* result = NULL; |
| 10516 | 10500 |
| 10517 HValue* object_header = | 10501 HValue* object_header = |
| 10518 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); | 10502 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); |
| 10519 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 10503 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
| 10520 BuildStoreMap(object_header, boilerplate_object_map); | 10504 HValue* boilerplate_object_map_constant = AddInstruction(new(zone) |
| 10505 HConstant(boilerplate_object_map, Representation::Tagged())); | |
| 10506 AddStore(object_header, AccessMap(), boilerplate_object_map_constant); | |
| 10521 | 10507 |
| 10522 HInstruction* elements; | 10508 HInstruction* elements; |
| 10523 if (elements_size == 0) { | 10509 if (elements_size == 0) { |
| 10524 Handle<Object> elements_field = | 10510 Handle<Object> elements_field = |
| 10525 Handle<Object>(boilerplate_object->elements(), isolate()); | 10511 Handle<Object>(boilerplate_object->elements(), isolate()); |
| 10526 elements = AddInstruction(new(zone) HConstant( | 10512 elements = AddInstruction(new(zone) HConstant( |
| 10527 elements_field, Representation::Tagged())); | 10513 elements_field, Representation::Tagged())); |
| 10528 } else { | 10514 } else { |
| 10529 elements = AddInstruction(new(zone) HInnerAllocatedObject( | 10515 elements = AddInstruction(new(zone) HInnerAllocatedObject( |
| 10530 target, elements_offset)); | 10516 target, elements_offset)); |
| 10531 result = elements; | 10517 result = elements; |
| 10532 } | 10518 } |
| 10533 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( | 10519 AddStore(object_header, AccessElements(), elements); |
| 10534 object_header, | |
| 10535 factory->elements_field_string(), | |
| 10536 elements, | |
| 10537 true, JSObject::kElementsOffset)); | |
| 10538 elements_store->SetGVNFlag(kChangesElementsPointer); | |
| 10539 | 10520 |
| 10540 Handle<Object> properties_field = | 10521 Handle<Object> properties_field = |
| 10541 Handle<Object>(boilerplate_object->properties(), isolate()); | 10522 Handle<Object>(boilerplate_object->properties(), isolate()); |
| 10542 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 10523 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
| 10543 HInstruction* properties = AddInstruction(new(zone) HConstant( | 10524 HInstruction* properties = AddInstruction(new(zone) HConstant( |
| 10544 properties_field, Representation::None())); | 10525 properties_field, Representation::None())); |
| 10545 AddInstruction(new(zone) HStoreNamedField(object_header, | 10526 ObjectAccess access = AccessInobject( |
| 10546 factory->empty_string(), | 10527 factory->empty_string(), JSObject::kPropertiesOffset); |
| 10547 properties, | 10528 AddStore(object_header, access, properties); |
| 10548 true, JSObject::kPropertiesOffset)); | |
| 10549 | 10529 |
| 10550 if (boilerplate_object->IsJSArray()) { | 10530 if (boilerplate_object->IsJSArray()) { |
| 10551 Handle<JSArray> boilerplate_array = | 10531 Handle<JSArray> boilerplate_array = |
| 10552 Handle<JSArray>::cast(boilerplate_object); | 10532 Handle<JSArray>::cast(boilerplate_object); |
| 10553 Handle<Object> length_field = | 10533 Handle<Object> length_field = |
| 10554 Handle<Object>(boilerplate_array->length(), isolate()); | 10534 Handle<Object>(boilerplate_array->length(), isolate()); |
| 10555 HInstruction* length = AddInstruction(new(zone) HConstant( | 10535 HInstruction* length = AddInstruction(new(zone) HConstant( |
| 10556 length_field, Representation::None())); | 10536 length_field, Representation::None())); |
| 10557 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( | 10537 AddStore(object_header, AccessArrayLength(), length); |
| 10558 object_header, | |
| 10559 factory->length_field_string(), | |
| 10560 length, | |
| 10561 true, JSArray::kLengthOffset)); | |
| 10562 length_store->SetGVNFlag(kChangesArrayLengths); | |
| 10563 } | 10538 } |
| 10564 | 10539 |
| 10565 return result; | 10540 return result; |
| 10566 } | 10541 } |
| 10567 | 10542 |
| 10568 | 10543 |
| 10569 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 10544 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 10570 ASSERT(!HasStackOverflow()); | 10545 ASSERT(!HasStackOverflow()); |
| 10571 ASSERT(current_block() != NULL); | 10546 ASSERT(current_block() != NULL); |
| 10572 ASSERT(current_block()->HasPredecessor()); | 10547 ASSERT(current_block()->HasPredecessor()); |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10940 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); | 10915 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); |
| 10941 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); | 10916 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); |
| 10942 typecheck->SetSuccessorAt(0, if_js_value); | 10917 typecheck->SetSuccessorAt(0, if_js_value); |
| 10943 typecheck->SetSuccessorAt(1, not_js_value); | 10918 typecheck->SetSuccessorAt(1, not_js_value); |
| 10944 current_block()->Finish(typecheck); | 10919 current_block()->Finish(typecheck); |
| 10945 not_js_value->Goto(join); | 10920 not_js_value->Goto(join); |
| 10946 | 10921 |
| 10947 // Create in-object property store to kValueOffset. | 10922 // Create in-object property store to kValueOffset. |
| 10948 set_current_block(if_js_value); | 10923 set_current_block(if_js_value); |
| 10949 Handle<String> name = isolate()->factory()->undefined_string(); | 10924 Handle<String> name = isolate()->factory()->undefined_string(); |
| 10950 AddInstruction(new(zone()) HStoreNamedField(object, | 10925 AddStore(object, AccessInobject(name, JSValue::kValueOffset), value); |
| 10951 name, | |
| 10952 value, | |
| 10953 true, // in-object store. | |
| 10954 JSValue::kValueOffset)); | |
| 10955 if_js_value->Goto(join); | 10926 if_js_value->Goto(join); |
| 10956 join->SetJoinId(call->id()); | 10927 join->SetJoinId(call->id()); |
| 10957 set_current_block(join); | 10928 set_current_block(join); |
| 10958 return ast_context()->ReturnValue(value); | 10929 return ast_context()->ReturnValue(value); |
| 10959 } | 10930 } |
| 10960 | 10931 |
| 10961 | 10932 |
| 10962 // Fast support for charCodeAt(n). | 10933 // Fast support for charCodeAt(n). |
| 10963 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 10934 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
| 10964 ASSERT(call->arguments()->length() == 2); | 10935 ASSERT(call->arguments()->length() == 2); |
| (...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11919 } | 11890 } |
| 11920 } | 11891 } |
| 11921 | 11892 |
| 11922 #ifdef DEBUG | 11893 #ifdef DEBUG |
| 11923 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11894 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11924 if (allocator_ != NULL) allocator_->Verify(); | 11895 if (allocator_ != NULL) allocator_->Verify(); |
| 11925 #endif | 11896 #endif |
| 11926 } | 11897 } |
| 11927 | 11898 |
| 11928 } } // namespace v8::internal | 11899 } } // namespace v8::internal |
| OLD | NEW |