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 1176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1187 | 1187 |
| 1188 environment()->Push(elements); | 1188 environment()->Push(elements); |
| 1189 capacity_checker.End(); | 1189 capacity_checker.End(); |
| 1190 | 1190 |
| 1191 if (is_js_array) { | 1191 if (is_js_array) { |
| 1192 HValue* new_length = AddInstruction( | 1192 HValue* new_length = AddInstruction( |
| 1193 HAdd::New(zone, context, length, graph_->GetConstant1())); | 1193 HAdd::New(zone, context, length, graph_->GetConstant1())); |
| 1194 new_length->AssumeRepresentation(Representation::Integer32()); | 1194 new_length->AssumeRepresentation(Representation::Integer32()); |
| 1195 new_length->ClearFlag(HValue::kCanOverflow); | 1195 new_length->ClearFlag(HValue::kCanOverflow); |
| 1196 | 1196 |
| 1197 Factory* factory = isolate()->factory(); | |
| 1198 Representation representation = IsFastElementsKind(kind) | 1197 Representation representation = IsFastElementsKind(kind) |
| 1199 ? Representation::Smi() : Representation::Tagged(); | 1198 ? Representation::Smi() : Representation::Tagged(); |
| 1200 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( | 1199 AddStore(object, HObjectAccess::ForArrayLength(), new_length, |
| 1201 object, | 1200 representation); |
| 1202 factory->length_field_string(), | |
| 1203 new_length, true, | |
| 1204 representation, | |
| 1205 JSArray::kLengthOffset)); | |
| 1206 length_store->SetGVNFlag(kChangesArrayLengths); | |
| 1207 } | 1201 } |
| 1208 | 1202 |
| 1209 length_checker.Else(); | 1203 length_checker.Else(); |
| 1210 | 1204 |
| 1211 AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 1205 AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
| 1212 environment()->Push(elements); | 1206 environment()->Push(elements); |
| 1213 | 1207 |
| 1214 length_checker.End(); | 1208 length_checker.End(); |
| 1215 | 1209 |
| 1216 return environment()->Pop(); | 1210 return environment()->Pop(); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1277 HValue* elements = AddLoadElements(object, mapcheck); | 1271 HValue* elements = AddLoadElements(object, mapcheck); |
| 1278 if (is_store && (fast_elements || fast_smi_only_elements) && | 1272 if (is_store && (fast_elements || fast_smi_only_elements) && |
| 1279 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1273 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 1280 HCheckMaps* check_cow_map = HCheckMaps::New( | 1274 HCheckMaps* check_cow_map = HCheckMaps::New( |
| 1281 elements, isolate()->factory()->fixed_array_map(), zone); | 1275 elements, isolate()->factory()->fixed_array_map(), zone); |
| 1282 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1276 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1283 AddInstruction(check_cow_map); | 1277 AddInstruction(check_cow_map); |
| 1284 } | 1278 } |
| 1285 HInstruction* length = NULL; | 1279 HInstruction* length = NULL; |
| 1286 if (is_js_array) { | 1280 if (is_js_array) { |
| 1287 length = AddInstruction( | 1281 length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck, |
| 1288 HLoadNamedField::NewArrayLength(zone, object, mapcheck, HType::Smi())); | 1282 Representation::Smi()); |
| 1283 length->set_type(HType::Smi()); | |
| 1289 } else { | 1284 } else { |
| 1290 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 1285 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
| 1291 } | 1286 } |
| 1292 HValue* checked_key = NULL; | 1287 HValue* checked_key = NULL; |
| 1293 if (IsExternalArrayElementsKind(elements_kind)) { | 1288 if (IsExternalArrayElementsKind(elements_kind)) { |
| 1294 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1289 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 1295 NoObservableSideEffectsScope no_effects(this); | 1290 NoObservableSideEffectsScope no_effects(this); |
| 1296 HLoadExternalArrayPointer* external_elements = | 1291 HLoadExternalArrayPointer* external_elements = |
| 1297 new(zone) HLoadExternalArrayPointer(elements); | 1292 new(zone) HLoadExternalArrayPointer(elements); |
| 1298 AddInstruction(external_elements); | 1293 AddInstruction(external_elements); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1404 HValue* elements = | 1399 HValue* elements = |
| 1405 AddInstruction(new(zone) HAllocate(context, total_size, | 1400 AddInstruction(new(zone) HAllocate(context, total_size, |
| 1406 HType::JSArray(), flags)); | 1401 HType::JSArray(), flags)); |
| 1407 return elements; | 1402 return elements; |
| 1408 } | 1403 } |
| 1409 | 1404 |
| 1410 | 1405 |
| 1411 void HGraphBuilder::BuildInitializeElements(HValue* elements, | 1406 void HGraphBuilder::BuildInitializeElements(HValue* elements, |
| 1412 ElementsKind kind, | 1407 ElementsKind kind, |
| 1413 HValue* capacity) { | 1408 HValue* capacity) { |
| 1414 Zone* zone = this->zone(); | |
| 1415 Factory* factory = isolate()->factory(); | 1409 Factory* factory = isolate()->factory(); |
| 1416 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1410 Handle<Map> map = IsFastDoubleElementsKind(kind) |
| 1417 ? factory->fixed_double_array_map() | 1411 ? factory->fixed_double_array_map() |
| 1418 : factory->fixed_array_map(); | 1412 : factory->fixed_array_map(); |
| 1419 BuildStoreMap(elements, map); | |
| 1420 | 1413 |
| 1421 Handle<String> fixed_array_length_field_name = factory->length_field_string(); | 1414 AddStoreMapConstant(elements, map); |
| 1422 Representation representation = IsFastElementsKind(kind) | 1415 Representation representation = IsFastElementsKind(kind) |
| 1423 ? Representation::Smi() : Representation::Tagged(); | 1416 ? Representation::Smi() : Representation::Tagged(); |
| 1424 HInstruction* store_length = | 1417 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity, |
| 1425 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, | 1418 representation); |
| 1426 capacity, true, representation, | |
| 1427 FixedArray::kLengthOffset); | |
| 1428 AddInstruction(store_length); | |
| 1429 } | 1419 } |
| 1430 | 1420 |
| 1431 | 1421 |
| 1432 HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, | 1422 HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, |
| 1433 ElementsKind kind, | 1423 ElementsKind kind, |
| 1434 HValue* capacity) { | 1424 HValue* capacity) { |
| 1435 HValue* new_elements = BuildAllocateElements(context, kind, capacity); | 1425 HValue* new_elements = BuildAllocateElements(context, kind, capacity); |
| 1436 BuildInitializeElements(new_elements, kind, capacity); | 1426 BuildInitializeElements(new_elements, kind, capacity); |
| 1437 return new_elements; | 1427 return new_elements; |
| 1438 } | 1428 } |
| 1439 | 1429 |
| 1440 | 1430 |
| 1441 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 1431 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
| 1442 HValue* array_map, | 1432 HValue* array_map, |
| 1443 AllocationSiteMode mode, | 1433 AllocationSiteMode mode, |
| 1444 HValue* allocation_site_payload, | 1434 HValue* allocation_site_payload, |
| 1445 HValue* length_field) { | 1435 HValue* length_field) { |
| 1446 | 1436 |
| 1447 BuildStoreMap(array, array_map); | 1437 AddStore(array, HObjectAccess::ForMap(), array_map); |
| 1448 | 1438 |
| 1449 HConstant* empty_fixed_array = | 1439 HConstant* empty_fixed_array = |
| 1450 new(zone()) HConstant( | 1440 new(zone()) HConstant( |
| 1451 Handle<FixedArray>(isolate()->heap()->empty_fixed_array()), | 1441 Handle<FixedArray>(isolate()->heap()->empty_fixed_array()), |
| 1452 Representation::Tagged()); | 1442 Representation::Tagged()); |
| 1453 AddInstruction(empty_fixed_array); | 1443 AddInstruction(empty_fixed_array); |
| 1454 | 1444 |
| 1455 AddInstruction(new(zone()) HStoreNamedField(array, | 1445 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 1456 isolate()->factory()->properties_field_symbol(), | 1446 AddStore(array, access, empty_fixed_array); |
| 1457 empty_fixed_array, | 1447 AddStore(array, HObjectAccess::ForArrayLength(), length_field); |
| 1458 true, | |
| 1459 Representation::Tagged(), | |
| 1460 JSArray::kPropertiesOffset)); | |
| 1461 | |
| 1462 HInstruction* length_store = AddInstruction( | |
| 1463 new(zone()) HStoreNamedField(array, | |
| 1464 isolate()->factory()->length_field_string(), | |
| 1465 length_field, | |
| 1466 true, | |
| 1467 Representation::Tagged(), | |
| 1468 JSArray::kLengthOffset)); | |
| 1469 length_store->SetGVNFlag(kChangesArrayLengths); | |
| 1470 | 1448 |
| 1471 if (mode == TRACK_ALLOCATION_SITE) { | 1449 if (mode == TRACK_ALLOCATION_SITE) { |
| 1472 BuildCreateAllocationSiteInfo(array, | 1450 BuildCreateAllocationSiteInfo(array, |
| 1473 JSArray::kSize, | 1451 JSArray::kSize, |
| 1474 allocation_site_payload); | 1452 allocation_site_payload); |
| 1475 } | 1453 } |
| 1476 | 1454 |
| 1477 int elements_location = JSArray::kSize; | 1455 int elements_location = JSArray::kSize; |
| 1478 if (mode == TRACK_ALLOCATION_SITE) { | 1456 if (mode == TRACK_ALLOCATION_SITE) { |
| 1479 elements_location += AllocationSiteInfo::kSize; | 1457 elements_location += AllocationSiteInfo::kSize; |
| 1480 } | 1458 } |
| 1481 | 1459 |
| 1482 HInnerAllocatedObject* elements = new(zone()) HInnerAllocatedObject( | 1460 HInnerAllocatedObject* elements = new(zone()) HInnerAllocatedObject( |
| 1483 array, | 1461 array, elements_location); |
| 1484 elements_location); | |
| 1485 AddInstruction(elements); | 1462 AddInstruction(elements); |
| 1486 | 1463 |
| 1487 HInstruction* elements_store = AddInstruction( | 1464 AddStore(array, HObjectAccess::ForElementsPointer(), elements); |
| 1488 new(zone()) HStoreNamedField( | |
| 1489 array, | |
| 1490 isolate()->factory()->elements_field_string(), | |
| 1491 elements, | |
| 1492 true, | |
| 1493 Representation::Tagged(), | |
| 1494 JSArray::kElementsOffset)); | |
| 1495 elements_store->SetGVNFlag(kChangesElementsPointer); | |
| 1496 | |
| 1497 return elements; | 1465 return elements; |
| 1498 } | 1466 } |
| 1499 | 1467 |
| 1500 | 1468 |
| 1501 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | 1469 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
| 1502 HValue* map) { | 1470 HValue* typecheck) { |
| 1503 Zone* zone = this->zone(); | 1471 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); |
| 1504 Factory* factory = isolate()->factory(); | |
| 1505 Handle<String> map_field_name = factory->map_field_string(); | |
| 1506 HInstruction* store_map = | |
| 1507 new(zone) HStoreNamedField(object, map_field_name, map, | |
| 1508 true, Representation::Tagged(), | |
| 1509 JSObject::kMapOffset); | |
| 1510 store_map->ClearGVNFlag(kChangesInobjectFields); | |
| 1511 store_map->SetGVNFlag(kChangesMaps); | |
| 1512 AddInstruction(store_map); | |
| 1513 return store_map; | |
| 1514 } | 1472 } |
| 1515 | 1473 |
| 1516 | 1474 |
| 1517 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | |
| 1518 Handle<Map> map) { | |
| 1519 Zone* zone = this->zone(); | |
| 1520 HValue* map_constant = | |
| 1521 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); | |
| 1522 return BuildStoreMap(object, map_constant); | |
| 1523 } | |
| 1524 | |
| 1525 | |
| 1526 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | |
| 1527 HValue* typecheck) { | |
| 1528 HLoadNamedField* instr = new(zone()) HLoadNamedField(object, true, | |
| 1529 Representation::Tagged(), JSObject::kElementsOffset, typecheck); | |
| 1530 AddInstruction(instr); | |
| 1531 instr->SetGVNFlag(kDependsOnElementsPointer); | |
| 1532 instr->ClearGVNFlag(kDependsOnMaps); | |
| 1533 instr->ClearGVNFlag(kDependsOnInobjectFields); | |
| 1534 return instr; | |
| 1535 } | |
| 1536 | |
| 1537 | |
| 1538 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1475 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
| 1539 HValue* old_capacity) { | 1476 HValue* old_capacity) { |
| 1540 Zone* zone = this->zone(); | 1477 Zone* zone = this->zone(); |
| 1541 HValue* half_old_capacity = | 1478 HValue* half_old_capacity = |
| 1542 AddInstruction(HShr::New(zone, context, old_capacity, | 1479 AddInstruction(HShr::New(zone, context, old_capacity, |
| 1543 graph_->GetConstant1())); | 1480 graph_->GetConstant1())); |
| 1544 half_old_capacity->AssumeRepresentation(Representation::Integer32()); | 1481 half_old_capacity->AssumeRepresentation(Representation::Integer32()); |
| 1545 half_old_capacity->ClearFlag(HValue::kCanOverflow); | 1482 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
| 1546 | 1483 |
| 1547 HValue* new_capacity = AddInstruction( | 1484 HValue* new_capacity = AddInstruction( |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1577 HBoundsCheck(length, max_size_constant, | 1514 HBoundsCheck(length, max_size_constant, |
| 1578 DONT_ALLOW_SMI_KEY, Representation::Integer32())); | 1515 DONT_ALLOW_SMI_KEY, Representation::Integer32())); |
| 1579 } | 1516 } |
| 1580 | 1517 |
| 1581 | 1518 |
| 1582 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 1519 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
| 1583 HValue* elements, | 1520 HValue* elements, |
| 1584 ElementsKind kind, | 1521 ElementsKind kind, |
| 1585 HValue* length, | 1522 HValue* length, |
| 1586 HValue* new_capacity) { | 1523 HValue* new_capacity) { |
| 1587 Zone* zone = this->zone(); | |
| 1588 HValue* context = environment()->LookupContext(); | 1524 HValue* context = environment()->LookupContext(); |
| 1589 | 1525 |
| 1590 BuildNewSpaceArrayCheck(new_capacity, kind); | 1526 BuildNewSpaceArrayCheck(new_capacity, kind); |
| 1591 | 1527 |
| 1592 HValue* new_elements = | 1528 HValue* new_elements = |
| 1593 BuildAllocateAndInitializeElements(context, kind, new_capacity); | 1529 BuildAllocateAndInitializeElements(context, kind, new_capacity); |
| 1594 | 1530 |
| 1595 BuildCopyElements(context, elements, kind, | 1531 BuildCopyElements(context, elements, kind, |
| 1596 new_elements, kind, | 1532 new_elements, kind, |
| 1597 length, new_capacity); | 1533 length, new_capacity); |
| 1598 | 1534 |
| 1599 Factory* factory = isolate()->factory(); | 1535 AddStore(object, HObjectAccess::ForElementsPointer(), new_elements); |
| 1600 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( | |
| 1601 object, | |
| 1602 factory->elements_field_string(), | |
| 1603 new_elements, true, Representation::Tagged(), | |
| 1604 JSArray::kElementsOffset)); | |
| 1605 elements_store->SetGVNFlag(kChangesElementsPointer); | |
| 1606 | 1536 |
| 1607 return new_elements; | 1537 return new_elements; |
| 1608 } | 1538 } |
| 1609 | 1539 |
| 1610 | 1540 |
| 1611 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, | 1541 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, |
| 1612 HValue* elements, | 1542 HValue* elements, |
| 1613 ElementsKind elements_kind, | 1543 ElementsKind elements_kind, |
| 1614 HValue* from, | 1544 HValue* from, |
| 1615 HValue* to) { | 1545 HValue* to) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1700 } | 1630 } |
| 1701 } | 1631 } |
| 1702 | 1632 |
| 1703 | 1633 |
| 1704 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, | 1634 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, |
| 1705 HValue* boilerplate, | 1635 HValue* boilerplate, |
| 1706 AllocationSiteMode mode, | 1636 AllocationSiteMode mode, |
| 1707 ElementsKind kind, | 1637 ElementsKind kind, |
| 1708 int length) { | 1638 int length) { |
| 1709 Zone* zone = this->zone(); | 1639 Zone* zone = this->zone(); |
| 1710 Factory* factory = isolate()->factory(); | |
| 1711 | 1640 |
| 1712 NoObservableSideEffectsScope no_effects(this); | 1641 NoObservableSideEffectsScope no_effects(this); |
| 1713 | 1642 |
| 1714 // All sizes here are multiples of kPointerSize. | 1643 // All sizes here are multiples of kPointerSize. |
| 1715 int size = JSArray::kSize; | 1644 int size = JSArray::kSize; |
| 1716 if (mode == TRACK_ALLOCATION_SITE) { | 1645 if (mode == TRACK_ALLOCATION_SITE) { |
| 1717 size += AllocationSiteInfo::kSize; | 1646 size += AllocationSiteInfo::kSize; |
| 1718 } | 1647 } |
| 1719 int elems_offset = size; | 1648 int elems_offset = size; |
| 1720 if (length > 0) { | 1649 if (length > 0) { |
| 1721 size += IsFastDoubleElementsKind(kind) | 1650 size += IsFastDoubleElementsKind(kind) |
| 1722 ? FixedDoubleArray::SizeFor(length) | 1651 ? FixedDoubleArray::SizeFor(length) |
| 1723 : FixedArray::SizeFor(length); | 1652 : FixedArray::SizeFor(length); |
| 1724 } | 1653 } |
| 1725 | 1654 |
| 1726 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); | 1655 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); |
| 1727 // Allocate both the JS array and the elements array in one big | 1656 // Allocate both the JS array and the elements array in one big |
| 1728 // allocation. This avoids multiple limit checks. | 1657 // allocation. This avoids multiple limit checks. |
| 1729 HValue* size_in_bytes = | 1658 HValue* size_in_bytes = |
| 1730 AddInstruction(new(zone) HConstant(size, Representation::Integer32())); | 1659 AddInstruction(new(zone) HConstant(size, Representation::Integer32())); |
| 1731 HInstruction* object = | 1660 HInstruction* object = |
| 1732 AddInstruction(new(zone) HAllocate(context, | 1661 AddInstruction(new(zone) HAllocate(context, |
| 1733 size_in_bytes, | 1662 size_in_bytes, |
| 1734 HType::JSObject(), | 1663 HType::JSObject(), |
| 1735 allocate_flags)); | 1664 allocate_flags)); |
| 1736 | 1665 |
| 1737 // Copy the JS array part. | 1666 // Copy the JS array part. |
| 1738 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 1667 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 1739 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 1668 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
| 1740 HInstruction* value = AddInstruction(new(zone) HLoadNamedField( | 1669 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
| 1741 boilerplate, true, Representation::Tagged(), i)); | 1670 AddStore(object, access, AddLoad(boilerplate, access)); |
| 1742 if (i != JSArray::kMapOffset) { | |
| 1743 AddInstruction(new(zone) HStoreNamedField(object, | |
| 1744 factory->empty_string(), | |
| 1745 value, true, | |
| 1746 Representation::Tagged(), i)); | |
| 1747 } else { | |
| 1748 BuildStoreMap(object, value); | |
| 1749 } | |
| 1750 } | 1671 } |
| 1751 } | 1672 } |
| 1752 | 1673 |
| 1753 // Create an allocation site info if requested. | 1674 // Create an allocation site info if requested. |
| 1754 if (mode == TRACK_ALLOCATION_SITE) { | 1675 if (mode == TRACK_ALLOCATION_SITE) { |
| 1755 BuildCreateAllocationSiteInfo(object, JSArray::kSize, boilerplate); | 1676 BuildCreateAllocationSiteInfo(object, JSArray::kSize, boilerplate); |
| 1756 } | 1677 } |
| 1757 | 1678 |
| 1758 if (length > 0) { | 1679 if (length > 0) { |
| 1759 // Get hold of the elements array of the boilerplate and setup the | 1680 // Get hold of the elements array of the boilerplate and setup the |
| 1760 // elements pointer in the resulting object. | 1681 // elements pointer in the resulting object. |
| 1761 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 1682 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 1762 HValue* object_elements = | 1683 HValue* object_elements = |
| 1763 AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset)); | 1684 AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset)); |
| 1764 AddInstruction(new(zone) HStoreNamedField(object, | 1685 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements); |
| 1765 factory->elements_field_string(), | |
| 1766 object_elements, true, | |
| 1767 Representation::Tagged(), | |
| 1768 JSObject::kElementsOffset)); | |
| 1769 | 1686 |
| 1770 // Copy the elements array header. | 1687 // Copy the elements array header. |
| 1771 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 1688 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
| 1772 HInstruction* value = | 1689 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
| 1773 AddInstruction(new(zone) HLoadNamedField( | 1690 AddStore(object_elements, access, AddLoad(boilerplate_elements, access)); |
| 1774 boilerplate_elements, true, Representation::Tagged(), i)); | |
| 1775 AddInstruction(new(zone) HStoreNamedField(object_elements, | |
| 1776 factory->empty_string(), | |
| 1777 value, true, | |
| 1778 Representation::Tagged(), i)); | |
| 1779 } | 1691 } |
| 1780 | 1692 |
| 1781 // Copy the elements array contents. | 1693 // Copy the elements array contents. |
| 1782 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold | 1694 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold |
| 1783 // copying loops with constant length up to a given boundary and use this | 1695 // copying loops with constant length up to a given boundary and use this |
| 1784 // helper here instead. | 1696 // helper here instead. |
| 1785 for (int i = 0; i < length; i++) { | 1697 for (int i = 0; i < length; i++) { |
| 1786 HValue* key_constant = | 1698 HValue* key_constant = |
| 1787 AddInstruction(new(zone) HConstant(i, Representation::Integer32())); | 1699 AddInstruction(new(zone) HConstant(i, Representation::Integer32())); |
| 1788 HInstruction* value = | 1700 HInstruction* value = |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1848 } | 1760 } |
| 1849 | 1761 |
| 1850 | 1762 |
| 1851 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, | 1763 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, |
| 1852 int previous_object_size, | 1764 int previous_object_size, |
| 1853 HValue* payload) { | 1765 HValue* payload) { |
| 1854 HInnerAllocatedObject* alloc_site = new(zone()) | 1766 HInnerAllocatedObject* alloc_site = new(zone()) |
| 1855 HInnerAllocatedObject(previous_object, previous_object_size); | 1767 HInnerAllocatedObject(previous_object, previous_object_size); |
| 1856 AddInstruction(alloc_site); | 1768 AddInstruction(alloc_site); |
| 1857 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); | 1769 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); |
| 1858 BuildStoreMap(alloc_site, alloc_site_map); | 1770 AddStoreMapConstant(alloc_site, alloc_site_map); |
| 1859 AddInstruction(new(zone()) HStoreNamedField(alloc_site, | 1771 HObjectAccess access = HObjectAccess::ForAllocationSitePayload(); |
| 1860 isolate()->factory()->payload_string(), | 1772 AddStore(alloc_site, access, payload); |
| 1861 payload, | |
| 1862 true, | |
| 1863 Representation::Tagged(), | |
| 1864 AllocationSiteInfo::kPayloadOffset)); | |
| 1865 return alloc_site; | 1773 return alloc_site; |
| 1866 } | 1774 } |
| 1867 | 1775 |
| 1868 | 1776 |
| 1869 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { | 1777 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { |
| 1778 // Get the global context, then the native context | |
| 1870 HInstruction* global_object = AddInstruction(new(zone()) | 1779 HInstruction* global_object = AddInstruction(new(zone()) |
| 1871 HGlobalObject(context)); | 1780 HGlobalObject(context)); |
| 1872 HInstruction* native_context = AddInstruction(new(zone()) | 1781 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 1873 HLoadNamedField(global_object, true, Representation::Tagged(), | 1782 GlobalObject::kNativeContextOffset); |
| 1874 GlobalObject::kNativeContextOffset)); | 1783 return AddLoad(global_object, access); |
| 1875 return native_context; | |
| 1876 } | 1784 } |
| 1877 | 1785 |
| 1878 | 1786 |
| 1879 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { | 1787 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { |
| 1880 HInstruction* native_context = BuildGetNativeContext(context); | 1788 HInstruction* native_context = BuildGetNativeContext(context); |
| 1881 int offset = Context::kHeaderSize + | 1789 HInstruction* index = AddInstruction(new(zone()) |
| 1882 kPointerSize * Context::ARRAY_FUNCTION_INDEX; | 1790 HConstant(Context::ARRAY_FUNCTION_INDEX, Representation::Integer32())); |
| 1883 HInstruction* array_function = AddInstruction(new(zone()) | 1791 |
| 1884 HLoadNamedField(native_context, true, Representation::Tagged(), offset)); | 1792 return AddInstruction(new (zone()) |
| 1885 return array_function; | 1793 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS)); |
| 1886 } | 1794 } |
| 1887 | 1795 |
| 1888 | 1796 |
| 1889 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 1797 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
| 1890 ElementsKind kind, | 1798 ElementsKind kind, |
| 1891 HValue* allocation_site_payload, | 1799 HValue* allocation_site_payload, |
| 1892 AllocationSiteMode mode) : | 1800 AllocationSiteMode mode) : |
| 1893 builder_(builder), | 1801 builder_(builder), |
| 1894 kind_(kind), | 1802 kind_(kind), |
| 1895 allocation_site_payload_(allocation_site_payload) { | 1803 allocation_site_payload_(allocation_site_payload) { |
| 1896 if (mode == DONT_TRACK_ALLOCATION_SITE) { | 1804 if (mode == DONT_TRACK_ALLOCATION_SITE) { |
| 1897 mode_ = mode; | 1805 mode_ = mode; |
| 1898 } else { | 1806 } else { |
| 1899 mode_ = AllocationSiteInfo::GetMode(kind); | 1807 mode_ = AllocationSiteInfo::GetMode(kind); |
| 1900 } | 1808 } |
| 1901 } | 1809 } |
| 1902 | 1810 |
| 1903 | 1811 |
| 1904 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 1812 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { |
| 1905 HInstruction* native_context = builder()->BuildGetNativeContext(context); | 1813 HInstruction* native_context = builder()->BuildGetNativeContext(context); |
| 1906 int offset = Context::kHeaderSize + | 1814 |
| 1907 kPointerSize * Context::JS_ARRAY_MAPS_INDEX; | 1815 HInstruction* index = builder()->AddInstruction(new(zone()) |
| 1908 HInstruction* map_array = AddInstruction(new(zone()) | 1816 HConstant(Context::JS_ARRAY_MAPS_INDEX, Representation::Integer32())); |
| 1909 HLoadNamedField(native_context, true, Representation::Tagged(), offset)); | 1817 |
| 1910 offset = kind_ * kPointerSize + FixedArrayBase::kHeaderSize; | 1818 HInstruction* map_array = builder()->AddInstruction(new(zone()) |
| 1911 return AddInstruction(new(zone()) HLoadNamedField( | 1819 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS)); |
| 1912 map_array, true, Representation::Tagged(), offset)); | 1820 |
| 1821 HInstruction* kind_index = builder()->AddInstruction(new(zone()) | |
| 1822 HConstant(kind_, Representation::Integer32())); | |
| 1823 | |
| 1824 return builder()->AddInstruction(new(zone()) | |
| 1825 HLoadKeyed(map_array, kind_index, NULL, FAST_ELEMENTS)); | |
|
danno
2013/05/14 14:41:58
Nice :-)
| |
| 1913 } | 1826 } |
| 1914 | 1827 |
| 1915 | 1828 |
| 1916 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1829 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
| 1917 HValue* length_node) { | 1830 HValue* length_node) { |
| 1918 HValue* context = builder()->environment()->LookupContext(); | 1831 HValue* context = builder()->environment()->LookupContext(); |
| 1919 ASSERT(length_node != NULL); | 1832 ASSERT(length_node != NULL); |
| 1920 | 1833 |
| 1921 int base_size = JSArray::kSize; | 1834 int base_size = JSArray::kSize; |
| 1922 if (mode_ == TRACK_ALLOCATION_SITE) { | 1835 if (mode_ == TRACK_ALLOCATION_SITE) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2011 | 1924 |
| 2012 if (fill_with_hole) { | 1925 if (fill_with_hole) { |
| 2013 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, | 1926 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, |
| 2014 graph()->GetConstant0(), capacity); | 1927 graph()->GetConstant0(), capacity); |
| 2015 } | 1928 } |
| 2016 | 1929 |
| 2017 return new_object; | 1930 return new_object; |
| 2018 } | 1931 } |
| 2019 | 1932 |
| 2020 | 1933 |
| 1934 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, | |
| 1935 HObjectAccess access, | |
| 1936 HValue *val, | |
| 1937 Representation representation) { | |
| 1938 HStoreNamedField *instr = new(zone()) | |
| 1939 HStoreNamedField(object, access, val, representation); | |
| 1940 AddInstruction(instr); | |
| 1941 return instr; | |
| 1942 } | |
| 1943 | |
| 1944 | |
| 1945 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, | |
| 1946 HObjectAccess access, | |
| 1947 HValue *typecheck, | |
| 1948 Representation representation) { | |
| 1949 HLoadNamedField *instr = | |
| 1950 new(zone()) HLoadNamedField(object, access, typecheck, representation); | |
| 1951 AddInstruction(instr); | |
| 1952 return instr; | |
| 1953 } | |
| 1954 | |
| 1955 | |
| 1956 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | |
| 1957 Handle<Map> map) { | |
| 1958 HValue* constant = | |
| 1959 AddInstruction(new(zone()) HConstant(map, Representation::Tagged())); | |
| 1960 HStoreNamedField *instr = | |
| 1961 new(zone()) HStoreNamedField(object, HObjectAccess::ForMap(), constant); | |
| 1962 AddInstruction(instr); | |
| 1963 return instr; | |
| 1964 } | |
| 1965 | |
| 1966 | |
| 2021 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 1967 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, |
| 2022 TypeFeedbackOracle* oracle) | 1968 TypeFeedbackOracle* oracle) |
| 2023 : HGraphBuilder(info), | 1969 : HGraphBuilder(info), |
| 2024 function_state_(NULL), | 1970 function_state_(NULL), |
| 2025 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 1971 initial_function_state_(this, info, oracle, NORMAL_RETURN), |
| 2026 ast_context_(NULL), | 1972 ast_context_(NULL), |
| 2027 break_scope_(NULL), | 1973 break_scope_(NULL), |
| 2028 inlined_count_(0), | 1974 inlined_count_(0), |
| 2029 globals_(10, info->zone()), | 1975 globals_(10, info->zone()), |
| 2030 inline_bailout_(false) { | 1976 inline_bailout_(false) { |
| (...skipping 4320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6351 ASSERT(current_block() != NULL); | 6297 ASSERT(current_block() != NULL); |
| 6352 ASSERT(current_block()->HasPredecessor()); | 6298 ASSERT(current_block()->HasPredecessor()); |
| 6353 return Bailout("DebuggerStatement"); | 6299 return Bailout("DebuggerStatement"); |
| 6354 } | 6300 } |
| 6355 | 6301 |
| 6356 | 6302 |
| 6357 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | 6303 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
| 6358 Code* unoptimized_code, FunctionLiteral* expr) { | 6304 Code* unoptimized_code, FunctionLiteral* expr) { |
| 6359 int start_position = expr->start_position(); | 6305 int start_position = expr->start_position(); |
| 6360 RelocIterator it(unoptimized_code); | 6306 RelocIterator it(unoptimized_code); |
| 6361 for (;!it.done(); it.next()) { | 6307 for (; !it.done(); it.next()) { |
| 6362 RelocInfo* rinfo = it.rinfo(); | 6308 RelocInfo* rinfo = it.rinfo(); |
| 6363 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | 6309 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; |
| 6364 Object* obj = rinfo->target_object(); | 6310 Object* obj = rinfo->target_object(); |
| 6365 if (obj->IsSharedFunctionInfo()) { | 6311 if (obj->IsSharedFunctionInfo()) { |
| 6366 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 6312 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
| 6367 if (shared->start_position() == start_position) { | 6313 if (shared->start_position() == start_position) { |
| 6368 return Handle<SharedFunctionInfo>(shared); | 6314 return Handle<SharedFunctionInfo>(shared); |
| 6369 } | 6315 } |
| 6370 } | 6316 } |
| 6371 } | 6317 } |
| (...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7027 if (!is_store) return false; | 6973 if (!is_store) return false; |
| 7028 | 6974 |
| 7029 // 2nd chance: A store into a non-existent field can still be inlined if we | 6975 // 2nd chance: A store into a non-existent field can still be inlined if we |
| 7030 // have a matching transition and some room left in the object. | 6976 // have a matching transition and some room left in the object. |
| 7031 type->LookupTransition(NULL, *name, lookup); | 6977 type->LookupTransition(NULL, *name, lookup); |
| 7032 return lookup->IsTransitionToField(*type) && | 6978 return lookup->IsTransitionToField(*type) && |
| 7033 (type->unused_property_fields() > 0); | 6979 (type->unused_property_fields() > 0); |
| 7034 } | 6980 } |
| 7035 | 6981 |
| 7036 | 6982 |
| 7037 static int ComputeLoadStoreFieldIndex(Handle<Map> type, | |
| 7038 LookupResult* lookup) { | |
| 7039 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type)); | |
| 7040 if (lookup->IsField()) { | |
| 7041 return lookup->GetLocalFieldIndexFromMap(*type); | |
| 7042 } else { | |
| 7043 Map* transition = lookup->GetTransitionMapFromMap(*type); | |
| 7044 int descriptor = transition->LastAdded(); | |
| 7045 int index = transition->instance_descriptors()->GetFieldIndex(descriptor); | |
| 7046 return index - type->inobject_properties(); | |
| 7047 } | |
| 7048 } | |
| 7049 | |
| 7050 | |
| 7051 static Representation ComputeLoadStoreRepresentation(Handle<Map> type, | 6983 static Representation ComputeLoadStoreRepresentation(Handle<Map> type, |
| 7052 LookupResult* lookup) { | 6984 LookupResult* lookup) { |
| 7053 if (lookup->IsField()) { | 6985 if (lookup->IsField()) { |
| 7054 return lookup->representation(); | 6986 return lookup->representation(); |
| 7055 } else { | 6987 } else { |
| 7056 Map* transition = lookup->GetTransitionMapFromMap(*type); | 6988 Map* transition = lookup->GetTransitionMapFromMap(*type); |
| 7057 int descriptor = transition->LastAdded(); | 6989 int descriptor = transition->LastAdded(); |
| 7058 PropertyDetails details = | 6990 PropertyDetails details = |
| 7059 transition->instance_descriptors()->GetDetails(descriptor); | 6991 transition->instance_descriptors()->GetDetails(descriptor); |
| 7060 return details.representation(); | 6992 return details.representation(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7105 } | 7037 } |
| 7106 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 7038 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
| 7107 } | 7039 } |
| 7108 ASSERT(proto->IsJSObject()); | 7040 ASSERT(proto->IsJSObject()); |
| 7109 AddInstruction(new(zone()) HCheckPrototypeMaps( | 7041 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7110 Handle<JSObject>(JSObject::cast(map->prototype())), | 7042 Handle<JSObject>(JSObject::cast(map->prototype())), |
| 7111 Handle<JSObject>(JSObject::cast(proto)), | 7043 Handle<JSObject>(JSObject::cast(proto)), |
| 7112 zone())); | 7044 zone())); |
| 7113 } | 7045 } |
| 7114 | 7046 |
| 7115 int index = ComputeLoadStoreFieldIndex(map, lookup); | 7047 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
| 7116 bool is_in_object = index < 0; | |
| 7117 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | 7048 Representation representation = ComputeLoadStoreRepresentation(map, lookup); |
| 7118 int offset = index * kPointerSize; | |
| 7119 if (index < 0) { | |
| 7120 // Negative property indices are in-object properties, indexed | |
| 7121 // from the end of the fixed part of the object. | |
| 7122 offset += map->instance_size(); | |
| 7123 } else { | |
| 7124 offset += FixedArray::kHeaderSize; | |
| 7125 } | |
| 7126 bool transition_to_field = lookup->IsTransitionToField(*map); | 7049 bool transition_to_field = lookup->IsTransitionToField(*map); |
| 7050 | |
| 7051 HStoreNamedField *instr; | |
| 7127 if (FLAG_track_double_fields && representation.IsDouble()) { | 7052 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 7128 if (transition_to_field) { | 7053 if (transition_to_field) { |
| 7054 // The store requires a mutable HeapNumber to be allocated. | |
| 7129 NoObservableSideEffectsScope no_side_effects(this); | 7055 NoObservableSideEffectsScope no_side_effects(this); |
| 7130 HInstruction* heap_number_size = AddInstruction(new(zone()) HConstant( | 7056 HInstruction* heap_number_size = AddInstruction(new(zone()) HConstant( |
| 7131 HeapNumber::kSize, Representation::Integer32())); | 7057 HeapNumber::kSize, Representation::Integer32())); |
| 7132 HInstruction* double_box = AddInstruction(new(zone()) HAllocate( | 7058 HInstruction* double_box = AddInstruction(new(zone()) HAllocate( |
| 7133 environment()->LookupContext(), heap_number_size, | 7059 environment()->LookupContext(), heap_number_size, |
| 7134 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); | 7060 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); |
| 7135 BuildStoreMap(double_box, isolate()->factory()->heap_number_map()); | 7061 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); |
| 7136 AddInstruction(new(zone()) HStoreNamedField( | 7062 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
| 7137 double_box, name, value, true, | 7063 value, Representation::Double()); |
| 7138 Representation::Double(), HeapNumber::kValueOffset)); | 7064 instr = new(zone()) HStoreNamedField(object, field_access, double_box); |
| 7139 value = double_box; | |
| 7140 representation = Representation::Tagged(); | |
| 7141 } else { | 7065 } else { |
| 7142 HInstruction* double_box = AddInstruction(new(zone()) HLoadNamedField( | 7066 // Already holds a HeapNumber; load the box and write its value field. |
| 7143 object, is_in_object, Representation::Tagged(), offset)); | 7067 HInstruction* double_box = AddLoad(object, field_access); |
| 7144 double_box->set_type(HType::HeapNumber()); | 7068 double_box->set_type(HType::HeapNumber()); |
| 7145 return new(zone()) HStoreNamedField( | 7069 instr = new(zone()) HStoreNamedField(double_box, |
| 7146 double_box, name, value, true, | 7070 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); |
| 7147 Representation::Double(), HeapNumber::kValueOffset); | |
| 7148 } | 7071 } |
| 7072 } else { | |
| 7073 // This is a non-double store. | |
| 7074 instr = new(zone()) HStoreNamedField( | |
| 7075 object, field_access, value, representation); | |
| 7149 } | 7076 } |
| 7150 HStoreNamedField* instr = new(zone()) HStoreNamedField( | 7077 |
| 7151 object, name, value, is_in_object, representation, offset); | |
| 7152 if (transition_to_field) { | 7078 if (transition_to_field) { |
| 7153 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 7079 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 7154 instr->set_transition(transition); | 7080 instr->set_transition(transition); |
| 7155 // TODO(fschneider): Record the new map type of the object in the IR to | 7081 // TODO(fschneider): Record the new map type of the object in the IR to |
| 7156 // enable elimination of redundant checks after the transition store. | 7082 // enable elimination of redundant checks after the transition store. |
| 7157 instr->SetGVNFlag(kChangesMaps); | 7083 instr->SetGVNFlag(kChangesMaps); |
| 7158 } | 7084 } |
| 7159 return instr; | 7085 return instr; |
| 7160 } | 7086 } |
| 7161 | 7087 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7211 Handle<String> name) { | 7137 Handle<String> name) { |
| 7212 if (!name->Equals(isolate()->heap()->length_string())) return false; | 7138 if (!name->Equals(isolate()->heap()->length_string())) return false; |
| 7213 | 7139 |
| 7214 for (int i = 0; i < types->length(); i++) { | 7140 for (int i = 0; i < types->length(); i++) { |
| 7215 if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false; | 7141 if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false; |
| 7216 } | 7142 } |
| 7217 | 7143 |
| 7218 BuildCheckNonSmi(object); | 7144 BuildCheckNonSmi(object); |
| 7219 | 7145 |
| 7220 HInstruction* typecheck = | 7146 HInstruction* typecheck = |
| 7221 AddInstruction(HCheckMaps::New(object, types, zone())); | 7147 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 7222 HInstruction* instr = | 7148 HInstruction* instr = new(zone()) |
| 7223 HLoadNamedField::NewArrayLength(zone(), object, typecheck); | 7149 HLoadNamedField(object, HObjectAccess::ForArrayLength(), typecheck); |
| 7150 | |
| 7224 instr->set_position(expr->position()); | 7151 instr->set_position(expr->position()); |
| 7225 ast_context()->ReturnInstruction(instr, expr->id()); | 7152 ast_context()->ReturnInstruction(instr, expr->id()); |
| 7226 return true; | 7153 return true; |
| 7227 } | 7154 } |
| 7228 | 7155 |
| 7229 | 7156 |
| 7230 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 7157 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
| 7231 HValue* object, | 7158 HValue* object, |
| 7232 SmallMapList* types, | 7159 SmallMapList* types, |
| 7233 Handle<String> name) { | 7160 Handle<String> name) { |
| 7234 | 7161 |
| 7235 if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) | 7162 if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) |
| 7236 return; | 7163 return; |
| 7237 | 7164 |
| 7238 BuildCheckNonSmi(object); | 7165 BuildCheckNonSmi(object); |
| 7239 | 7166 |
| 7240 // Use monomorphic load if property lookup results in the same field index | 7167 // Use monomorphic load if property lookup results in the same field index |
| 7241 // for all maps. Requires special map check on the set of all handled maps. | 7168 // for all maps. Requires special map check on the set of all handled maps. |
| 7242 HInstruction* instr = NULL; | 7169 HInstruction* instr = NULL; |
| 7243 if (types->length() > 0 && types->length() <= kMaxLoadPolymorphism) { | 7170 LookupResult lookup(isolate()); |
| 7244 LookupResult lookup(isolate()); | 7171 int count; |
| 7245 int previous_field_offset = 0; | 7172 Representation representation = Representation::None(); |
| 7246 bool previous_field_is_in_object = false; | 7173 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| 7247 Representation representation = Representation::None(); | 7174 for (count = 0; |
| 7248 int count; | 7175 count < types->length() && count < kMaxLoadPolymorphism; |
| 7249 for (count = 0; count < types->length(); ++count) { | 7176 ++count) { |
| 7250 Handle<Map> map = types->at(count); | 7177 Handle<Map> map = types->at(count); |
| 7251 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 7178 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| 7252 | 7179 |
| 7253 int index = ComputeLoadStoreFieldIndex(map, &lookup); | 7180 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| 7254 Representation new_representation = | 7181 Representation new_representation = |
| 7255 ComputeLoadStoreRepresentation(map, &lookup); | 7182 ComputeLoadStoreRepresentation(map, &lookup); |
| 7256 bool is_in_object = index < 0; | |
| 7257 int offset = index * kPointerSize; | |
| 7258 | 7183 |
| 7259 if (index < 0) { | 7184 if (count == 0) { |
| 7260 // Negative property indices are in-object properties, indexed | 7185 // First time through the loop; set access and representation. |
| 7261 // from the end of the fixed part of the object. | 7186 access = new_access; |
| 7262 offset += map->instance_size(); | 7187 representation = new_representation; |
| 7263 } else { | 7188 } else if (!representation.IsCompatibleForLoad(new_representation)) { |
| 7264 offset += FixedArray::kHeaderSize; | 7189 // Representations did not match. |
| 7265 } | 7190 break; |
| 7266 | 7191 } else if (access.offset() != new_access.offset()) { |
| 7267 if (count == 0) { | 7192 // Offsets did not match. |
| 7268 previous_field_offset = offset; | 7193 break; |
| 7269 previous_field_is_in_object = is_in_object; | 7194 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 7270 representation = new_representation; | 7195 // In-objectness did not match. |
| 7271 } else if (offset != previous_field_offset || | 7196 break; |
| 7272 is_in_object != previous_field_is_in_object || | |
| 7273 (FLAG_track_fields && | |
| 7274 !representation.IsCompatibleForLoad(new_representation))) { | |
| 7275 break; | |
| 7276 } | |
| 7277 | |
| 7278 representation = representation.generalize(new_representation); | |
| 7279 } | |
| 7280 | |
| 7281 if (count == types->length()) { | |
| 7282 AddInstruction(HCheckMaps::New(object, types, zone())); | |
| 7283 instr = DoBuildLoadNamedField( | |
| 7284 object, previous_field_is_in_object, | |
| 7285 representation, previous_field_offset); | |
| 7286 } | 7197 } |
| 7287 } | 7198 } |
| 7288 | 7199 |
| 7289 if (instr == NULL) { | 7200 if (count == types->length()) { |
| 7201 // Everything matched; can use monomorphic load. | |
| 7202 AddInstruction(HCheckMaps::New(object, types, zone())); | |
| 7203 instr = BuildLoadNamedField(object, access, representation); | |
| 7204 } else { | |
| 7205 // Something did not match; must use a polymorphic load. | |
| 7290 HValue* context = environment()->LookupContext(); | 7206 HValue* context = environment()->LookupContext(); |
| 7291 instr = new(zone()) HLoadNamedFieldPolymorphic( | 7207 instr = new(zone()) HLoadNamedFieldPolymorphic( |
| 7292 context, object, types, name, zone()); | 7208 context, object, types, name, zone()); |
| 7293 } | 7209 } |
| 7294 | 7210 |
| 7295 instr->set_position(expr->position()); | 7211 instr->set_position(expr->position()); |
| 7296 return ast_context()->ReturnInstruction(instr, expr->id()); | 7212 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7297 } | 7213 } |
| 7298 | 7214 |
| 7299 | 7215 |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7836 HValue* value = environment()->Pop(); | 7752 HValue* value = environment()->Pop(); |
| 7837 HThrow* instr = new(zone()) HThrow(context, value); | 7753 HThrow* instr = new(zone()) HThrow(context, value); |
| 7838 instr->set_position(expr->position()); | 7754 instr->set_position(expr->position()); |
| 7839 AddInstruction(instr); | 7755 AddInstruction(instr); |
| 7840 AddSimulate(expr->id()); | 7756 AddSimulate(expr->id()); |
| 7841 current_block()->FinishExit(new(zone()) HAbnormalExit); | 7757 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 7842 set_current_block(NULL); | 7758 set_current_block(NULL); |
| 7843 } | 7759 } |
| 7844 | 7760 |
| 7845 | 7761 |
| 7846 HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField( | 7762 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( |
| 7847 HValue* object, | 7763 HValue* object, |
| 7848 Handle<Map> map, | 7764 HObjectAccess access, |
| 7849 LookupResult* lookup) { | 7765 Representation representation) { |
| 7850 int index = lookup->GetLocalFieldIndexFromMap(*map); | |
| 7851 // Negative property indices are in-object properties, indexed from the end of | |
| 7852 // the fixed part of the object. Non-negative property indices are in the | |
| 7853 // properties array. | |
| 7854 int inobject = index < 0; | |
| 7855 Representation representation = lookup->representation(); | |
| 7856 int offset = inobject | |
| 7857 ? index * kPointerSize + map->instance_size() | |
| 7858 : index * kPointerSize + FixedArray::kHeaderSize; | |
| 7859 return DoBuildLoadNamedField(object, inobject, representation, offset); | |
| 7860 } | |
| 7861 | |
| 7862 | |
| 7863 HLoadNamedField* HGraphBuilder::DoBuildLoadNamedField( | |
| 7864 HValue* object, | |
| 7865 bool inobject, | |
| 7866 Representation representation, | |
| 7867 int offset) { | |
| 7868 bool load_double = false; | 7766 bool load_double = false; |
| 7869 if (representation.IsDouble()) { | 7767 if (representation.IsDouble()) { |
| 7870 representation = Representation::Tagged(); | 7768 representation = Representation::Tagged(); |
| 7871 load_double = FLAG_track_double_fields; | 7769 load_double = FLAG_track_double_fields; |
| 7872 } | 7770 } |
| 7873 HLoadNamedField* field = | 7771 HLoadNamedField* field = |
| 7874 new(zone()) HLoadNamedField(object, inobject, representation, offset); | 7772 new(zone()) HLoadNamedField(object, access, NULL, representation); |
| 7875 if (load_double) { | 7773 if (load_double) { |
| 7876 AddInstruction(field); | 7774 AddInstruction(field); |
| 7877 field->set_type(HType::HeapNumber()); | 7775 field->set_type(HType::HeapNumber()); |
| 7878 return new(zone()) HLoadNamedField( | 7776 return new(zone()) HLoadNamedField(field, |
| 7879 field, true, Representation::Double(), HeapNumber::kValueOffset); | 7777 HObjectAccess::ForHeapNumberValue(), NULL, Representation::Double()); |
| 7880 } | 7778 } |
| 7881 return field; | 7779 return field; |
| 7882 } | 7780 } |
| 7883 | 7781 |
| 7884 | 7782 |
| 7885 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 7783 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 7886 HValue* object, | 7784 HValue* object, |
| 7887 Handle<String> name, | 7785 Handle<String> name, |
| 7888 Property* expr) { | 7786 Property* expr) { |
| 7889 if (expr->IsUninitialized()) { | 7787 if (expr->IsUninitialized()) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 7910 Handle<String> name, | 7808 Handle<String> name, |
| 7911 Property* expr, | 7809 Property* expr, |
| 7912 Handle<Map> map) { | 7810 Handle<Map> map) { |
| 7913 // Handle a load from a known field. | 7811 // Handle a load from a known field. |
| 7914 ASSERT(!map->is_dictionary_map()); | 7812 ASSERT(!map->is_dictionary_map()); |
| 7915 | 7813 |
| 7916 // Handle access to various length properties | 7814 // Handle access to various length properties |
| 7917 if (name->Equals(isolate()->heap()->length_string())) { | 7815 if (name->Equals(isolate()->heap()->length_string())) { |
| 7918 if (map->instance_type() == JS_ARRAY_TYPE) { | 7816 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 7919 AddCheckMapsWithTransitions(object, map); | 7817 AddCheckMapsWithTransitions(object, map); |
| 7920 return HLoadNamedField::NewArrayLength(zone(), object, object); | 7818 return new(zone()) HLoadNamedField(object, |
| 7819 HObjectAccess::ForArrayLength()); | |
| 7921 } | 7820 } |
| 7922 } | 7821 } |
| 7923 | 7822 |
| 7924 LookupResult lookup(isolate()); | 7823 LookupResult lookup(isolate()); |
| 7925 map->LookupDescriptor(NULL, *name, &lookup); | 7824 map->LookupDescriptor(NULL, *name, &lookup); |
| 7926 if (lookup.IsField()) { | 7825 if (lookup.IsField()) { |
| 7927 AddCheckMap(object, map); | 7826 AddCheckMap(object, map); |
| 7928 return BuildLoadNamedField(object, map, &lookup); | 7827 return BuildLoadNamedField(object, |
| 7828 HObjectAccess::ForField(map, &lookup, name), | |
| 7829 ComputeLoadStoreRepresentation(map, &lookup)); | |
| 7929 } | 7830 } |
| 7930 | 7831 |
| 7931 // Handle a load of a constant known function. | 7832 // Handle a load of a constant known function. |
| 7932 if (lookup.IsConstantFunction()) { | 7833 if (lookup.IsConstantFunction()) { |
| 7933 AddCheckMap(object, map); | 7834 AddCheckMap(object, map); |
| 7934 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 7835 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
| 7935 return new(zone()) HConstant(function, Representation::Tagged()); | 7836 return new(zone()) HConstant(function, Representation::Tagged()); |
| 7936 } | 7837 } |
| 7937 | 7838 |
| 7938 // Handle a load from a known field somewhere in the prototype chain. | 7839 // Handle a load from a known field somewhere in the prototype chain. |
| 7939 LookupInPrototypes(map, name, &lookup); | 7840 LookupInPrototypes(map, name, &lookup); |
| 7940 if (lookup.IsField()) { | 7841 if (lookup.IsField()) { |
| 7941 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7842 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7942 Handle<JSObject> holder(lookup.holder()); | 7843 Handle<JSObject> holder(lookup.holder()); |
| 7943 Handle<Map> holder_map(holder->map()); | 7844 Handle<Map> holder_map(holder->map()); |
| 7944 AddCheckMap(object, map); | 7845 AddCheckMap(object, map); |
| 7945 AddInstruction( | 7846 AddInstruction( |
| 7946 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7847 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); |
| 7947 HValue* holder_value = AddInstruction( | 7848 HValue* holder_value = AddInstruction(new(zone()) |
| 7948 new(zone()) HConstant(holder, Representation::Tagged())); | 7849 HConstant(holder, Representation::Tagged())); |
| 7949 return BuildLoadNamedField(holder_value, holder_map, &lookup); | 7850 return BuildLoadNamedField(holder_value, |
| 7851 HObjectAccess::ForField(holder_map, &lookup, name), | |
| 7852 ComputeLoadStoreRepresentation(map, &lookup)); | |
| 7950 } | 7853 } |
| 7951 | 7854 |
| 7952 // Handle a load of a constant function somewhere in the prototype chain. | 7855 // Handle a load of a constant function somewhere in the prototype chain. |
| 7953 if (lookup.IsConstantFunction()) { | 7856 if (lookup.IsConstantFunction()) { |
| 7954 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7857 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7955 Handle<JSObject> holder(lookup.holder()); | 7858 Handle<JSObject> holder(lookup.holder()); |
| 7956 Handle<Map> holder_map(holder->map()); | 7859 Handle<Map> holder_map(holder->map()); |
| 7957 AddCheckMap(object, map); | 7860 AddCheckMap(object, map); |
| 7958 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7861 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); |
| 7959 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 7862 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8202 // it's a keyed property) and registered in the full codegen. | 8105 // it's a keyed property) and registered in the full codegen. |
| 8203 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 8106 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
| 8204 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 8107 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
| 8205 HHasInstanceTypeAndBranch* typecheck = | 8108 HHasInstanceTypeAndBranch* typecheck = |
| 8206 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 8109 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
| 8207 typecheck->SetSuccessorAt(0, if_jsarray); | 8110 typecheck->SetSuccessorAt(0, if_jsarray); |
| 8208 typecheck->SetSuccessorAt(1, if_fastobject); | 8111 typecheck->SetSuccessorAt(1, if_fastobject); |
| 8209 current_block()->Finish(typecheck); | 8112 current_block()->Finish(typecheck); |
| 8210 | 8113 |
| 8211 set_current_block(if_jsarray); | 8114 set_current_block(if_jsarray); |
| 8212 HInstruction* length; | 8115 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), |
| 8213 length = AddInstruction( | 8116 typecheck, Representation::Smi()); |
| 8214 HLoadNamedField::NewArrayLength(zone(), object, typecheck, | 8117 length->set_type(HType::Smi()); |
| 8215 HType::Smi())); | 8118 |
| 8216 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 8119 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
| 8217 access = AddInstruction(BuildFastElementAccess( | 8120 access = AddInstruction(BuildFastElementAccess( |
| 8218 elements, checked_key, val, elements_kind_branch, | 8121 elements, checked_key, val, elements_kind_branch, |
| 8219 elements_kind, is_store, STANDARD_STORE)); | 8122 elements_kind, is_store, STANDARD_STORE)); |
| 8220 if (!is_store) { | 8123 if (!is_store) { |
| 8221 Push(access); | 8124 Push(access); |
| 8222 } | 8125 } |
| 8223 | 8126 |
| 8224 *has_side_effects |= access->HasObservableSideEffects(); | 8127 *has_side_effects |= access->HasObservableSideEffects(); |
| 8225 // The caller will use has_side_effects and add correct Simulate. | 8128 // The caller will use has_side_effects and add correct Simulate. |
| (...skipping 2622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10848 } | 10751 } |
| 10849 | 10752 |
| 10850 | 10753 |
| 10851 void HOptimizedGraphBuilder::BuildEmitDeepCopy( | 10754 void HOptimizedGraphBuilder::BuildEmitDeepCopy( |
| 10852 Handle<JSObject> boilerplate_object, | 10755 Handle<JSObject> boilerplate_object, |
| 10853 Handle<JSObject> original_boilerplate_object, | 10756 Handle<JSObject> original_boilerplate_object, |
| 10854 HInstruction* target, | 10757 HInstruction* target, |
| 10855 int* offset, | 10758 int* offset, |
| 10856 AllocationSiteMode mode) { | 10759 AllocationSiteMode mode) { |
| 10857 Zone* zone = this->zone(); | 10760 Zone* zone = this->zone(); |
| 10858 Factory* factory = isolate()->factory(); | |
| 10859 | 10761 |
| 10860 HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant( | 10762 HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant( |
| 10861 original_boilerplate_object, Representation::Tagged())); | 10763 original_boilerplate_object, Representation::Tagged())); |
| 10862 | 10764 |
| 10863 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && | 10765 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && |
| 10864 boilerplate_object->map()->CanTrackAllocationSite(); | 10766 boilerplate_object->map()->CanTrackAllocationSite(); |
| 10865 | 10767 |
| 10866 // Only elements backing stores for non-COW arrays need to be copied. | 10768 // Only elements backing stores for non-COW arrays need to be copied. |
| 10867 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 10769 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
| 10868 Handle<FixedArrayBase> original_elements( | 10770 Handle<FixedArrayBase> original_elements( |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 10897 | 10799 |
| 10898 for (int i = 0; i < limit; i++) { | 10800 for (int i = 0; i < limit; i++) { |
| 10899 PropertyDetails details = descriptors->GetDetails(i); | 10801 PropertyDetails details = descriptors->GetDetails(i); |
| 10900 if (details.type() != FIELD) continue; | 10802 if (details.type() != FIELD) continue; |
| 10901 int index = descriptors->GetFieldIndex(i); | 10803 int index = descriptors->GetFieldIndex(i); |
| 10902 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); | 10804 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); |
| 10903 Handle<Name> name(descriptors->GetKey(i)); | 10805 Handle<Name> name(descriptors->GetKey(i)); |
| 10904 Handle<Object> value = | 10806 Handle<Object> value = |
| 10905 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), | 10807 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), |
| 10906 isolate()); | 10808 isolate()); |
| 10809 | |
| 10810 // The access for the store depends on the type of the boilerplate. | |
| 10811 HObjectAccess access = boilerplate_object->IsJSArray() ? | |
| 10812 HObjectAccess::ForJSArrayOffset(property_offset) : | |
| 10813 HObjectAccess::ForJSObjectOffset(property_offset); | |
| 10814 | |
| 10907 if (value->IsJSObject()) { | 10815 if (value->IsJSObject()) { |
| 10908 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 10816 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 10909 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 10817 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
| 10910 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), | 10818 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), |
| 10911 isolate())); | 10819 isolate())); |
| 10912 HInstruction* value_instruction = | 10820 HInstruction* value_instruction = |
| 10913 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 10821 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); |
| 10914 AddInstruction(new(zone) HStoreNamedField( | 10822 |
| 10915 object_properties, name, value_instruction, true, | 10823 AddStore(object_properties, access, value_instruction); |
| 10916 Representation::Tagged(), property_offset)); | 10824 |
| 10917 BuildEmitDeepCopy(value_object, original_value_object, target, | 10825 BuildEmitDeepCopy(value_object, original_value_object, target, |
| 10918 offset, DONT_TRACK_ALLOCATION_SITE); | 10826 offset, DONT_TRACK_ALLOCATION_SITE); |
| 10919 } else { | 10827 } else { |
| 10920 Representation representation = details.representation(); | 10828 Representation representation = details.representation(); |
| 10921 HInstruction* value_instruction = AddInstruction(new(zone) HConstant( | 10829 HInstruction* value_instruction = AddInstruction(new(zone) HConstant( |
| 10922 value, Representation::Tagged())); | 10830 value, Representation::Tagged())); |
| 10831 | |
| 10923 if (representation.IsDouble()) { | 10832 if (representation.IsDouble()) { |
| 10833 // Allocate a HeapNumber box and store the value into it. | |
| 10924 HInstruction* double_box = | 10834 HInstruction* double_box = |
| 10925 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 10835 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); |
| 10926 BuildStoreMap(double_box, factory->heap_number_map()); | 10836 AddStoreMapConstant(double_box, |
| 10927 AddInstruction(new(zone) HStoreNamedField( | 10837 isolate()->factory()->heap_number_map()); |
| 10928 double_box, name, value_instruction, true, | 10838 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
| 10929 Representation::Double(), HeapNumber::kValueOffset)); | 10839 value_instruction, Representation::Double()); |
| 10930 value_instruction = double_box; | 10840 value_instruction = double_box; |
| 10931 *offset += HeapNumber::kSize; | 10841 *offset += HeapNumber::kSize; |
| 10932 } | 10842 } |
| 10933 AddInstruction(new(zone) HStoreNamedField( | 10843 |
| 10934 object_properties, name, value_instruction, true, | 10844 AddStore(object_properties, access, value_instruction); |
| 10935 Representation::Tagged(), property_offset)); | |
| 10936 } | 10845 } |
| 10937 } | 10846 } |
| 10938 | 10847 |
| 10939 // Build Allocation Site Info if desired | 10848 // Build Allocation Site Info if desired |
| 10940 if (create_allocation_site_info) { | 10849 if (create_allocation_site_info) { |
| 10941 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate); | 10850 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate); |
| 10942 } | 10851 } |
| 10943 | 10852 |
| 10944 if (object_elements != NULL) { | 10853 if (object_elements != NULL) { |
| 10945 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( | 10854 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10997 | 10906 |
| 10998 | 10907 |
| 10999 HValue* HOptimizedGraphBuilder::BuildCopyObjectHeader( | 10908 HValue* HOptimizedGraphBuilder::BuildCopyObjectHeader( |
| 11000 Handle<JSObject> boilerplate_object, | 10909 Handle<JSObject> boilerplate_object, |
| 11001 HInstruction* target, | 10910 HInstruction* target, |
| 11002 int object_offset, | 10911 int object_offset, |
| 11003 int elements_offset, | 10912 int elements_offset, |
| 11004 int elements_size) { | 10913 int elements_size) { |
| 11005 ASSERT(boilerplate_object->properties()->length() == 0); | 10914 ASSERT(boilerplate_object->properties()->length() == 0); |
| 11006 Zone* zone = this->zone(); | 10915 Zone* zone = this->zone(); |
| 11007 Factory* factory = isolate()->factory(); | |
| 11008 HValue* result = NULL; | 10916 HValue* result = NULL; |
| 11009 | 10917 |
| 11010 HValue* object_header = | 10918 HValue* object_header = |
| 11011 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); | 10919 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); |
| 11012 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 10920 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
| 11013 BuildStoreMap(object_header, boilerplate_object_map); | 10921 AddStoreMapConstant(object_header, boilerplate_object_map); |
| 11014 | 10922 |
| 11015 HInstruction* elements; | 10923 HInstruction* elements; |
| 11016 if (elements_size == 0) { | 10924 if (elements_size == 0) { |
| 11017 Handle<Object> elements_field = | 10925 Handle<Object> elements_field = |
| 11018 Handle<Object>(boilerplate_object->elements(), isolate()); | 10926 Handle<Object>(boilerplate_object->elements(), isolate()); |
| 11019 elements = AddInstruction(new(zone) HConstant( | 10927 elements = AddInstruction(new(zone) HConstant( |
| 11020 elements_field, Representation::Tagged())); | 10928 elements_field, Representation::Tagged())); |
| 11021 } else { | 10929 } else { |
| 11022 elements = AddInstruction(new(zone) HInnerAllocatedObject( | 10930 elements = AddInstruction(new(zone) HInnerAllocatedObject( |
| 11023 target, elements_offset)); | 10931 target, elements_offset)); |
| 11024 result = elements; | 10932 result = elements; |
| 11025 } | 10933 } |
| 11026 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( | 10934 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); |
| 11027 object_header, | |
| 11028 factory->elements_field_string(), | |
| 11029 elements, | |
| 11030 true, Representation::Tagged(), JSObject::kElementsOffset)); | |
| 11031 elements_store->SetGVNFlag(kChangesElementsPointer); | |
| 11032 | 10935 |
| 11033 Handle<Object> properties_field = | 10936 Handle<Object> properties_field = |
| 11034 Handle<Object>(boilerplate_object->properties(), isolate()); | 10937 Handle<Object>(boilerplate_object->properties(), isolate()); |
| 11035 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 10938 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
| 11036 HInstruction* properties = AddInstruction(new(zone) HConstant( | 10939 HInstruction* properties = AddInstruction(new(zone) HConstant( |
| 11037 properties_field, Representation::None())); | 10940 properties_field, Representation::None())); |
| 11038 AddInstruction(new(zone) HStoreNamedField(object_header, | 10941 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 11039 factory->empty_string(), | 10942 AddStore(object_header, access, properties); |
| 11040 properties, true, | |
| 11041 Representation::Tagged(), | |
| 11042 JSObject::kPropertiesOffset)); | |
| 11043 | 10943 |
| 11044 if (boilerplate_object->IsJSArray()) { | 10944 if (boilerplate_object->IsJSArray()) { |
| 11045 Handle<JSArray> boilerplate_array = | 10945 Handle<JSArray> boilerplate_array = |
| 11046 Handle<JSArray>::cast(boilerplate_object); | 10946 Handle<JSArray>::cast(boilerplate_object); |
| 11047 Handle<Object> length_field = | 10947 Handle<Object> length_field = |
| 11048 Handle<Object>(boilerplate_array->length(), isolate()); | 10948 Handle<Object>(boilerplate_array->length(), isolate()); |
| 11049 HInstruction* length = AddInstruction(new(zone) HConstant( | 10949 HInstruction* length = AddInstruction(new(zone) HConstant( |
| 11050 length_field, Representation::None())); | 10950 length_field, Representation::None())); |
| 10951 | |
| 11051 ASSERT(boilerplate_array->length()->IsSmi()); | 10952 ASSERT(boilerplate_array->length()->IsSmi()); |
| 11052 Representation representation = | 10953 Representation representation = |
| 11053 IsFastElementsKind(boilerplate_array->GetElementsKind()) | 10954 IsFastElementsKind(boilerplate_array->GetElementsKind()) |
| 11054 ? Representation::Smi() : Representation::Tagged(); | 10955 ? Representation::Smi() : Representation::Tagged(); |
| 11055 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( | 10956 AddStore(object_header, HObjectAccess::ForArrayLength(), |
| 11056 object_header, | 10957 length, representation); |
| 11057 factory->length_field_string(), | |
| 11058 length, | |
| 11059 true, representation, JSArray::kLengthOffset)); | |
| 11060 length_store->SetGVNFlag(kChangesArrayLengths); | |
| 11061 } | 10958 } |
| 11062 | 10959 |
| 11063 return result; | 10960 return result; |
| 11064 } | 10961 } |
| 11065 | 10962 |
| 11066 | 10963 |
| 11067 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 10964 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 11068 ASSERT(!HasStackOverflow()); | 10965 ASSERT(!HasStackOverflow()); |
| 11069 ASSERT(current_block() != NULL); | 10966 ASSERT(current_block() != NULL); |
| 11070 ASSERT(current_block()->HasPredecessor()); | 10967 ASSERT(current_block()->HasPredecessor()); |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11437 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); | 11334 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); |
| 11438 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); | 11335 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); |
| 11439 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); | 11336 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); |
| 11440 typecheck->SetSuccessorAt(0, if_js_value); | 11337 typecheck->SetSuccessorAt(0, if_js_value); |
| 11441 typecheck->SetSuccessorAt(1, not_js_value); | 11338 typecheck->SetSuccessorAt(1, not_js_value); |
| 11442 current_block()->Finish(typecheck); | 11339 current_block()->Finish(typecheck); |
| 11443 not_js_value->Goto(join); | 11340 not_js_value->Goto(join); |
| 11444 | 11341 |
| 11445 // Create in-object property store to kValueOffset. | 11342 // Create in-object property store to kValueOffset. |
| 11446 set_current_block(if_js_value); | 11343 set_current_block(if_js_value); |
| 11447 Handle<String> name = isolate()->factory()->undefined_string(); | 11344 AddStore(object, |
| 11448 AddInstruction(new(zone()) HStoreNamedField(object, | 11345 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); |
| 11449 name, | |
| 11450 value, | |
| 11451 true, // in-object store. | |
| 11452 Representation::Tagged(), | |
| 11453 JSValue::kValueOffset)); | |
| 11454 if_js_value->Goto(join); | 11346 if_js_value->Goto(join); |
| 11455 join->SetJoinId(call->id()); | 11347 join->SetJoinId(call->id()); |
| 11456 set_current_block(join); | 11348 set_current_block(join); |
| 11457 return ast_context()->ReturnValue(value); | 11349 return ast_context()->ReturnValue(value); |
| 11458 } | 11350 } |
| 11459 | 11351 |
| 11460 | 11352 |
| 11461 // Fast support for charCodeAt(n). | 11353 // Fast support for charCodeAt(n). |
| 11462 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 11354 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
| 11463 ASSERT(call->arguments()->length() == 2); | 11355 ASSERT(call->arguments()->length() == 2); |
| (...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12418 } | 12310 } |
| 12419 } | 12311 } |
| 12420 | 12312 |
| 12421 #ifdef DEBUG | 12313 #ifdef DEBUG |
| 12422 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 12314 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 12423 if (allocator_ != NULL) allocator_->Verify(); | 12315 if (allocator_ != NULL) allocator_->Verify(); |
| 12424 #endif | 12316 #endif |
| 12425 } | 12317 } |
| 12426 | 12318 |
| 12427 } } // namespace v8::internal | 12319 } } // namespace v8::internal |
| OLD | NEW |