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 |