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 1141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1152 capacity_checker.Else(); | 1152 capacity_checker.Else(); |
| 1153 | 1153 |
| 1154 environment()->Push(elements); | 1154 environment()->Push(elements); |
| 1155 capacity_checker.End(); | 1155 capacity_checker.End(); |
| 1156 | 1156 |
| 1157 if (is_js_array) { | 1157 if (is_js_array) { |
| 1158 HValue* new_length = AddInstruction( | 1158 HValue* new_length = AddInstruction( |
| 1159 HAdd::New(zone, context, length, graph_->GetConstant1())); | 1159 HAdd::New(zone, context, length, graph_->GetConstant1())); |
| 1160 new_length->ClearFlag(HValue::kCanOverflow); | 1160 new_length->ClearFlag(HValue::kCanOverflow); |
| 1161 | 1161 |
| 1162 Representation representation = IsFastElementsKind(kind) | 1162 AddStore(object, HObjectAccess::ForArrayLength(IsFastElementsKind(kind)), |
| 1163 ? Representation::Smi() : Representation::Tagged(); | 1163 new_length); |
| 1164 AddStore(object, HObjectAccess::ForArrayLength(), new_length, | |
| 1165 representation); | |
| 1166 } | 1164 } |
| 1167 | 1165 |
| 1168 length_checker.Else(); | 1166 length_checker.Else(); |
| 1169 | 1167 |
| 1170 Add<HBoundsCheck>(key, length); | 1168 Add<HBoundsCheck>(key, length); |
| 1171 environment()->Push(elements); | 1169 environment()->Push(elements); |
| 1172 | 1170 |
| 1173 length_checker.End(); | 1171 length_checker.End(); |
| 1174 | 1172 |
| 1175 return environment()->Pop(); | 1173 return environment()->Pop(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1234 HValue* elements = AddLoadElements(object, mapcheck); | 1232 HValue* elements = AddLoadElements(object, mapcheck); |
| 1235 if (is_store && (fast_elements || fast_smi_only_elements) && | 1233 if (is_store && (fast_elements || fast_smi_only_elements) && |
| 1236 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1234 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 1237 HCheckMaps* check_cow_map = HCheckMaps::New( | 1235 HCheckMaps* check_cow_map = HCheckMaps::New( |
| 1238 elements, isolate()->factory()->fixed_array_map(), zone); | 1236 elements, isolate()->factory()->fixed_array_map(), zone); |
| 1239 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1237 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1240 AddInstruction(check_cow_map); | 1238 AddInstruction(check_cow_map); |
| 1241 } | 1239 } |
| 1242 HInstruction* length = NULL; | 1240 HInstruction* length = NULL; |
| 1243 if (is_js_array) { | 1241 if (is_js_array) { |
| 1244 length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck, | 1242 length = AddLoad(object, HObjectAccess::ForArrayLength(true), mapcheck); |
| 1245 Representation::Smi()); | |
| 1246 } else { | 1243 } else { |
| 1247 length = AddLoadFixedArrayLength(elements); | 1244 length = AddLoadFixedArrayLength(elements); |
| 1248 } | 1245 } |
| 1249 length->set_type(HType::Smi()); | 1246 length->set_type(HType::Smi()); |
| 1250 HValue* checked_key = NULL; | 1247 HValue* checked_key = NULL; |
| 1251 if (IsExternalArrayElementsKind(elements_kind)) { | 1248 if (IsExternalArrayElementsKind(elements_kind)) { |
| 1252 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1249 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 1253 NoObservableSideEffectsScope no_effects(this); | 1250 NoObservableSideEffectsScope no_effects(this); |
| 1254 HLoadExternalArrayPointer* external_elements = | 1251 HLoadExternalArrayPointer* external_elements = |
| 1255 Add<HLoadExternalArrayPointer>(elements); | 1252 Add<HLoadExternalArrayPointer>(elements); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1353 | 1350 |
| 1354 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 1351 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
| 1355 ElementsKind kind, | 1352 ElementsKind kind, |
| 1356 HValue* capacity) { | 1353 HValue* capacity) { |
| 1357 Factory* factory = isolate()->factory(); | 1354 Factory* factory = isolate()->factory(); |
| 1358 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1355 Handle<Map> map = IsFastDoubleElementsKind(kind) |
| 1359 ? factory->fixed_double_array_map() | 1356 ? factory->fixed_double_array_map() |
| 1360 : factory->fixed_array_map(); | 1357 : factory->fixed_array_map(); |
| 1361 | 1358 |
| 1362 AddStoreMapConstant(elements, map); | 1359 AddStoreMapConstant(elements, map); |
| 1363 Representation representation = IsFastElementsKind(kind) | 1360 AddStore(elements, |
| 1364 ? Representation::Smi() : Representation::Tagged(); | 1361 HObjectAccess::ForFixedArrayLength(IsFastElementsKind(kind)), capacity); |
|
danno
2013/07/08 11:12:25
This is always Smi()
| |
| 1365 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity, | |
| 1366 representation); | |
| 1367 } | 1362 } |
| 1368 | 1363 |
| 1369 | 1364 |
| 1370 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( | 1365 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
| 1371 HValue* context, | 1366 HValue* context, |
| 1372 ElementsKind kind, | 1367 ElementsKind kind, |
| 1373 HValue* capacity) { | 1368 HValue* capacity) { |
| 1374 HValue* new_elements = BuildAllocateElements(context, kind, capacity); | 1369 HValue* new_elements = BuildAllocateElements(context, kind, capacity); |
| 1375 BuildInitializeElementsHeader(new_elements, kind, capacity); | 1370 BuildInitializeElementsHeader(new_elements, kind, capacity); |
| 1376 return new_elements; | 1371 return new_elements; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1410 } | 1405 } |
| 1411 | 1406 |
| 1412 | 1407 |
| 1413 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 1408 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
| 1414 HValue* typecheck) { | 1409 HValue* typecheck) { |
| 1415 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); | 1410 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); |
| 1416 } | 1411 } |
| 1417 | 1412 |
| 1418 | 1413 |
| 1419 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { | 1414 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
| 1420 HLoadNamedField* instr = AddLoad(object, HObjectAccess::ForFixedArrayLength(), | 1415 return AddLoad(object, HObjectAccess::ForFixedArrayLength(true)); |
| 1421 NULL, Representation::Smi()); | |
| 1422 instr->set_type(HType::Smi()); | |
| 1423 return instr; | |
| 1424 } | 1416 } |
| 1425 | 1417 |
| 1426 | 1418 |
| 1427 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1419 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
| 1428 HValue* old_capacity) { | 1420 HValue* old_capacity) { |
| 1429 Zone* zone = this->zone(); | 1421 Zone* zone = this->zone(); |
| 1430 HValue* half_old_capacity = | 1422 HValue* half_old_capacity = |
| 1431 AddInstruction(HShr::New(zone, context, old_capacity, | 1423 AddInstruction(HShr::New(zone, context, old_capacity, |
| 1432 graph_->GetConstant1())); | 1424 graph_->GetConstant1())); |
| 1433 half_old_capacity->ClearFlag(HValue::kCanOverflow); | 1425 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1747 allocation_site_payload_(NULL), | 1739 allocation_site_payload_(NULL), |
| 1748 constructor_function_(constructor_function) { | 1740 constructor_function_(constructor_function) { |
| 1749 } | 1741 } |
| 1750 | 1742 |
| 1751 | 1743 |
| 1752 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 1744 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { |
| 1753 if (kind_ == GetInitialFastElementsKind()) { | 1745 if (kind_ == GetInitialFastElementsKind()) { |
| 1754 // No need for a context lookup if the kind_ matches the initial | 1746 // No need for a context lookup if the kind_ matches the initial |
| 1755 // map, because we can just load the map in that case. | 1747 // map, because we can just load the map in that case. |
| 1756 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1748 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 1757 HInstruction* load = | 1749 return builder()->AddInstruction( |
| 1758 builder()->BuildLoadNamedField(constructor_function_, | 1750 builder()->BuildLoadNamedField(constructor_function_, access)); |
| 1759 access, | |
| 1760 Representation::Tagged()); | |
| 1761 return builder()->AddInstruction(load); | |
| 1762 } | 1751 } |
| 1763 | 1752 |
| 1764 HInstruction* native_context = builder()->BuildGetNativeContext(context); | 1753 HInstruction* native_context = builder()->BuildGetNativeContext(context); |
| 1765 HInstruction* index = builder()->Add<HConstant>( | 1754 HInstruction* index = builder()->Add<HConstant>( |
| 1766 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 1755 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
| 1767 | 1756 |
| 1768 HInstruction* map_array = builder()->Add<HLoadKeyed>( | 1757 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
| 1769 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1758 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1770 | 1759 |
| 1771 HInstruction* kind_index = builder()->Add<HConstant>(kind_); | 1760 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
| 1772 | 1761 |
| 1773 return builder()->Add<HLoadKeyed>( | 1762 return builder()->Add<HLoadKeyed>( |
| 1774 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1763 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1775 } | 1764 } |
| 1776 | 1765 |
| 1777 | 1766 |
| 1778 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1767 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
| 1779 // Find the map near the constructor function | 1768 // Find the map near the constructor function |
| 1780 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1769 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 1781 return builder()->AddInstruction( | 1770 return builder()->AddInstruction( |
| 1782 builder()->BuildLoadNamedField(constructor_function_, | 1771 builder()->BuildLoadNamedField(constructor_function_, access)); |
| 1783 access, | |
| 1784 Representation::Tagged())); | |
| 1785 } | 1772 } |
| 1786 | 1773 |
| 1787 | 1774 |
| 1788 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1775 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
| 1789 HValue* length_node) { | 1776 HValue* length_node) { |
| 1790 HValue* context = builder()->environment()->LookupContext(); | 1777 HValue* context = builder()->environment()->LookupContext(); |
| 1791 ASSERT(length_node != NULL); | 1778 ASSERT(length_node != NULL); |
| 1792 | 1779 |
| 1793 int base_size = JSArray::kSize; | 1780 int base_size = JSArray::kSize; |
| 1794 if (mode_ == TRACK_ALLOCATION_SITE) { | 1781 if (mode_ == TRACK_ALLOCATION_SITE) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1879 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, | 1866 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, |
| 1880 graph()->GetConstant0(), capacity); | 1867 graph()->GetConstant0(), capacity); |
| 1881 } | 1868 } |
| 1882 | 1869 |
| 1883 return new_object; | 1870 return new_object; |
| 1884 } | 1871 } |
| 1885 | 1872 |
| 1886 | 1873 |
| 1887 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, | 1874 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, |
| 1888 HObjectAccess access, | 1875 HObjectAccess access, |
| 1889 HValue *val, | 1876 HValue *val) { |
| 1890 Representation representation) { | 1877 return Add<HStoreNamedField>(object, access, val); |
| 1891 return Add<HStoreNamedField>(object, access, val, representation); | |
| 1892 } | 1878 } |
| 1893 | 1879 |
| 1894 | 1880 |
| 1895 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, | 1881 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, |
| 1896 HObjectAccess access, | 1882 HObjectAccess access, |
| 1897 HValue *typecheck, | 1883 HValue *typecheck) { |
| 1898 Representation representation) { | 1884 return Add<HLoadNamedField>(object, access, typecheck); |
| 1899 return Add<HLoadNamedField>(object, access, typecheck, representation); | |
| 1900 } | 1885 } |
| 1901 | 1886 |
| 1902 | 1887 |
| 1903 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 1888 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
| 1904 Handle<Map> map) { | 1889 Handle<Map> map) { |
| 1905 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), | 1890 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), |
| 1906 Add<HConstant>(map)); | 1891 Add<HConstant>(map)); |
| 1907 } | 1892 } |
| 1908 | 1893 |
| 1909 | 1894 |
| (...skipping 3776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5686 if (!is_store) return false; | 5671 if (!is_store) return false; |
| 5687 | 5672 |
| 5688 // 2nd chance: A store into a non-existent field can still be inlined if we | 5673 // 2nd chance: A store into a non-existent field can still be inlined if we |
| 5689 // have a matching transition and some room left in the object. | 5674 // have a matching transition and some room left in the object. |
| 5690 type->LookupTransition(NULL, *name, lookup); | 5675 type->LookupTransition(NULL, *name, lookup); |
| 5691 return lookup->IsTransitionToField(*type) && | 5676 return lookup->IsTransitionToField(*type) && |
| 5692 (type->unused_property_fields() > 0); | 5677 (type->unused_property_fields() > 0); |
| 5693 } | 5678 } |
| 5694 | 5679 |
| 5695 | 5680 |
| 5696 static Representation ComputeLoadStoreRepresentation(Handle<Map> type, | |
| 5697 LookupResult* lookup) { | |
| 5698 if (lookup->IsField()) { | |
| 5699 return lookup->representation(); | |
| 5700 } else { | |
| 5701 Map* transition = lookup->GetTransitionMapFromMap(*type); | |
| 5702 int descriptor = transition->LastAdded(); | |
| 5703 PropertyDetails details = | |
| 5704 transition->instance_descriptors()->GetDetails(descriptor); | |
| 5705 return details.representation(); | |
| 5706 } | |
| 5707 } | |
| 5708 | |
| 5709 | |
| 5710 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { | 5681 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { |
| 5711 BuildCheckHeapObject(object); | 5682 BuildCheckHeapObject(object); |
| 5712 AddInstruction(HCheckMaps::New(object, map, zone())); | 5683 AddInstruction(HCheckMaps::New(object, map, zone())); |
| 5713 } | 5684 } |
| 5714 | 5685 |
| 5715 | 5686 |
| 5716 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, | 5687 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
| 5717 Handle<Map> map) { | 5688 Handle<Map> map) { |
| 5718 BuildCheckHeapObject(object); | 5689 BuildCheckHeapObject(object); |
| 5719 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | 5690 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 5750 } | 5721 } |
| 5751 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 5722 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
| 5752 } | 5723 } |
| 5753 ASSERT(proto->IsJSObject()); | 5724 ASSERT(proto->IsJSObject()); |
| 5754 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), | 5725 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), |
| 5755 Handle<JSObject>(JSObject::cast(proto)), | 5726 Handle<JSObject>(JSObject::cast(proto)), |
| 5756 zone(), top_info()); | 5727 zone(), top_info()); |
| 5757 } | 5728 } |
| 5758 | 5729 |
| 5759 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 5730 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
| 5760 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | |
| 5761 bool transition_to_field = lookup->IsTransitionToField(*map); | 5731 bool transition_to_field = lookup->IsTransitionToField(*map); |
| 5762 | 5732 |
| 5763 HStoreNamedField *instr; | 5733 HStoreNamedField *instr; |
| 5764 if (FLAG_track_double_fields && representation.IsDouble()) { | 5734 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { |
| 5735 HObjectAccess heap_number_access = | |
| 5736 field_access.WithRepresentation(Representation::Tagged()); | |
| 5765 if (transition_to_field) { | 5737 if (transition_to_field) { |
| 5766 // The store requires a mutable HeapNumber to be allocated. | 5738 // The store requires a mutable HeapNumber to be allocated. |
| 5767 NoObservableSideEffectsScope no_side_effects(this); | 5739 NoObservableSideEffectsScope no_side_effects(this); |
| 5768 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); | 5740 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); |
| 5769 HInstruction* double_box = Add<HAllocate>( | 5741 HInstruction* heap_number = Add<HAllocate>( |
| 5770 environment()->LookupContext(), heap_number_size, | 5742 environment()->LookupContext(), heap_number_size, |
| 5771 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); | 5743 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); |
| 5772 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); | 5744 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); |
| 5773 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 5745 AddStore(heap_number, HObjectAccess::ForHeapNumberValue(), value); |
| 5774 value, Representation::Double()); | 5746 instr = new(zone()) HStoreNamedField( |
| 5775 instr = new(zone()) HStoreNamedField(object, field_access, double_box); | 5747 object, heap_number_access, heap_number); |
| 5776 } else { | 5748 } else { |
| 5777 // Already holds a HeapNumber; load the box and write its value field. | 5749 // Already holds a HeapNumber; load the box and write its value field. |
| 5778 HInstruction* double_box = AddLoad(object, field_access); | 5750 HInstruction* heap_number = AddLoad(object, heap_number_access); |
| 5779 double_box->set_type(HType::HeapNumber()); | 5751 heap_number->set_type(HType::HeapNumber()); |
| 5780 instr = new(zone()) HStoreNamedField(double_box, | 5752 instr = new(zone()) HStoreNamedField(heap_number, |
| 5781 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); | 5753 HObjectAccess::ForHeapNumberValue(), value); |
| 5782 } | 5754 } |
| 5783 } else { | 5755 } else { |
| 5784 // This is a non-double store. | 5756 // This is a normal store. |
| 5785 instr = new(zone()) HStoreNamedField( | 5757 instr = new(zone()) HStoreNamedField(object, field_access, value); |
| 5786 object, field_access, value, representation); | |
| 5787 } | 5758 } |
| 5788 | 5759 |
| 5789 if (transition_to_field) { | 5760 if (transition_to_field) { |
| 5790 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 5761 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 5791 instr->SetTransition(transition, top_info()); | 5762 instr->SetTransition(transition, top_info()); |
| 5792 // TODO(fschneider): Record the new map type of the object in the IR to | 5763 // TODO(fschneider): Record the new map type of the object in the IR to |
| 5793 // enable elimination of redundant checks after the transition store. | 5764 // enable elimination of redundant checks after the transition store. |
| 5794 instr->SetGVNFlag(kChangesMaps); | 5765 instr->SetGVNFlag(kChangesMaps); |
| 5795 } | 5766 } |
| 5796 return instr; | 5767 return instr; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5845 Property* expr, | 5816 Property* expr, |
| 5846 HValue* object, | 5817 HValue* object, |
| 5847 SmallMapList* types, | 5818 SmallMapList* types, |
| 5848 Handle<String> name) { | 5819 Handle<String> name) { |
| 5849 // Use monomorphic load if property lookup results in the same field index | 5820 // Use monomorphic load if property lookup results in the same field index |
| 5850 // for all maps. Requires special map check on the set of all handled maps. | 5821 // for all maps. Requires special map check on the set of all handled maps. |
| 5851 if (types->length() > kMaxLoadPolymorphism) return NULL; | 5822 if (types->length() > kMaxLoadPolymorphism) return NULL; |
| 5852 | 5823 |
| 5853 LookupResult lookup(isolate()); | 5824 LookupResult lookup(isolate()); |
| 5854 int count; | 5825 int count; |
| 5855 Representation representation = Representation::None(); | |
| 5856 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 5826 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| 5857 for (count = 0; count < types->length(); ++count) { | 5827 for (count = 0; count < types->length(); ++count) { |
| 5858 Handle<Map> map = types->at(count); | 5828 Handle<Map> map = types->at(count); |
| 5859 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 5829 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| 5860 | 5830 |
| 5861 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 5831 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| 5862 Representation new_representation = | |
| 5863 ComputeLoadStoreRepresentation(map, &lookup); | |
| 5864 | 5832 |
| 5865 if (count == 0) { | 5833 if (count == 0) { |
| 5866 // First time through the loop; set access and representation. | 5834 // First time through the loop; set access and representation. |
| 5867 access = new_access; | 5835 access = new_access; |
| 5868 } else if (!representation.IsCompatibleForLoad(new_representation)) { | 5836 } else if (!access.representation().IsCompatibleForLoad( |
| 5837 new_access.representation())) { | |
| 5869 // Representations did not match. | 5838 // Representations did not match. |
| 5870 break; | 5839 break; |
| 5871 } else if (access.offset() != new_access.offset()) { | 5840 } else if (access.offset() != new_access.offset()) { |
| 5872 // Offsets did not match. | 5841 // Offsets did not match. |
| 5873 break; | 5842 break; |
| 5874 } else if (access.IsInobject() != new_access.IsInobject()) { | 5843 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 5875 // In-objectness did not match. | 5844 // In-objectness did not match. |
| 5876 break; | 5845 break; |
| 5877 } | 5846 } |
| 5878 representation = representation.generalize(new_representation); | 5847 access = access.WithRepresentation( |
| 5848 access.representation().generalize(new_access.representation())); | |
| 5879 } | 5849 } |
| 5880 | 5850 |
| 5881 if (count != types->length()) return NULL; | 5851 if (count != types->length()) return NULL; |
| 5882 | 5852 |
| 5883 // Everything matched; can use monomorphic load. | 5853 // Everything matched; can use monomorphic load. |
| 5884 BuildCheckHeapObject(object); | 5854 BuildCheckHeapObject(object); |
| 5885 AddInstruction(HCheckMaps::New(object, types, zone())); | 5855 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 5886 return BuildLoadNamedField(object, access, representation); | 5856 return BuildLoadNamedField(object, access); |
| 5887 } | 5857 } |
| 5888 | 5858 |
| 5889 | 5859 |
| 5890 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 5860 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| 5891 Property* expr, | 5861 Property* expr, |
| 5892 HValue* object, | 5862 HValue* object, |
| 5893 SmallMapList* types, | 5863 SmallMapList* types, |
| 5894 Handle<String> name) { | 5864 Handle<String> name) { |
| 5895 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( | 5865 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( |
| 5896 expr, object, types, name); | 5866 expr, object, types, name); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 5923 LookupResult lookup(isolate()); | 5893 LookupResult lookup(isolate()); |
| 5924 int count; | 5894 int count; |
| 5925 Representation representation = Representation::None(); | 5895 Representation representation = Representation::None(); |
| 5926 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 5896 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| 5927 for (count = 0; count < types->length(); ++count) { | 5897 for (count = 0; count < types->length(); ++count) { |
| 5928 Handle<Map> map = types->at(count); | 5898 Handle<Map> map = types->at(count); |
| 5929 // Pass false to ignore transitions. | 5899 // Pass false to ignore transitions. |
| 5930 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 5900 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| 5931 | 5901 |
| 5932 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 5902 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| 5933 Representation new_representation = | 5903 Representation new_representation = new_access.representation(); |
| 5934 ComputeLoadStoreRepresentation(map, &lookup); | |
| 5935 | 5904 |
| 5936 if (count == 0) { | 5905 if (count == 0) { |
| 5937 // First time through the loop; set access and representation. | 5906 // First time through the loop; set access and representation. |
| 5938 access = new_access; | 5907 access = new_access; |
| 5939 representation = new_representation; | 5908 representation = new_representation; |
| 5940 } else if (!representation.IsCompatibleForStore(new_representation)) { | 5909 } else if (!representation.IsCompatibleForStore(new_representation)) { |
| 5941 // Representations did not match. | 5910 // Representations did not match. |
| 5942 break; | 5911 break; |
| 5943 } else if (access.offset() != new_access.offset()) { | 5912 } else if (access.offset() != new_access.offset()) { |
| 5944 // Offsets did not match. | 5913 // Offsets did not match. |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6493 HValue* context = environment()->LookupContext(); | 6462 HValue* context = environment()->LookupContext(); |
| 6494 HValue* value = environment()->Pop(); | 6463 HValue* value = environment()->Pop(); |
| 6495 HThrow* instr = Add<HThrow>(context, value); | 6464 HThrow* instr = Add<HThrow>(context, value); |
| 6496 instr->set_position(expr->position()); | 6465 instr->set_position(expr->position()); |
| 6497 AddSimulate(expr->id()); | 6466 AddSimulate(expr->id()); |
| 6498 current_block()->FinishExit(new(zone()) HAbnormalExit); | 6467 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 6499 set_current_block(NULL); | 6468 set_current_block(NULL); |
| 6500 } | 6469 } |
| 6501 | 6470 |
| 6502 | 6471 |
| 6503 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( | 6472 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 6504 HValue* object, | 6473 HObjectAccess access) { |
| 6505 HObjectAccess access, | 6474 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
| 6506 Representation representation) { | 6475 // load the heap number |
| 6507 bool load_double = false; | 6476 HLoadNamedField* heap_number = |
| 6508 if (representation.IsDouble()) { | 6477 AddLoad(object, access.WithRepresentation(Representation::Tagged())); |
| 6509 representation = Representation::Tagged(); | 6478 heap_number->set_type(HType::HeapNumber()); |
| 6510 load_double = FLAG_track_double_fields; | 6479 // load the double value from it |
| 6480 return new(zone()) HLoadNamedField(heap_number, | |
| 6481 HObjectAccess::ForHeapNumberValue(), NULL); | |
| 6511 } | 6482 } |
| 6512 HLoadNamedField* field = | 6483 return new(zone()) HLoadNamedField(object, access, NULL); |
| 6513 new(zone()) HLoadNamedField(object, access, NULL, representation); | |
| 6514 if (load_double) { | |
| 6515 AddInstruction(field); | |
| 6516 field->set_type(HType::HeapNumber()); | |
| 6517 return new(zone()) HLoadNamedField(field, | |
| 6518 HObjectAccess::ForHeapNumberValue(), NULL, Representation::Double()); | |
| 6519 } | |
| 6520 return field; | |
| 6521 } | 6484 } |
| 6522 | 6485 |
| 6523 | 6486 |
| 6524 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 6487 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 6525 HValue* object, | 6488 HValue* object, |
| 6526 Handle<String> name, | 6489 Handle<String> name, |
| 6527 Property* expr) { | 6490 Property* expr) { |
| 6528 if (expr->IsUninitialized()) { | 6491 if (expr->IsUninitialized()) { |
| 6529 AddSoftDeoptimize(); | 6492 AddSoftDeoptimize(); |
| 6530 } | 6493 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 6559 return new(zone()) HLoadNamedField(object, | 6522 return new(zone()) HLoadNamedField(object, |
| 6560 HObjectAccess::ForArrayLength()); | 6523 HObjectAccess::ForArrayLength()); |
| 6561 } | 6524 } |
| 6562 } | 6525 } |
| 6563 | 6526 |
| 6564 LookupResult lookup(isolate()); | 6527 LookupResult lookup(isolate()); |
| 6565 map->LookupDescriptor(NULL, *name, &lookup); | 6528 map->LookupDescriptor(NULL, *name, &lookup); |
| 6566 if (lookup.IsField()) { | 6529 if (lookup.IsField()) { |
| 6567 AddCheckMap(object, map); | 6530 AddCheckMap(object, map); |
| 6568 return BuildLoadNamedField(object, | 6531 return BuildLoadNamedField(object, |
| 6569 HObjectAccess::ForField(map, &lookup, name), | 6532 HObjectAccess::ForField(map, &lookup, name)); |
| 6570 ComputeLoadStoreRepresentation(map, &lookup)); | |
| 6571 } | 6533 } |
| 6572 | 6534 |
| 6573 // Handle a load of a constant known function. | 6535 // Handle a load of a constant known function. |
| 6574 if (lookup.IsConstantFunction()) { | 6536 if (lookup.IsConstantFunction()) { |
| 6575 AddCheckMap(object, map); | 6537 AddCheckMap(object, map); |
| 6576 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 6538 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
| 6577 return new(zone()) HConstant(function); | 6539 return new(zone()) HConstant(function); |
| 6578 } | 6540 } |
| 6579 | 6541 |
| 6580 // Handle a load from a known field somewhere in the prototype chain. | 6542 // Handle a load from a known field somewhere in the prototype chain. |
| 6581 LookupInPrototypes(map, name, &lookup); | 6543 LookupInPrototypes(map, name, &lookup); |
| 6582 if (lookup.IsField()) { | 6544 if (lookup.IsField()) { |
| 6583 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 6545 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 6584 Handle<JSObject> holder(lookup.holder()); | 6546 Handle<JSObject> holder(lookup.holder()); |
| 6585 Handle<Map> holder_map(holder->map()); | 6547 Handle<Map> holder_map(holder->map()); |
| 6586 AddCheckMap(object, map); | 6548 AddCheckMap(object, map); |
| 6587 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 6549 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); |
| 6588 HValue* holder_value = Add<HConstant>(holder); | 6550 HValue* holder_value = Add<HConstant>(holder); |
| 6589 return BuildLoadNamedField(holder_value, | 6551 return BuildLoadNamedField(holder_value, |
| 6590 HObjectAccess::ForField(holder_map, &lookup, name), | 6552 HObjectAccess::ForField(holder_map, &lookup, name)); |
| 6591 ComputeLoadStoreRepresentation(map, &lookup)); | |
| 6592 } | 6553 } |
| 6593 | 6554 |
| 6594 // Handle a load of a constant function somewhere in the prototype chain. | 6555 // Handle a load of a constant function somewhere in the prototype chain. |
| 6595 if (lookup.IsConstantFunction()) { | 6556 if (lookup.IsConstantFunction()) { |
| 6596 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 6557 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 6597 Handle<JSObject> holder(lookup.holder()); | 6558 Handle<JSObject> holder(lookup.holder()); |
| 6598 Handle<Map> holder_map(holder->map()); | 6559 Handle<Map> holder_map(holder->map()); |
| 6599 AddCheckMap(object, map); | 6560 AddCheckMap(object, map); |
| 6600 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 6561 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); |
| 6601 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 6562 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6853 // it's a keyed property) and registered in the full codegen. | 6814 // it's a keyed property) and registered in the full codegen. |
| 6854 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 6815 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
| 6855 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 6816 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
| 6856 HHasInstanceTypeAndBranch* typecheck = | 6817 HHasInstanceTypeAndBranch* typecheck = |
| 6857 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 6818 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
| 6858 typecheck->SetSuccessorAt(0, if_jsarray); | 6819 typecheck->SetSuccessorAt(0, if_jsarray); |
| 6859 typecheck->SetSuccessorAt(1, if_fastobject); | 6820 typecheck->SetSuccessorAt(1, if_fastobject); |
| 6860 current_block()->Finish(typecheck); | 6821 current_block()->Finish(typecheck); |
| 6861 | 6822 |
| 6862 set_current_block(if_jsarray); | 6823 set_current_block(if_jsarray); |
| 6863 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), | 6824 HInstruction* length = AddLoad(object, |
| 6864 typecheck, Representation::Smi()); | 6825 HObjectAccess::ForArrayLength(true), typecheck); |
| 6865 length->set_type(HType::Smi()); | 6826 length->set_type(HType::Smi()); |
| 6866 | 6827 |
| 6867 checked_key = Add<HBoundsCheck>(key, length); | 6828 checked_key = Add<HBoundsCheck>(key, length); |
| 6868 access = AddInstruction(BuildFastElementAccess( | 6829 access = AddInstruction(BuildFastElementAccess( |
| 6869 elements, checked_key, val, elements_kind_branch, | 6830 elements, checked_key, val, elements_kind_branch, |
| 6870 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); | 6831 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); |
| 6871 if (!is_store) { | 6832 if (!is_store) { |
| 6872 Push(access); | 6833 Push(access); |
| 6873 } | 6834 } |
| 6874 | 6835 |
| (...skipping 2704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9579 AddStore(object_header, access, properties); | 9540 AddStore(object_header, access, properties); |
| 9580 | 9541 |
| 9581 if (boilerplate_object->IsJSArray()) { | 9542 if (boilerplate_object->IsJSArray()) { |
| 9582 Handle<JSArray> boilerplate_array = | 9543 Handle<JSArray> boilerplate_array = |
| 9583 Handle<JSArray>::cast(boilerplate_object); | 9544 Handle<JSArray>::cast(boilerplate_object); |
| 9584 Handle<Object> length_field = | 9545 Handle<Object> length_field = |
| 9585 Handle<Object>(boilerplate_array->length(), isolate()); | 9546 Handle<Object>(boilerplate_array->length(), isolate()); |
| 9586 HInstruction* length = Add<HConstant>(length_field); | 9547 HInstruction* length = Add<HConstant>(length_field); |
| 9587 | 9548 |
| 9588 ASSERT(boilerplate_array->length()->IsSmi()); | 9549 ASSERT(boilerplate_array->length()->IsSmi()); |
| 9589 Representation representation = | 9550 AddStore(object_header, HObjectAccess::ForArrayLength( |
| 9590 IsFastElementsKind(boilerplate_array->GetElementsKind()) | 9551 IsFastElementsKind(boilerplate_array->GetElementsKind())), |
| 9591 ? Representation::Smi() : Representation::Tagged(); | 9552 length); |
| 9592 AddStore(object_header, HObjectAccess::ForArrayLength(), | |
| 9593 length, representation); | |
| 9594 } | 9553 } |
| 9595 | 9554 |
| 9596 return result; | 9555 return result; |
| 9597 } | 9556 } |
| 9598 | 9557 |
| 9599 | 9558 |
| 9600 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 9559 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| 9601 Handle<JSObject> boilerplate_object, | 9560 Handle<JSObject> boilerplate_object, |
| 9602 Handle<JSObject> original_boilerplate_object, | 9561 Handle<JSObject> original_boilerplate_object, |
| 9603 HValue* object_properties, | 9562 HValue* object_properties, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9648 if (data_target != NULL) { | 9607 if (data_target != NULL) { |
| 9649 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); | 9608 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); |
| 9650 *data_offset += HeapNumber::kSize; | 9609 *data_offset += HeapNumber::kSize; |
| 9651 } else { | 9610 } else { |
| 9652 double_box = Add<HInnerAllocatedObject>(target, *offset); | 9611 double_box = Add<HInnerAllocatedObject>(target, *offset); |
| 9653 *offset += HeapNumber::kSize; | 9612 *offset += HeapNumber::kSize; |
| 9654 } | 9613 } |
| 9655 AddStoreMapConstant(double_box, | 9614 AddStoreMapConstant(double_box, |
| 9656 isolate()->factory()->heap_number_map()); | 9615 isolate()->factory()->heap_number_map()); |
| 9657 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 9616 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
| 9658 value_instruction, Representation::Double()); | 9617 value_instruction); |
| 9659 value_instruction = double_box; | 9618 value_instruction = double_box; |
| 9660 } | 9619 } |
| 9661 | 9620 |
| 9662 AddStore(object_properties, access, value_instruction); | 9621 AddStore(object_properties, access, value_instruction); |
| 9663 } | 9622 } |
| 9664 } | 9623 } |
| 9665 | 9624 |
| 9666 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 9625 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
| 9667 HInstruction* value_instruction = | 9626 HInstruction* value_instruction = |
| 9668 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 9627 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
| (...skipping 1369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11038 if (ShouldProduceTraceOutput()) { | 10997 if (ShouldProduceTraceOutput()) { |
| 11039 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10998 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11040 } | 10999 } |
| 11041 | 11000 |
| 11042 #ifdef DEBUG | 11001 #ifdef DEBUG |
| 11043 graph_->Verify(false); // No full verify. | 11002 graph_->Verify(false); // No full verify. |
| 11044 #endif | 11003 #endif |
| 11045 } | 11004 } |
| 11046 | 11005 |
| 11047 } } // namespace v8::internal | 11006 } } // namespace v8::internal |
| OLD | NEW |