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 |