| 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 1173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1184 ElementsKind to_kind, | 1184 ElementsKind to_kind, |
| 1185 bool is_jsarray) { | 1185 bool is_jsarray) { |
| 1186 ASSERT(!IsFastHoleyElementsKind(from_kind) || | 1186 ASSERT(!IsFastHoleyElementsKind(from_kind) || |
| 1187 IsFastHoleyElementsKind(to_kind)); | 1187 IsFastHoleyElementsKind(to_kind)); |
| 1188 | 1188 |
| 1189 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { | 1189 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { |
| 1190 Add<HTrapAllocationMemento>(object); | 1190 Add<HTrapAllocationMemento>(object); |
| 1191 } | 1191 } |
| 1192 | 1192 |
| 1193 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { | 1193 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 1194 HInstruction* elements = AddLoadElements(object, NULL); | 1194 HInstruction* elements = AddLoadElements(object); |
| 1195 | 1195 |
| 1196 HInstruction* empty_fixed_array = Add<HConstant>( | 1196 HInstruction* empty_fixed_array = Add<HConstant>( |
| 1197 isolate()->factory()->empty_fixed_array()); | 1197 isolate()->factory()->empty_fixed_array()); |
| 1198 | 1198 |
| 1199 IfBuilder if_builder(this); | 1199 IfBuilder if_builder(this); |
| 1200 | 1200 |
| 1201 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); | 1201 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); |
| 1202 | 1202 |
| 1203 if_builder.Then(); | 1203 if_builder.Then(); |
| 1204 | 1204 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1215 } | 1215 } |
| 1216 | 1216 |
| 1217 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); | 1217 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); |
| 1218 } | 1218 } |
| 1219 | 1219 |
| 1220 | 1220 |
| 1221 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1221 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
| 1222 HValue* object, | 1222 HValue* object, |
| 1223 HValue* key, | 1223 HValue* key, |
| 1224 HValue* val, | 1224 HValue* val, |
| 1225 HCheckMaps* mapcheck, | 1225 HCheckMaps* checked_object, |
| 1226 bool is_js_array, | 1226 bool is_js_array, |
| 1227 ElementsKind elements_kind, | 1227 ElementsKind elements_kind, |
| 1228 bool is_store, | 1228 bool is_store, |
| 1229 LoadKeyedHoleMode load_mode, | 1229 LoadKeyedHoleMode load_mode, |
| 1230 KeyedAccessStoreMode store_mode) { | 1230 KeyedAccessStoreMode store_mode) { |
| 1231 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 1231 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
| 1232 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 1232 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
| 1233 // on a HElementsTransition instruction. The flag can also be removed if the | 1233 // on a HElementsTransition instruction. The flag can also be removed if the |
| 1234 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 1234 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
| 1235 // ElementsKind transitions. Finally, the dependency can be removed for stores | 1235 // ElementsKind transitions. Finally, the dependency can be removed for stores |
| 1236 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 1236 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
| 1237 // generated store code. | 1237 // generated store code. |
| 1238 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 1238 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
| 1239 (elements_kind == FAST_ELEMENTS && is_store)) { | 1239 (elements_kind == FAST_ELEMENTS && is_store)) { |
| 1240 if (mapcheck != NULL) { | 1240 if (checked_object != NULL) { |
| 1241 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 1241 checked_object->ClearGVNFlag(kDependsOnElementsKind); |
| 1242 } | 1242 } |
| 1243 } | 1243 } |
| 1244 if (checked_object != NULL) object = checked_object; |
| 1244 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 1245 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
| 1245 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 1246 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
| 1246 HValue* elements = AddLoadElements(object, mapcheck); | 1247 HValue* elements = AddLoadElements(object); |
| 1247 if (is_store && (fast_elements || fast_smi_only_elements) && | 1248 if (is_store && (fast_elements || fast_smi_only_elements) && |
| 1248 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1249 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 1249 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 1250 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
| 1250 elements, isolate()->factory()->fixed_array_map(), top_info()); | 1251 elements, isolate()->factory()->fixed_array_map(), top_info()); |
| 1251 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1252 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1252 } | 1253 } |
| 1253 HInstruction* length = NULL; | 1254 HInstruction* length = NULL; |
| 1254 if (is_js_array) { | 1255 if (is_js_array) { |
| 1255 length = Add<HLoadNamedField>(object, | 1256 length = Add<HLoadNamedField>( |
| 1256 HObjectAccess::ForArrayLength(elements_kind), mapcheck); | 1257 object, HObjectAccess::ForArrayLength(elements_kind)); |
| 1257 } else { | 1258 } else { |
| 1258 length = AddLoadFixedArrayLength(elements); | 1259 length = AddLoadFixedArrayLength(elements); |
| 1259 } | 1260 } |
| 1260 length->set_type(HType::Smi()); | 1261 length->set_type(HType::Smi()); |
| 1261 HValue* checked_key = NULL; | 1262 HValue* checked_key = NULL; |
| 1262 if (IsExternalArrayElementsKind(elements_kind)) { | 1263 if (IsExternalArrayElementsKind(elements_kind)) { |
| 1263 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1264 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 1264 NoObservableSideEffectsScope no_effects(this); | 1265 NoObservableSideEffectsScope no_effects(this); |
| 1265 HLoadExternalArrayPointer* external_elements = | 1266 HLoadExternalArrayPointer* external_elements = |
| 1266 Add<HLoadExternalArrayPointer>(elements); | 1267 Add<HLoadExternalArrayPointer>(elements); |
| 1267 IfBuilder length_checker(this); | 1268 IfBuilder length_checker(this); |
| 1268 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 1269 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
| 1269 length_checker.Then(); | 1270 length_checker.Then(); |
| 1270 IfBuilder negative_checker(this); | 1271 IfBuilder negative_checker(this); |
| 1271 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 1272 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
| 1272 key, graph()->GetConstant0(), Token::GTE); | 1273 key, graph()->GetConstant0(), Token::GTE); |
| 1273 negative_checker.Then(); | 1274 negative_checker.Then(); |
| 1274 HInstruction* result = AddExternalArrayElementAccess( | 1275 HInstruction* result = AddExternalArrayElementAccess( |
| 1275 external_elements, key, val, bounds_check, elements_kind, is_store); | 1276 external_elements, key, val, bounds_check, elements_kind, is_store); |
| 1276 negative_checker.ElseDeopt("Negative key encountered"); | 1277 negative_checker.ElseDeopt("Negative key encountered"); |
| 1277 length_checker.End(); | 1278 length_checker.End(); |
| 1278 return result; | 1279 return result; |
| 1279 } else { | 1280 } else { |
| 1280 ASSERT(store_mode == STANDARD_STORE); | 1281 ASSERT(store_mode == STANDARD_STORE); |
| 1281 checked_key = Add<HBoundsCheck>(key, length); | 1282 checked_key = Add<HBoundsCheck>(key, length); |
| 1282 HLoadExternalArrayPointer* external_elements = | 1283 HLoadExternalArrayPointer* external_elements = |
| 1283 Add<HLoadExternalArrayPointer>(elements); | 1284 Add<HLoadExternalArrayPointer>(elements); |
| 1284 return AddExternalArrayElementAccess( | 1285 return AddExternalArrayElementAccess( |
| 1285 external_elements, checked_key, val, | 1286 external_elements, checked_key, val, |
| 1286 mapcheck, elements_kind, is_store); | 1287 checked_object, elements_kind, is_store); |
| 1287 } | 1288 } |
| 1288 } | 1289 } |
| 1289 ASSERT(fast_smi_only_elements || | 1290 ASSERT(fast_smi_only_elements || |
| 1290 fast_elements || | 1291 fast_elements || |
| 1291 IsFastDoubleElementsKind(elements_kind)); | 1292 IsFastDoubleElementsKind(elements_kind)); |
| 1292 | 1293 |
| 1293 // In case val is stored into a fast smi array, assure that the value is a smi | 1294 // In case val is stored into a fast smi array, assure that the value is a smi |
| 1294 // before manipulating the backing store. Otherwise the actual store may | 1295 // before manipulating the backing store. Otherwise the actual store may |
| 1295 // deopt, leaving the backing store in an invalid state. | 1296 // deopt, leaving the backing store in an invalid state. |
| 1296 if (is_store && IsFastSmiElementsKind(elements_kind) && | 1297 if (is_store && IsFastSmiElementsKind(elements_kind) && |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1313 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, | 1314 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, |
| 1314 length); | 1315 length); |
| 1315 } else { | 1316 } else { |
| 1316 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 1317 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
| 1317 elements, isolate()->factory()->fixed_array_map(), | 1318 elements, isolate()->factory()->fixed_array_map(), |
| 1318 top_info()); | 1319 top_info()); |
| 1319 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1320 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1320 } | 1321 } |
| 1321 } | 1322 } |
| 1322 } | 1323 } |
| 1323 return AddFastElementAccess(elements, checked_key, val, mapcheck, | 1324 return AddFastElementAccess(elements, checked_key, val, checked_object, |
| 1324 elements_kind, is_store, load_mode, store_mode); | 1325 elements_kind, is_store, load_mode, store_mode); |
| 1325 } | 1326 } |
| 1326 | 1327 |
| 1327 | 1328 |
| 1328 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, | 1329 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, |
| 1329 HValue* capacity) { | 1330 HValue* capacity) { |
| 1330 int elements_size; | 1331 int elements_size; |
| 1331 InstanceType instance_type; | 1332 InstanceType instance_type; |
| 1332 | 1333 |
| 1333 if (IsFastDoubleElementsKind(kind)) { | 1334 if (IsFastDoubleElementsKind(kind)) { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1486 UNREACHABLE(); | 1487 UNREACHABLE(); |
| 1487 return NULL; | 1488 return NULL; |
| 1488 } | 1489 } |
| 1489 } | 1490 } |
| 1490 // It's an element load (!is_store). | 1491 // It's an element load (!is_store). |
| 1491 return Add<HLoadKeyed>( | 1492 return Add<HLoadKeyed>( |
| 1492 elements, checked_key, load_dependency, elements_kind, load_mode); | 1493 elements, checked_key, load_dependency, elements_kind, load_mode); |
| 1493 } | 1494 } |
| 1494 | 1495 |
| 1495 | 1496 |
| 1496 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 1497 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) { |
| 1497 HValue* typecheck) { | 1498 return Add<HLoadNamedField>(object, HObjectAccess::ForElementsPointer()); |
| 1498 return Add<HLoadNamedField>(object, | |
| 1499 HObjectAccess::ForElementsPointer(), | |
| 1500 typecheck); | |
| 1501 } | 1499 } |
| 1502 | 1500 |
| 1503 | 1501 |
| 1504 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { | 1502 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
| 1505 return Add<HLoadNamedField>(object, | 1503 return Add<HLoadNamedField>(object, |
| 1506 HObjectAccess::ForFixedArrayLength()); | 1504 HObjectAccess::ForFixedArrayLength()); |
| 1507 } | 1505 } |
| 1508 | 1506 |
| 1509 | 1507 |
| 1510 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { | 1508 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1693 } | 1691 } |
| 1694 | 1692 |
| 1695 // Create an allocation site info if requested. | 1693 // Create an allocation site info if requested. |
| 1696 if (mode == TRACK_ALLOCATION_SITE) { | 1694 if (mode == TRACK_ALLOCATION_SITE) { |
| 1697 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); | 1695 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); |
| 1698 } | 1696 } |
| 1699 | 1697 |
| 1700 if (length > 0) { | 1698 if (length > 0) { |
| 1701 // Get hold of the elements array of the boilerplate and setup the | 1699 // Get hold of the elements array of the boilerplate and setup the |
| 1702 // elements pointer in the resulting object. | 1700 // elements pointer in the resulting object. |
| 1703 HValue* boilerplate_elements = AddLoadElements(boilerplate, NULL); | 1701 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 1704 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); | 1702 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); |
| 1705 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 1703 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 1706 object_elements); | 1704 object_elements); |
| 1707 | 1705 |
| 1708 // Copy the elements array header. | 1706 // Copy the elements array header. |
| 1709 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 1707 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
| 1710 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | 1708 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
| 1711 Add<HStoreNamedField>(object_elements, access, | 1709 Add<HStoreNamedField>(object_elements, access, |
| 1712 Add<HLoadNamedField>(boilerplate_elements, access)); | 1710 Add<HLoadNamedField>(boilerplate_elements, access)); |
| 1713 } | 1711 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1826 constructor_function_(constructor_function) { | 1824 constructor_function_(constructor_function) { |
| 1827 } | 1825 } |
| 1828 | 1826 |
| 1829 | 1827 |
| 1830 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { | 1828 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { |
| 1831 if (kind_ == GetInitialFastElementsKind()) { | 1829 if (kind_ == GetInitialFastElementsKind()) { |
| 1832 // No need for a context lookup if the kind_ matches the initial | 1830 // No need for a context lookup if the kind_ matches the initial |
| 1833 // map, because we can just load the map in that case. | 1831 // map, because we can just load the map in that case. |
| 1834 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1832 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 1835 return builder()->AddInstruction( | 1833 return builder()->AddInstruction( |
| 1836 builder()->BuildLoadNamedField(constructor_function_, access, NULL)); | 1834 builder()->BuildLoadNamedField(constructor_function_, access)); |
| 1837 } | 1835 } |
| 1838 | 1836 |
| 1839 HInstruction* native_context = builder()->BuildGetNativeContext(); | 1837 HInstruction* native_context = builder()->BuildGetNativeContext(); |
| 1840 HInstruction* index = builder()->Add<HConstant>( | 1838 HInstruction* index = builder()->Add<HConstant>( |
| 1841 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 1839 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
| 1842 | 1840 |
| 1843 HInstruction* map_array = builder()->Add<HLoadKeyed>( | 1841 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
| 1844 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1842 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1845 | 1843 |
| 1846 HInstruction* kind_index = builder()->Add<HConstant>(kind_); | 1844 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
| 1847 | 1845 |
| 1848 return builder()->Add<HLoadKeyed>( | 1846 return builder()->Add<HLoadKeyed>( |
| 1849 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1847 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1850 } | 1848 } |
| 1851 | 1849 |
| 1852 | 1850 |
| 1853 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1851 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
| 1854 // Find the map near the constructor function | 1852 // Find the map near the constructor function |
| 1855 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1853 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 1856 return builder()->AddInstruction( | 1854 return builder()->AddInstruction( |
| 1857 builder()->BuildLoadNamedField(constructor_function_, access, NULL)); | 1855 builder()->BuildLoadNamedField(constructor_function_, access)); |
| 1858 } | 1856 } |
| 1859 | 1857 |
| 1860 | 1858 |
| 1861 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1859 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
| 1862 HValue* length_node) { | 1860 HValue* length_node) { |
| 1863 ASSERT(length_node != NULL); | 1861 ASSERT(length_node != NULL); |
| 1864 | 1862 |
| 1865 int base_size = JSArray::kSize; | 1863 int base_size = JSArray::kSize; |
| 1866 if (mode_ == TRACK_ALLOCATION_SITE) { | 1864 if (mode_ == TRACK_ALLOCATION_SITE) { |
| 1867 base_size += AllocationMemento::kSize; | 1865 base_size += AllocationMemento::kSize; |
| (...skipping 2423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4291 // TODO(mvstanton): This heuristic is only a temporary solution. In the | 4289 // TODO(mvstanton): This heuristic is only a temporary solution. In the |
| 4292 // end, we want to quit creating allocation site info after a certain number | 4290 // end, we want to quit creating allocation site info after a certain number |
| 4293 // of GCs for a call site. | 4291 // of GCs for a call site. |
| 4294 AllocationSiteMode mode = AllocationSite::GetMode( | 4292 AllocationSiteMode mode = AllocationSite::GetMode( |
| 4295 boilerplate_elements_kind); | 4293 boilerplate_elements_kind); |
| 4296 | 4294 |
| 4297 // Check whether to use fast or slow deep-copying for boilerplate. | 4295 // Check whether to use fast or slow deep-copying for boilerplate. |
| 4298 int data_size = 0; | 4296 int data_size = 0; |
| 4299 int pointer_size = 0; | 4297 int pointer_size = 0; |
| 4300 int max_properties = kMaxFastLiteralProperties; | 4298 int max_properties = kMaxFastLiteralProperties; |
| 4301 HCheckMaps* type_check = NULL; | |
| 4302 if (IsFastLiteral(original_boilerplate_object, | 4299 if (IsFastLiteral(original_boilerplate_object, |
| 4303 kMaxFastLiteralDepth, | 4300 kMaxFastLiteralDepth, |
| 4304 &max_properties, | 4301 &max_properties, |
| 4305 &data_size, | 4302 &data_size, |
| 4306 &pointer_size)) { | 4303 &pointer_size)) { |
| 4307 if (mode == TRACK_ALLOCATION_SITE) { | 4304 if (mode == TRACK_ALLOCATION_SITE) { |
| 4308 pointer_size += AllocationMemento::kSize; | 4305 pointer_size += AllocationMemento::kSize; |
| 4309 } | 4306 } |
| 4310 | 4307 |
| 4311 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); | 4308 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4329 | 4326 |
| 4330 Runtime::FunctionId function_id = (expr->depth() > 1) | 4327 Runtime::FunctionId function_id = (expr->depth() > 1) |
| 4331 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 4328 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
| 4332 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 4329 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 4333 Runtime::FunctionForId(function_id), | 4330 Runtime::FunctionForId(function_id), |
| 4334 3); | 4331 3); |
| 4335 | 4332 |
| 4336 // De-opt if elements kind changed from boilerplate_elements_kind. | 4333 // De-opt if elements kind changed from boilerplate_elements_kind. |
| 4337 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), | 4334 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), |
| 4338 isolate()); | 4335 isolate()); |
| 4339 type_check = Add<HCheckMaps>(literal, map, top_info()); | 4336 literal = Add<HCheckMaps>(literal, map, top_info()); |
| 4340 } | 4337 } |
| 4341 | 4338 |
| 4342 // The array is expected in the bailout environment during computation | 4339 // The array is expected in the bailout environment during computation |
| 4343 // of the property values and is the value of the entire expression. | 4340 // of the property values and is the value of the entire expression. |
| 4344 Push(literal); | 4341 Push(literal); |
| 4345 // The literal index is on the stack, too. | 4342 // The literal index is on the stack, too. |
| 4346 Push(Add<HConstant>(expr->literal_index())); | 4343 Push(Add<HConstant>(expr->literal_index())); |
| 4347 | 4344 |
| 4348 HInstruction* elements = NULL; | 4345 HInstruction* elements = NULL; |
| 4349 | 4346 |
| 4350 for (int i = 0; i < length; i++) { | 4347 for (int i = 0; i < length; i++) { |
| 4351 Expression* subexpr = subexprs->at(i); | 4348 Expression* subexpr = subexprs->at(i); |
| 4352 // If the subexpression is a literal or a simple materialized literal it | 4349 // If the subexpression is a literal or a simple materialized literal it |
| 4353 // is already set in the cloned array. | 4350 // is already set in the cloned array. |
| 4354 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 4351 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 4355 | 4352 |
| 4356 CHECK_ALIVE(VisitForValue(subexpr)); | 4353 CHECK_ALIVE(VisitForValue(subexpr)); |
| 4357 HValue* value = Pop(); | 4354 HValue* value = Pop(); |
| 4358 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); | 4355 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); |
| 4359 | 4356 |
| 4360 elements = AddLoadElements(literal, type_check); | 4357 elements = AddLoadElements(literal); |
| 4361 | 4358 |
| 4362 HValue* key = Add<HConstant>(i); | 4359 HValue* key = Add<HConstant>(i); |
| 4363 | 4360 |
| 4364 switch (boilerplate_elements_kind) { | 4361 switch (boilerplate_elements_kind) { |
| 4365 case FAST_SMI_ELEMENTS: | 4362 case FAST_SMI_ELEMENTS: |
| 4366 case FAST_HOLEY_SMI_ELEMENTS: | 4363 case FAST_HOLEY_SMI_ELEMENTS: |
| 4367 case FAST_ELEMENTS: | 4364 case FAST_ELEMENTS: |
| 4368 case FAST_HOLEY_ELEMENTS: | 4365 case FAST_HOLEY_ELEMENTS: |
| 4369 case FAST_DOUBLE_ELEMENTS: | 4366 case FAST_DOUBLE_ELEMENTS: |
| 4370 case FAST_HOLEY_DOUBLE_ELEMENTS: { | 4367 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4573 // In-objectness did not match. | 4570 // In-objectness did not match. |
| 4574 break; | 4571 break; |
| 4575 } | 4572 } |
| 4576 access = access.WithRepresentation( | 4573 access = access.WithRepresentation( |
| 4577 access.representation().generalize(new_access.representation())); | 4574 access.representation().generalize(new_access.representation())); |
| 4578 } | 4575 } |
| 4579 | 4576 |
| 4580 if (count == types->length()) { | 4577 if (count == types->length()) { |
| 4581 // Everything matched; can use monomorphic load. | 4578 // Everything matched; can use monomorphic load. |
| 4582 BuildCheckHeapObject(object); | 4579 BuildCheckHeapObject(object); |
| 4583 HCheckMaps* type_check = Add<HCheckMaps>(object, types); | 4580 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); |
| 4584 return BuildLoadNamedField(object, access, type_check); | 4581 return BuildLoadNamedField(checked_object, access); |
| 4585 } | 4582 } |
| 4586 | 4583 |
| 4587 if (count != 0) return NULL; | 4584 if (count != 0) return NULL; |
| 4588 | 4585 |
| 4589 // Second chance: the property is on the prototype and all maps have the | 4586 // Second chance: the property is on the prototype and all maps have the |
| 4590 // same prototype. | 4587 // same prototype. |
| 4591 Handle<Map> map(types->at(0)); | 4588 Handle<Map> map(types->at(0)); |
| 4592 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; | 4589 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; |
| 4593 | 4590 |
| 4594 Handle<Object> prototype(map->prototype(), isolate()); | 4591 Handle<Object> prototype(map->prototype(), isolate()); |
| 4595 for (count = 1; count < types->length(); ++count) { | 4592 for (count = 1; count < types->length(); ++count) { |
| 4596 Handle<Map> test_map(types->at(count)); | 4593 Handle<Map> test_map(types->at(count)); |
| 4597 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; | 4594 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; |
| 4598 if (test_map->prototype() != *prototype) return NULL; | 4595 if (test_map->prototype() != *prototype) return NULL; |
| 4599 } | 4596 } |
| 4600 | 4597 |
| 4601 LookupInPrototypes(map, name, &lookup); | 4598 LookupInPrototypes(map, name, &lookup); |
| 4602 if (!lookup.IsField()) return NULL; | 4599 if (!lookup.IsField()) return NULL; |
| 4603 | 4600 |
| 4604 BuildCheckHeapObject(object); | 4601 BuildCheckHeapObject(object); |
| 4605 HCheckMaps* type_check = Add<HCheckMaps>(object, types); | 4602 Add<HCheckMaps>(object, types); |
| 4606 | 4603 |
| 4607 Handle<JSObject> holder(lookup.holder()); | 4604 Handle<JSObject> holder(lookup.holder()); |
| 4608 Handle<Map> holder_map(holder->map()); | 4605 Handle<Map> holder_map(holder->map()); |
| 4609 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder); | 4606 HValue* checked_holder = BuildCheckPrototypeMaps( |
| 4610 HValue* holder_value = Add<HConstant>(holder); | 4607 Handle<JSObject>::cast(prototype), holder); |
| 4611 return BuildLoadNamedField(holder_value, | 4608 return BuildLoadNamedField(checked_holder, |
| 4612 HObjectAccess::ForField(holder_map, &lookup, name), type_check); | 4609 HObjectAccess::ForField(holder_map, &lookup, name)); |
| 4613 } | 4610 } |
| 4614 | 4611 |
| 4615 | 4612 |
| 4616 // Returns true if an instance of this map can never find a property with this | 4613 // Returns true if an instance of this map can never find a property with this |
| 4617 // name in its prototype chain. This means all prototypes up to the top are | 4614 // name in its prototype chain. This means all prototypes up to the top are |
| 4618 // fast and don't have the name in them. It would be good if we could optimize | 4615 // fast and don't have the name in them. It would be good if we could optimize |
| 4619 // polymorphic loads where the property is sometimes found in the prototype | 4616 // polymorphic loads where the property is sometimes found in the prototype |
| 4620 // chain. | 4617 // chain. |
| 4621 static bool PrototypeChainCanNeverResolve( | 4618 static bool PrototypeChainCanNeverResolve( |
| 4622 Handle<Map> map, Handle<String> name) { | 4619 Handle<Map> map, Handle<String> name) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4677 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4674 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 4678 HCompareMap* compare = | 4675 HCompareMap* compare = |
| 4679 new(zone()) HCompareMap(object, map, if_true, if_false); | 4676 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 4680 current_block()->Finish(compare); | 4677 current_block()->Finish(compare); |
| 4681 | 4678 |
| 4682 set_current_block(if_true); | 4679 set_current_block(if_true); |
| 4683 | 4680 |
| 4684 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. | 4681 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. |
| 4685 if (lookup.IsField()) { | 4682 if (lookup.IsField()) { |
| 4686 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); | 4683 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); |
| 4687 HLoadNamedField* load = BuildLoadNamedField(object, access, compare); | 4684 HLoadNamedField* load = BuildLoadNamedField(compare, access); |
| 4688 load->set_position(expr->position()); | 4685 load->set_position(expr->position()); |
| 4689 AddInstruction(load); | 4686 AddInstruction(load); |
| 4690 if (!ast_context()->IsEffect()) Push(load); | 4687 if (!ast_context()->IsEffect()) Push(load); |
| 4691 } else if (lookup.IsConstant()) { | 4688 } else if (lookup.IsConstant()) { |
| 4692 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 4689 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
| 4693 HConstant* hconstant = Add<HConstant>(constant); | 4690 HConstant* hconstant = Add<HConstant>(constant); |
| 4694 if (!ast_context()->IsEffect()) Push(hconstant); | 4691 if (!ast_context()->IsEffect()) Push(hconstant); |
| 4695 } else { | 4692 } else { |
| 4696 ASSERT(!lookup.IsFound()); | 4693 ASSERT(!lookup.IsFound()); |
| 4697 if (map->prototype()->IsJSObject()) { | 4694 if (map->prototype()->IsJSObject()) { |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5350 HValue* value = environment()->Pop(); | 5347 HValue* value = environment()->Pop(); |
| 5351 HThrow* instr = Add<HThrow>(value); | 5348 HThrow* instr = Add<HThrow>(value); |
| 5352 instr->set_position(expr->position()); | 5349 instr->set_position(expr->position()); |
| 5353 Add<HSimulate>(expr->id()); | 5350 Add<HSimulate>(expr->id()); |
| 5354 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5351 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 5355 set_current_block(NULL); | 5352 set_current_block(NULL); |
| 5356 } | 5353 } |
| 5357 | 5354 |
| 5358 | 5355 |
| 5359 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5356 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 5360 HObjectAccess access, | 5357 HObjectAccess access) { |
| 5361 HValue* typecheck) { | |
| 5362 if (FLAG_track_double_fields && access.representation().IsDouble()) { | 5358 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
| 5363 // load the heap number | 5359 // load the heap number |
| 5364 HLoadNamedField* heap_number = Add<HLoadNamedField>( | 5360 HLoadNamedField* heap_number = Add<HLoadNamedField>( |
| 5365 object, access.WithRepresentation(Representation::Tagged())); | 5361 object, access.WithRepresentation(Representation::Tagged())); |
| 5366 heap_number->set_type(HType::HeapNumber()); | 5362 heap_number->set_type(HType::HeapNumber()); |
| 5367 // load the double value from it | 5363 // load the double value from it |
| 5368 return New<HLoadNamedField>(heap_number, | 5364 return New<HLoadNamedField>( |
| 5369 HObjectAccess::ForHeapNumberValue(), | 5365 heap_number, HObjectAccess::ForHeapNumberValue()); |
| 5370 typecheck); | |
| 5371 } | 5366 } |
| 5372 return New<HLoadNamedField>(object, access, typecheck); | 5367 return New<HLoadNamedField>(object, access); |
| 5373 } | 5368 } |
| 5374 | 5369 |
| 5375 | 5370 |
| 5376 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object, | 5371 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object, |
| 5377 HValue* typecheck) { | 5372 HValue* checked_string) { |
| 5378 if (FLAG_fold_constants && object->IsConstant()) { | 5373 if (FLAG_fold_constants && object->IsConstant()) { |
| 5379 HConstant* constant = HConstant::cast(object); | 5374 HConstant* constant = HConstant::cast(object); |
| 5380 if (constant->HasStringValue()) { | 5375 if (constant->HasStringValue()) { |
| 5381 return New<HConstant>(constant->StringValue()->length()); | 5376 return New<HConstant>(constant->StringValue()->length()); |
| 5382 } | 5377 } |
| 5383 } | 5378 } |
| 5384 return BuildLoadNamedField( | 5379 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength()); |
| 5385 object, HObjectAccess::ForStringLength(), typecheck); | |
| 5386 } | 5380 } |
| 5387 | 5381 |
| 5388 | 5382 |
| 5389 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5383 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 5390 HValue* object, | 5384 HValue* object, |
| 5391 Handle<String> name, | 5385 Handle<String> name, |
| 5392 Property* expr) { | 5386 Property* expr) { |
| 5393 if (expr->IsUninitialized()) { | 5387 if (expr->IsUninitialized()) { |
| 5394 Add<HDeoptimize>("Insufficient feedback for generic named load", | 5388 Add<HDeoptimize>("Insufficient feedback for generic named load", |
| 5395 Deoptimizer::SOFT); | 5389 Deoptimizer::SOFT); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5414 HValue* object, | 5408 HValue* object, |
| 5415 Handle<String> name, | 5409 Handle<String> name, |
| 5416 Property* expr, | 5410 Property* expr, |
| 5417 Handle<Map> map) { | 5411 Handle<Map> map) { |
| 5418 // Handle a load from a known field. | 5412 // Handle a load from a known field. |
| 5419 ASSERT(!map->is_dictionary_map()); | 5413 ASSERT(!map->is_dictionary_map()); |
| 5420 | 5414 |
| 5421 // Handle access to various length properties | 5415 // Handle access to various length properties |
| 5422 if (name->Equals(isolate()->heap()->length_string())) { | 5416 if (name->Equals(isolate()->heap()->length_string())) { |
| 5423 if (map->instance_type() == JS_ARRAY_TYPE) { | 5417 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 5424 HCheckMaps* type_check = AddCheckMap(object, map); | 5418 HCheckMaps* checked_object = AddCheckMap(object, map); |
| 5425 return New<HLoadNamedField>(object, | 5419 return New<HLoadNamedField>( |
| 5426 HObjectAccess::ForArrayLength(map->elements_kind()), type_check); | 5420 checked_object, HObjectAccess::ForArrayLength(map->elements_kind())); |
| 5427 } | 5421 } |
| 5428 } | 5422 } |
| 5429 | 5423 |
| 5430 LookupResult lookup(isolate()); | 5424 LookupResult lookup(isolate()); |
| 5431 map->LookupDescriptor(NULL, *name, &lookup); | 5425 map->LookupDescriptor(NULL, *name, &lookup); |
| 5432 if (lookup.IsField()) { | 5426 if (lookup.IsField()) { |
| 5433 HCheckMaps* type_check = AddCheckMap(object, map); | 5427 HCheckMaps* checked_object = AddCheckMap(object, map); |
| 5434 return BuildLoadNamedField(object, | 5428 return BuildLoadNamedField( |
| 5435 HObjectAccess::ForField(map, &lookup, name), type_check); | 5429 checked_object, HObjectAccess::ForField(map, &lookup, name)); |
| 5436 } | 5430 } |
| 5437 | 5431 |
| 5438 // Handle a load of a constant known function. | 5432 // Handle a load of a constant known function. |
| 5439 if (lookup.IsConstant()) { | 5433 if (lookup.IsConstant()) { |
| 5440 AddCheckMap(object, map); | 5434 AddCheckMap(object, map); |
| 5441 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 5435 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
| 5442 return New<HConstant>(constant); | 5436 return New<HConstant>(constant); |
| 5443 } | 5437 } |
| 5444 | 5438 |
| 5445 // Handle a load from a known field somewhere in the prototype chain. | 5439 // Handle a load from a known field somewhere in the prototype chain. |
| 5446 LookupInPrototypes(map, name, &lookup); | 5440 LookupInPrototypes(map, name, &lookup); |
| 5447 if (lookup.IsField()) { | 5441 if (lookup.IsField()) { |
| 5448 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5442 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 5449 Handle<JSObject> holder(lookup.holder()); | 5443 Handle<JSObject> holder(lookup.holder()); |
| 5450 Handle<Map> holder_map(holder->map()); | 5444 Handle<Map> holder_map(holder->map()); |
| 5451 HCheckMaps* type_check = AddCheckMap(object, map); | 5445 AddCheckMap(object, map); |
| 5452 BuildCheckPrototypeMaps(prototype, holder); | 5446 HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder); |
| 5453 HValue* holder_value = Add<HConstant>(holder); | 5447 return BuildLoadNamedField( |
| 5454 return BuildLoadNamedField(holder_value, | 5448 checked_holder, HObjectAccess::ForField(holder_map, &lookup, name)); |
| 5455 HObjectAccess::ForField(holder_map, &lookup, name), type_check); | |
| 5456 } | 5449 } |
| 5457 | 5450 |
| 5458 // Handle a load of a constant function somewhere in the prototype chain. | 5451 // Handle a load of a constant function somewhere in the prototype chain. |
| 5459 if (lookup.IsConstant()) { | 5452 if (lookup.IsConstant()) { |
| 5460 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5453 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 5461 Handle<JSObject> holder(lookup.holder()); | 5454 Handle<JSObject> holder(lookup.holder()); |
| 5462 Handle<Map> holder_map(holder->map()); | 5455 Handle<Map> holder_map(holder->map()); |
| 5463 AddCheckMap(object, map); | 5456 AddCheckMap(object, map); |
| 5464 BuildCheckPrototypeMaps(prototype, holder); | 5457 BuildCheckPrototypeMaps(prototype, holder); |
| 5465 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); | 5458 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5638 } else { | 5631 } else { |
| 5639 instr = BuildMonomorphicElementAccess( | 5632 instr = BuildMonomorphicElementAccess( |
| 5640 object, key, val, transition, untransitionable_map, is_store, | 5633 object, key, val, transition, untransitionable_map, is_store, |
| 5641 store_mode); | 5634 store_mode); |
| 5642 } | 5635 } |
| 5643 *has_side_effects |= instr->HasObservableSideEffects(); | 5636 *has_side_effects |= instr->HasObservableSideEffects(); |
| 5644 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5637 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
| 5645 return is_store ? NULL : instr; | 5638 return is_store ? NULL : instr; |
| 5646 } | 5639 } |
| 5647 | 5640 |
| 5648 HInstruction* checkspec = | 5641 HInstruction* checked_object = |
| 5649 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); | 5642 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); |
| 5650 HBasicBlock* join = graph()->CreateBasicBlock(); | 5643 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 5651 | 5644 |
| 5652 HInstruction* elements = AddLoadElements(object, checkspec); | 5645 HInstruction* elements = AddLoadElements(checked_object); |
| 5653 | 5646 |
| 5654 for (int i = 0; i < untransitionable_maps.length(); ++i) { | 5647 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
| 5655 Handle<Map> map = untransitionable_maps[i]; | 5648 Handle<Map> map = untransitionable_maps[i]; |
| 5656 ElementsKind elements_kind = map->elements_kind(); | 5649 ElementsKind elements_kind = map->elements_kind(); |
| 5657 HBasicBlock* this_map = graph()->CreateBasicBlock(); | 5650 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
| 5658 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 5651 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
| 5659 HCompareMap* mapcompare = | 5652 HCompareMap* mapcompare = |
| 5660 new(zone()) HCompareMap(object, map, this_map, other_map); | 5653 new(zone()) HCompareMap(object, map, this_map, other_map); |
| 5661 current_block()->Finish(mapcompare); | 5654 current_block()->Finish(mapcompare); |
| 5662 | 5655 |
| 5663 set_current_block(this_map); | 5656 set_current_block(this_map); |
| 5664 HInstruction* checked_key = NULL; | 5657 HInstruction* checked_key = NULL; |
| 5665 HInstruction* access = NULL; | 5658 HInstruction* access = NULL; |
| 5666 if (IsFastElementsKind(elements_kind)) { | 5659 if (IsFastElementsKind(elements_kind)) { |
| 5667 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { | 5660 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { |
| 5668 Add<HCheckMaps>( | 5661 Add<HCheckMaps>( |
| 5669 elements, isolate()->factory()->fixed_array_map(), | 5662 elements, isolate()->factory()->fixed_array_map(), |
| 5670 top_info(), mapcompare); | 5663 top_info(), mapcompare); |
| 5671 } | 5664 } |
| 5672 if (map->instance_type() == JS_ARRAY_TYPE) { | 5665 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 5673 HInstruction* length = Add<HLoadNamedField>( | 5666 HInstruction* length = Add<HLoadNamedField>( |
| 5674 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare); | 5667 mapcompare, HObjectAccess::ForArrayLength(elements_kind)); |
| 5675 checked_key = Add<HBoundsCheck>(key, length); | 5668 checked_key = Add<HBoundsCheck>(key, length); |
| 5676 } else { | 5669 } else { |
| 5677 HInstruction* length = AddLoadFixedArrayLength(elements); | 5670 HInstruction* length = AddLoadFixedArrayLength(elements); |
| 5678 checked_key = Add<HBoundsCheck>(key, length); | 5671 checked_key = Add<HBoundsCheck>(key, length); |
| 5679 } | 5672 } |
| 5680 access = AddFastElementAccess( | 5673 access = AddFastElementAccess( |
| 5681 elements, checked_key, val, mapcompare, | 5674 elements, checked_key, val, mapcompare, |
| 5682 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); | 5675 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); |
| 5683 } else if (IsDictionaryElementsKind(elements_kind)) { | 5676 } else if (IsDictionaryElementsKind(elements_kind)) { |
| 5684 if (is_store) { | 5677 if (is_store) { |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5940 Drop(1); | 5933 Drop(1); |
| 5941 } | 5934 } |
| 5942 } | 5935 } |
| 5943 return ast_context()->ReturnValue(load); | 5936 return ast_context()->ReturnValue(load); |
| 5944 } | 5937 } |
| 5945 instr->set_position(expr->position()); | 5938 instr->set_position(expr->position()); |
| 5946 return ast_context()->ReturnInstruction(instr, expr->id()); | 5939 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5947 } | 5940 } |
| 5948 | 5941 |
| 5949 | 5942 |
| 5950 void HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | 5943 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, |
| 5951 CompilationInfo* info) { | 5944 CompilationInfo* info) { |
| 5952 HConstant* constant_value = New<HConstant>(constant); | 5945 HConstant* constant_value = New<HConstant>(constant); |
| 5953 | 5946 |
| 5954 if (constant->map()->CanOmitMapChecks()) { | 5947 if (constant->map()->CanOmitMapChecks()) { |
| 5955 constant->map()->AddDependentCompilationInfo( | 5948 constant->map()->AddDependentCompilationInfo( |
| 5956 DependentCode::kPrototypeCheckGroup, info); | 5949 DependentCode::kPrototypeCheckGroup, info); |
| 5957 return; | 5950 return constant_value; |
| 5958 } | 5951 } |
| 5959 | 5952 |
| 5960 AddInstruction(constant_value); | 5953 AddInstruction(constant_value); |
| 5961 HCheckMaps* check = | 5954 HCheckMaps* check = |
| 5962 Add<HCheckMaps>(constant_value, handle(constant->map()), info); | 5955 Add<HCheckMaps>(constant_value, handle(constant->map()), info); |
| 5963 check->ClearGVNFlag(kDependsOnElementsKind); | 5956 check->ClearGVNFlag(kDependsOnElementsKind); |
| 5957 return check; |
| 5964 } | 5958 } |
| 5965 | 5959 |
| 5966 | 5960 |
| 5967 void HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, | 5961 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, |
| 5968 Handle<JSObject> holder) { | 5962 Handle<JSObject> holder) { |
| 5969 BuildConstantMapCheck(prototype, top_info()); | |
| 5970 while (!prototype.is_identical_to(holder)) { | 5963 while (!prototype.is_identical_to(holder)) { |
| 5964 BuildConstantMapCheck(prototype, top_info()); |
| 5971 prototype = handle(JSObject::cast(prototype->GetPrototype())); | 5965 prototype = handle(JSObject::cast(prototype->GetPrototype())); |
| 5972 BuildConstantMapCheck(prototype, top_info()); | |
| 5973 } | 5966 } |
| 5967 |
| 5968 HInstruction* checked_object = BuildConstantMapCheck(prototype, top_info()); |
| 5969 if (!checked_object->IsLinked()) AddInstruction(checked_object); |
| 5970 return checked_object; |
| 5974 } | 5971 } |
| 5975 | 5972 |
| 5976 | 5973 |
| 5977 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 5974 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 5978 Handle<Map> receiver_map) { | 5975 Handle<Map> receiver_map) { |
| 5979 if (!holder.is_null()) { | 5976 if (!holder.is_null()) { |
| 5980 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 5977 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
| 5981 BuildCheckPrototypeMaps(prototype, holder); | 5978 BuildCheckPrototypeMaps(prototype, holder); |
| 5982 } | 5979 } |
| 5983 } | 5980 } |
| (...skipping 3845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9829 if (ShouldProduceTraceOutput()) { | 9826 if (ShouldProduceTraceOutput()) { |
| 9830 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9827 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9831 } | 9828 } |
| 9832 | 9829 |
| 9833 #ifdef DEBUG | 9830 #ifdef DEBUG |
| 9834 graph_->Verify(false); // No full verify. | 9831 graph_->Verify(false); // No full verify. |
| 9835 #endif | 9832 #endif |
| 9836 } | 9833 } |
| 9837 | 9834 |
| 9838 } } // namespace v8::internal | 9835 } } // namespace v8::internal |
| OLD | NEW |