OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1166 capacity_checker.Else(); | 1166 capacity_checker.Else(); |
1167 | 1167 |
1168 environment()->Push(elements); | 1168 environment()->Push(elements); |
1169 capacity_checker.End(); | 1169 capacity_checker.End(); |
1170 | 1170 |
1171 if (is_js_array) { | 1171 if (is_js_array) { |
1172 HValue* new_length = AddInstruction( | 1172 HValue* new_length = AddInstruction( |
1173 HAdd::New(zone, context, length, graph_->GetConstant1())); | 1173 HAdd::New(zone, context, length, graph_->GetConstant1())); |
1174 new_length->ClearFlag(HValue::kCanOverflow); | 1174 new_length->ClearFlag(HValue::kCanOverflow); |
1175 | 1175 |
1176 Representation representation = IsFastElementsKind(kind) | 1176 AddStore(object, HObjectAccess::ForArrayLength(IsFastElementsKind(kind)), |
1177 ? Representation::Smi() : Representation::Tagged(); | 1177 new_length); |
1178 AddStore(object, HObjectAccess::ForArrayLength(), new_length, | |
1179 representation); | |
1180 } | 1178 } |
1181 | 1179 |
1182 length_checker.Else(); | 1180 length_checker.Else(); |
1183 | 1181 |
1184 Add<HBoundsCheck>(key, length); | 1182 Add<HBoundsCheck>(key, length); |
1185 environment()->Push(elements); | 1183 environment()->Push(elements); |
1186 | 1184 |
1187 length_checker.End(); | 1185 length_checker.End(); |
1188 | 1186 |
1189 return environment()->Pop(); | 1187 return environment()->Pop(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 HValue* elements = AddLoadElements(object, mapcheck); | 1245 HValue* elements = AddLoadElements(object, mapcheck); |
1248 if (is_store && (fast_elements || fast_smi_only_elements) && | 1246 if (is_store && (fast_elements || fast_smi_only_elements) && |
1249 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1247 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
1250 HCheckMaps* check_cow_map = HCheckMaps::New( | 1248 HCheckMaps* check_cow_map = HCheckMaps::New( |
1251 elements, isolate()->factory()->fixed_array_map(), zone); | 1249 elements, isolate()->factory()->fixed_array_map(), zone); |
1252 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1250 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1253 AddInstruction(check_cow_map); | 1251 AddInstruction(check_cow_map); |
1254 } | 1252 } |
1255 HInstruction* length = NULL; | 1253 HInstruction* length = NULL; |
1256 if (is_js_array) { | 1254 if (is_js_array) { |
1257 length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck, | 1255 length = AddLoad(object, HObjectAccess::ForArrayLength(true), mapcheck); |
1258 Representation::Smi()); | |
1259 } else { | 1256 } else { |
1260 length = AddLoadFixedArrayLength(elements); | 1257 length = AddLoadFixedArrayLength(elements); |
1261 } | 1258 } |
1262 length->set_type(HType::Smi()); | 1259 length->set_type(HType::Smi()); |
1263 HValue* checked_key = NULL; | 1260 HValue* checked_key = NULL; |
1264 if (IsExternalArrayElementsKind(elements_kind)) { | 1261 if (IsExternalArrayElementsKind(elements_kind)) { |
1265 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1262 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
1266 NoObservableSideEffectsScope no_effects(this); | 1263 NoObservableSideEffectsScope no_effects(this); |
1267 HLoadExternalArrayPointer* external_elements = | 1264 HLoadExternalArrayPointer* external_elements = |
1268 Add<HLoadExternalArrayPointer>(elements); | 1265 Add<HLoadExternalArrayPointer>(elements); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1366 | 1363 |
1367 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 1364 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
1368 ElementsKind kind, | 1365 ElementsKind kind, |
1369 HValue* capacity) { | 1366 HValue* capacity) { |
1370 Factory* factory = isolate()->factory(); | 1367 Factory* factory = isolate()->factory(); |
1371 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1368 Handle<Map> map = IsFastDoubleElementsKind(kind) |
1372 ? factory->fixed_double_array_map() | 1369 ? factory->fixed_double_array_map() |
1373 : factory->fixed_array_map(); | 1370 : factory->fixed_array_map(); |
1374 | 1371 |
1375 AddStoreMapConstant(elements, map); | 1372 AddStoreMapConstant(elements, map); |
1376 Representation representation = IsFastElementsKind(kind) | 1373 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity); |
1377 ? Representation::Smi() : Representation::Tagged(); | |
1378 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity, | |
1379 representation); | |
1380 } | 1374 } |
1381 | 1375 |
1382 | 1376 |
1383 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( | 1377 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
1384 HValue* context, | 1378 HValue* context, |
1385 ElementsKind kind, | 1379 ElementsKind kind, |
1386 HValue* capacity) { | 1380 HValue* capacity) { |
1387 HValue* new_elements = BuildAllocateElements(context, kind, capacity); | 1381 HValue* new_elements = BuildAllocateElements(context, kind, capacity); |
1388 BuildInitializeElementsHeader(new_elements, kind, capacity); | 1382 BuildInitializeElementsHeader(new_elements, kind, capacity); |
1389 return new_elements; | 1383 return new_elements; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1423 } | 1417 } |
1424 | 1418 |
1425 | 1419 |
1426 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 1420 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
1427 HValue* typecheck) { | 1421 HValue* typecheck) { |
1428 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); | 1422 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); |
1429 } | 1423 } |
1430 | 1424 |
1431 | 1425 |
1432 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { | 1426 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
1433 HLoadNamedField* instr = AddLoad(object, HObjectAccess::ForFixedArrayLength(), | 1427 return AddLoad(object, HObjectAccess::ForFixedArrayLength()); |
1434 NULL, Representation::Smi()); | |
1435 instr->set_type(HType::Smi()); | |
1436 return instr; | |
1437 } | 1428 } |
1438 | 1429 |
1439 | 1430 |
1440 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1431 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
1441 HValue* old_capacity) { | 1432 HValue* old_capacity) { |
1442 Zone* zone = this->zone(); | 1433 Zone* zone = this->zone(); |
1443 HValue* half_old_capacity = | 1434 HValue* half_old_capacity = |
1444 AddInstruction(HShr::New(zone, context, old_capacity, | 1435 AddInstruction(HShr::New(zone, context, old_capacity, |
1445 graph_->GetConstant1())); | 1436 graph_->GetConstant1())); |
1446 half_old_capacity->ClearFlag(HValue::kCanOverflow); | 1437 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1796 allocation_site_payload_(NULL), | 1787 allocation_site_payload_(NULL), |
1797 constructor_function_(constructor_function) { | 1788 constructor_function_(constructor_function) { |
1798 } | 1789 } |
1799 | 1790 |
1800 | 1791 |
1801 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 1792 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { |
1802 if (kind_ == GetInitialFastElementsKind()) { | 1793 if (kind_ == GetInitialFastElementsKind()) { |
1803 // No need for a context lookup if the kind_ matches the initial | 1794 // No need for a context lookup if the kind_ matches the initial |
1804 // map, because we can just load the map in that case. | 1795 // map, because we can just load the map in that case. |
1805 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1796 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1806 HInstruction* load = | 1797 return builder()->AddInstruction( |
1807 builder()->BuildLoadNamedField(constructor_function_, | 1798 builder()->BuildLoadNamedField(constructor_function_, access)); |
1808 access, | |
1809 Representation::Tagged()); | |
1810 return builder()->AddInstruction(load); | |
1811 } | 1799 } |
1812 | 1800 |
1813 HInstruction* native_context = builder()->BuildGetNativeContext(context); | 1801 HInstruction* native_context = builder()->BuildGetNativeContext(context); |
1814 HInstruction* index = builder()->Add<HConstant>( | 1802 HInstruction* index = builder()->Add<HConstant>( |
1815 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 1803 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
1816 | 1804 |
1817 HInstruction* map_array = builder()->Add<HLoadKeyed>( | 1805 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
1818 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1806 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1819 | 1807 |
1820 HInstruction* kind_index = builder()->Add<HConstant>(kind_); | 1808 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
1821 | 1809 |
1822 return builder()->Add<HLoadKeyed>( | 1810 return builder()->Add<HLoadKeyed>( |
1823 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1811 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1824 } | 1812 } |
1825 | 1813 |
1826 | 1814 |
1827 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1815 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
1828 // Find the map near the constructor function | 1816 // Find the map near the constructor function |
1829 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1817 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1830 return builder()->AddInstruction( | 1818 return builder()->AddInstruction( |
1831 builder()->BuildLoadNamedField(constructor_function_, | 1819 builder()->BuildLoadNamedField(constructor_function_, access)); |
1832 access, | |
1833 Representation::Tagged())); | |
1834 } | 1820 } |
1835 | 1821 |
1836 | 1822 |
1837 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1823 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
1838 HValue* length_node) { | 1824 HValue* length_node) { |
1839 HValue* context = builder()->environment()->LookupContext(); | 1825 HValue* context = builder()->environment()->LookupContext(); |
1840 ASSERT(length_node != NULL); | 1826 ASSERT(length_node != NULL); |
1841 | 1827 |
1842 int base_size = JSArray::kSize; | 1828 int base_size = JSArray::kSize; |
1843 if (mode_ == TRACK_ALLOCATION_SITE) { | 1829 if (mode_ == TRACK_ALLOCATION_SITE) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1928 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, | 1914 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, |
1929 graph()->GetConstant0(), capacity); | 1915 graph()->GetConstant0(), capacity); |
1930 } | 1916 } |
1931 | 1917 |
1932 return new_object; | 1918 return new_object; |
1933 } | 1919 } |
1934 | 1920 |
1935 | 1921 |
1936 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, | 1922 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, |
1937 HObjectAccess access, | 1923 HObjectAccess access, |
1938 HValue *val, | 1924 HValue *val) { |
1939 Representation representation) { | 1925 return Add<HStoreNamedField>(object, access, val); |
1940 return Add<HStoreNamedField>(object, access, val, representation); | |
1941 } | 1926 } |
1942 | 1927 |
1943 | 1928 |
1944 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, | 1929 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, |
1945 HObjectAccess access, | 1930 HObjectAccess access, |
1946 HValue *typecheck, | 1931 HValue *typecheck) { |
1947 Representation representation) { | 1932 return Add<HLoadNamedField>(object, access, typecheck); |
1948 return Add<HLoadNamedField>(object, access, typecheck, representation); | |
1949 } | 1933 } |
1950 | 1934 |
1951 | 1935 |
1952 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 1936 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
1953 Handle<Map> map) { | 1937 Handle<Map> map) { |
1954 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), | 1938 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), |
1955 Add<HConstant>(map)); | 1939 Add<HConstant>(map)); |
1956 } | 1940 } |
1957 | 1941 |
1958 | 1942 |
(...skipping 2827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4786 if (!is_store) return false; | 4770 if (!is_store) return false; |
4787 | 4771 |
4788 // 2nd chance: A store into a non-existent field can still be inlined if we | 4772 // 2nd chance: A store into a non-existent field can still be inlined if we |
4789 // have a matching transition and some room left in the object. | 4773 // have a matching transition and some room left in the object. |
4790 type->LookupTransition(NULL, *name, lookup); | 4774 type->LookupTransition(NULL, *name, lookup); |
4791 return lookup->IsTransitionToField(*type) && | 4775 return lookup->IsTransitionToField(*type) && |
4792 (type->unused_property_fields() > 0); | 4776 (type->unused_property_fields() > 0); |
4793 } | 4777 } |
4794 | 4778 |
4795 | 4779 |
4796 static Representation ComputeLoadStoreRepresentation(Handle<Map> type, | |
4797 LookupResult* lookup) { | |
4798 if (lookup->IsField()) { | |
4799 return lookup->representation(); | |
4800 } else { | |
4801 Map* transition = lookup->GetTransitionMapFromMap(*type); | |
4802 int descriptor = transition->LastAdded(); | |
4803 PropertyDetails details = | |
4804 transition->instance_descriptors()->GetDetails(descriptor); | |
4805 return details.representation(); | |
4806 } | |
4807 } | |
4808 | |
4809 | |
4810 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { | 4780 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { |
4811 BuildCheckHeapObject(object); | 4781 BuildCheckHeapObject(object); |
4812 AddInstruction(HCheckMaps::New(object, map, zone())); | 4782 AddInstruction(HCheckMaps::New(object, map, zone())); |
4813 } | 4783 } |
4814 | 4784 |
4815 | 4785 |
4816 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, | 4786 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
4817 Handle<Map> map) { | 4787 Handle<Map> map) { |
4818 BuildCheckHeapObject(object); | 4788 BuildCheckHeapObject(object); |
4819 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | 4789 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
(...skipping 30 matching lines...) Expand all Loading... |
4850 } | 4820 } |
4851 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 4821 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
4852 } | 4822 } |
4853 ASSERT(proto->IsJSObject()); | 4823 ASSERT(proto->IsJSObject()); |
4854 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), | 4824 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), |
4855 Handle<JSObject>(JSObject::cast(proto)), | 4825 Handle<JSObject>(JSObject::cast(proto)), |
4856 zone(), top_info()); | 4826 zone(), top_info()); |
4857 } | 4827 } |
4858 | 4828 |
4859 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 4829 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
4860 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | |
4861 bool transition_to_field = lookup->IsTransitionToField(*map); | 4830 bool transition_to_field = lookup->IsTransitionToField(*map); |
4862 | 4831 |
4863 HStoreNamedField *instr; | 4832 HStoreNamedField *instr; |
4864 if (FLAG_track_double_fields && representation.IsDouble()) { | 4833 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { |
| 4834 HObjectAccess heap_number_access = |
| 4835 field_access.WithRepresentation(Representation::Tagged()); |
4865 if (transition_to_field) { | 4836 if (transition_to_field) { |
4866 // The store requires a mutable HeapNumber to be allocated. | 4837 // The store requires a mutable HeapNumber to be allocated. |
4867 NoObservableSideEffectsScope no_side_effects(this); | 4838 NoObservableSideEffectsScope no_side_effects(this); |
4868 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); | 4839 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); |
4869 HInstruction* double_box = Add<HAllocate>( | 4840 HInstruction* heap_number = Add<HAllocate>( |
4870 environment()->LookupContext(), heap_number_size, | 4841 environment()->LookupContext(), heap_number_size, |
4871 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); | 4842 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); |
4872 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); | 4843 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); |
4873 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 4844 AddStore(heap_number, HObjectAccess::ForHeapNumberValue(), value); |
4874 value, Representation::Double()); | 4845 instr = new(zone()) HStoreNamedField( |
4875 instr = new(zone()) HStoreNamedField(object, field_access, double_box); | 4846 object, heap_number_access, heap_number); |
4876 } else { | 4847 } else { |
4877 // Already holds a HeapNumber; load the box and write its value field. | 4848 // Already holds a HeapNumber; load the box and write its value field. |
4878 HInstruction* double_box = AddLoad(object, field_access); | 4849 HInstruction* heap_number = AddLoad(object, heap_number_access); |
4879 double_box->set_type(HType::HeapNumber()); | 4850 heap_number->set_type(HType::HeapNumber()); |
4880 instr = new(zone()) HStoreNamedField(double_box, | 4851 instr = new(zone()) HStoreNamedField(heap_number, |
4881 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); | 4852 HObjectAccess::ForHeapNumberValue(), value); |
4882 } | 4853 } |
4883 } else { | 4854 } else { |
4884 // This is a non-double store. | 4855 // This is a normal store. |
4885 instr = new(zone()) HStoreNamedField( | 4856 instr = new(zone()) HStoreNamedField(object, field_access, value); |
4886 object, field_access, value, representation); | |
4887 } | 4857 } |
4888 | 4858 |
4889 if (transition_to_field) { | 4859 if (transition_to_field) { |
4890 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 4860 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
4891 instr->SetTransition(transition, top_info()); | 4861 instr->SetTransition(transition, top_info()); |
4892 // TODO(fschneider): Record the new map type of the object in the IR to | 4862 // TODO(fschneider): Record the new map type of the object in the IR to |
4893 // enable elimination of redundant checks after the transition store. | 4863 // enable elimination of redundant checks after the transition store. |
4894 instr->SetGVNFlag(kChangesMaps); | 4864 instr->SetGVNFlag(kChangesMaps); |
4895 } | 4865 } |
4896 return instr; | 4866 return instr; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4945 Property* expr, | 4915 Property* expr, |
4946 HValue* object, | 4916 HValue* object, |
4947 SmallMapList* types, | 4917 SmallMapList* types, |
4948 Handle<String> name) { | 4918 Handle<String> name) { |
4949 // Use monomorphic load if property lookup results in the same field index | 4919 // Use monomorphic load if property lookup results in the same field index |
4950 // for all maps. Requires special map check on the set of all handled maps. | 4920 // for all maps. Requires special map check on the set of all handled maps. |
4951 if (types->length() > kMaxLoadPolymorphism) return NULL; | 4921 if (types->length() > kMaxLoadPolymorphism) return NULL; |
4952 | 4922 |
4953 LookupResult lookup(isolate()); | 4923 LookupResult lookup(isolate()); |
4954 int count; | 4924 int count; |
4955 Representation representation = Representation::None(); | |
4956 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 4925 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
4957 for (count = 0; count < types->length(); ++count) { | 4926 for (count = 0; count < types->length(); ++count) { |
4958 Handle<Map> map = types->at(count); | 4927 Handle<Map> map = types->at(count); |
4959 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 4928 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
4960 | 4929 |
4961 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 4930 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
4962 Representation new_representation = | |
4963 ComputeLoadStoreRepresentation(map, &lookup); | |
4964 | 4931 |
4965 if (count == 0) { | 4932 if (count == 0) { |
4966 // First time through the loop; set access and representation. | 4933 // First time through the loop; set access and representation. |
4967 access = new_access; | 4934 access = new_access; |
4968 } else if (!representation.IsCompatibleForLoad(new_representation)) { | 4935 } else if (!access.representation().IsCompatibleForLoad( |
| 4936 new_access.representation())) { |
4969 // Representations did not match. | 4937 // Representations did not match. |
4970 break; | 4938 break; |
4971 } else if (access.offset() != new_access.offset()) { | 4939 } else if (access.offset() != new_access.offset()) { |
4972 // Offsets did not match. | 4940 // Offsets did not match. |
4973 break; | 4941 break; |
4974 } else if (access.IsInobject() != new_access.IsInobject()) { | 4942 } else if (access.IsInobject() != new_access.IsInobject()) { |
4975 // In-objectness did not match. | 4943 // In-objectness did not match. |
4976 break; | 4944 break; |
4977 } | 4945 } |
4978 representation = representation.generalize(new_representation); | 4946 access = access.WithRepresentation( |
| 4947 access.representation().generalize(new_access.representation())); |
4979 } | 4948 } |
4980 | 4949 |
4981 if (count == types->length()) { | 4950 if (count == types->length()) { |
4982 // Everything matched; can use monomorphic load. | 4951 // Everything matched; can use monomorphic load. |
4983 BuildCheckHeapObject(object); | 4952 BuildCheckHeapObject(object); |
4984 AddInstruction(HCheckMaps::New(object, types, zone())); | 4953 AddInstruction(HCheckMaps::New(object, types, zone())); |
4985 return BuildLoadNamedField(object, access, representation); | 4954 return BuildLoadNamedField(object, access); |
4986 } | 4955 } |
4987 | 4956 |
4988 if (count != 0) return NULL; | 4957 if (count != 0) return NULL; |
4989 | 4958 |
4990 // Second chance: the property is on the prototype and all maps have the | 4959 // Second chance: the property is on the prototype and all maps have the |
4991 // same prototype. | 4960 // same prototype. |
4992 Handle<Map> map(types->at(0)); | 4961 Handle<Map> map(types->at(0)); |
4993 if (map->has_named_interceptor()) return NULL; | 4962 if (map->has_named_interceptor()) return NULL; |
4994 if (map->is_dictionary_map()) return NULL; | 4963 if (map->is_dictionary_map()) return NULL; |
4995 | 4964 |
4996 Handle<Object> prototype(map->prototype(), isolate()); | 4965 Handle<Object> prototype(map->prototype(), isolate()); |
4997 for (count = 1; count < types->length(); ++count) { | 4966 for (count = 1; count < types->length(); ++count) { |
4998 Handle<Map> test_map(types->at(count)); | 4967 Handle<Map> test_map(types->at(count)); |
4999 // Ensure the property is on the prototype, not the object itself. | 4968 // Ensure the property is on the prototype, not the object itself. |
5000 if (map->has_named_interceptor()) return NULL; | 4969 if (map->has_named_interceptor()) return NULL; |
5001 if (test_map->is_dictionary_map()) return NULL; | 4970 if (test_map->is_dictionary_map()) return NULL; |
5002 test_map->LookupDescriptor(NULL, *name, &lookup); | 4971 test_map->LookupDescriptor(NULL, *name, &lookup); |
5003 if (lookup.IsFound()) return NULL; | 4972 if (lookup.IsFound()) return NULL; |
5004 if (test_map->prototype() != *prototype) return NULL; | 4973 if (test_map->prototype() != *prototype) return NULL; |
5005 } | 4974 } |
5006 | 4975 |
5007 LookupInPrototypes(map, name, &lookup); | 4976 LookupInPrototypes(map, name, &lookup); |
5008 if (!lookup.IsField()) return NULL; | 4977 if (!lookup.IsField()) return NULL; |
5009 | 4978 |
5010 BuildCheckHeapObject(object); | 4979 BuildCheckHeapObject(object); |
5011 AddInstruction(HCheckMaps::New(object, types, zone())); | 4980 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 4981 |
5012 Handle<JSObject> holder(lookup.holder()); | 4982 Handle<JSObject> holder(lookup.holder()); |
5013 Handle<Map> holder_map(holder->map()); | 4983 Handle<Map> holder_map(holder->map()); |
5014 AddInstruction(new(zone()) HCheckPrototypeMaps( | 4984 AddInstruction(new(zone()) HCheckPrototypeMaps( |
5015 Handle<JSObject>::cast(prototype), holder, zone(), top_info())); | 4985 Handle<JSObject>::cast(prototype), holder, zone(), top_info())); |
5016 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); | 4986 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); |
5017 return BuildLoadNamedField(holder_value, | 4987 return BuildLoadNamedField(holder_value, |
5018 HObjectAccess::ForField(holder_map, &lookup, name), | 4988 HObjectAccess::ForField(holder_map, &lookup, name)); |
5019 ComputeLoadStoreRepresentation(map, &lookup)); | |
5020 } | 4989 } |
5021 | 4990 |
5022 | 4991 |
5023 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4992 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
5024 Property* expr, | 4993 Property* expr, |
5025 HValue* object, | 4994 HValue* object, |
5026 SmallMapList* types, | 4995 SmallMapList* types, |
5027 Handle<String> name) { | 4996 Handle<String> name) { |
5028 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( | 4997 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( |
5029 expr, object, types, name); | 4998 expr, object, types, name); |
(...skipping 26 matching lines...) Expand all Loading... |
5056 LookupResult lookup(isolate()); | 5025 LookupResult lookup(isolate()); |
5057 int count; | 5026 int count; |
5058 Representation representation = Representation::None(); | 5027 Representation representation = Representation::None(); |
5059 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 5028 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
5060 for (count = 0; count < types->length(); ++count) { | 5029 for (count = 0; count < types->length(); ++count) { |
5061 Handle<Map> map = types->at(count); | 5030 Handle<Map> map = types->at(count); |
5062 // Pass false to ignore transitions. | 5031 // Pass false to ignore transitions. |
5063 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 5032 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
5064 | 5033 |
5065 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 5034 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
5066 Representation new_representation = | 5035 Representation new_representation = new_access.representation(); |
5067 ComputeLoadStoreRepresentation(map, &lookup); | |
5068 | 5036 |
5069 if (count == 0) { | 5037 if (count == 0) { |
5070 // First time through the loop; set access and representation. | 5038 // First time through the loop; set access and representation. |
5071 access = new_access; | 5039 access = new_access; |
5072 representation = new_representation; | 5040 representation = new_representation; |
5073 } else if (!representation.IsCompatibleForStore(new_representation)) { | 5041 } else if (!representation.IsCompatibleForStore(new_representation)) { |
5074 // Representations did not match. | 5042 // Representations did not match. |
5075 break; | 5043 break; |
5076 } else if (access.offset() != new_access.offset()) { | 5044 } else if (access.offset() != new_access.offset()) { |
5077 // Offsets did not match. | 5045 // Offsets did not match. |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5639 HValue* context = environment()->LookupContext(); | 5607 HValue* context = environment()->LookupContext(); |
5640 HValue* value = environment()->Pop(); | 5608 HValue* value = environment()->Pop(); |
5641 HThrow* instr = Add<HThrow>(context, value); | 5609 HThrow* instr = Add<HThrow>(context, value); |
5642 instr->set_position(expr->position()); | 5610 instr->set_position(expr->position()); |
5643 AddSimulate(expr->id()); | 5611 AddSimulate(expr->id()); |
5644 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5612 current_block()->FinishExit(new(zone()) HAbnormalExit); |
5645 set_current_block(NULL); | 5613 set_current_block(NULL); |
5646 } | 5614 } |
5647 | 5615 |
5648 | 5616 |
5649 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( | 5617 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
5650 HValue* object, | 5618 HObjectAccess access) { |
5651 HObjectAccess access, | 5619 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
5652 Representation representation) { | 5620 // load the heap number |
5653 bool load_double = false; | 5621 HLoadNamedField* heap_number = |
5654 if (representation.IsDouble()) { | 5622 AddLoad(object, access.WithRepresentation(Representation::Tagged())); |
5655 representation = Representation::Tagged(); | 5623 heap_number->set_type(HType::HeapNumber()); |
5656 load_double = FLAG_track_double_fields; | 5624 // load the double value from it |
| 5625 return new(zone()) HLoadNamedField(heap_number, |
| 5626 HObjectAccess::ForHeapNumberValue(), NULL); |
5657 } | 5627 } |
5658 HLoadNamedField* field = | 5628 return new(zone()) HLoadNamedField(object, access, NULL); |
5659 new(zone()) HLoadNamedField(object, access, NULL, representation); | |
5660 if (load_double) { | |
5661 AddInstruction(field); | |
5662 field->set_type(HType::HeapNumber()); | |
5663 return new(zone()) HLoadNamedField(field, | |
5664 HObjectAccess::ForHeapNumberValue(), NULL, Representation::Double()); | |
5665 } | |
5666 return field; | |
5667 } | 5629 } |
5668 | 5630 |
5669 | 5631 |
5670 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5632 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
5671 HValue* object, | 5633 HValue* object, |
5672 Handle<String> name, | 5634 Handle<String> name, |
5673 Property* expr) { | 5635 Property* expr) { |
5674 if (expr->IsUninitialized()) { | 5636 if (expr->IsUninitialized()) { |
5675 AddSoftDeoptimize(); | 5637 AddSoftDeoptimize(); |
5676 } | 5638 } |
(...skipping 28 matching lines...) Expand all Loading... |
5705 return new(zone()) HLoadNamedField(object, | 5667 return new(zone()) HLoadNamedField(object, |
5706 HObjectAccess::ForArrayLength()); | 5668 HObjectAccess::ForArrayLength()); |
5707 } | 5669 } |
5708 } | 5670 } |
5709 | 5671 |
5710 LookupResult lookup(isolate()); | 5672 LookupResult lookup(isolate()); |
5711 map->LookupDescriptor(NULL, *name, &lookup); | 5673 map->LookupDescriptor(NULL, *name, &lookup); |
5712 if (lookup.IsField()) { | 5674 if (lookup.IsField()) { |
5713 AddCheckMap(object, map); | 5675 AddCheckMap(object, map); |
5714 return BuildLoadNamedField(object, | 5676 return BuildLoadNamedField(object, |
5715 HObjectAccess::ForField(map, &lookup, name), | 5677 HObjectAccess::ForField(map, &lookup, name)); |
5716 ComputeLoadStoreRepresentation(map, &lookup)); | |
5717 } | 5678 } |
5718 | 5679 |
5719 // Handle a load of a constant known function. | 5680 // Handle a load of a constant known function. |
5720 if (lookup.IsConstantFunction()) { | 5681 if (lookup.IsConstantFunction()) { |
5721 AddCheckMap(object, map); | 5682 AddCheckMap(object, map); |
5722 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 5683 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
5723 return new(zone()) HConstant(function); | 5684 return new(zone()) HConstant(function); |
5724 } | 5685 } |
5725 | 5686 |
5726 // Handle a load from a known field somewhere in the prototype chain. | 5687 // Handle a load from a known field somewhere in the prototype chain. |
5727 LookupInPrototypes(map, name, &lookup); | 5688 LookupInPrototypes(map, name, &lookup); |
5728 if (lookup.IsField()) { | 5689 if (lookup.IsField()) { |
5729 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5690 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5730 Handle<JSObject> holder(lookup.holder()); | 5691 Handle<JSObject> holder(lookup.holder()); |
5731 Handle<Map> holder_map(holder->map()); | 5692 Handle<Map> holder_map(holder->map()); |
5732 AddCheckMap(object, map); | 5693 AddCheckMap(object, map); |
5733 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5694 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); |
5734 HValue* holder_value = Add<HConstant>(holder); | 5695 HValue* holder_value = Add<HConstant>(holder); |
5735 return BuildLoadNamedField(holder_value, | 5696 return BuildLoadNamedField(holder_value, |
5736 HObjectAccess::ForField(holder_map, &lookup, name), | 5697 HObjectAccess::ForField(holder_map, &lookup, name)); |
5737 ComputeLoadStoreRepresentation(map, &lookup)); | |
5738 } | 5698 } |
5739 | 5699 |
5740 // Handle a load of a constant function somewhere in the prototype chain. | 5700 // Handle a load of a constant function somewhere in the prototype chain. |
5741 if (lookup.IsConstantFunction()) { | 5701 if (lookup.IsConstantFunction()) { |
5742 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5702 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5743 Handle<JSObject> holder(lookup.holder()); | 5703 Handle<JSObject> holder(lookup.holder()); |
5744 Handle<Map> holder_map(holder->map()); | 5704 Handle<Map> holder_map(holder->map()); |
5745 AddCheckMap(object, map); | 5705 AddCheckMap(object, map); |
5746 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5706 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); |
5747 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 5707 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5999 // it's a keyed property) and registered in the full codegen. | 5959 // it's a keyed property) and registered in the full codegen. |
6000 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 5960 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
6001 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 5961 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
6002 HHasInstanceTypeAndBranch* typecheck = | 5962 HHasInstanceTypeAndBranch* typecheck = |
6003 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 5963 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
6004 typecheck->SetSuccessorAt(0, if_jsarray); | 5964 typecheck->SetSuccessorAt(0, if_jsarray); |
6005 typecheck->SetSuccessorAt(1, if_fastobject); | 5965 typecheck->SetSuccessorAt(1, if_fastobject); |
6006 current_block()->Finish(typecheck); | 5966 current_block()->Finish(typecheck); |
6007 | 5967 |
6008 set_current_block(if_jsarray); | 5968 set_current_block(if_jsarray); |
6009 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), | 5969 HInstruction* length = AddLoad(object, |
6010 typecheck, Representation::Smi()); | 5970 HObjectAccess::ForArrayLength(true), typecheck); |
6011 length->set_type(HType::Smi()); | 5971 length->set_type(HType::Smi()); |
6012 | 5972 |
6013 checked_key = Add<HBoundsCheck>(key, length); | 5973 checked_key = Add<HBoundsCheck>(key, length); |
6014 access = AddInstruction(BuildFastElementAccess( | 5974 access = AddInstruction(BuildFastElementAccess( |
6015 elements, checked_key, val, elements_kind_branch, | 5975 elements, checked_key, val, elements_kind_branch, |
6016 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); | 5976 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); |
6017 if (!is_store) { | 5977 if (!is_store) { |
6018 Push(access); | 5978 Push(access); |
6019 } | 5979 } |
6020 | 5980 |
(...skipping 2692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8713 AddStore(object_header, access, properties); | 8673 AddStore(object_header, access, properties); |
8714 | 8674 |
8715 if (boilerplate_object->IsJSArray()) { | 8675 if (boilerplate_object->IsJSArray()) { |
8716 Handle<JSArray> boilerplate_array = | 8676 Handle<JSArray> boilerplate_array = |
8717 Handle<JSArray>::cast(boilerplate_object); | 8677 Handle<JSArray>::cast(boilerplate_object); |
8718 Handle<Object> length_field = | 8678 Handle<Object> length_field = |
8719 Handle<Object>(boilerplate_array->length(), isolate()); | 8679 Handle<Object>(boilerplate_array->length(), isolate()); |
8720 HInstruction* length = Add<HConstant>(length_field); | 8680 HInstruction* length = Add<HConstant>(length_field); |
8721 | 8681 |
8722 ASSERT(boilerplate_array->length()->IsSmi()); | 8682 ASSERT(boilerplate_array->length()->IsSmi()); |
8723 Representation representation = | 8683 AddStore(object_header, HObjectAccess::ForArrayLength( |
8724 IsFastElementsKind(boilerplate_array->GetElementsKind()) | 8684 IsFastElementsKind(boilerplate_array->GetElementsKind())), |
8725 ? Representation::Smi() : Representation::Tagged(); | 8685 length); |
8726 AddStore(object_header, HObjectAccess::ForArrayLength(), | |
8727 length, representation); | |
8728 } | 8686 } |
8729 | 8687 |
8730 return result; | 8688 return result; |
8731 } | 8689 } |
8732 | 8690 |
8733 | 8691 |
8734 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 8692 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
8735 Handle<JSObject> boilerplate_object, | 8693 Handle<JSObject> boilerplate_object, |
8736 Handle<JSObject> original_boilerplate_object, | 8694 Handle<JSObject> original_boilerplate_object, |
8737 HValue* object_properties, | 8695 HValue* object_properties, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8783 if (data_target != NULL) { | 8741 if (data_target != NULL) { |
8784 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); | 8742 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); |
8785 *data_offset += HeapNumber::kSize; | 8743 *data_offset += HeapNumber::kSize; |
8786 } else { | 8744 } else { |
8787 double_box = Add<HInnerAllocatedObject>(target, *offset); | 8745 double_box = Add<HInnerAllocatedObject>(target, *offset); |
8788 *offset += HeapNumber::kSize; | 8746 *offset += HeapNumber::kSize; |
8789 } | 8747 } |
8790 AddStoreMapConstant(double_box, | 8748 AddStoreMapConstant(double_box, |
8791 isolate()->factory()->heap_number_map()); | 8749 isolate()->factory()->heap_number_map()); |
8792 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 8750 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
8793 value_instruction, Representation::Double()); | 8751 value_instruction); |
8794 value_instruction = double_box; | 8752 value_instruction = double_box; |
8795 } | 8753 } |
8796 | 8754 |
8797 AddStore(object_properties, access, value_instruction); | 8755 AddStore(object_properties, access, value_instruction); |
8798 } | 8756 } |
8799 } | 8757 } |
8800 | 8758 |
8801 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 8759 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
8802 HInstruction* value_instruction = | 8760 HInstruction* value_instruction = |
8803 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 8761 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
(...skipping 1372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10176 if (ShouldProduceTraceOutput()) { | 10134 if (ShouldProduceTraceOutput()) { |
10177 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10135 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
10178 } | 10136 } |
10179 | 10137 |
10180 #ifdef DEBUG | 10138 #ifdef DEBUG |
10181 graph_->Verify(false); // No full verify. | 10139 graph_->Verify(false); // No full verify. |
10182 #endif | 10140 #endif |
10183 } | 10141 } |
10184 | 10142 |
10185 } } // namespace v8::internal | 10143 } } // namespace v8::internal |
OLD | NEW |