| 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 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1299 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { | 1299 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
| 1300 Handle<JSFunction> f = Handle<JSFunction>::cast( | 1300 Handle<JSFunction> f = Handle<JSFunction>::cast( |
| 1301 HConstant::cast(function)->handle(isolate())); | 1301 HConstant::cast(function)->handle(isolate())); |
| 1302 SharedFunctionInfo* shared = f->shared(); | 1302 SharedFunctionInfo* shared = f->shared(); |
| 1303 if (!shared->is_classic_mode() || shared->native()) return object; | 1303 if (!shared->is_classic_mode() || shared->native()) return object; |
| 1304 } | 1304 } |
| 1305 return Add<HWrapReceiver>(object, function); | 1305 return Add<HWrapReceiver>(object, function); |
| 1306 } | 1306 } |
| 1307 | 1307 |
| 1308 | 1308 |
| 1309 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1309 HValue* HGraphBuilder::BuildCheckForCapacityGrow( |
| 1310 HValue* elements, | 1310 HValue* object, |
| 1311 ElementsKind kind, | 1311 HValue* elements, |
| 1312 HValue* length, | 1312 ElementsKind kind, |
| 1313 HValue* key, | 1313 HValue* length, |
| 1314 bool is_js_array, | 1314 HValue* key, |
| 1315 bool is_store) { | 1315 bool is_js_array, |
| 1316 PropertyAccessType access_type) { |
| 1316 IfBuilder length_checker(this); | 1317 IfBuilder length_checker(this); |
| 1317 | 1318 |
| 1318 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; | 1319 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; |
| 1319 length_checker.If<HCompareNumericAndBranch>(key, length, token); | 1320 length_checker.If<HCompareNumericAndBranch>(key, length, token); |
| 1320 | 1321 |
| 1321 length_checker.Then(); | 1322 length_checker.Then(); |
| 1322 | 1323 |
| 1323 HValue* current_capacity = AddLoadFixedArrayLength(elements); | 1324 HValue* current_capacity = AddLoadFixedArrayLength(elements); |
| 1324 | 1325 |
| 1325 IfBuilder capacity_checker(this); | 1326 IfBuilder capacity_checker(this); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1345 capacity_checker.Else(); | 1346 capacity_checker.Else(); |
| 1346 | 1347 |
| 1347 environment()->Push(elements); | 1348 environment()->Push(elements); |
| 1348 capacity_checker.End(); | 1349 capacity_checker.End(); |
| 1349 | 1350 |
| 1350 if (is_js_array) { | 1351 if (is_js_array) { |
| 1351 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); | 1352 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); |
| 1352 new_length->ClearFlag(HValue::kCanOverflow); | 1353 new_length->ClearFlag(HValue::kCanOverflow); |
| 1353 | 1354 |
| 1354 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), | 1355 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), |
| 1355 new_length, INITIALIZING_STORE); | 1356 new_length); |
| 1356 } | 1357 } |
| 1357 | 1358 |
| 1358 if (is_store && kind == FAST_SMI_ELEMENTS) { | 1359 if (access_type == STORE && kind == FAST_SMI_ELEMENTS) { |
| 1359 HValue* checked_elements = environment()->Top(); | 1360 HValue* checked_elements = environment()->Top(); |
| 1360 | 1361 |
| 1361 // Write zero to ensure that the new element is initialized with some smi. | 1362 // Write zero to ensure that the new element is initialized with some smi. |
| 1362 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind, | 1363 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind); |
| 1363 INITIALIZING_STORE); | |
| 1364 } | 1364 } |
| 1365 | 1365 |
| 1366 length_checker.Else(); | 1366 length_checker.Else(); |
| 1367 Add<HBoundsCheck>(key, length); | 1367 Add<HBoundsCheck>(key, length); |
| 1368 | 1368 |
| 1369 environment()->Push(elements); | 1369 environment()->Push(elements); |
| 1370 length_checker.End(); | 1370 length_checker.End(); |
| 1371 | 1371 |
| 1372 return environment()->Pop(); | 1372 return environment()->Pop(); |
| 1373 } | 1373 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1431 ? Add<HLoadNamedField>(object, static_cast<HValue*>(NULL), | 1431 ? Add<HLoadNamedField>(object, static_cast<HValue*>(NULL), |
| 1432 HObjectAccess::ForArrayLength(from_kind)) | 1432 HObjectAccess::ForArrayLength(from_kind)) |
| 1433 : elements_length; | 1433 : elements_length; |
| 1434 | 1434 |
| 1435 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, | 1435 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
| 1436 array_length, elements_length); | 1436 array_length, elements_length); |
| 1437 | 1437 |
| 1438 if_builder.End(); | 1438 if_builder.End(); |
| 1439 } | 1439 } |
| 1440 | 1440 |
| 1441 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map, | 1441 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); |
| 1442 INITIALIZING_STORE); | |
| 1443 } | 1442 } |
| 1444 | 1443 |
| 1445 | 1444 |
| 1446 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper( | 1445 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper( |
| 1447 HValue* elements, | 1446 HValue* elements, |
| 1448 HValue* key, | 1447 HValue* key, |
| 1449 HValue* hash, | 1448 HValue* hash, |
| 1450 HValue* mask, | 1449 HValue* mask, |
| 1451 int current_probe) { | 1450 int current_probe) { |
| 1452 if (current_probe == kNumberDictionaryProbes) { | 1451 if (current_probe == kNumberDictionaryProbes) { |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1602 context(), static_cast<HValue*>(NULL), | 1601 context(), static_cast<HValue*>(NULL), |
| 1603 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 1602 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
| 1604 HValue* native_context = Add<HLoadNamedField>( | 1603 HValue* native_context = Add<HLoadNamedField>( |
| 1605 global_object, static_cast<HValue*>(NULL), | 1604 global_object, static_cast<HValue*>(NULL), |
| 1606 HObjectAccess::ForGlobalObjectNativeContext()); | 1605 HObjectAccess::ForGlobalObjectNativeContext()); |
| 1607 AddStoreMapNoWriteBarrier(result, Add<HLoadNamedField>( | 1606 AddStoreMapNoWriteBarrier(result, Add<HLoadNamedField>( |
| 1608 native_context, static_cast<HValue*>(NULL), | 1607 native_context, static_cast<HValue*>(NULL), |
| 1609 HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX))); | 1608 HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX))); |
| 1610 Add<HStoreNamedField>( | 1609 Add<HStoreNamedField>( |
| 1611 result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset), | 1610 result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset), |
| 1612 Add<HConstant>(isolate()->factory()->empty_fixed_array()), | 1611 Add<HConstant>(isolate()->factory()->empty_fixed_array())); |
| 1613 INITIALIZING_STORE); | |
| 1614 Add<HStoreNamedField>( | 1612 Add<HStoreNamedField>( |
| 1615 result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset), | 1613 result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset), |
| 1616 elements, INITIALIZING_STORE); | 1614 elements); |
| 1617 Add<HStoreNamedField>( | 1615 Add<HStoreNamedField>( |
| 1618 result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), | 1616 result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length); |
| 1619 length, INITIALIZING_STORE); | |
| 1620 | 1617 |
| 1621 // Initialize the additional fields. | 1618 // Initialize the additional fields. |
| 1622 Add<HStoreNamedField>( | 1619 Add<HStoreNamedField>( |
| 1623 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset), | 1620 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset), |
| 1624 index, INITIALIZING_STORE); | 1621 index); |
| 1625 Add<HStoreNamedField>( | 1622 Add<HStoreNamedField>( |
| 1626 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset), | 1623 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset), |
| 1627 input, INITIALIZING_STORE); | 1624 input); |
| 1628 | 1625 |
| 1629 // Initialize the elements header. | 1626 // Initialize the elements header. |
| 1630 AddStoreMapConstantNoWriteBarrier(elements, | 1627 AddStoreMapConstantNoWriteBarrier(elements, |
| 1631 isolate()->factory()->fixed_array_map()); | 1628 isolate()->factory()->fixed_array_map()); |
| 1632 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), | 1629 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), length); |
| 1633 length, INITIALIZING_STORE); | |
| 1634 | 1630 |
| 1635 // Initialize the elements contents with undefined. | 1631 // Initialize the elements contents with undefined. |
| 1636 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); | 1632 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); |
| 1637 index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1633 index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); |
| 1638 { | 1634 { |
| 1639 Add<HStoreKeyed>(elements, index, graph()->GetConstantUndefined(), | 1635 Add<HStoreKeyed>(elements, index, graph()->GetConstantUndefined(), |
| 1640 FAST_ELEMENTS, INITIALIZING_STORE); | 1636 FAST_ELEMENTS); |
| 1641 } | 1637 } |
| 1642 loop.EndBody(); | 1638 loop.EndBody(); |
| 1643 | 1639 |
| 1644 return result; | 1640 return result; |
| 1645 } | 1641 } |
| 1646 | 1642 |
| 1647 | 1643 |
| 1648 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) { | 1644 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) { |
| 1649 NoObservableSideEffectsScope scope(this); | 1645 NoObservableSideEffectsScope scope(this); |
| 1650 | 1646 |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 if_onebyte.Else(); | 1889 if_onebyte.Else(); |
| 1894 { | 1890 { |
| 1895 // We can safely skip the write barrier for storing the map here. | 1891 // We can safely skip the write barrier for storing the map here. |
| 1896 Handle<Map> map = isolate()->factory()->cons_string_map(); | 1892 Handle<Map> map = isolate()->factory()->cons_string_map(); |
| 1897 AddStoreMapConstantNoWriteBarrier(result, map); | 1893 AddStoreMapConstantNoWriteBarrier(result, map); |
| 1898 } | 1894 } |
| 1899 if_onebyte.End(); | 1895 if_onebyte.End(); |
| 1900 | 1896 |
| 1901 // Initialize the cons string fields. | 1897 // Initialize the cons string fields. |
| 1902 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(), | 1898 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(), |
| 1903 Add<HConstant>(String::kEmptyHashField), | 1899 Add<HConstant>(String::kEmptyHashField)); |
| 1904 INITIALIZING_STORE); | 1900 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length); |
| 1905 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length, | 1901 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left); |
| 1906 INITIALIZING_STORE); | 1902 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right); |
| 1907 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left, | |
| 1908 INITIALIZING_STORE); | |
| 1909 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right, | |
| 1910 INITIALIZING_STORE); | |
| 1911 | 1903 |
| 1912 // Count the native string addition. | 1904 // Count the native string addition. |
| 1913 AddIncrementCounter(isolate()->counters()->string_add_native()); | 1905 AddIncrementCounter(isolate()->counters()->string_add_native()); |
| 1914 | 1906 |
| 1915 return result; | 1907 return result; |
| 1916 } | 1908 } |
| 1917 | 1909 |
| 1918 | 1910 |
| 1919 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, | 1911 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, |
| 1920 HValue* src_offset, | 1912 HValue* src_offset, |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2049 // Allocate the string object. HAllocate does not care whether we pass | 2041 // Allocate the string object. HAllocate does not care whether we pass |
| 2050 // STRING_TYPE or ASCII_STRING_TYPE here, so we just use STRING_TYPE here. | 2042 // STRING_TYPE or ASCII_STRING_TYPE here, so we just use STRING_TYPE here. |
| 2051 HAllocate* result = BuildAllocate( | 2043 HAllocate* result = BuildAllocate( |
| 2052 size, HType::String(), STRING_TYPE, allocation_mode); | 2044 size, HType::String(), STRING_TYPE, allocation_mode); |
| 2053 | 2045 |
| 2054 // We can safely skip the write barrier for storing map here. | 2046 // We can safely skip the write barrier for storing map here. |
| 2055 AddStoreMapNoWriteBarrier(result, map); | 2047 AddStoreMapNoWriteBarrier(result, map); |
| 2056 | 2048 |
| 2057 // Initialize the string fields. | 2049 // Initialize the string fields. |
| 2058 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(), | 2050 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(), |
| 2059 Add<HConstant>(String::kEmptyHashField), | 2051 Add<HConstant>(String::kEmptyHashField)); |
| 2060 INITIALIZING_STORE); | 2052 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length); |
| 2061 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length, | |
| 2062 INITIALIZING_STORE); | |
| 2063 | 2053 |
| 2064 // Copy characters to the result string. | 2054 // Copy characters to the result string. |
| 2065 IfBuilder if_twobyte(this); | 2055 IfBuilder if_twobyte(this); |
| 2066 if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map); | 2056 if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map); |
| 2067 if_twobyte.Then(); | 2057 if_twobyte.Then(); |
| 2068 { | 2058 { |
| 2069 // Copy characters from the left string. | 2059 // Copy characters from the left string. |
| 2070 BuildCopySeqStringChars( | 2060 BuildCopySeqStringChars( |
| 2071 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 2061 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
| 2072 result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 2062 result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2165 return Pop(); | 2155 return Pop(); |
| 2166 } | 2156 } |
| 2167 | 2157 |
| 2168 | 2158 |
| 2169 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 2159 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
| 2170 HValue* checked_object, | 2160 HValue* checked_object, |
| 2171 HValue* key, | 2161 HValue* key, |
| 2172 HValue* val, | 2162 HValue* val, |
| 2173 bool is_js_array, | 2163 bool is_js_array, |
| 2174 ElementsKind elements_kind, | 2164 ElementsKind elements_kind, |
| 2175 bool is_store, | 2165 PropertyAccessType access_type, |
| 2176 LoadKeyedHoleMode load_mode, | 2166 LoadKeyedHoleMode load_mode, |
| 2177 KeyedAccessStoreMode store_mode) { | 2167 KeyedAccessStoreMode store_mode) { |
| 2178 ASSERT((!IsExternalArrayElementsKind(elements_kind) && | 2168 ASSERT((!IsExternalArrayElementsKind(elements_kind) && |
| 2179 !IsFixedTypedArrayElementsKind(elements_kind)) || | 2169 !IsFixedTypedArrayElementsKind(elements_kind)) || |
| 2180 !is_js_array); | 2170 !is_js_array); |
| 2181 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 2171 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
| 2182 // on a HElementsTransition instruction. The flag can also be removed if the | 2172 // on a HElementsTransition instruction. The flag can also be removed if the |
| 2183 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 2173 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
| 2184 // ElementsKind transitions. Finally, the dependency can be removed for stores | 2174 // ElementsKind transitions. Finally, the dependency can be removed for stores |
| 2185 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 2175 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
| 2186 // generated store code. | 2176 // generated store code. |
| 2187 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 2177 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
| 2188 (elements_kind == FAST_ELEMENTS && is_store)) { | 2178 (elements_kind == FAST_ELEMENTS && access_type == STORE)) { |
| 2189 checked_object->ClearGVNFlag(kDependsOnElementsKind); | 2179 checked_object->ClearGVNFlag(kDependsOnElementsKind); |
| 2190 } | 2180 } |
| 2191 | 2181 |
| 2192 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 2182 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
| 2193 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 2183 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
| 2194 HValue* elements = AddLoadElements(checked_object); | 2184 HValue* elements = AddLoadElements(checked_object); |
| 2195 if (is_store && (fast_elements || fast_smi_only_elements) && | 2185 if (access_type == STORE && (fast_elements || fast_smi_only_elements) && |
| 2196 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 2186 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 2197 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 2187 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
| 2198 elements, isolate()->factory()->fixed_array_map(), top_info()); | 2188 elements, isolate()->factory()->fixed_array_map(), top_info()); |
| 2199 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 2189 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 2200 } | 2190 } |
| 2201 HInstruction* length = NULL; | 2191 HInstruction* length = NULL; |
| 2202 if (is_js_array) { | 2192 if (is_js_array) { |
| 2203 length = Add<HLoadNamedField>( | 2193 length = Add<HLoadNamedField>( |
| 2204 checked_object, static_cast<HValue*>(NULL), | 2194 checked_object, static_cast<HValue*>(NULL), |
| 2205 HObjectAccess::ForArrayLength(elements_kind)); | 2195 HObjectAccess::ForArrayLength(elements_kind)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2221 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 2211 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 2222 NoObservableSideEffectsScope no_effects(this); | 2212 NoObservableSideEffectsScope no_effects(this); |
| 2223 IfBuilder length_checker(this); | 2213 IfBuilder length_checker(this); |
| 2224 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 2214 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
| 2225 length_checker.Then(); | 2215 length_checker.Then(); |
| 2226 IfBuilder negative_checker(this); | 2216 IfBuilder negative_checker(this); |
| 2227 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 2217 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
| 2228 key, graph()->GetConstant0(), Token::GTE); | 2218 key, graph()->GetConstant0(), Token::GTE); |
| 2229 negative_checker.Then(); | 2219 negative_checker.Then(); |
| 2230 HInstruction* result = AddElementAccess( | 2220 HInstruction* result = AddElementAccess( |
| 2231 backing_store, key, val, bounds_check, elements_kind, is_store); | 2221 backing_store, key, val, bounds_check, elements_kind, access_type); |
| 2232 negative_checker.ElseDeopt("Negative key encountered"); | 2222 negative_checker.ElseDeopt("Negative key encountered"); |
| 2233 negative_checker.End(); | 2223 negative_checker.End(); |
| 2234 length_checker.End(); | 2224 length_checker.End(); |
| 2235 return result; | 2225 return result; |
| 2236 } else { | 2226 } else { |
| 2237 ASSERT(store_mode == STANDARD_STORE); | 2227 ASSERT(store_mode == STANDARD_STORE); |
| 2238 checked_key = Add<HBoundsCheck>(key, length); | 2228 checked_key = Add<HBoundsCheck>(key, length); |
| 2239 return AddElementAccess( | 2229 return AddElementAccess( |
| 2240 backing_store, checked_key, val, | 2230 backing_store, checked_key, val, |
| 2241 checked_object, elements_kind, is_store); | 2231 checked_object, elements_kind, access_type); |
| 2242 } | 2232 } |
| 2243 } | 2233 } |
| 2244 ASSERT(fast_smi_only_elements || | 2234 ASSERT(fast_smi_only_elements || |
| 2245 fast_elements || | 2235 fast_elements || |
| 2246 IsFastDoubleElementsKind(elements_kind)); | 2236 IsFastDoubleElementsKind(elements_kind)); |
| 2247 | 2237 |
| 2248 // In case val is stored into a fast smi array, assure that the value is a smi | 2238 // In case val is stored into a fast smi array, assure that the value is a smi |
| 2249 // before manipulating the backing store. Otherwise the actual store may | 2239 // before manipulating the backing store. Otherwise the actual store may |
| 2250 // deopt, leaving the backing store in an invalid state. | 2240 // deopt, leaving the backing store in an invalid state. |
| 2251 if (is_store && IsFastSmiElementsKind(elements_kind) && | 2241 if (access_type == STORE && IsFastSmiElementsKind(elements_kind) && |
| 2252 !val->type().IsSmi()) { | 2242 !val->type().IsSmi()) { |
| 2253 val = AddUncasted<HForceRepresentation>(val, Representation::Smi()); | 2243 val = AddUncasted<HForceRepresentation>(val, Representation::Smi()); |
| 2254 } | 2244 } |
| 2255 | 2245 |
| 2256 if (IsGrowStoreMode(store_mode)) { | 2246 if (IsGrowStoreMode(store_mode)) { |
| 2257 NoObservableSideEffectsScope no_effects(this); | 2247 NoObservableSideEffectsScope no_effects(this); |
| 2258 elements = BuildCheckForCapacityGrow(checked_object, elements, | 2248 elements = BuildCheckForCapacityGrow(checked_object, elements, |
| 2259 elements_kind, length, key, | 2249 elements_kind, length, key, |
| 2260 is_js_array, is_store); | 2250 is_js_array, access_type); |
| 2261 checked_key = key; | 2251 checked_key = key; |
| 2262 } else { | 2252 } else { |
| 2263 checked_key = Add<HBoundsCheck>(key, length); | 2253 checked_key = Add<HBoundsCheck>(key, length); |
| 2264 | 2254 |
| 2265 if (is_store && (fast_elements || fast_smi_only_elements)) { | 2255 if (access_type == STORE && (fast_elements || fast_smi_only_elements)) { |
| 2266 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 2256 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
| 2267 NoObservableSideEffectsScope no_effects(this); | 2257 NoObservableSideEffectsScope no_effects(this); |
| 2268 elements = BuildCopyElementsOnWrite(checked_object, elements, | 2258 elements = BuildCopyElementsOnWrite(checked_object, elements, |
| 2269 elements_kind, length); | 2259 elements_kind, length); |
| 2270 } else { | 2260 } else { |
| 2271 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 2261 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
| 2272 elements, isolate()->factory()->fixed_array_map(), top_info()); | 2262 elements, isolate()->factory()->fixed_array_map(), top_info()); |
| 2273 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 2263 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 2274 } | 2264 } |
| 2275 } | 2265 } |
| 2276 } | 2266 } |
| 2277 return AddElementAccess(elements, checked_key, val, checked_object, | 2267 return AddElementAccess(elements, checked_key, val, checked_object, |
| 2278 elements_kind, is_store, load_mode); | 2268 elements_kind, access_type, load_mode); |
| 2279 } | 2269 } |
| 2280 | 2270 |
| 2281 | 2271 |
| 2282 | 2272 |
| 2283 HValue* HGraphBuilder::BuildAllocateArrayFromLength( | 2273 HValue* HGraphBuilder::BuildAllocateArrayFromLength( |
| 2284 JSArrayBuilder* array_builder, | 2274 JSArrayBuilder* array_builder, |
| 2285 HValue* length_argument) { | 2275 HValue* length_argument) { |
| 2286 if (length_argument->IsConstant() && | 2276 if (length_argument->IsConstant() && |
| 2287 HConstant::cast(length_argument)->HasSmiValue()) { | 2277 HConstant::cast(length_argument)->HasSmiValue()) { |
| 2288 int array_length = HConstant::cast(length_argument)->Integer32Value(); | 2278 int array_length = HConstant::cast(length_argument)->Integer32Value(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2354 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 2344 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
| 2355 ElementsKind kind, | 2345 ElementsKind kind, |
| 2356 HValue* capacity) { | 2346 HValue* capacity) { |
| 2357 Factory* factory = isolate()->factory(); | 2347 Factory* factory = isolate()->factory(); |
| 2358 Handle<Map> map = IsFastDoubleElementsKind(kind) | 2348 Handle<Map> map = IsFastDoubleElementsKind(kind) |
| 2359 ? factory->fixed_double_array_map() | 2349 ? factory->fixed_double_array_map() |
| 2360 : factory->fixed_array_map(); | 2350 : factory->fixed_array_map(); |
| 2361 | 2351 |
| 2362 AddStoreMapConstant(elements, map); | 2352 AddStoreMapConstant(elements, map); |
| 2363 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), | 2353 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), |
| 2364 capacity, INITIALIZING_STORE); | 2354 capacity); |
| 2365 } | 2355 } |
| 2366 | 2356 |
| 2367 | 2357 |
| 2368 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( | 2358 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
| 2369 ElementsKind kind, | 2359 ElementsKind kind, |
| 2370 HValue* capacity) { | 2360 HValue* capacity) { |
| 2371 // The HForceRepresentation is to prevent possible deopt on int-smi | 2361 // The HForceRepresentation is to prevent possible deopt on int-smi |
| 2372 // conversion after allocation but before the new object fields are set. | 2362 // conversion after allocation but before the new object fields are set. |
| 2373 capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi()); | 2363 capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi()); |
| 2374 HValue* new_elements = BuildAllocateElements(kind, capacity); | 2364 HValue* new_elements = BuildAllocateElements(kind, capacity); |
| 2375 BuildInitializeElementsHeader(new_elements, kind, capacity); | 2365 BuildInitializeElementsHeader(new_elements, kind, capacity); |
| 2376 return new_elements; | 2366 return new_elements; |
| 2377 } | 2367 } |
| 2378 | 2368 |
| 2379 | 2369 |
| 2380 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 2370 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
| 2381 HValue* array_map, | 2371 HValue* array_map, |
| 2382 AllocationSiteMode mode, | 2372 AllocationSiteMode mode, |
| 2383 ElementsKind elements_kind, | 2373 ElementsKind elements_kind, |
| 2384 HValue* allocation_site_payload, | 2374 HValue* allocation_site_payload, |
| 2385 HValue* length_field) { | 2375 HValue* length_field) { |
| 2386 | 2376 |
| 2387 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map, | 2377 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map); |
| 2388 INITIALIZING_STORE); | |
| 2389 | 2378 |
| 2390 HConstant* empty_fixed_array = | 2379 HConstant* empty_fixed_array = |
| 2391 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 2380 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
| 2392 | 2381 |
| 2393 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 2382 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 2394 Add<HStoreNamedField>(array, access, empty_fixed_array, INITIALIZING_STORE); | 2383 Add<HStoreNamedField>(array, access, empty_fixed_array); |
| 2395 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), | 2384 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), |
| 2396 length_field, INITIALIZING_STORE); | 2385 length_field); |
| 2397 | 2386 |
| 2398 if (mode == TRACK_ALLOCATION_SITE) { | 2387 if (mode == TRACK_ALLOCATION_SITE) { |
| 2399 BuildCreateAllocationMemento( | 2388 BuildCreateAllocationMemento( |
| 2400 array, Add<HConstant>(JSArray::kSize), allocation_site_payload); | 2389 array, Add<HConstant>(JSArray::kSize), allocation_site_payload); |
| 2401 } | 2390 } |
| 2402 | 2391 |
| 2403 int elements_location = JSArray::kSize; | 2392 int elements_location = JSArray::kSize; |
| 2404 if (mode == TRACK_ALLOCATION_SITE) { | 2393 if (mode == TRACK_ALLOCATION_SITE) { |
| 2405 elements_location += AllocationMemento::kSize; | 2394 elements_location += AllocationMemento::kSize; |
| 2406 } | 2395 } |
| 2407 | 2396 |
| 2408 HInnerAllocatedObject* elements = Add<HInnerAllocatedObject>( | 2397 HInnerAllocatedObject* elements = Add<HInnerAllocatedObject>( |
| 2409 array, Add<HConstant>(elements_location)); | 2398 array, Add<HConstant>(elements_location)); |
| 2410 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements, | 2399 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); |
| 2411 INITIALIZING_STORE); | |
| 2412 return elements; | 2400 return elements; |
| 2413 } | 2401 } |
| 2414 | 2402 |
| 2415 | 2403 |
| 2416 HInstruction* HGraphBuilder::AddElementAccess( | 2404 HInstruction* HGraphBuilder::AddElementAccess( |
| 2417 HValue* elements, | 2405 HValue* elements, |
| 2418 HValue* checked_key, | 2406 HValue* checked_key, |
| 2419 HValue* val, | 2407 HValue* val, |
| 2420 HValue* dependency, | 2408 HValue* dependency, |
| 2421 ElementsKind elements_kind, | 2409 ElementsKind elements_kind, |
| 2422 bool is_store, | 2410 PropertyAccessType access_type, |
| 2423 LoadKeyedHoleMode load_mode) { | 2411 LoadKeyedHoleMode load_mode) { |
| 2424 if (is_store) { | 2412 if (access_type == STORE) { |
| 2425 ASSERT(val != NULL); | 2413 ASSERT(val != NULL); |
| 2426 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || | 2414 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || |
| 2427 elements_kind == UINT8_CLAMPED_ELEMENTS) { | 2415 elements_kind == UINT8_CLAMPED_ELEMENTS) { |
| 2428 val = Add<HClampToUint8>(val); | 2416 val = Add<HClampToUint8>(val); |
| 2429 } | 2417 } |
| 2430 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, | 2418 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, |
| 2431 elements_kind == FAST_SMI_ELEMENTS | 2419 elements_kind == FAST_SMI_ELEMENTS |
| 2432 ? STORE_TO_INITIALIZED_ENTRY | 2420 ? STORE_TO_INITIALIZED_ENTRY |
| 2433 : INITIALIZING_STORE); | 2421 : INITIALIZING_STORE); |
| 2434 } | 2422 } |
| 2435 | 2423 |
| 2436 ASSERT(!is_store); | 2424 ASSERT(access_type == LOAD); |
| 2437 ASSERT(val == NULL); | 2425 ASSERT(val == NULL); |
| 2438 HLoadKeyed* load = Add<HLoadKeyed>( | 2426 HLoadKeyed* load = Add<HLoadKeyed>( |
| 2439 elements, checked_key, dependency, elements_kind, load_mode); | 2427 elements, checked_key, dependency, elements_kind, load_mode); |
| 2440 if (FLAG_opt_safe_uint32_operations && | 2428 if (FLAG_opt_safe_uint32_operations && |
| 2441 (elements_kind == EXTERNAL_UINT32_ELEMENTS || | 2429 (elements_kind == EXTERNAL_UINT32_ELEMENTS || |
| 2442 elements_kind == UINT32_ELEMENTS)) { | 2430 elements_kind == UINT32_ELEMENTS)) { |
| 2443 graph()->RecordUint32Instruction(load); | 2431 graph()->RecordUint32Instruction(load); |
| 2444 } | 2432 } |
| 2445 return load; | 2433 return load; |
| 2446 } | 2434 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2493 BuildNewSpaceArrayCheck(new_capacity, new_kind); | 2481 BuildNewSpaceArrayCheck(new_capacity, new_kind); |
| 2494 | 2482 |
| 2495 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 2483 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
| 2496 new_kind, new_capacity); | 2484 new_kind, new_capacity); |
| 2497 | 2485 |
| 2498 BuildCopyElements(elements, kind, | 2486 BuildCopyElements(elements, kind, |
| 2499 new_elements, new_kind, | 2487 new_elements, new_kind, |
| 2500 length, new_capacity); | 2488 length, new_capacity); |
| 2501 | 2489 |
| 2502 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 2490 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 2503 new_elements, INITIALIZING_STORE); | 2491 new_elements); |
| 2504 | 2492 |
| 2505 return new_elements; | 2493 return new_elements; |
| 2506 } | 2494 } |
| 2507 | 2495 |
| 2508 | 2496 |
| 2509 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, | 2497 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, |
| 2510 ElementsKind elements_kind, | 2498 ElementsKind elements_kind, |
| 2511 HValue* from, | 2499 HValue* from, |
| 2512 HValue* to) { | 2500 HValue* to) { |
| 2513 // Fast elements kinds need to be initialized in case statements below cause | 2501 // Fast elements kinds need to be initialized in case statements below cause |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2534 | 2522 |
| 2535 // Since we're about to store a hole value, the store instruction below must | 2523 // Since we're about to store a hole value, the store instruction below must |
| 2536 // assume an elements kind that supports heap object values. | 2524 // assume an elements kind that supports heap object values. |
| 2537 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 2525 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
| 2538 elements_kind = FAST_HOLEY_ELEMENTS; | 2526 elements_kind = FAST_HOLEY_ELEMENTS; |
| 2539 } | 2527 } |
| 2540 | 2528 |
| 2541 if (initial_capacity >= 0) { | 2529 if (initial_capacity >= 0) { |
| 2542 for (int i = 0; i < initial_capacity; i++) { | 2530 for (int i = 0; i < initial_capacity; i++) { |
| 2543 HInstruction* key = Add<HConstant>(i); | 2531 HInstruction* key = Add<HConstant>(i); |
| 2544 Add<HStoreKeyed>(elements, key, hole, elements_kind, | 2532 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
| 2545 PREINITIALIZING_STORE); | |
| 2546 } | 2533 } |
| 2547 } else { | 2534 } else { |
| 2548 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); | 2535 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
| 2549 | 2536 |
| 2550 HValue* key = builder.BeginBody(from, to, Token::LT); | 2537 HValue* key = builder.BeginBody(from, to, Token::LT); |
| 2551 | 2538 |
| 2552 Add<HStoreKeyed>(elements, key, hole, elements_kind, PREINITIALIZING_STORE); | 2539 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
| 2553 | 2540 |
| 2554 builder.EndBody(); | 2541 builder.EndBody(); |
| 2555 } | 2542 } |
| 2556 } | 2543 } |
| 2557 | 2544 |
| 2558 | 2545 |
| 2559 void HGraphBuilder::BuildCopyElements(HValue* from_elements, | 2546 void HGraphBuilder::BuildCopyElements(HValue* from_elements, |
| 2560 ElementsKind from_elements_kind, | 2547 ElementsKind from_elements_kind, |
| 2561 HValue* to_elements, | 2548 HValue* to_elements, |
| 2562 ElementsKind to_elements_kind, | 2549 ElementsKind to_elements_kind, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2588 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 2575 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
| 2589 | 2576 |
| 2590 if (IsHoleyElementsKind(from_elements_kind) && | 2577 if (IsHoleyElementsKind(from_elements_kind) && |
| 2591 from_elements_kind != to_elements_kind) { | 2578 from_elements_kind != to_elements_kind) { |
| 2592 IfBuilder if_hole(this); | 2579 IfBuilder if_hole(this); |
| 2593 if_hole.If<HCompareHoleAndBranch>(element); | 2580 if_hole.If<HCompareHoleAndBranch>(element); |
| 2594 if_hole.Then(); | 2581 if_hole.Then(); |
| 2595 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) | 2582 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) |
| 2596 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) | 2583 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) |
| 2597 : graph()->GetConstantHole(); | 2584 : graph()->GetConstantHole(); |
| 2598 Add<HStoreKeyed>(to_elements, key, hole_constant, kind, | 2585 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); |
| 2599 PREINITIALIZING_STORE); | |
| 2600 if_hole.Else(); | 2586 if_hole.Else(); |
| 2601 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind, | 2587 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
| 2602 INITIALIZING_STORE); | |
| 2603 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2588 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 2604 if_hole.End(); | 2589 if_hole.End(); |
| 2605 } else { | 2590 } else { |
| 2606 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind, | 2591 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
| 2607 INITIALIZING_STORE); | |
| 2608 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2592 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 2609 } | 2593 } |
| 2610 | 2594 |
| 2611 builder.EndBody(); | 2595 builder.EndBody(); |
| 2612 | 2596 |
| 2613 if (!pre_fill_with_holes && length != capacity) { | 2597 if (!pre_fill_with_holes && length != capacity) { |
| 2614 // Fill unused capacity with the hole. | 2598 // Fill unused capacity with the hole. |
| 2615 BuildFillElementsWithHole(to_elements, to_elements_kind, | 2599 BuildFillElementsWithHole(to_elements, to_elements_kind, |
| 2616 key, capacity); | 2600 key, capacity); |
| 2617 } | 2601 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2636 HType::JSObject(), | 2620 HType::JSObject(), |
| 2637 NOT_TENURED, | 2621 NOT_TENURED, |
| 2638 JS_OBJECT_TYPE); | 2622 JS_OBJECT_TYPE); |
| 2639 | 2623 |
| 2640 // Copy the JS array part. | 2624 // Copy the JS array part. |
| 2641 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 2625 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 2642 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 2626 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
| 2643 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 2627 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
| 2644 Add<HStoreNamedField>( | 2628 Add<HStoreNamedField>( |
| 2645 object, access, Add<HLoadNamedField>( | 2629 object, access, Add<HLoadNamedField>( |
| 2646 boilerplate, static_cast<HValue*>(NULL), access), | 2630 boilerplate, static_cast<HValue*>(NULL), access)); |
| 2647 INITIALIZING_STORE); | |
| 2648 } | 2631 } |
| 2649 } | 2632 } |
| 2650 | 2633 |
| 2651 // Create an allocation site info if requested. | 2634 // Create an allocation site info if requested. |
| 2652 if (mode == TRACK_ALLOCATION_SITE) { | 2635 if (mode == TRACK_ALLOCATION_SITE) { |
| 2653 BuildCreateAllocationMemento( | 2636 BuildCreateAllocationMemento( |
| 2654 object, Add<HConstant>(JSArray::kSize), allocation_site); | 2637 object, Add<HConstant>(JSArray::kSize), allocation_site); |
| 2655 } | 2638 } |
| 2656 | 2639 |
| 2657 if (length > 0) { | 2640 if (length > 0) { |
| 2658 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 2641 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 2659 HValue* object_elements; | 2642 HValue* object_elements; |
| 2660 if (IsFastDoubleElementsKind(kind)) { | 2643 if (IsFastDoubleElementsKind(kind)) { |
| 2661 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); | 2644 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); |
| 2662 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), | 2645 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), |
| 2663 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); | 2646 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); |
| 2664 } else { | 2647 } else { |
| 2665 HValue* elems_size = Add<HConstant>(FixedArray::SizeFor(length)); | 2648 HValue* elems_size = Add<HConstant>(FixedArray::SizeFor(length)); |
| 2666 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), | 2649 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), |
| 2667 NOT_TENURED, FIXED_ARRAY_TYPE); | 2650 NOT_TENURED, FIXED_ARRAY_TYPE); |
| 2668 } | 2651 } |
| 2669 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 2652 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 2670 object_elements, INITIALIZING_STORE); | 2653 object_elements); |
| 2671 | 2654 |
| 2672 // Copy the elements array header. | 2655 // Copy the elements array header. |
| 2673 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 2656 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
| 2674 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | 2657 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
| 2675 Add<HStoreNamedField>( | 2658 Add<HStoreNamedField>( |
| 2676 object_elements, access, Add<HLoadNamedField>( | 2659 object_elements, access, Add<HLoadNamedField>( |
| 2677 boilerplate_elements, static_cast<HValue*>(NULL), access), | 2660 boilerplate_elements, static_cast<HValue*>(NULL), access)); |
| 2678 INITIALIZING_STORE); | |
| 2679 } | 2661 } |
| 2680 | 2662 |
| 2681 // Copy the elements array contents. | 2663 // Copy the elements array contents. |
| 2682 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold | 2664 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold |
| 2683 // copying loops with constant length up to a given boundary and use this | 2665 // copying loops with constant length up to a given boundary and use this |
| 2684 // helper here instead. | 2666 // helper here instead. |
| 2685 for (int i = 0; i < length; i++) { | 2667 for (int i = 0; i < length; i++) { |
| 2686 HValue* key_constant = Add<HConstant>(i); | 2668 HValue* key_constant = Add<HConstant>(i); |
| 2687 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, | 2669 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, |
| 2688 static_cast<HValue*>(NULL), kind); | 2670 static_cast<HValue*>(NULL), kind); |
| 2689 Add<HStoreKeyed>(object_elements, key_constant, value, kind, | 2671 Add<HStoreKeyed>(object_elements, key_constant, value, kind); |
| 2690 INITIALIZING_STORE); | |
| 2691 } | 2672 } |
| 2692 } | 2673 } |
| 2693 | 2674 |
| 2694 return object; | 2675 return object; |
| 2695 } | 2676 } |
| 2696 | 2677 |
| 2697 | 2678 |
| 2698 void HGraphBuilder::BuildCompareNil( | 2679 void HGraphBuilder::BuildCompareNil( |
| 2699 HValue* value, | 2680 HValue* value, |
| 2700 Type* type, | 2681 Type* type, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2750 void HGraphBuilder::BuildCreateAllocationMemento( | 2731 void HGraphBuilder::BuildCreateAllocationMemento( |
| 2751 HValue* previous_object, | 2732 HValue* previous_object, |
| 2752 HValue* previous_object_size, | 2733 HValue* previous_object_size, |
| 2753 HValue* allocation_site) { | 2734 HValue* allocation_site) { |
| 2754 ASSERT(allocation_site != NULL); | 2735 ASSERT(allocation_site != NULL); |
| 2755 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>( | 2736 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>( |
| 2756 previous_object, previous_object_size); | 2737 previous_object, previous_object_size); |
| 2757 AddStoreMapConstant( | 2738 AddStoreMapConstant( |
| 2758 allocation_memento, isolate()->factory()->allocation_memento_map()); | 2739 allocation_memento, isolate()->factory()->allocation_memento_map()); |
| 2759 Add<HStoreNamedField>( | 2740 Add<HStoreNamedField>( |
| 2760 allocation_memento, HObjectAccess::ForAllocationMementoSite(), | 2741 allocation_memento, |
| 2761 allocation_site, INITIALIZING_STORE); | 2742 HObjectAccess::ForAllocationMementoSite(), |
| 2743 allocation_site); |
| 2762 if (FLAG_allocation_site_pretenuring) { | 2744 if (FLAG_allocation_site_pretenuring) { |
| 2763 HValue* memento_create_count = Add<HLoadNamedField>( | 2745 HValue* memento_create_count = Add<HLoadNamedField>( |
| 2764 allocation_site, static_cast<HValue*>(NULL), | 2746 allocation_site, static_cast<HValue*>(NULL), |
| 2765 HObjectAccess::ForAllocationSiteOffset( | 2747 HObjectAccess::ForAllocationSiteOffset( |
| 2766 AllocationSite::kPretenureCreateCountOffset)); | 2748 AllocationSite::kPretenureCreateCountOffset)); |
| 2767 memento_create_count = AddUncasted<HAdd>( | 2749 memento_create_count = AddUncasted<HAdd>( |
| 2768 memento_create_count, graph()->GetConstant1()); | 2750 memento_create_count, graph()->GetConstant1()); |
| 2769 // This smi value is reset to zero after every gc, overflow isn't a problem | 2751 // This smi value is reset to zero after every gc, overflow isn't a problem |
| 2770 // since the counter is bounded by the new space size. | 2752 // since the counter is bounded by the new space size. |
| 2771 memento_create_count->ClearFlag(HValue::kCanOverflow); | 2753 memento_create_count->ClearFlag(HValue::kCanOverflow); |
| 2772 HStoreNamedField* store = Add<HStoreNamedField>( | 2754 HStoreNamedField* store = Add<HStoreNamedField>( |
| 2773 allocation_site, HObjectAccess::ForAllocationSiteOffset( | 2755 allocation_site, HObjectAccess::ForAllocationSiteOffset( |
| 2774 AllocationSite::kPretenureCreateCountOffset), memento_create_count, | 2756 AllocationSite::kPretenureCreateCountOffset), memento_create_count); |
| 2775 INITIALIZING_STORE); | |
| 2776 // No write barrier needed to store a smi. | 2757 // No write barrier needed to store a smi. |
| 2777 store->SkipWriteBarrier(); | 2758 store->SkipWriteBarrier(); |
| 2778 } | 2759 } |
| 2779 } | 2760 } |
| 2780 | 2761 |
| 2781 | 2762 |
| 2782 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) { | 2763 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) { |
| 2783 // Get the global context, then the native context | 2764 // Get the global context, then the native context |
| 2784 HInstruction* context = | 2765 HInstruction* context = |
| 2785 Add<HLoadNamedField>(closure, static_cast<HValue*>(NULL), | 2766 Add<HLoadNamedField>(closure, static_cast<HValue*>(NULL), |
| 2786 HObjectAccess::ForFunctionContextPointer()); | 2767 HObjectAccess::ForFunctionContextPointer()); |
| 2787 HInstruction* global_object = Add<HLoadNamedField>( | 2768 HInstruction* global_object = Add<HLoadNamedField>( |
| 2788 context, static_cast<HValue*>(NULL), | 2769 context, static_cast<HValue*>(NULL), |
| 2789 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 2770 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
| 2790 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 2771 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset( |
| 2791 GlobalObject::kNativeContextOffset); | 2772 GlobalObject::kNativeContextOffset); |
| 2792 return Add<HLoadNamedField>( | 2773 return Add<HLoadNamedField>( |
| 2793 global_object, static_cast<HValue*>(NULL), access); | 2774 global_object, static_cast<HValue*>(NULL), access); |
| 2794 } | 2775 } |
| 2795 | 2776 |
| 2796 | 2777 |
| 2797 HInstruction* HGraphBuilder::BuildGetNativeContext() { | 2778 HInstruction* HGraphBuilder::BuildGetNativeContext() { |
| 2798 // Get the global context, then the native context | 2779 // Get the global context, then the native context |
| 2799 HValue* global_object = Add<HLoadNamedField>( | 2780 HValue* global_object = Add<HLoadNamedField>( |
| 2800 context(), static_cast<HValue*>(NULL), | 2781 context(), static_cast<HValue*>(NULL), |
| 2801 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 2782 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
| 2802 return Add<HLoadNamedField>( | 2783 return Add<HLoadNamedField>( |
| 2803 global_object, static_cast<HValue*>(NULL), | 2784 global_object, static_cast<HValue*>(NULL), |
| 2804 HObjectAccess::ForJSObjectOffset(GlobalObject::kNativeContextOffset)); | 2785 HObjectAccess::ForObservableJSObjectOffset( |
| 2786 GlobalObject::kNativeContextOffset)); |
| 2805 } | 2787 } |
| 2806 | 2788 |
| 2807 | 2789 |
| 2808 HInstruction* HGraphBuilder::BuildGetArrayFunction() { | 2790 HInstruction* HGraphBuilder::BuildGetArrayFunction() { |
| 2809 HInstruction* native_context = BuildGetNativeContext(); | 2791 HInstruction* native_context = BuildGetNativeContext(); |
| 2810 HInstruction* index = | 2792 HInstruction* index = |
| 2811 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); | 2793 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); |
| 2812 return Add<HLoadKeyed>( | 2794 return Add<HLoadKeyed>( |
| 2813 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 2795 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 2814 } | 2796 } |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2985 graph()->GetConstant0(), capacity); | 2967 graph()->GetConstant0(), capacity); |
| 2986 } | 2968 } |
| 2987 | 2969 |
| 2988 return new_object; | 2970 return new_object; |
| 2989 } | 2971 } |
| 2990 | 2972 |
| 2991 | 2973 |
| 2992 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 2974 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
| 2993 Handle<Map> map) { | 2975 Handle<Map> map) { |
| 2994 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), | 2976 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), |
| 2995 Add<HConstant>(map), INITIALIZING_STORE); | 2977 Add<HConstant>(map)); |
| 2996 } | 2978 } |
| 2997 | 2979 |
| 2998 | 2980 |
| 2999 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) { | 2981 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) { |
| 3000 HValue* global_object = Add<HLoadNamedField>( | 2982 HValue* global_object = Add<HLoadNamedField>( |
| 3001 context(), static_cast<HValue*>(NULL), | 2983 context(), static_cast<HValue*>(NULL), |
| 3002 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 2984 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
| 3003 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 2985 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset( |
| 3004 GlobalObject::kBuiltinsOffset); | 2986 GlobalObject::kBuiltinsOffset); |
| 3005 HValue* builtins = Add<HLoadNamedField>( | 2987 HValue* builtins = Add<HLoadNamedField>( |
| 3006 global_object, static_cast<HValue*>(NULL), access); | 2988 global_object, static_cast<HValue*>(NULL), access); |
| 3007 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( | 2989 HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset( |
| 3008 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); | 2990 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); |
| 3009 return Add<HLoadNamedField>( | 2991 return Add<HLoadNamedField>( |
| 3010 builtins, static_cast<HValue*>(NULL), function_access); | 2992 builtins, static_cast<HValue*>(NULL), function_access); |
| 3011 } | 2993 } |
| 3012 | 2994 |
| 3013 | 2995 |
| 3014 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) | 2996 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) |
| 3015 : HGraphBuilder(info), | 2997 : HGraphBuilder(info), |
| 3016 function_state_(NULL), | 2998 function_state_(NULL), |
| 3017 initial_function_state_(this, info, NORMAL_RETURN), | 2999 initial_function_state_(this, info, NORMAL_RETURN), |
| 3018 ast_context_(NULL), | 3000 ast_context_(NULL), |
| (...skipping 1777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4796 set_current_block(join); | 4778 set_current_block(join); |
| 4797 if (join != NULL && !ast_context()->IsEffect()) { | 4779 if (join != NULL && !ast_context()->IsEffect()) { |
| 4798 return ast_context()->ReturnValue(Pop()); | 4780 return ast_context()->ReturnValue(Pop()); |
| 4799 } | 4781 } |
| 4800 } | 4782 } |
| 4801 } | 4783 } |
| 4802 | 4784 |
| 4803 | 4785 |
| 4804 HOptimizedGraphBuilder::GlobalPropertyAccess | 4786 HOptimizedGraphBuilder::GlobalPropertyAccess |
| 4805 HOptimizedGraphBuilder::LookupGlobalProperty( | 4787 HOptimizedGraphBuilder::LookupGlobalProperty( |
| 4806 Variable* var, LookupResult* lookup, bool is_store) { | 4788 Variable* var, LookupResult* lookup, PropertyAccessType access_type) { |
| 4807 if (var->is_this() || !current_info()->has_global_object()) { | 4789 if (var->is_this() || !current_info()->has_global_object()) { |
| 4808 return kUseGeneric; | 4790 return kUseGeneric; |
| 4809 } | 4791 } |
| 4810 Handle<GlobalObject> global(current_info()->global_object()); | 4792 Handle<GlobalObject> global(current_info()->global_object()); |
| 4811 global->Lookup(*var->name(), lookup); | 4793 global->Lookup(*var->name(), lookup); |
| 4812 if (!lookup->IsNormal() || | 4794 if (!lookup->IsNormal() || |
| 4813 (is_store && lookup->IsReadOnly()) || | 4795 (access_type == STORE && lookup->IsReadOnly()) || |
| 4814 lookup->holder() != *global) { | 4796 lookup->holder() != *global) { |
| 4815 return kUseGeneric; | 4797 return kUseGeneric; |
| 4816 } | 4798 } |
| 4817 | 4799 |
| 4818 return kUseCell; | 4800 return kUseCell; |
| 4819 } | 4801 } |
| 4820 | 4802 |
| 4821 | 4803 |
| 4822 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 4804 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 4823 ASSERT(var->IsContextSlot()); | 4805 ASSERT(var->IsContextSlot()); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 4849 // Handle known global constants like 'undefined' specially to avoid a | 4831 // Handle known global constants like 'undefined' specially to avoid a |
| 4850 // load from a global cell for them. | 4832 // load from a global cell for them. |
| 4851 Handle<Object> constant_value = | 4833 Handle<Object> constant_value = |
| 4852 isolate()->factory()->GlobalConstantFor(variable->name()); | 4834 isolate()->factory()->GlobalConstantFor(variable->name()); |
| 4853 if (!constant_value.is_null()) { | 4835 if (!constant_value.is_null()) { |
| 4854 HConstant* instr = New<HConstant>(constant_value); | 4836 HConstant* instr = New<HConstant>(constant_value); |
| 4855 return ast_context()->ReturnInstruction(instr, expr->id()); | 4837 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4856 } | 4838 } |
| 4857 | 4839 |
| 4858 LookupResult lookup(isolate()); | 4840 LookupResult lookup(isolate()); |
| 4859 GlobalPropertyAccess type = | 4841 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, LOAD); |
| 4860 LookupGlobalProperty(variable, &lookup, false); | |
| 4861 | 4842 |
| 4862 if (type == kUseCell && | 4843 if (type == kUseCell && |
| 4863 current_info()->global_object()->IsAccessCheckNeeded()) { | 4844 current_info()->global_object()->IsAccessCheckNeeded()) { |
| 4864 type = kUseGeneric; | 4845 type = kUseGeneric; |
| 4865 } | 4846 } |
| 4866 | 4847 |
| 4867 if (type == kUseCell) { | 4848 if (type == kUseCell) { |
| 4868 Handle<GlobalObject> global(current_info()->global_object()); | 4849 Handle<GlobalObject> global(current_info()->global_object()); |
| 4869 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 4850 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 4870 if (cell->type()->IsConstant()) { | 4851 if (cell->type()->IsConstant()) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4932 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4913 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 4933 Handle<FixedArray> literals(closure->literals()); | 4914 Handle<FixedArray> literals(closure->literals()); |
| 4934 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, | 4915 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, |
| 4935 expr->pattern(), | 4916 expr->pattern(), |
| 4936 expr->flags(), | 4917 expr->flags(), |
| 4937 expr->literal_index()); | 4918 expr->literal_index()); |
| 4938 return ast_context()->ReturnInstruction(instr, expr->id()); | 4919 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4939 } | 4920 } |
| 4940 | 4921 |
| 4941 | 4922 |
| 4942 static bool CanInlinePropertyAccess(Handle<HeapType> type) { | 4923 static bool CanInlinePropertyAccess(Type* type) { |
| 4943 if (type->Is(HeapType::NumberOrString())) return true; | 4924 if (type->Is(Type::NumberOrString())) return true; |
| 4944 if (!type->IsClass()) return false; | 4925 if (!type->IsClass()) return false; |
| 4945 Handle<Map> map = type->AsClass(); | 4926 Handle<Map> map = type->AsClass(); |
| 4946 return map->IsJSObjectMap() && | 4927 return map->IsJSObjectMap() && |
| 4947 !map->is_dictionary_map() && | 4928 !map->is_dictionary_map() && |
| 4948 !map->has_named_interceptor(); | 4929 !map->has_named_interceptor(); |
| 4949 } | 4930 } |
| 4950 | 4931 |
| 4951 | 4932 |
| 4952 static void LookupInPrototypes(Handle<Map> map, | |
| 4953 Handle<String> name, | |
| 4954 LookupResult* lookup) { | |
| 4955 while (map->prototype()->IsJSObject()) { | |
| 4956 Handle<JSObject> holder(JSObject::cast(map->prototype())); | |
| 4957 map = handle(holder->map()); | |
| 4958 if (!CanInlinePropertyAccess(IC::MapToType(map))) break; | |
| 4959 map->LookupDescriptor(*holder, *name, lookup); | |
| 4960 if (lookup->IsFound()) return; | |
| 4961 } | |
| 4962 lookup->NotFound(); | |
| 4963 } | |
| 4964 | |
| 4965 | |
| 4966 // Tries to find a JavaScript accessor of the given name in the prototype chain | |
| 4967 // starting at the given map. Return true iff there is one, including the | |
| 4968 // corresponding AccessorPair plus its holder (which could be null when the | |
| 4969 // accessor is found directly in the given map). | |
| 4970 static bool LookupAccessorPair(Handle<Map> map, | |
| 4971 Handle<String> name, | |
| 4972 Handle<AccessorPair>* accessors, | |
| 4973 Handle<JSObject>* holder) { | |
| 4974 Isolate* isolate = map->GetIsolate(); | |
| 4975 LookupResult lookup(isolate); | |
| 4976 | |
| 4977 // Check for a JavaScript accessor directly in the map. | |
| 4978 map->LookupDescriptor(NULL, *name, &lookup); | |
| 4979 if (lookup.IsPropertyCallbacks()) { | |
| 4980 Handle<Object> callback(lookup.GetValueFromMap(*map), isolate); | |
| 4981 if (!callback->IsAccessorPair()) return false; | |
| 4982 *accessors = Handle<AccessorPair>::cast(callback); | |
| 4983 *holder = Handle<JSObject>(); | |
| 4984 return true; | |
| 4985 } | |
| 4986 | |
| 4987 // Everything else, e.g. a field, can't be an accessor call. | |
| 4988 if (lookup.IsFound()) return false; | |
| 4989 | |
| 4990 // Check for a JavaScript accessor somewhere in the proto chain. | |
| 4991 LookupInPrototypes(map, name, &lookup); | |
| 4992 if (lookup.IsPropertyCallbacks()) { | |
| 4993 Handle<Object> callback(lookup.GetValue(), isolate); | |
| 4994 if (!callback->IsAccessorPair()) return false; | |
| 4995 *accessors = Handle<AccessorPair>::cast(callback); | |
| 4996 *holder = Handle<JSObject>(lookup.holder()); | |
| 4997 return true; | |
| 4998 } | |
| 4999 | |
| 5000 // We haven't found a JavaScript accessor anywhere. | |
| 5001 return false; | |
| 5002 } | |
| 5003 | |
| 5004 | |
| 5005 static bool LookupSetter(Handle<Map> map, | |
| 5006 Handle<String> name, | |
| 5007 Handle<JSFunction>* setter, | |
| 5008 Handle<JSObject>* holder) { | |
| 5009 Handle<AccessorPair> accessors; | |
| 5010 if (LookupAccessorPair(map, name, &accessors, holder) && | |
| 5011 accessors->setter()->IsJSFunction()) { | |
| 5012 Handle<JSFunction> func(JSFunction::cast(accessors->setter())); | |
| 5013 CallOptimization call_optimization(func); | |
| 5014 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. | |
| 5015 if (call_optimization.is_simple_api_call()) return false; | |
| 5016 *setter = func; | |
| 5017 return true; | |
| 5018 } | |
| 5019 return false; | |
| 5020 } | |
| 5021 | |
| 5022 | |
| 5023 // Determines whether the given array or object literal boilerplate satisfies | 4933 // Determines whether the given array or object literal boilerplate satisfies |
| 5024 // all limits to be considered for fast deep-copying and computes the total | 4934 // all limits to be considered for fast deep-copying and computes the total |
| 5025 // size of all objects that are part of the graph. | 4935 // size of all objects that are part of the graph. |
| 5026 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 4936 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
| 5027 int max_depth, | 4937 int max_depth, |
| 5028 int* max_properties) { | 4938 int* max_properties) { |
| 5029 if (boilerplate->map()->is_deprecated()) { | 4939 if (boilerplate->map()->is_deprecated()) { |
| 5030 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); | 4940 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); |
| 5031 if (result.is_null()) return false; | 4941 if (result.is_null()) return false; |
| 5032 } | 4942 } |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5156 case ObjectLiteral::Property::COMPUTED: | 5066 case ObjectLiteral::Property::COMPUTED: |
| 5157 if (key->value()->IsInternalizedString()) { | 5067 if (key->value()->IsInternalizedString()) { |
| 5158 if (property->emit_store()) { | 5068 if (property->emit_store()) { |
| 5159 CHECK_ALIVE(VisitForValue(value)); | 5069 CHECK_ALIVE(VisitForValue(value)); |
| 5160 HValue* value = Pop(); | 5070 HValue* value = Pop(); |
| 5161 Handle<Map> map = property->GetReceiverType(); | 5071 Handle<Map> map = property->GetReceiverType(); |
| 5162 Handle<String> name = property->key()->AsPropertyName(); | 5072 Handle<String> name = property->key()->AsPropertyName(); |
| 5163 HInstruction* store; | 5073 HInstruction* store; |
| 5164 if (map.is_null()) { | 5074 if (map.is_null()) { |
| 5165 // If we don't know the monomorphic type, do a generic store. | 5075 // If we don't know the monomorphic type, do a generic store. |
| 5166 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); | 5076 CHECK_ALIVE(store = BuildNamedGeneric( |
| 5077 STORE, literal, name, value)); |
| 5167 } else { | 5078 } else { |
| 5168 #if DEBUG | 5079 PropertyAccessInfo info(this, STORE, ToType(map), name); |
| 5169 Handle<JSFunction> setter; | 5080 if (info.CanAccessMonomorphic()) { |
| 5170 Handle<JSObject> holder; | 5081 HValue* checked_literal = BuildCheckMap(literal, map); |
| 5171 ASSERT(!LookupSetter(map, name, &setter, &holder)); | 5082 ASSERT(!info.lookup()->IsPropertyCallbacks()); |
| 5172 #endif | 5083 store = BuildMonomorphicAccess( |
| 5173 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, | 5084 &info, literal, checked_literal, value, |
| 5174 name, | 5085 BailoutId::None(), BailoutId::None()); |
| 5175 value, | 5086 } else { |
| 5176 map)); | 5087 CHECK_ALIVE(store = BuildNamedGeneric( |
| 5088 STORE, literal, name, value)); |
| 5089 } |
| 5177 } | 5090 } |
| 5178 AddInstruction(store); | 5091 AddInstruction(store); |
| 5179 if (store->HasObservableSideEffects()) { | 5092 if (store->HasObservableSideEffects()) { |
| 5180 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); | 5093 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
| 5181 } | 5094 } |
| 5182 } else { | 5095 } else { |
| 5183 CHECK_ALIVE(VisitForEffect(value)); | 5096 CHECK_ALIVE(VisitForEffect(value)); |
| 5184 } | 5097 } |
| 5185 break; | 5098 break; |
| 5186 } | 5099 } |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5317 HValue* key = Add<HConstant>(i); | 5230 HValue* key = Add<HConstant>(i); |
| 5318 | 5231 |
| 5319 switch (boilerplate_elements_kind) { | 5232 switch (boilerplate_elements_kind) { |
| 5320 case FAST_SMI_ELEMENTS: | 5233 case FAST_SMI_ELEMENTS: |
| 5321 case FAST_HOLEY_SMI_ELEMENTS: | 5234 case FAST_HOLEY_SMI_ELEMENTS: |
| 5322 case FAST_ELEMENTS: | 5235 case FAST_ELEMENTS: |
| 5323 case FAST_HOLEY_ELEMENTS: | 5236 case FAST_HOLEY_ELEMENTS: |
| 5324 case FAST_DOUBLE_ELEMENTS: | 5237 case FAST_DOUBLE_ELEMENTS: |
| 5325 case FAST_HOLEY_DOUBLE_ELEMENTS: { | 5238 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
| 5326 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, | 5239 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, |
| 5327 boilerplate_elements_kind, | 5240 boilerplate_elements_kind); |
| 5328 INITIALIZING_STORE); | |
| 5329 instr->SetUninitialized(uninitialized); | 5241 instr->SetUninitialized(uninitialized); |
| 5330 break; | 5242 break; |
| 5331 } | 5243 } |
| 5332 default: | 5244 default: |
| 5333 UNREACHABLE(); | 5245 UNREACHABLE(); |
| 5334 break; | 5246 break; |
| 5335 } | 5247 } |
| 5336 | 5248 |
| 5337 Add<HSimulate>(expr->GetIdForElement(i)); | 5249 Add<HSimulate>(expr->GetIdForElement(i)); |
| 5338 } | 5250 } |
| 5339 | 5251 |
| 5340 Drop(1); // array literal index | 5252 Drop(1); // array literal index |
| 5341 return ast_context()->ReturnValue(Pop()); | 5253 return ast_context()->ReturnValue(Pop()); |
| 5342 } | 5254 } |
| 5343 | 5255 |
| 5344 | 5256 |
| 5345 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, | 5257 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, |
| 5346 Handle<Map> map) { | 5258 Handle<Map> map) { |
| 5347 BuildCheckHeapObject(object); | 5259 BuildCheckHeapObject(object); |
| 5348 return Add<HCheckMaps>(object, map, top_info()); | 5260 return Add<HCheckMaps>(object, map, top_info()); |
| 5349 } | 5261 } |
| 5350 | 5262 |
| 5351 | 5263 |
| 5352 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 5264 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( |
| 5265 PropertyAccessInfo* info, |
| 5353 HValue* checked_object, | 5266 HValue* checked_object, |
| 5354 Handle<String> name, | 5267 HValue* value) { |
| 5355 HValue* value, | 5268 bool transition_to_field = info->lookup()->IsTransition(); |
| 5356 Handle<Map> map, | 5269 // TODO(verwaest): Move this logic into PropertyAccessInfo. |
| 5357 LookupResult* lookup) { | 5270 HObjectAccess field_access = HObjectAccess::ForField( |
| 5358 ASSERT(lookup->IsFound()); | 5271 info->map(), info->lookup(), info->name()); |
| 5359 // If the property does not exist yet, we have to check that it wasn't made | |
| 5360 // readonly or turned into a setter by some meanwhile modifications on the | |
| 5361 // prototype chain. | |
| 5362 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { | |
| 5363 Object* proto = map->prototype(); | |
| 5364 // First check that the prototype chain isn't affected already. | |
| 5365 LookupResult proto_result(isolate()); | |
| 5366 proto->Lookup(*name, &proto_result); | |
| 5367 if (proto_result.IsProperty()) { | |
| 5368 // If the inherited property could induce readonly-ness, bail out. | |
| 5369 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { | |
| 5370 Bailout(kImproperObjectOnPrototypeChainForStore); | |
| 5371 return NULL; | |
| 5372 } | |
| 5373 // We only need to check up to the preexisting property. | |
| 5374 proto = proto_result.holder(); | |
| 5375 } else { | |
| 5376 // Otherwise, find the top prototype. | |
| 5377 while (proto->GetPrototype(isolate())->IsJSObject()) { | |
| 5378 proto = proto->GetPrototype(isolate()); | |
| 5379 } | |
| 5380 ASSERT(proto->GetPrototype(isolate())->IsNull()); | |
| 5381 } | |
| 5382 ASSERT(proto->IsJSObject()); | |
| 5383 BuildCheckPrototypeMaps( | |
| 5384 Handle<JSObject>(JSObject::cast(map->prototype())), | |
| 5385 Handle<JSObject>(JSObject::cast(proto))); | |
| 5386 } | |
| 5387 | |
| 5388 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | |
| 5389 bool transition_to_field = lookup->IsTransitionToField(*map); | |
| 5390 | 5272 |
| 5391 HStoreNamedField *instr; | 5273 HStoreNamedField *instr; |
| 5392 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { | 5274 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { |
| 5393 HObjectAccess heap_number_access = | 5275 HObjectAccess heap_number_access = |
| 5394 field_access.WithRepresentation(Representation::Tagged()); | 5276 field_access.WithRepresentation(Representation::Tagged()); |
| 5395 if (transition_to_field) { | 5277 if (transition_to_field) { |
| 5396 // The store requires a mutable HeapNumber to be allocated. | 5278 // The store requires a mutable HeapNumber to be allocated. |
| 5397 NoObservableSideEffectsScope no_side_effects(this); | 5279 NoObservableSideEffectsScope no_side_effects(this); |
| 5398 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); | 5280 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); |
| 5399 | 5281 |
| 5400 PretenureFlag pretenure_flag = !FLAG_allocation_site_pretenuring ? | 5282 PretenureFlag pretenure_flag = !FLAG_allocation_site_pretenuring ? |
| 5401 isolate()->heap()->GetPretenureMode() : NOT_TENURED; | 5283 isolate()->heap()->GetPretenureMode() : NOT_TENURED; |
| 5402 | 5284 |
| 5403 HInstruction* heap_number = Add<HAllocate>(heap_number_size, | 5285 HInstruction* heap_number = Add<HAllocate>(heap_number_size, |
| 5404 HType::HeapNumber(), | 5286 HType::HeapNumber(), |
| 5405 pretenure_flag, | 5287 pretenure_flag, |
| 5406 HEAP_NUMBER_TYPE); | 5288 HEAP_NUMBER_TYPE); |
| 5407 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); | 5289 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); |
| 5408 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), | 5290 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), |
| 5409 value, INITIALIZING_STORE); | 5291 value); |
| 5410 instr = New<HStoreNamedField>(checked_object->ActualValue(), | 5292 instr = New<HStoreNamedField>(checked_object->ActualValue(), |
| 5411 heap_number_access, | 5293 heap_number_access, |
| 5412 heap_number, INITIALIZING_STORE); | 5294 heap_number); |
| 5413 } else { | 5295 } else { |
| 5414 // Already holds a HeapNumber; load the box and write its value field. | 5296 // Already holds a HeapNumber; load the box and write its value field. |
| 5415 HInstruction* heap_number = Add<HLoadNamedField>( | 5297 HInstruction* heap_number = Add<HLoadNamedField>( |
| 5416 checked_object, static_cast<HValue*>(NULL), heap_number_access); | 5298 checked_object, static_cast<HValue*>(NULL), heap_number_access); |
| 5417 heap_number->set_type(HType::HeapNumber()); | 5299 heap_number->set_type(HType::HeapNumber()); |
| 5418 instr = New<HStoreNamedField>(heap_number, | 5300 instr = New<HStoreNamedField>(heap_number, |
| 5419 HObjectAccess::ForHeapNumberValue(), | 5301 HObjectAccess::ForHeapNumberValue(), |
| 5420 value, STORE_TO_INITIALIZED_ENTRY); | 5302 value, STORE_TO_INITIALIZED_ENTRY); |
| 5421 } | 5303 } |
| 5422 } else { | 5304 } else { |
| 5423 // This is a normal store. | 5305 // This is a normal store. |
| 5424 instr = New<HStoreNamedField>( | 5306 instr = New<HStoreNamedField>( |
| 5425 checked_object->ActualValue(), field_access, value, | 5307 checked_object->ActualValue(), field_access, value, |
| 5426 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); | 5308 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); |
| 5427 } | 5309 } |
| 5428 | 5310 |
| 5429 if (transition_to_field) { | 5311 if (transition_to_field) { |
| 5430 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 5312 HConstant* transition_constant = Add<HConstant>(info->transition()); |
| 5431 HConstant* transition_constant = Add<HConstant>(transition); | |
| 5432 instr->SetTransition(transition_constant, top_info()); | 5313 instr->SetTransition(transition_constant, top_info()); |
| 5433 // TODO(fschneider): Record the new map type of the object in the IR to | |
| 5434 // enable elimination of redundant checks after the transition store. | |
| 5435 instr->SetGVNFlag(kChangesMaps); | 5314 instr->SetGVNFlag(kChangesMaps); |
| 5436 } | 5315 } |
| 5437 return instr; | 5316 return instr; |
| 5438 } | 5317 } |
| 5439 | 5318 |
| 5440 | 5319 |
| 5441 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | 5320 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( |
| 5442 HValue* object, | |
| 5443 Handle<String> name, | |
| 5444 HValue* value) { | |
| 5445 return New<HStoreNamedGeneric>( | |
| 5446 object, | |
| 5447 name, | |
| 5448 value, | |
| 5449 function_strict_mode_flag()); | |
| 5450 } | |
| 5451 | |
| 5452 | |
| 5453 // Sets the lookup result and returns true if the load/store can be inlined. | |
| 5454 static bool ComputeStoreField(Handle<Map> type, | |
| 5455 Handle<String> name, | |
| 5456 LookupResult* lookup, | |
| 5457 bool lookup_transition = true) { | |
| 5458 ASSERT(!type->is_observed()); | |
| 5459 if (!CanInlinePropertyAccess(IC::MapToType(type))) { | |
| 5460 lookup->NotFound(); | |
| 5461 return false; | |
| 5462 } | |
| 5463 // If we directly find a field, the access can be inlined. | |
| 5464 type->LookupDescriptor(NULL, *name, lookup); | |
| 5465 if (lookup->IsField()) return true; | |
| 5466 | |
| 5467 if (!lookup_transition) return false; | |
| 5468 | |
| 5469 type->LookupTransition(NULL, *name, lookup); | |
| 5470 return lookup->IsTransitionToField(*type) && | |
| 5471 (type->unused_property_fields() > 0); | |
| 5472 } | |
| 5473 | |
| 5474 | |
| 5475 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( | |
| 5476 HValue* object, | |
| 5477 Handle<String> name, | |
| 5478 HValue* value, | |
| 5479 Handle<Map> map) { | |
| 5480 // Handle a store to a known field. | |
| 5481 LookupResult lookup(isolate()); | |
| 5482 if (ComputeStoreField(map, name, &lookup)) { | |
| 5483 HCheckMaps* checked_object = AddCheckMap(object, map); | |
| 5484 return BuildStoreNamedField(checked_object, name, value, map, &lookup); | |
| 5485 } | |
| 5486 | |
| 5487 // No luck, do a generic store. | |
| 5488 return BuildStoreNamedGeneric(object, name, value); | |
| 5489 } | |
| 5490 | |
| 5491 | |
| 5492 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad( | |
| 5493 PropertyAccessInfo* info) { | 5321 PropertyAccessInfo* info) { |
| 5494 if (!CanInlinePropertyAccess(type_)) return false; | 5322 if (!CanInlinePropertyAccess(type_)) return false; |
| 5495 | 5323 |
| 5496 // Currently only handle HeapType::Number as a polymorphic case. | 5324 // Currently only handle Type::Number as a polymorphic case. |
| 5497 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 5325 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
| 5498 // instruction. | 5326 // instruction. |
| 5499 if (type_->Is(HeapType::Number())) return false; | 5327 if (type_->Is(Type::Number())) return false; |
| 5500 | 5328 |
| 5501 // Values are only compatible for monomorphic load if they all behave the same | 5329 // Values are only compatible for monomorphic load if they all behave the same |
| 5502 // regarding value wrappers. | 5330 // regarding value wrappers. |
| 5503 if (type_->Is(HeapType::NumberOrString())) { | 5331 if (type_->Is(Type::NumberOrString())) { |
| 5504 if (!info->type_->Is(HeapType::NumberOrString())) return false; | 5332 if (!info->type_->Is(Type::NumberOrString())) return false; |
| 5505 } else { | 5333 } else { |
| 5506 if (info->type_->Is(HeapType::NumberOrString())) return false; | 5334 if (info->type_->Is(Type::NumberOrString())) return false; |
| 5507 } | 5335 } |
| 5508 | 5336 |
| 5509 if (!LookupDescriptor()) return false; | 5337 if (!LookupDescriptor()) return false; |
| 5510 | 5338 |
| 5511 if (!lookup_.IsFound()) { | 5339 if (!lookup_.IsFound()) { |
| 5512 return (!info->lookup_.IsFound() || info->has_holder()) && | 5340 return (!info->lookup_.IsFound() || info->has_holder()) && |
| 5513 map()->prototype() == info->map()->prototype(); | 5341 map()->prototype() == info->map()->prototype(); |
| 5514 } | 5342 } |
| 5515 | 5343 |
| 5516 // Mismatch if the other access info found the property in the prototype | 5344 // Mismatch if the other access info found the property in the prototype |
| 5517 // chain. | 5345 // chain. |
| 5518 if (info->has_holder()) return false; | 5346 if (info->has_holder()) return false; |
| 5519 | 5347 |
| 5520 if (lookup_.IsPropertyCallbacks()) { | 5348 if (lookup_.IsPropertyCallbacks()) { |
| 5521 return accessor_.is_identical_to(info->accessor_); | 5349 return accessor_.is_identical_to(info->accessor_) && |
| 5350 api_holder_.is_identical_to(info->api_holder_); |
| 5522 } | 5351 } |
| 5523 | 5352 |
| 5524 if (lookup_.IsConstant()) { | 5353 if (lookup_.IsConstant()) { |
| 5525 return constant_.is_identical_to(info->constant_); | 5354 return constant_.is_identical_to(info->constant_); |
| 5526 } | 5355 } |
| 5527 | 5356 |
| 5528 ASSERT(lookup_.IsField()); | 5357 ASSERT(lookup_.IsField()); |
| 5529 if (!info->lookup_.IsField()) return false; | 5358 if (!info->lookup_.IsField()) return false; |
| 5530 | 5359 |
| 5531 Representation r = access_.representation(); | 5360 Representation r = access_.representation(); |
| 5532 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; | 5361 if (IsLoad()) { |
| 5362 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; |
| 5363 } else { |
| 5364 if (!info->access_.representation().IsCompatibleForStore(r)) return false; |
| 5365 } |
| 5533 if (info->access_.offset() != access_.offset()) return false; | 5366 if (info->access_.offset() != access_.offset()) return false; |
| 5534 if (info->access_.IsInobject() != access_.IsInobject()) return false; | 5367 if (info->access_.IsInobject() != access_.IsInobject()) return false; |
| 5535 info->GeneralizeRepresentation(r); | 5368 info->GeneralizeRepresentation(r); |
| 5536 return true; | 5369 return true; |
| 5537 } | 5370 } |
| 5538 | 5371 |
| 5539 | 5372 |
| 5540 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { | 5373 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { |
| 5541 if (!type_->IsClass()) return true; | 5374 if (!type_->IsClass()) return true; |
| 5542 map()->LookupDescriptor(NULL, *name_, &lookup_); | 5375 map()->LookupDescriptor(NULL, *name_, &lookup_); |
| 5543 return LoadResult(map()); | 5376 return LoadResult(map()); |
| 5544 } | 5377 } |
| 5545 | 5378 |
| 5546 | 5379 |
| 5547 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { | 5380 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { |
| 5381 if (!IsLoad() && lookup_.IsProperty() && |
| 5382 (lookup_.IsReadOnly() || !lookup_.IsCacheable())) { |
| 5383 return false; |
| 5384 } |
| 5385 |
| 5548 if (lookup_.IsField()) { | 5386 if (lookup_.IsField()) { |
| 5549 access_ = HObjectAccess::ForField(map, &lookup_, name_); | 5387 access_ = HObjectAccess::ForField(map, &lookup_, name_); |
| 5550 } else if (lookup_.IsPropertyCallbacks()) { | 5388 } else if (lookup_.IsPropertyCallbacks()) { |
| 5551 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); | 5389 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); |
| 5552 if (!callback->IsAccessorPair()) return false; | 5390 if (!callback->IsAccessorPair()) return false; |
| 5553 Object* getter = Handle<AccessorPair>::cast(callback)->getter(); | 5391 Object* raw_accessor = IsLoad() |
| 5554 if (!getter->IsJSFunction()) return false; | 5392 ? Handle<AccessorPair>::cast(callback)->getter() |
| 5555 Handle<JSFunction> accessor = handle(JSFunction::cast(getter)); | 5393 : Handle<AccessorPair>::cast(callback)->setter(); |
| 5556 CallOptimization call_optimization(accessor); | 5394 if (!raw_accessor->IsJSFunction()) return false; |
| 5557 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. | 5395 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); |
| 5558 if (call_optimization.is_simple_api_call()) return false; | 5396 if (accessor->shared()->IsApiFunction()) { |
| 5397 CallOptimization call_optimization(accessor); |
| 5398 if (!call_optimization.is_simple_api_call()) return false; |
| 5399 CallOptimization::HolderLookup holder_lookup; |
| 5400 api_holder_ = call_optimization.LookupHolderOfExpectedType( |
| 5401 map, &holder_lookup); |
| 5402 switch (holder_lookup) { |
| 5403 case CallOptimization::kHolderNotFound: |
| 5404 return false; |
| 5405 case CallOptimization::kHolderIsReceiver: |
| 5406 case CallOptimization::kHolderFound: |
| 5407 break; |
| 5408 } |
| 5409 } |
| 5559 accessor_ = accessor; | 5410 accessor_ = accessor; |
| 5560 } else if (lookup_.IsConstant()) { | 5411 } else if (lookup_.IsConstant()) { |
| 5561 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); | 5412 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); |
| 5562 } | 5413 } |
| 5563 | 5414 |
| 5564 return true; | 5415 return true; |
| 5565 } | 5416 } |
| 5566 | 5417 |
| 5567 | 5418 |
| 5568 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 5419 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
| 5569 Handle<Map> map = this->map(); | 5420 Handle<Map> map = this->map(); |
| 5570 | 5421 |
| 5571 while (map->prototype()->IsJSObject()) { | 5422 while (map->prototype()->IsJSObject()) { |
| 5572 holder_ = handle(JSObject::cast(map->prototype())); | 5423 holder_ = handle(JSObject::cast(map->prototype())); |
| 5573 if (holder_->map()->is_deprecated()) { | 5424 if (holder_->map()->is_deprecated()) { |
| 5574 JSObject::TryMigrateInstance(holder_); | 5425 JSObject::TryMigrateInstance(holder_); |
| 5575 } | 5426 } |
| 5576 map = Handle<Map>(holder_->map()); | 5427 map = Handle<Map>(holder_->map()); |
| 5577 if (!CanInlinePropertyAccess(IC::MapToType(map))) { | 5428 if (!CanInlinePropertyAccess(ToType(map))) { |
| 5578 lookup_.NotFound(); | 5429 lookup_.NotFound(); |
| 5579 return false; | 5430 return false; |
| 5580 } | 5431 } |
| 5581 map->LookupDescriptor(*holder_, *name_, &lookup_); | 5432 map->LookupDescriptor(*holder_, *name_, &lookup_); |
| 5582 if (lookup_.IsFound()) return LoadResult(map); | 5433 if (lookup_.IsFound()) return LoadResult(map); |
| 5583 } | 5434 } |
| 5584 lookup_.NotFound(); | 5435 lookup_.NotFound(); |
| 5585 return true; | 5436 return true; |
| 5586 } | 5437 } |
| 5587 | 5438 |
| 5588 | 5439 |
| 5589 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { | 5440 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { |
| 5590 if (!CanInlinePropertyAccess(type_)) return false; | 5441 if (!CanInlinePropertyAccess(type_)) return false; |
| 5591 if (IsJSObjectFieldAccessor()) return true; | 5442 if (IsJSObjectFieldAccessor()) return IsLoad(); |
| 5592 if (!LookupDescriptor()) return false; | 5443 if (!LookupDescriptor()) return false; |
| 5593 if (lookup_.IsFound()) return true; | 5444 if (lookup_.IsFound()) { |
| 5594 return LookupInPrototypes(); | 5445 if (IsLoad()) return true; |
| 5446 return !lookup_.IsReadOnly() && lookup_.IsCacheable(); |
| 5447 } |
| 5448 if (!LookupInPrototypes()) return false; |
| 5449 if (IsLoad()) return true; |
| 5450 |
| 5451 if (lookup_.IsPropertyCallbacks()) return true; |
| 5452 Handle<Map> map = this->map(); |
| 5453 map->LookupTransition(NULL, *name_, &lookup_); |
| 5454 if (lookup_.IsTransitionToField(*map) && map->unused_property_fields() > 0) { |
| 5455 transition_ = handle(lookup_.GetTransitionMapFromMap(*map)); |
| 5456 return true; |
| 5457 } |
| 5458 return false; |
| 5595 } | 5459 } |
| 5596 | 5460 |
| 5597 | 5461 |
| 5598 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( | 5462 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( |
| 5599 SmallMapList* types) { | 5463 SmallMapList* types) { |
| 5600 ASSERT(type_->Is(IC::MapToType(types->first()))); | 5464 ASSERT(type_->Is(ToType(types->first()))); |
| 5601 if (!CanLoadMonomorphic()) return false; | 5465 if (!CanAccessMonomorphic()) return false; |
| 5466 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); |
| 5602 if (types->length() > kMaxLoadPolymorphism) return false; | 5467 if (types->length() > kMaxLoadPolymorphism) return false; |
| 5603 | 5468 |
| 5604 if (IsArrayLength()) { | |
| 5605 bool is_fast = IsFastElementsKind(map()->elements_kind()); | |
| 5606 for (int i = 1; i < types->length(); ++i) { | |
| 5607 Handle<Map> test_map = types->at(i); | |
| 5608 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; | |
| 5609 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { | |
| 5610 return false; | |
| 5611 } | |
| 5612 } | |
| 5613 return true; | |
| 5614 } | |
| 5615 | |
| 5616 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 5469 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
| 5617 if (GetJSObjectFieldAccess(&access)) { | 5470 if (GetJSObjectFieldAccess(&access)) { |
| 5618 for (int i = 1; i < types->length(); ++i) { | 5471 for (int i = 1; i < types->length(); ++i) { |
| 5619 PropertyAccessInfo test_info( | 5472 PropertyAccessInfo test_info( |
| 5620 builder_, IC::MapToType(types->at(i)), name_); | 5473 builder_, access_type_, ToType(types->at(i)), name_); |
| 5621 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default | 5474 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default |
| 5622 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; | 5475 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; |
| 5623 if (!access.Equals(test_access)) return false; | 5476 if (!access.Equals(test_access)) return false; |
| 5624 } | 5477 } |
| 5625 return true; | 5478 return true; |
| 5626 } | 5479 } |
| 5627 | 5480 |
| 5628 // Currently only handle HeapType::Number as a polymorphic case. | 5481 // Currently only handle Type::Number as a polymorphic case. |
| 5629 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 5482 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
| 5630 // instruction. | 5483 // instruction. |
| 5631 if (type_->Is(HeapType::Number())) return false; | 5484 if (type_->Is(Type::Number())) return false; |
| 5485 |
| 5486 // Multiple maps cannot transition to the same target map. |
| 5487 ASSERT(!IsLoad() || !lookup_.IsTransition()); |
| 5488 if (lookup_.IsTransition() && types->length() > 1) return false; |
| 5632 | 5489 |
| 5633 for (int i = 1; i < types->length(); ++i) { | 5490 for (int i = 1; i < types->length(); ++i) { |
| 5634 PropertyAccessInfo test_info(builder_, IC::MapToType(types->at(i)), name_); | 5491 PropertyAccessInfo test_info( |
| 5635 if (!test_info.IsCompatibleForLoad(this)) return false; | 5492 builder_, access_type_, ToType(types->at(i)), name_); |
| 5493 if (!test_info.IsCompatible(this)) return false; |
| 5636 } | 5494 } |
| 5637 | 5495 |
| 5638 return true; | 5496 return true; |
| 5639 } | 5497 } |
| 5640 | 5498 |
| 5641 | 5499 |
| 5642 static bool NeedsWrappingFor(Handle<HeapType> type, Handle<JSFunction> target) { | 5500 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) { |
| 5643 return type->Is(HeapType::NumberOrString()) && | 5501 return type->Is(Type::NumberOrString()) && |
| 5644 target->shared()->is_classic_mode() && | 5502 target->shared()->is_classic_mode() && |
| 5645 !target->shared()->native(); | 5503 !target->shared()->native(); |
| 5646 } | 5504 } |
| 5647 | 5505 |
| 5648 | 5506 |
| 5649 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( | 5507 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( |
| 5650 PropertyAccessInfo* info, | 5508 PropertyAccessInfo* info, |
| 5651 HValue* object, | 5509 HValue* object, |
| 5652 HValue* checked_object, | 5510 HValue* checked_object, |
| 5511 HValue* value, |
| 5653 BailoutId ast_id, | 5512 BailoutId ast_id, |
| 5654 BailoutId return_id, | 5513 BailoutId return_id, |
| 5655 bool can_inline_accessor) { | 5514 bool can_inline_accessor) { |
| 5656 | 5515 |
| 5657 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 5516 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
| 5658 if (info->GetJSObjectFieldAccess(&access)) { | 5517 if (info->GetJSObjectFieldAccess(&access)) { |
| 5659 return New<HLoadNamedField>( | 5518 ASSERT(info->IsLoad()); |
| 5660 checked_object, static_cast<HValue*>(NULL), access); | 5519 return New<HLoadNamedField>(object, checked_object, access); |
| 5661 } | 5520 } |
| 5662 | 5521 |
| 5663 HValue* checked_holder = checked_object; | 5522 HValue* checked_holder = checked_object; |
| 5664 if (info->has_holder()) { | 5523 if (info->has_holder()) { |
| 5665 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 5524 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
| 5666 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 5525 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
| 5667 } | 5526 } |
| 5668 | 5527 |
| 5669 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); | 5528 if (!info->lookup()->IsFound()) { |
| 5529 ASSERT(info->IsLoad()); |
| 5530 return graph()->GetConstantUndefined(); |
| 5531 } |
| 5670 | 5532 |
| 5671 if (info->lookup()->IsField()) { | 5533 if (info->lookup()->IsField()) { |
| 5672 return BuildLoadNamedField(checked_holder, info->access()); | 5534 if (info->IsLoad()) { |
| 5535 return BuildLoadNamedField(checked_holder, info->access()); |
| 5536 } else { |
| 5537 return BuildStoreNamedField(info, checked_object, value); |
| 5538 } |
| 5539 } |
| 5540 |
| 5541 if (info->lookup()->IsTransition()) { |
| 5542 ASSERT(!info->IsLoad()); |
| 5543 return BuildStoreNamedField(info, checked_object, value); |
| 5673 } | 5544 } |
| 5674 | 5545 |
| 5675 if (info->lookup()->IsPropertyCallbacks()) { | 5546 if (info->lookup()->IsPropertyCallbacks()) { |
| 5547 Push(checked_object); |
| 5548 int argument_count = 1; |
| 5549 if (!info->IsLoad()) { |
| 5550 argument_count = 2; |
| 5551 Push(value); |
| 5552 } |
| 5553 |
| 5676 if (NeedsWrappingFor(info->type(), info->accessor())) { | 5554 if (NeedsWrappingFor(info->type(), info->accessor())) { |
| 5677 HValue* function = Add<HConstant>(info->accessor()); | 5555 HValue* function = Add<HConstant>(info->accessor()); |
| 5678 Add<HPushArgument>(checked_object); | 5556 PushArgumentsFromEnvironment(argument_count); |
| 5679 return New<HCallFunction>(function, 1, WRAP_AND_CALL); | 5557 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); |
| 5680 } else { | 5558 } else if (FLAG_inline_accessors && can_inline_accessor) { |
| 5681 Push(checked_object); | 5559 bool success = info->IsLoad() |
| 5682 if (FLAG_inline_accessors && | 5560 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
| 5683 can_inline_accessor && | 5561 : TryInlineSetter( |
| 5684 TryInlineGetter(info->accessor(), ast_id, return_id)) { | 5562 info->accessor(), info->map(), ast_id, return_id, value); |
| 5685 return NULL; | 5563 if (success) return NULL; |
| 5686 } | |
| 5687 Add<HPushArgument>(Pop()); | |
| 5688 return BuildCallConstantFunction(info->accessor(), 1); | |
| 5689 } | 5564 } |
| 5565 |
| 5566 PushArgumentsFromEnvironment(argument_count); |
| 5567 return BuildCallConstantFunction(info->accessor(), argument_count); |
| 5690 } | 5568 } |
| 5691 | 5569 |
| 5692 ASSERT(info->lookup()->IsConstant()); | 5570 ASSERT(info->lookup()->IsConstant()); |
| 5693 return New<HConstant>(info->constant()); | 5571 if (info->IsLoad()) { |
| 5572 return New<HConstant>(info->constant()); |
| 5573 } else { |
| 5574 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
| 5575 } |
| 5694 } | 5576 } |
| 5695 | 5577 |
| 5696 | 5578 |
| 5697 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 5579 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( |
| 5580 PropertyAccessType access_type, |
| 5698 BailoutId ast_id, | 5581 BailoutId ast_id, |
| 5699 BailoutId return_id, | 5582 BailoutId return_id, |
| 5700 HValue* object, | 5583 HValue* object, |
| 5584 HValue* value, |
| 5701 SmallMapList* types, | 5585 SmallMapList* types, |
| 5702 Handle<String> name) { | 5586 Handle<String> name) { |
| 5703 // Something did not match; must use a polymorphic load. | 5587 // Something did not match; must use a polymorphic load. |
| 5704 int count = 0; | 5588 int count = 0; |
| 5705 HBasicBlock* join = NULL; | 5589 HBasicBlock* join = NULL; |
| 5706 HBasicBlock* number_block = NULL; | 5590 HBasicBlock* number_block = NULL; |
| 5707 bool handled_string = false; | 5591 bool handled_string = false; |
| 5708 | 5592 |
| 5709 bool handle_smi = false; | 5593 bool handle_smi = false; |
| 5594 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); |
| 5710 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 5595 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 5711 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); | 5596 PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name); |
| 5712 if (info.type()->Is(HeapType::String())) { | 5597 if (info.type()->Is(Type::String())) { |
| 5713 if (handled_string) continue; | 5598 if (handled_string) continue; |
| 5714 handled_string = true; | 5599 handled_string = true; |
| 5715 } | 5600 } |
| 5716 if (info.CanLoadMonomorphic()) { | 5601 if (info.CanAccessMonomorphic()) { |
| 5717 count++; | 5602 count++; |
| 5718 if (info.type()->Is(HeapType::Number())) { | 5603 if (info.type()->Is(Type::Number())) { |
| 5719 handle_smi = true; | 5604 handle_smi = true; |
| 5720 break; | 5605 break; |
| 5721 } | 5606 } |
| 5722 } | 5607 } |
| 5723 } | 5608 } |
| 5724 | 5609 |
| 5725 count = 0; | 5610 count = 0; |
| 5726 HControlInstruction* smi_check = NULL; | 5611 HControlInstruction* smi_check = NULL; |
| 5727 handled_string = false; | 5612 handled_string = false; |
| 5728 | 5613 |
| 5729 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 5614 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 5730 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); | 5615 PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name); |
| 5731 if (info.type()->Is(HeapType::String())) { | 5616 if (info.type()->Is(Type::String())) { |
| 5732 if (handled_string) continue; | 5617 if (handled_string) continue; |
| 5733 handled_string = true; | 5618 handled_string = true; |
| 5734 } | 5619 } |
| 5735 if (!info.CanLoadMonomorphic()) continue; | 5620 if (!info.CanAccessMonomorphic()) continue; |
| 5736 | 5621 |
| 5737 if (count == 0) { | 5622 if (count == 0) { |
| 5738 join = graph()->CreateBasicBlock(); | 5623 join = graph()->CreateBasicBlock(); |
| 5739 if (handle_smi) { | 5624 if (handle_smi) { |
| 5740 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 5625 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
| 5741 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 5626 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
| 5742 number_block = graph()->CreateBasicBlock(); | 5627 number_block = graph()->CreateBasicBlock(); |
| 5743 smi_check = New<HIsSmiAndBranch>( | 5628 smi_check = New<HIsSmiAndBranch>( |
| 5744 object, empty_smi_block, not_smi_block); | 5629 object, empty_smi_block, not_smi_block); |
| 5745 FinishCurrentBlock(smi_check); | 5630 FinishCurrentBlock(smi_check); |
| 5746 Goto(empty_smi_block, number_block); | 5631 Goto(empty_smi_block, number_block); |
| 5747 set_current_block(not_smi_block); | 5632 set_current_block(not_smi_block); |
| 5748 } else { | 5633 } else { |
| 5749 BuildCheckHeapObject(object); | 5634 BuildCheckHeapObject(object); |
| 5750 } | 5635 } |
| 5751 } | 5636 } |
| 5752 ++count; | 5637 ++count; |
| 5753 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5638 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 5754 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5639 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 5755 HUnaryControlInstruction* compare; | 5640 HUnaryControlInstruction* compare; |
| 5756 | 5641 |
| 5757 HValue* dependency; | 5642 HValue* dependency; |
| 5758 if (info.type()->Is(HeapType::Number())) { | 5643 if (info.type()->Is(Type::Number())) { |
| 5759 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); | 5644 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 5760 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false); | 5645 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false); |
| 5761 dependency = smi_check; | 5646 dependency = smi_check; |
| 5762 } else if (info.type()->Is(HeapType::String())) { | 5647 } else if (info.type()->Is(Type::String())) { |
| 5763 compare = New<HIsStringAndBranch>(object, if_true, if_false); | 5648 compare = New<HIsStringAndBranch>(object, if_true, if_false); |
| 5764 dependency = compare; | 5649 dependency = compare; |
| 5765 } else { | 5650 } else { |
| 5766 compare = New<HCompareMap>(object, info.map(), if_true, if_false); | 5651 compare = New<HCompareMap>(object, info.map(), if_true, if_false); |
| 5767 dependency = compare; | 5652 dependency = compare; |
| 5768 } | 5653 } |
| 5769 FinishCurrentBlock(compare); | 5654 FinishCurrentBlock(compare); |
| 5770 | 5655 |
| 5771 if (info.type()->Is(HeapType::Number())) { | 5656 if (info.type()->Is(Type::Number())) { |
| 5772 Goto(if_true, number_block); | 5657 Goto(if_true, number_block); |
| 5773 if_true = number_block; | 5658 if_true = number_block; |
| 5774 number_block->SetJoinId(ast_id); | 5659 number_block->SetJoinId(ast_id); |
| 5775 } | 5660 } |
| 5776 | 5661 |
| 5777 set_current_block(if_true); | 5662 set_current_block(if_true); |
| 5778 | 5663 |
| 5779 HInstruction* load = BuildLoadMonomorphic( | 5664 HInstruction* access = BuildMonomorphicAccess( |
| 5780 &info, object, dependency, ast_id, | 5665 &info, object, dependency, value, ast_id, |
| 5781 return_id, FLAG_polymorphic_inlining); | 5666 return_id, FLAG_polymorphic_inlining); |
| 5782 if (load == NULL) { | 5667 |
| 5668 HValue* result = NULL; |
| 5669 switch (access_type) { |
| 5670 case LOAD: |
| 5671 result = access; |
| 5672 break; |
| 5673 case STORE: |
| 5674 result = value; |
| 5675 break; |
| 5676 } |
| 5677 |
| 5678 if (access == NULL) { |
| 5783 if (HasStackOverflow()) return; | 5679 if (HasStackOverflow()) return; |
| 5784 } else { | 5680 } else { |
| 5785 if (!load->IsLinked()) { | 5681 if (!access->IsLinked()) AddInstruction(access); |
| 5786 AddInstruction(load); | 5682 if (!ast_context()->IsEffect()) Push(result); |
| 5787 } | |
| 5788 if (!ast_context()->IsEffect()) Push(load); | |
| 5789 } | 5683 } |
| 5790 | 5684 |
| 5791 if (current_block() != NULL) Goto(join); | 5685 if (current_block() != NULL) Goto(join); |
| 5792 set_current_block(if_false); | 5686 set_current_block(if_false); |
| 5793 } | 5687 } |
| 5794 | 5688 |
| 5795 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 5689 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 5796 // know about and do not want to handle ones we've never seen. Otherwise | 5690 // know about and do not want to handle ones we've never seen. Otherwise |
| 5797 // use a generic IC. | 5691 // use a generic IC. |
| 5798 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 5692 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 5799 // Because the deopt may be the only path in the polymorphic load, make sure | 5693 // Because the deopt may be the only path in the polymorphic load, make sure |
| 5800 // that the environment stack matches the depth on deopt that it otherwise | 5694 // that the environment stack matches the depth on deopt that it otherwise |
| 5801 // would have had after a successful load. | 5695 // would have had after a successful load. |
| 5802 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 5696 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
| 5803 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); | 5697 FinishExitWithHardDeoptimization("Uknown map in polymorphic access", join); |
| 5804 } else { | 5698 } else { |
| 5805 HInstruction* load = Add<HLoadNamedGeneric>(object, name); | 5699 HInstruction* instr = BuildNamedGeneric(access_type, object, name, value); |
| 5806 if (!ast_context()->IsEffect()) Push(load); | 5700 AddInstruction(instr); |
| 5701 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); |
| 5807 | 5702 |
| 5808 if (join != NULL) { | 5703 if (join != NULL) { |
| 5809 Goto(join); | 5704 Goto(join); |
| 5810 } else { | 5705 } else { |
| 5811 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5706 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5812 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 5707 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 5813 return; | 5708 return; |
| 5814 } | 5709 } |
| 5815 } | 5710 } |
| 5816 | 5711 |
| 5817 ASSERT(join != NULL); | 5712 ASSERT(join != NULL); |
| 5818 join->SetJoinId(ast_id); | 5713 join->SetJoinId(ast_id); |
| 5819 set_current_block(join); | 5714 set_current_block(join); |
| 5820 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 5715 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 5821 } | 5716 } |
| 5822 | 5717 |
| 5823 | 5718 |
| 5824 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | |
| 5825 BailoutId assignment_id, | |
| 5826 HValue* object, | |
| 5827 HValue* value, | |
| 5828 SmallMapList* types, | |
| 5829 Handle<String> name) { | |
| 5830 // Use monomorphic store if property lookup results in the same field index | |
| 5831 // for all maps. Requires special map check on the set of all handled maps. | |
| 5832 if (types->length() > kMaxStorePolymorphism) return false; | |
| 5833 | |
| 5834 LookupResult lookup(isolate()); | |
| 5835 int count; | |
| 5836 Representation representation = Representation::None(); | |
| 5837 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | |
| 5838 for (count = 0; count < types->length(); ++count) { | |
| 5839 Handle<Map> map = types->at(count); | |
| 5840 // Pass false to ignore transitions. | |
| 5841 if (!ComputeStoreField(map, name, &lookup, false)) break; | |
| 5842 ASSERT(!map->is_observed()); | |
| 5843 | |
| 5844 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | |
| 5845 Representation new_representation = new_access.representation(); | |
| 5846 | |
| 5847 if (count == 0) { | |
| 5848 // First time through the loop; set access and representation. | |
| 5849 access = new_access; | |
| 5850 representation = new_representation; | |
| 5851 } else if (!representation.IsCompatibleForStore(new_representation)) { | |
| 5852 // Representations did not match. | |
| 5853 break; | |
| 5854 } else if (access.offset() != new_access.offset()) { | |
| 5855 // Offsets did not match. | |
| 5856 break; | |
| 5857 } else if (access.IsInobject() != new_access.IsInobject()) { | |
| 5858 // In-objectness did not match. | |
| 5859 break; | |
| 5860 } | |
| 5861 } | |
| 5862 | |
| 5863 if (count != types->length()) return false; | |
| 5864 | |
| 5865 // Everything matched; can use monomorphic store. | |
| 5866 BuildCheckHeapObject(object); | |
| 5867 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); | |
| 5868 HInstruction* store; | |
| 5869 CHECK_ALIVE_OR_RETURN( | |
| 5870 store = BuildStoreNamedField( | |
| 5871 checked_object, name, value, types->at(count - 1), &lookup), | |
| 5872 true); | |
| 5873 if (!ast_context()->IsEffect()) Push(value); | |
| 5874 AddInstruction(store); | |
| 5875 Add<HSimulate>(assignment_id); | |
| 5876 if (!ast_context()->IsEffect()) Drop(1); | |
| 5877 ast_context()->ReturnValue(value); | |
| 5878 return true; | |
| 5879 } | |
| 5880 | |
| 5881 | |
| 5882 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | |
| 5883 BailoutId assignment_id, | |
| 5884 HValue* object, | |
| 5885 HValue* value, | |
| 5886 SmallMapList* types, | |
| 5887 Handle<String> name) { | |
| 5888 if (TryStorePolymorphicAsMonomorphic( | |
| 5889 assignment_id, object, value, types, name)) { | |
| 5890 return; | |
| 5891 } | |
| 5892 | |
| 5893 // TODO(ager): We should recognize when the prototype chains for different | |
| 5894 // maps are identical. In that case we can avoid repeatedly generating the | |
| 5895 // same prototype map checks. | |
| 5896 int count = 0; | |
| 5897 HBasicBlock* join = NULL; | |
| 5898 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | |
| 5899 Handle<Map> map = types->at(i); | |
| 5900 LookupResult lookup(isolate()); | |
| 5901 if (ComputeStoreField(map, name, &lookup)) { | |
| 5902 if (count == 0) { | |
| 5903 BuildCheckHeapObject(object); | |
| 5904 join = graph()->CreateBasicBlock(); | |
| 5905 } | |
| 5906 ++count; | |
| 5907 HBasicBlock* if_true = graph()->CreateBasicBlock(); | |
| 5908 HBasicBlock* if_false = graph()->CreateBasicBlock(); | |
| 5909 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); | |
| 5910 FinishCurrentBlock(compare); | |
| 5911 | |
| 5912 set_current_block(if_true); | |
| 5913 HInstruction* instr; | |
| 5914 CHECK_ALIVE(instr = BuildStoreNamedField( | |
| 5915 compare, name, value, map, &lookup)); | |
| 5916 // Goto will add the HSimulate for the store. | |
| 5917 AddInstruction(instr); | |
| 5918 if (!ast_context()->IsEffect()) Push(value); | |
| 5919 Goto(join); | |
| 5920 | |
| 5921 set_current_block(if_false); | |
| 5922 } | |
| 5923 } | |
| 5924 | |
| 5925 // Finish up. Unconditionally deoptimize if we've handled all the maps we | |
| 5926 // know about and do not want to handle ones we've never seen. Otherwise | |
| 5927 // use a generic IC. | |
| 5928 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | |
| 5929 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join); | |
| 5930 } else { | |
| 5931 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); | |
| 5932 AddInstruction(instr); | |
| 5933 | |
| 5934 if (join != NULL) { | |
| 5935 if (!ast_context()->IsEffect()) { | |
| 5936 Push(value); | |
| 5937 } | |
| 5938 Goto(join); | |
| 5939 } else { | |
| 5940 // The HSimulate for the store should not see the stored value in | |
| 5941 // effect contexts (it is not materialized at expr->id() in the | |
| 5942 // unoptimized code). | |
| 5943 if (instr->HasObservableSideEffects()) { | |
| 5944 if (ast_context()->IsEffect()) { | |
| 5945 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); | |
| 5946 } else { | |
| 5947 Push(value); | |
| 5948 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); | |
| 5949 Drop(1); | |
| 5950 } | |
| 5951 } | |
| 5952 return ast_context()->ReturnValue(value); | |
| 5953 } | |
| 5954 } | |
| 5955 | |
| 5956 ASSERT(join != NULL); | |
| 5957 join->SetJoinId(assignment_id); | |
| 5958 set_current_block(join); | |
| 5959 if (!ast_context()->IsEffect()) { | |
| 5960 ast_context()->ReturnValue(Pop()); | |
| 5961 } | |
| 5962 } | |
| 5963 | |
| 5964 | |
| 5965 static bool ComputeReceiverTypes(Expression* expr, | 5719 static bool ComputeReceiverTypes(Expression* expr, |
| 5966 HValue* receiver, | 5720 HValue* receiver, |
| 5967 SmallMapList** t) { | 5721 SmallMapList** t, |
| 5722 Zone* zone) { |
| 5968 SmallMapList* types = expr->GetReceiverTypes(); | 5723 SmallMapList* types = expr->GetReceiverTypes(); |
| 5969 *t = types; | 5724 *t = types; |
| 5970 bool monomorphic = expr->IsMonomorphic(); | 5725 bool monomorphic = expr->IsMonomorphic(); |
| 5971 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { | 5726 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { |
| 5972 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); | 5727 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); |
| 5973 types->FilterForPossibleTransitions(root_map); | 5728 types->FilterForPossibleTransitions(root_map); |
| 5974 monomorphic = types->length() == 1; | 5729 monomorphic = types->length() == 1; |
| 5975 } | 5730 } |
| 5976 return monomorphic && CanInlinePropertyAccess(IC::MapToType(types->first())); | 5731 return monomorphic && CanInlinePropertyAccess( |
| 5732 IC::MapToType<Type>(types->first(), zone)); |
| 5977 } | 5733 } |
| 5978 | 5734 |
| 5979 | 5735 |
| 5736 static bool AreStringTypes(SmallMapList* types) { |
| 5737 for (int i = 0; i < types->length(); i++) { |
| 5738 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; |
| 5739 } |
| 5740 return true; |
| 5741 } |
| 5742 |
| 5743 |
| 5980 void HOptimizedGraphBuilder::BuildStore(Expression* expr, | 5744 void HOptimizedGraphBuilder::BuildStore(Expression* expr, |
| 5981 Property* prop, | 5745 Property* prop, |
| 5982 BailoutId ast_id, | 5746 BailoutId ast_id, |
| 5983 BailoutId return_id, | 5747 BailoutId return_id, |
| 5984 bool is_uninitialized) { | 5748 bool is_uninitialized) { |
| 5985 HValue* value = environment()->ExpressionStackAt(0); | |
| 5986 | |
| 5987 if (!prop->key()->IsPropertyName()) { | 5749 if (!prop->key()->IsPropertyName()) { |
| 5988 // Keyed store. | 5750 // Keyed store. |
| 5751 HValue* value = environment()->ExpressionStackAt(0); |
| 5989 HValue* key = environment()->ExpressionStackAt(1); | 5752 HValue* key = environment()->ExpressionStackAt(1); |
| 5990 HValue* object = environment()->ExpressionStackAt(2); | 5753 HValue* object = environment()->ExpressionStackAt(2); |
| 5991 bool has_side_effects = false; | 5754 bool has_side_effects = false; |
| 5992 HandleKeyedElementAccess(object, key, value, expr, | 5755 HandleKeyedElementAccess(object, key, value, expr, |
| 5993 true, // is_store | 5756 STORE, &has_side_effects); |
| 5994 &has_side_effects); | |
| 5995 Drop(3); | 5757 Drop(3); |
| 5996 Push(value); | 5758 Push(value); |
| 5997 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); | 5759 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); |
| 5998 return ast_context()->ReturnValue(Pop()); | 5760 return ast_context()->ReturnValue(Pop()); |
| 5999 } | 5761 } |
| 6000 | 5762 |
| 6001 // Named store. | 5763 // Named store. |
| 6002 HValue* object = environment()->ExpressionStackAt(1); | 5764 HValue* value = Pop(); |
| 6003 | 5765 HValue* object = Pop(); |
| 6004 if (is_uninitialized) { | |
| 6005 Add<HDeoptimize>("Insufficient type feedback for property assignment", | |
| 6006 Deoptimizer::SOFT); | |
| 6007 } | |
| 6008 | 5766 |
| 6009 Literal* key = prop->key()->AsLiteral(); | 5767 Literal* key = prop->key()->AsLiteral(); |
| 6010 Handle<String> name = Handle<String>::cast(key->value()); | 5768 Handle<String> name = Handle<String>::cast(key->value()); |
| 6011 ASSERT(!name.is_null()); | 5769 ASSERT(!name.is_null()); |
| 6012 | 5770 |
| 6013 HInstruction* instr = NULL; | 5771 HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr, |
| 6014 | 5772 object, name, value, is_uninitialized); |
| 6015 SmallMapList* types; | 5773 if (instr == NULL) return; |
| 6016 bool monomorphic = ComputeReceiverTypes(expr, object, &types); | |
| 6017 | |
| 6018 if (monomorphic) { | |
| 6019 Handle<Map> map = types->first(); | |
| 6020 Handle<JSFunction> setter; | |
| 6021 Handle<JSObject> holder; | |
| 6022 if (LookupSetter(map, name, &setter, &holder)) { | |
| 6023 AddCheckMap(object, map); | |
| 6024 AddCheckPrototypeMaps(holder, map); | |
| 6025 bool needs_wrapping = NeedsWrappingFor(IC::MapToType(map), setter); | |
| 6026 bool try_inline = FLAG_inline_accessors && !needs_wrapping; | |
| 6027 if (try_inline && TryInlineSetter(setter, ast_id, return_id, value)) { | |
| 6028 return; | |
| 6029 } | |
| 6030 Drop(2); | |
| 6031 Add<HPushArgument>(object); | |
| 6032 Add<HPushArgument>(value); | |
| 6033 if (needs_wrapping) { | |
| 6034 HValue* function = Add<HConstant>(setter); | |
| 6035 instr = New<HCallFunction>(function, 2, WRAP_AND_CALL); | |
| 6036 } else { | |
| 6037 instr = BuildCallConstantFunction(setter, 2); | |
| 6038 } | |
| 6039 } else { | |
| 6040 Drop(2); | |
| 6041 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | |
| 6042 name, | |
| 6043 value, | |
| 6044 map)); | |
| 6045 } | |
| 6046 } else if (types != NULL && types->length() > 1) { | |
| 6047 Drop(2); | |
| 6048 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name); | |
| 6049 } else { | |
| 6050 Drop(2); | |
| 6051 instr = BuildStoreNamedGeneric(object, name, value); | |
| 6052 } | |
| 6053 | 5774 |
| 6054 if (!ast_context()->IsEffect()) Push(value); | 5775 if (!ast_context()->IsEffect()) Push(value); |
| 6055 AddInstruction(instr); | 5776 AddInstruction(instr); |
| 6056 if (instr->HasObservableSideEffects()) { | 5777 if (instr->HasObservableSideEffects()) { |
| 6057 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5778 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6058 } | 5779 } |
| 6059 if (!ast_context()->IsEffect()) Drop(1); | 5780 if (!ast_context()->IsEffect()) Drop(1); |
| 6060 return ast_context()->ReturnValue(value); | 5781 return ast_context()->ReturnValue(value); |
| 6061 } | 5782 } |
| 6062 | 5783 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 6075 | 5796 |
| 6076 | 5797 |
| 6077 // Because not every expression has a position and there is not common | 5798 // Because not every expression has a position and there is not common |
| 6078 // superclass of Assignment and CountOperation, we cannot just pass the | 5799 // superclass of Assignment and CountOperation, we cannot just pass the |
| 6079 // owning expression instead of position and ast_id separately. | 5800 // owning expression instead of position and ast_id separately. |
| 6080 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 5801 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 6081 Variable* var, | 5802 Variable* var, |
| 6082 HValue* value, | 5803 HValue* value, |
| 6083 BailoutId ast_id) { | 5804 BailoutId ast_id) { |
| 6084 LookupResult lookup(isolate()); | 5805 LookupResult lookup(isolate()); |
| 6085 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5806 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, STORE); |
| 6086 if (type == kUseCell) { | 5807 if (type == kUseCell) { |
| 6087 Handle<GlobalObject> global(current_info()->global_object()); | 5808 Handle<GlobalObject> global(current_info()->global_object()); |
| 6088 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 5809 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 6089 if (cell->type()->IsConstant()) { | 5810 if (cell->type()->IsConstant()) { |
| 6090 IfBuilder builder(this); | 5811 IfBuilder builder(this); |
| 6091 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | 5812 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
| 6092 if (cell->type()->AsConstant()->IsNumber()) { | 5813 if (cell->type()->AsConstant()->IsNumber()) { |
| 6093 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | 5814 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
| 6094 } else { | 5815 } else { |
| 6095 builder.If<HCompareObjectEqAndBranch>(value, constant); | 5816 builder.If<HCompareObjectEqAndBranch>(value, constant); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6207 CHECK_ALIVE(VisitForValue(prop->key())); | 5928 CHECK_ALIVE(VisitForValue(prop->key())); |
| 6208 key = Top(); | 5929 key = Top(); |
| 6209 } | 5930 } |
| 6210 | 5931 |
| 6211 CHECK_ALIVE(PushLoad(prop, object, key)); | 5932 CHECK_ALIVE(PushLoad(prop, object, key)); |
| 6212 | 5933 |
| 6213 CHECK_ALIVE(VisitForValue(expr->value())); | 5934 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6214 HValue* right = Pop(); | 5935 HValue* right = Pop(); |
| 6215 HValue* left = Pop(); | 5936 HValue* left = Pop(); |
| 6216 | 5937 |
| 6217 Push(BuildBinaryOperation(operation, left, right)); | 5938 Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE)); |
| 5939 |
| 6218 BuildStore(expr, prop, expr->id(), | 5940 BuildStore(expr, prop, expr->id(), |
| 6219 expr->AssignmentId(), expr->IsUninitialized()); | 5941 expr->AssignmentId(), expr->IsUninitialized()); |
| 6220 } else { | 5942 } else { |
| 6221 return Bailout(kInvalidLhsInCompoundAssignment); | 5943 return Bailout(kInvalidLhsInCompoundAssignment); |
| 6222 } | 5944 } |
| 6223 } | 5945 } |
| 6224 | 5946 |
| 6225 | 5947 |
| 6226 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5948 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
| 6227 ASSERT(!HasStackOverflow()); | 5949 ASSERT(!HasStackOverflow()); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6420 if (string->IsConstant()) { | 6142 if (string->IsConstant()) { |
| 6421 HConstant* c_string = HConstant::cast(string); | 6143 HConstant* c_string = HConstant::cast(string); |
| 6422 if (c_string->HasStringValue()) { | 6144 if (c_string->HasStringValue()) { |
| 6423 return Add<HConstant>(c_string->StringValue()->length()); | 6145 return Add<HConstant>(c_string->StringValue()->length()); |
| 6424 } | 6146 } |
| 6425 } | 6147 } |
| 6426 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); | 6148 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); |
| 6427 } | 6149 } |
| 6428 | 6150 |
| 6429 | 6151 |
| 6430 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 6152 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( |
| 6153 PropertyAccessType access_type, |
| 6431 HValue* object, | 6154 HValue* object, |
| 6432 Handle<String> name, | 6155 Handle<String> name, |
| 6433 Property* expr) { | 6156 HValue* value, |
| 6434 if (!expr->IsForCall() && expr->IsUninitialized()) { | 6157 bool is_uninitialized) { |
| 6435 Add<HDeoptimize>("Insufficient type feedback for generic named load", | 6158 if (is_uninitialized) { |
| 6159 Add<HDeoptimize>("Insufficient type feedback for generic named access", |
| 6436 Deoptimizer::SOFT); | 6160 Deoptimizer::SOFT); |
| 6437 } | 6161 } |
| 6438 return New<HLoadNamedGeneric>(object, name); | 6162 if (access_type == LOAD) { |
| 6163 return New<HLoadNamedGeneric>(object, name); |
| 6164 } else { |
| 6165 return New<HStoreNamedGeneric>( |
| 6166 object, name, value, function_strict_mode_flag()); |
| 6167 } |
| 6439 } | 6168 } |
| 6440 | 6169 |
| 6441 | 6170 |
| 6442 | 6171 |
| 6443 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 6172 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( |
| 6444 HValue* key) { | 6173 PropertyAccessType access_type, |
| 6445 return New<HLoadKeyedGeneric>(object, key); | 6174 HValue* object, |
| 6175 HValue* key, |
| 6176 HValue* value) { |
| 6177 if (access_type == LOAD) { |
| 6178 return New<HLoadKeyedGeneric>(object, key); |
| 6179 } else { |
| 6180 return New<HStoreKeyedGeneric>( |
| 6181 object, key, value, function_strict_mode_flag()); |
| 6182 } |
| 6446 } | 6183 } |
| 6447 | 6184 |
| 6448 | 6185 |
| 6449 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { | 6186 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { |
| 6450 // Loads from a "stock" fast holey double arrays can elide the hole check. | 6187 // Loads from a "stock" fast holey double arrays can elide the hole check. |
| 6451 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 6188 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
| 6452 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 6189 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
| 6453 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 6190 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 6454 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 6191 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
| 6455 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); | 6192 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
| 6456 BuildCheckPrototypeMaps(prototype, object_prototype); | 6193 BuildCheckPrototypeMaps(prototype, object_prototype); |
| 6457 load_mode = ALLOW_RETURN_HOLE; | 6194 load_mode = ALLOW_RETURN_HOLE; |
| 6458 graph()->MarkDependsOnEmptyArrayProtoElements(); | 6195 graph()->MarkDependsOnEmptyArrayProtoElements(); |
| 6459 } | 6196 } |
| 6460 | 6197 |
| 6461 return load_mode; | 6198 return load_mode; |
| 6462 } | 6199 } |
| 6463 | 6200 |
| 6464 | 6201 |
| 6465 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 6202 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
| 6466 HValue* object, | 6203 HValue* object, |
| 6467 HValue* key, | 6204 HValue* key, |
| 6468 HValue* val, | 6205 HValue* val, |
| 6469 HValue* dependency, | 6206 HValue* dependency, |
| 6470 Handle<Map> map, | 6207 Handle<Map> map, |
| 6471 bool is_store, | 6208 PropertyAccessType access_type, |
| 6472 KeyedAccessStoreMode store_mode) { | 6209 KeyedAccessStoreMode store_mode) { |
| 6473 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(), | 6210 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(), |
| 6474 dependency); | 6211 dependency); |
| 6475 if (dependency) { | 6212 if (dependency) { |
| 6476 checked_object->ClearGVNFlag(kDependsOnElementsKind); | 6213 checked_object->ClearGVNFlag(kDependsOnElementsKind); |
| 6477 } | 6214 } |
| 6478 | 6215 |
| 6479 if (is_store && map->prototype()->IsJSObject()) { | 6216 if (access_type == STORE && map->prototype()->IsJSObject()) { |
| 6480 // monomorphic stores need a prototype chain check because shape | 6217 // monomorphic stores need a prototype chain check because shape |
| 6481 // changes could allow callbacks on elements in the chain that | 6218 // changes could allow callbacks on elements in the chain that |
| 6482 // aren't compatible with monomorphic keyed stores. | 6219 // aren't compatible with monomorphic keyed stores. |
| 6483 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 6220 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 6484 Object* holder = map->prototype(); | 6221 Object* holder = map->prototype(); |
| 6485 while (holder->GetPrototype(isolate())->IsJSObject()) { | 6222 while (holder->GetPrototype(isolate())->IsJSObject()) { |
| 6486 holder = holder->GetPrototype(isolate()); | 6223 holder = holder->GetPrototype(isolate()); |
| 6487 } | 6224 } |
| 6488 ASSERT(holder->GetPrototype(isolate())->IsNull()); | 6225 ASSERT(holder->GetPrototype(isolate())->IsNull()); |
| 6489 | 6226 |
| 6490 BuildCheckPrototypeMaps(prototype, | 6227 BuildCheckPrototypeMaps(prototype, |
| 6491 Handle<JSObject>(JSObject::cast(holder))); | 6228 Handle<JSObject>(JSObject::cast(holder))); |
| 6492 } | 6229 } |
| 6493 | 6230 |
| 6494 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 6231 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
| 6495 return BuildUncheckedMonomorphicElementAccess( | 6232 return BuildUncheckedMonomorphicElementAccess( |
| 6496 checked_object, key, val, | 6233 checked_object, key, val, |
| 6497 map->instance_type() == JS_ARRAY_TYPE, | 6234 map->instance_type() == JS_ARRAY_TYPE, |
| 6498 map->elements_kind(), is_store, | 6235 map->elements_kind(), access_type, |
| 6499 load_mode, store_mode); | 6236 load_mode, store_mode); |
| 6500 } | 6237 } |
| 6501 | 6238 |
| 6502 | 6239 |
| 6503 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( | 6240 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( |
| 6504 HValue* object, | 6241 HValue* object, |
| 6505 HValue* key, | 6242 HValue* key, |
| 6506 HValue* val, | 6243 HValue* val, |
| 6507 SmallMapList* maps) { | 6244 SmallMapList* maps) { |
| 6508 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 6245 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6554 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps); | 6291 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps); |
| 6555 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS. | 6292 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS. |
| 6556 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS. | 6293 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS. |
| 6557 ElementsKind consolidated_elements_kind = has_seen_holey_elements | 6294 ElementsKind consolidated_elements_kind = has_seen_holey_elements |
| 6558 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind()) | 6295 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind()) |
| 6559 : most_general_consolidated_map->elements_kind(); | 6296 : most_general_consolidated_map->elements_kind(); |
| 6560 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 6297 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
| 6561 checked_object, key, val, | 6298 checked_object, key, val, |
| 6562 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | 6299 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, |
| 6563 consolidated_elements_kind, | 6300 consolidated_elements_kind, |
| 6564 false, NEVER_RETURN_HOLE, STANDARD_STORE); | 6301 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE); |
| 6565 return instr; | 6302 return instr; |
| 6566 } | 6303 } |
| 6567 | 6304 |
| 6568 | 6305 |
| 6569 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 6306 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
| 6570 HValue* object, | 6307 HValue* object, |
| 6571 HValue* key, | 6308 HValue* key, |
| 6572 HValue* val, | 6309 HValue* val, |
| 6573 SmallMapList* maps, | 6310 SmallMapList* maps, |
| 6574 bool is_store, | 6311 PropertyAccessType access_type, |
| 6575 KeyedAccessStoreMode store_mode, | 6312 KeyedAccessStoreMode store_mode, |
| 6576 bool* has_side_effects) { | 6313 bool* has_side_effects) { |
| 6577 *has_side_effects = false; | 6314 *has_side_effects = false; |
| 6578 BuildCheckHeapObject(object); | 6315 BuildCheckHeapObject(object); |
| 6579 | 6316 |
| 6580 if (!is_store) { | 6317 if (access_type == LOAD) { |
| 6581 HInstruction* consolidated_load = | 6318 HInstruction* consolidated_load = |
| 6582 TryBuildConsolidatedElementLoad(object, key, val, maps); | 6319 TryBuildConsolidatedElementLoad(object, key, val, maps); |
| 6583 if (consolidated_load != NULL) { | 6320 if (consolidated_load != NULL) { |
| 6584 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | 6321 *has_side_effects |= consolidated_load->HasObservableSideEffects(); |
| 6585 return consolidated_load; | 6322 return consolidated_load; |
| 6586 } | 6323 } |
| 6587 } | 6324 } |
| 6588 | 6325 |
| 6589 // Elements_kind transition support. | 6326 // Elements_kind transition support. |
| 6590 MapHandleList transition_target(maps->length()); | 6327 MapHandleList transition_target(maps->length()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6623 } | 6360 } |
| 6624 | 6361 |
| 6625 // If only one map is left after transitioning, handle this case | 6362 // If only one map is left after transitioning, handle this case |
| 6626 // monomorphically. | 6363 // monomorphically. |
| 6627 ASSERT(untransitionable_maps.length() >= 1); | 6364 ASSERT(untransitionable_maps.length() >= 1); |
| 6628 if (untransitionable_maps.length() == 1) { | 6365 if (untransitionable_maps.length() == 1) { |
| 6629 Handle<Map> untransitionable_map = untransitionable_maps[0]; | 6366 Handle<Map> untransitionable_map = untransitionable_maps[0]; |
| 6630 HInstruction* instr = NULL; | 6367 HInstruction* instr = NULL; |
| 6631 if (untransitionable_map->has_slow_elements_kind() || | 6368 if (untransitionable_map->has_slow_elements_kind() || |
| 6632 !untransitionable_map->IsJSObjectMap()) { | 6369 !untransitionable_map->IsJSObjectMap()) { |
| 6633 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 6370 instr = AddInstruction(BuildKeyedGeneric(access_type, object, key, val)); |
| 6634 : BuildLoadKeyedGeneric(object, key)); | |
| 6635 } else { | 6371 } else { |
| 6636 instr = BuildMonomorphicElementAccess( | 6372 instr = BuildMonomorphicElementAccess( |
| 6637 object, key, val, transition, untransitionable_map, is_store, | 6373 object, key, val, transition, untransitionable_map, access_type, |
| 6638 store_mode); | 6374 store_mode); |
| 6639 } | 6375 } |
| 6640 *has_side_effects |= instr->HasObservableSideEffects(); | 6376 *has_side_effects |= instr->HasObservableSideEffects(); |
| 6641 return is_store ? NULL : instr; | 6377 return access_type == STORE ? NULL : instr; |
| 6642 } | 6378 } |
| 6643 | 6379 |
| 6644 HBasicBlock* join = graph()->CreateBasicBlock(); | 6380 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 6645 | 6381 |
| 6646 for (int i = 0; i < untransitionable_maps.length(); ++i) { | 6382 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
| 6647 Handle<Map> map = untransitionable_maps[i]; | 6383 Handle<Map> map = untransitionable_maps[i]; |
| 6648 if (!map->IsJSObjectMap()) continue; | 6384 if (!map->IsJSObjectMap()) continue; |
| 6649 ElementsKind elements_kind = map->elements_kind(); | 6385 ElementsKind elements_kind = map->elements_kind(); |
| 6650 HBasicBlock* this_map = graph()->CreateBasicBlock(); | 6386 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
| 6651 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 6387 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
| 6652 HCompareMap* mapcompare = | 6388 HCompareMap* mapcompare = |
| 6653 New<HCompareMap>(object, map, this_map, other_map); | 6389 New<HCompareMap>(object, map, this_map, other_map); |
| 6654 FinishCurrentBlock(mapcompare); | 6390 FinishCurrentBlock(mapcompare); |
| 6655 | 6391 |
| 6656 set_current_block(this_map); | 6392 set_current_block(this_map); |
| 6657 HInstruction* access = NULL; | 6393 HInstruction* access = NULL; |
| 6658 if (IsDictionaryElementsKind(elements_kind)) { | 6394 if (IsDictionaryElementsKind(elements_kind)) { |
| 6659 access = is_store | 6395 access = AddInstruction(BuildKeyedGeneric(access_type, object, key, val)); |
| 6660 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) | |
| 6661 : AddInstruction(BuildLoadKeyedGeneric(object, key)); | |
| 6662 } else { | 6396 } else { |
| 6663 ASSERT(IsFastElementsKind(elements_kind) || | 6397 ASSERT(IsFastElementsKind(elements_kind) || |
| 6664 IsExternalArrayElementsKind(elements_kind)); | 6398 IsExternalArrayElementsKind(elements_kind)); |
| 6665 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 6399 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
| 6666 // Happily, mapcompare is a checked object. | 6400 // Happily, mapcompare is a checked object. |
| 6667 access = BuildUncheckedMonomorphicElementAccess( | 6401 access = BuildUncheckedMonomorphicElementAccess( |
| 6668 mapcompare, key, val, | 6402 mapcompare, key, val, |
| 6669 map->instance_type() == JS_ARRAY_TYPE, | 6403 map->instance_type() == JS_ARRAY_TYPE, |
| 6670 elements_kind, is_store, | 6404 elements_kind, access_type, |
| 6671 load_mode, | 6405 load_mode, |
| 6672 store_mode); | 6406 store_mode); |
| 6673 } | 6407 } |
| 6674 *has_side_effects |= access->HasObservableSideEffects(); | 6408 *has_side_effects |= access->HasObservableSideEffects(); |
| 6675 // The caller will use has_side_effects and add a correct Simulate. | 6409 // The caller will use has_side_effects and add a correct Simulate. |
| 6676 access->SetFlag(HValue::kHasNoObservableSideEffects); | 6410 access->SetFlag(HValue::kHasNoObservableSideEffects); |
| 6677 if (!is_store) { | 6411 if (access_type == LOAD) { |
| 6678 Push(access); | 6412 Push(access); |
| 6679 } | 6413 } |
| 6680 NoObservableSideEffectsScope scope(this); | 6414 NoObservableSideEffectsScope scope(this); |
| 6681 GotoNoSimulate(join); | 6415 GotoNoSimulate(join); |
| 6682 set_current_block(other_map); | 6416 set_current_block(other_map); |
| 6683 } | 6417 } |
| 6684 | 6418 |
| 6685 // Deopt if none of the cases matched. | 6419 // Deopt if none of the cases matched. |
| 6686 NoObservableSideEffectsScope scope(this); | 6420 NoObservableSideEffectsScope scope(this); |
| 6687 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", | 6421 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", |
| 6688 join); | 6422 join); |
| 6689 set_current_block(join); | 6423 set_current_block(join); |
| 6690 return is_store ? NULL : Pop(); | 6424 return access_type == STORE ? NULL : Pop(); |
| 6691 } | 6425 } |
| 6692 | 6426 |
| 6693 | 6427 |
| 6694 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 6428 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
| 6695 HValue* obj, | 6429 HValue* obj, |
| 6696 HValue* key, | 6430 HValue* key, |
| 6697 HValue* val, | 6431 HValue* val, |
| 6698 Expression* expr, | 6432 Expression* expr, |
| 6699 bool is_store, | 6433 PropertyAccessType access_type, |
| 6700 bool* has_side_effects) { | 6434 bool* has_side_effects) { |
| 6701 ASSERT(!expr->IsPropertyName()); | 6435 ASSERT(!expr->IsPropertyName()); |
| 6702 HInstruction* instr = NULL; | 6436 HInstruction* instr = NULL; |
| 6703 | 6437 |
| 6704 SmallMapList* types; | 6438 SmallMapList* types; |
| 6705 bool monomorphic = ComputeReceiverTypes(expr, obj, &types); | 6439 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone()); |
| 6706 | 6440 |
| 6707 bool force_generic = false; | 6441 bool force_generic = false; |
| 6708 if (is_store && (monomorphic || (types != NULL && !types->is_empty()))) { | 6442 if (access_type == STORE && |
| 6443 (monomorphic || (types != NULL && !types->is_empty()))) { |
| 6709 // Stores can't be mono/polymorphic if their prototype chain has dictionary | 6444 // Stores can't be mono/polymorphic if their prototype chain has dictionary |
| 6710 // elements. However a receiver map that has dictionary elements itself | 6445 // elements. However a receiver map that has dictionary elements itself |
| 6711 // should be left to normal mono/poly behavior (the other maps may benefit | 6446 // should be left to normal mono/poly behavior (the other maps may benefit |
| 6712 // from highly optimized stores). | 6447 // from highly optimized stores). |
| 6713 for (int i = 0; i < types->length(); i++) { | 6448 for (int i = 0; i < types->length(); i++) { |
| 6714 Handle<Map> current_map = types->at(i); | 6449 Handle<Map> current_map = types->at(i); |
| 6715 if (current_map->DictionaryElementsInPrototypeChainOnly()) { | 6450 if (current_map->DictionaryElementsInPrototypeChainOnly()) { |
| 6716 force_generic = true; | 6451 force_generic = true; |
| 6717 monomorphic = false; | 6452 monomorphic = false; |
| 6718 break; | 6453 break; |
| 6719 } | 6454 } |
| 6720 } | 6455 } |
| 6721 } | 6456 } |
| 6722 | 6457 |
| 6723 if (monomorphic) { | 6458 if (monomorphic) { |
| 6724 Handle<Map> map = types->first(); | 6459 Handle<Map> map = types->first(); |
| 6725 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) { | 6460 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) { |
| 6726 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 6461 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val)); |
| 6727 : BuildLoadKeyedGeneric(obj, key); | |
| 6728 AddInstruction(instr); | |
| 6729 } else { | 6462 } else { |
| 6730 BuildCheckHeapObject(obj); | 6463 BuildCheckHeapObject(obj); |
| 6731 instr = BuildMonomorphicElementAccess( | 6464 instr = BuildMonomorphicElementAccess( |
| 6732 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 6465 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); |
| 6733 } | 6466 } |
| 6734 } else if (!force_generic && (types != NULL && !types->is_empty())) { | 6467 } else if (!force_generic && (types != NULL && !types->is_empty())) { |
| 6735 return HandlePolymorphicElementAccess( | 6468 return HandlePolymorphicElementAccess( |
| 6736 obj, key, val, types, is_store, | 6469 obj, key, val, types, access_type, |
| 6737 expr->GetStoreMode(), has_side_effects); | 6470 expr->GetStoreMode(), has_side_effects); |
| 6738 } else { | 6471 } else { |
| 6739 if (is_store) { | 6472 if (access_type == STORE) { |
| 6740 if (expr->IsAssignment() && | 6473 if (expr->IsAssignment() && |
| 6741 expr->AsAssignment()->HasNoTypeInformation()) { | 6474 expr->AsAssignment()->HasNoTypeInformation()) { |
| 6742 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 6475 Add<HDeoptimize>("Insufficient type feedback for keyed store", |
| 6743 Deoptimizer::SOFT); | 6476 Deoptimizer::SOFT); |
| 6744 } | 6477 } |
| 6745 instr = BuildStoreKeyedGeneric(obj, key, val); | |
| 6746 } else { | 6478 } else { |
| 6747 if (expr->AsProperty()->HasNoTypeInformation()) { | 6479 if (expr->AsProperty()->HasNoTypeInformation()) { |
| 6748 Add<HDeoptimize>("Insufficient type feedback for keyed load", | 6480 Add<HDeoptimize>("Insufficient type feedback for keyed load", |
| 6749 Deoptimizer::SOFT); | 6481 Deoptimizer::SOFT); |
| 6750 } | 6482 } |
| 6751 instr = BuildLoadKeyedGeneric(obj, key); | |
| 6752 } | 6483 } |
| 6753 AddInstruction(instr); | 6484 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val)); |
| 6754 } | 6485 } |
| 6755 *has_side_effects = instr->HasObservableSideEffects(); | 6486 *has_side_effects = instr->HasObservableSideEffects(); |
| 6756 return instr; | 6487 return instr; |
| 6757 } | 6488 } |
| 6758 | 6489 |
| 6759 | 6490 |
| 6760 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | |
| 6761 HValue* object, | |
| 6762 HValue* key, | |
| 6763 HValue* value) { | |
| 6764 return New<HStoreKeyedGeneric>( | |
| 6765 object, | |
| 6766 key, | |
| 6767 value, | |
| 6768 function_strict_mode_flag()); | |
| 6769 } | |
| 6770 | |
| 6771 | |
| 6772 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { | 6491 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { |
| 6773 // Outermost function already has arguments on the stack. | 6492 // Outermost function already has arguments on the stack. |
| 6774 if (function_state()->outer() == NULL) return; | 6493 if (function_state()->outer() == NULL) return; |
| 6775 | 6494 |
| 6776 if (function_state()->arguments_pushed()) return; | 6495 if (function_state()->arguments_pushed()) return; |
| 6777 | 6496 |
| 6778 // Push arguments when entering inlined function. | 6497 // Push arguments when entering inlined function. |
| 6779 HEnterInlined* entry = function_state()->entry(); | 6498 HEnterInlined* entry = function_state()->entry(); |
| 6780 entry->set_arguments_pushed(); | 6499 entry->set_arguments_pushed(); |
| 6781 | 6500 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6839 HInstruction* length = Add<HConstant>(argument_count); | 6558 HInstruction* length = Add<HConstant>(argument_count); |
| 6840 HInstruction* checked_key = Add<HBoundsCheck>(key, length); | 6559 HInstruction* checked_key = Add<HBoundsCheck>(key, length); |
| 6841 result = New<HAccessArgumentsAt>(elements, length, checked_key); | 6560 result = New<HAccessArgumentsAt>(elements, length, checked_key); |
| 6842 } | 6561 } |
| 6843 } | 6562 } |
| 6844 ast_context()->ReturnInstruction(result, expr->id()); | 6563 ast_context()->ReturnInstruction(result, expr->id()); |
| 6845 return true; | 6564 return true; |
| 6846 } | 6565 } |
| 6847 | 6566 |
| 6848 | 6567 |
| 6568 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess( |
| 6569 PropertyAccessType access, |
| 6570 BailoutId ast_id, |
| 6571 BailoutId return_id, |
| 6572 Expression* expr, |
| 6573 HValue* object, |
| 6574 Handle<String> name, |
| 6575 HValue* value, |
| 6576 bool is_uninitialized) { |
| 6577 SmallMapList* types; |
| 6578 ComputeReceiverTypes(expr, object, &types, zone()); |
| 6579 ASSERT(types != NULL); |
| 6580 |
| 6581 if (types->length() > 0) { |
| 6582 PropertyAccessInfo info(this, access, ToType(types->first()), name); |
| 6583 if (!info.CanAccessAsMonomorphic(types)) { |
| 6584 HandlePolymorphicNamedFieldAccess( |
| 6585 access, ast_id, return_id, object, value, types, name); |
| 6586 return NULL; |
| 6587 } |
| 6588 |
| 6589 HValue* checked_object; |
| 6590 // Type::Number() is only supported by polymorphic load/call handling. |
| 6591 ASSERT(!info.type()->Is(Type::Number())); |
| 6592 BuildCheckHeapObject(object); |
| 6593 if (AreStringTypes(types)) { |
| 6594 checked_object = |
| 6595 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
| 6596 } else { |
| 6597 checked_object = Add<HCheckMaps>(object, types); |
| 6598 } |
| 6599 return BuildMonomorphicAccess( |
| 6600 &info, object, checked_object, value, ast_id, return_id); |
| 6601 } |
| 6602 |
| 6603 return BuildNamedGeneric(access, object, name, value, is_uninitialized); |
| 6604 } |
| 6605 |
| 6606 |
| 6849 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 6607 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
| 6850 HValue* object, | 6608 HValue* object, |
| 6851 HValue* key) { | 6609 HValue* key) { |
| 6852 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 6610 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
| 6853 Push(object); | 6611 Push(object); |
| 6854 if (key != NULL) Push(key); | 6612 if (key != NULL) Push(key); |
| 6855 BuildLoad(expr, expr->LoadId()); | 6613 BuildLoad(expr, expr->LoadId()); |
| 6856 } | 6614 } |
| 6857 | 6615 |
| 6858 | 6616 |
| 6859 static bool AreStringTypes(SmallMapList* types) { | |
| 6860 for (int i = 0; i < types->length(); i++) { | |
| 6861 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; | |
| 6862 } | |
| 6863 return true; | |
| 6864 } | |
| 6865 | |
| 6866 | |
| 6867 void HOptimizedGraphBuilder::BuildLoad(Property* expr, | 6617 void HOptimizedGraphBuilder::BuildLoad(Property* expr, |
| 6868 BailoutId ast_id) { | 6618 BailoutId ast_id) { |
| 6869 HInstruction* instr = NULL; | 6619 HInstruction* instr = NULL; |
| 6870 if (expr->IsStringAccess()) { | 6620 if (expr->IsStringAccess()) { |
| 6871 HValue* index = Pop(); | 6621 HValue* index = Pop(); |
| 6872 HValue* string = Pop(); | 6622 HValue* string = Pop(); |
| 6873 HInstruction* char_code = BuildStringCharCodeAt(string, index); | 6623 HInstruction* char_code = BuildStringCharCodeAt(string, index); |
| 6874 AddInstruction(char_code); | 6624 AddInstruction(char_code); |
| 6875 instr = NewUncasted<HStringCharFromCode>(char_code); | 6625 instr = NewUncasted<HStringCharFromCode>(char_code); |
| 6876 | 6626 |
| 6877 } else if (expr->IsFunctionPrototype()) { | 6627 } else if (expr->IsFunctionPrototype()) { |
| 6878 HValue* function = Pop(); | 6628 HValue* function = Pop(); |
| 6879 BuildCheckHeapObject(function); | 6629 BuildCheckHeapObject(function); |
| 6880 instr = New<HLoadFunctionPrototype>(function); | 6630 instr = New<HLoadFunctionPrototype>(function); |
| 6881 | 6631 |
| 6882 } else if (expr->key()->IsPropertyName()) { | 6632 } else if (expr->key()->IsPropertyName()) { |
| 6883 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6633 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 6884 HValue* object = Pop(); | 6634 HValue* object = Pop(); |
| 6885 | 6635 |
| 6886 SmallMapList* types; | 6636 instr = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr, |
| 6887 ComputeReceiverTypes(expr, object, &types); | 6637 object, name, NULL, expr->IsUninitialized()); |
| 6888 ASSERT(types != NULL); | 6638 if (instr == NULL) return; |
| 6889 | 6639 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); |
| 6890 if (types->length() > 0) { | |
| 6891 PropertyAccessInfo info(this, IC::MapToType(types->first()), name); | |
| 6892 if (!info.CanLoadAsMonomorphic(types)) { | |
| 6893 return HandlePolymorphicLoadNamedField( | |
| 6894 ast_id, expr->LoadId(), object, types, name); | |
| 6895 } | |
| 6896 | |
| 6897 HValue* checked_object; | |
| 6898 // HeapType::Number() is only supported by polymorphic load/call handling. | |
| 6899 ASSERT(!info.type()->Is(HeapType::Number())); | |
| 6900 BuildCheckHeapObject(object); | |
| 6901 if (AreStringTypes(types)) { | |
| 6902 checked_object = | |
| 6903 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | |
| 6904 } else { | |
| 6905 checked_object = Add<HCheckMaps>(object, types); | |
| 6906 } | |
| 6907 instr = BuildLoadMonomorphic( | |
| 6908 &info, object, checked_object, ast_id, expr->LoadId()); | |
| 6909 if (instr == NULL) return; | |
| 6910 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); | |
| 6911 } else { | |
| 6912 instr = BuildLoadNamedGeneric(object, name, expr); | |
| 6913 } | |
| 6914 | 6640 |
| 6915 } else { | 6641 } else { |
| 6916 HValue* key = Pop(); | 6642 HValue* key = Pop(); |
| 6917 HValue* obj = Pop(); | 6643 HValue* obj = Pop(); |
| 6918 | 6644 |
| 6919 bool has_side_effects = false; | 6645 bool has_side_effects = false; |
| 6920 HValue* load = HandleKeyedElementAccess( | 6646 HValue* load = HandleKeyedElementAccess( |
| 6921 obj, key, NULL, expr, | 6647 obj, key, NULL, expr, LOAD, &has_side_effects); |
| 6922 false, // is_store | |
| 6923 &has_side_effects); | |
| 6924 if (has_side_effects) { | 6648 if (has_side_effects) { |
| 6925 if (ast_context()->IsEffect()) { | 6649 if (ast_context()->IsEffect()) { |
| 6926 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6650 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6927 } else { | 6651 } else { |
| 6928 Push(load); | 6652 Push(load); |
| 6929 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6653 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6930 Drop(1); | 6654 Drop(1); |
| 6931 } | 6655 } |
| 6932 } | 6656 } |
| 6933 return ast_context()->ReturnValue(load); | 6657 return ast_context()->ReturnValue(load); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7089 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6813 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 7090 FunctionSorter order[kMaxCallPolymorphism]; | 6814 FunctionSorter order[kMaxCallPolymorphism]; |
| 7091 | 6815 |
| 7092 bool handle_smi = false; | 6816 bool handle_smi = false; |
| 7093 bool handled_string = false; | 6817 bool handled_string = false; |
| 7094 int ordered_functions = 0; | 6818 int ordered_functions = 0; |
| 7095 | 6819 |
| 7096 for (int i = 0; | 6820 for (int i = 0; |
| 7097 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 6821 i < types->length() && ordered_functions < kMaxCallPolymorphism; |
| 7098 ++i) { | 6822 ++i) { |
| 7099 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); | 6823 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); |
| 7100 if (info.CanLoadMonomorphic() && | 6824 if (info.CanAccessMonomorphic() && |
| 7101 info.lookup()->IsConstant() && | 6825 info.lookup()->IsConstant() && |
| 7102 info.constant()->IsJSFunction()) { | 6826 info.constant()->IsJSFunction()) { |
| 7103 if (info.type()->Is(HeapType::String())) { | 6827 if (info.type()->Is(Type::String())) { |
| 7104 if (handled_string) continue; | 6828 if (handled_string) continue; |
| 7105 handled_string = true; | 6829 handled_string = true; |
| 7106 } | 6830 } |
| 7107 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); | 6831 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
| 7108 if (info.type()->Is(HeapType::Number())) { | 6832 if (info.type()->Is(Type::Number())) { |
| 7109 handle_smi = true; | 6833 handle_smi = true; |
| 7110 } | 6834 } |
| 7111 expr->set_target(target); | 6835 expr->set_target(target); |
| 7112 order[ordered_functions++] = | 6836 order[ordered_functions++] = |
| 7113 FunctionSorter(i, | 6837 FunctionSorter(i, |
| 7114 expr->target()->shared()->profiler_ticks(), | 6838 expr->target()->shared()->profiler_ticks(), |
| 7115 InliningAstSize(expr->target()), | 6839 InliningAstSize(expr->target()), |
| 7116 expr->target()->shared()->SourceSize()); | 6840 expr->target()->shared()->SourceSize()); |
| 7117 } | 6841 } |
| 7118 } | 6842 } |
| 7119 | 6843 |
| 7120 std::sort(order, order + ordered_functions); | 6844 std::sort(order, order + ordered_functions); |
| 7121 | 6845 |
| 7122 HBasicBlock* number_block = NULL; | 6846 HBasicBlock* number_block = NULL; |
| 7123 HBasicBlock* join = NULL; | 6847 HBasicBlock* join = NULL; |
| 7124 handled_string = false; | 6848 handled_string = false; |
| 7125 int count = 0; | 6849 int count = 0; |
| 7126 | 6850 |
| 7127 for (int fn = 0; fn < ordered_functions; ++fn) { | 6851 for (int fn = 0; fn < ordered_functions; ++fn) { |
| 7128 int i = order[fn].index(); | 6852 int i = order[fn].index(); |
| 7129 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); | 6853 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); |
| 7130 if (info.type()->Is(HeapType::String())) { | 6854 if (info.type()->Is(Type::String())) { |
| 7131 if (handled_string) continue; | 6855 if (handled_string) continue; |
| 7132 handled_string = true; | 6856 handled_string = true; |
| 7133 } | 6857 } |
| 7134 // Reloads the target. | 6858 // Reloads the target. |
| 7135 info.CanLoadMonomorphic(); | 6859 info.CanAccessMonomorphic(); |
| 7136 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); | 6860 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
| 7137 | 6861 |
| 7138 expr->set_target(target); | 6862 expr->set_target(target); |
| 7139 if (count == 0) { | 6863 if (count == 0) { |
| 7140 // Only needed once. | 6864 // Only needed once. |
| 7141 join = graph()->CreateBasicBlock(); | 6865 join = graph()->CreateBasicBlock(); |
| 7142 if (handle_smi) { | 6866 if (handle_smi) { |
| 7143 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 6867 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
| 7144 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 6868 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
| 7145 number_block = graph()->CreateBasicBlock(); | 6869 number_block = graph()->CreateBasicBlock(); |
| 7146 FinishCurrentBlock(New<HIsSmiAndBranch>( | 6870 FinishCurrentBlock(New<HIsSmiAndBranch>( |
| 7147 receiver, empty_smi_block, not_smi_block)); | 6871 receiver, empty_smi_block, not_smi_block)); |
| 7148 Goto(empty_smi_block, number_block); | 6872 Goto(empty_smi_block, number_block); |
| 7149 set_current_block(not_smi_block); | 6873 set_current_block(not_smi_block); |
| 7150 } else { | 6874 } else { |
| 7151 BuildCheckHeapObject(receiver); | 6875 BuildCheckHeapObject(receiver); |
| 7152 } | 6876 } |
| 7153 } | 6877 } |
| 7154 ++count; | 6878 ++count; |
| 7155 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6879 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 7156 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6880 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 7157 HUnaryControlInstruction* compare; | 6881 HUnaryControlInstruction* compare; |
| 7158 | 6882 |
| 7159 Handle<Map> map = info.map(); | 6883 Handle<Map> map = info.map(); |
| 7160 if (info.type()->Is(HeapType::Number())) { | 6884 if (info.type()->Is(Type::Number())) { |
| 7161 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); | 6885 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 7162 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); | 6886 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); |
| 7163 } else if (info.type()->Is(HeapType::String())) { | 6887 } else if (info.type()->Is(Type::String())) { |
| 7164 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); | 6888 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); |
| 7165 } else { | 6889 } else { |
| 7166 compare = New<HCompareMap>(receiver, map, if_true, if_false); | 6890 compare = New<HCompareMap>(receiver, map, if_true, if_false); |
| 7167 } | 6891 } |
| 7168 FinishCurrentBlock(compare); | 6892 FinishCurrentBlock(compare); |
| 7169 | 6893 |
| 7170 if (info.type()->Is(HeapType::Number())) { | 6894 if (info.type()->Is(Type::Number())) { |
| 7171 Goto(if_true, number_block); | 6895 Goto(if_true, number_block); |
| 7172 if_true = number_block; | 6896 if_true = number_block; |
| 7173 number_block->SetJoinId(expr->id()); | 6897 number_block->SetJoinId(expr->id()); |
| 7174 } | 6898 } |
| 7175 | 6899 |
| 7176 set_current_block(if_true); | 6900 set_current_block(if_true); |
| 7177 | 6901 |
| 7178 AddCheckPrototypeMaps(info.holder(), map); | 6902 AddCheckPrototypeMaps(info.holder(), map); |
| 7179 | 6903 |
| 7180 HValue* function = Add<HConstant>(expr->target()); | 6904 HValue* function = Add<HConstant>(expr->target()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7219 // use a generic IC. | 6943 // use a generic IC. |
| 7220 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6944 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 7221 // Because the deopt may be the only path in the polymorphic call, make sure | 6945 // Because the deopt may be the only path in the polymorphic call, make sure |
| 7222 // that the environment stack matches the depth on deopt that it otherwise | 6946 // that the environment stack matches the depth on deopt that it otherwise |
| 7223 // would have had after a successful call. | 6947 // would have had after a successful call. |
| 7224 Drop(1); // Drop receiver. | 6948 Drop(1); // Drop receiver. |
| 7225 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 6949 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
| 7226 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | 6950 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
| 7227 } else { | 6951 } else { |
| 7228 Property* prop = expr->expression()->AsProperty(); | 6952 Property* prop = expr->expression()->AsProperty(); |
| 7229 HInstruction* function = BuildLoadNamedGeneric(receiver, name, prop); | 6953 HInstruction* function = BuildNamedGeneric( |
| 6954 LOAD, receiver, name, NULL, prop->IsUninitialized()); |
| 7230 AddInstruction(function); | 6955 AddInstruction(function); |
| 7231 Push(function); | 6956 Push(function); |
| 7232 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 6957 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
| 7233 | 6958 |
| 7234 environment()->SetExpressionStackAt(1, function); | 6959 environment()->SetExpressionStackAt(1, function); |
| 7235 environment()->SetExpressionStackAt(0, receiver); | 6960 environment()->SetExpressionStackAt(0, receiver); |
| 7236 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 6961 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 7237 | 6962 |
| 7238 CallFunctionFlags flags = receiver->type().IsJSObject() | 6963 CallFunctionFlags flags = receiver->type().IsJSObject() |
| 7239 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; | 6964 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7639 return TryInline(expr->target(), | 7364 return TryInline(expr->target(), |
| 7640 expr->arguments()->length(), | 7365 expr->arguments()->length(), |
| 7641 implicit_return_value, | 7366 implicit_return_value, |
| 7642 expr->id(), | 7367 expr->id(), |
| 7643 expr->ReturnId(), | 7368 expr->ReturnId(), |
| 7644 CONSTRUCT_CALL_RETURN); | 7369 CONSTRUCT_CALL_RETURN); |
| 7645 } | 7370 } |
| 7646 | 7371 |
| 7647 | 7372 |
| 7648 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, | 7373 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
| 7374 Handle<Map> receiver_map, |
| 7649 BailoutId ast_id, | 7375 BailoutId ast_id, |
| 7650 BailoutId return_id) { | 7376 BailoutId return_id) { |
| 7377 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true; |
| 7651 return TryInline(getter, | 7378 return TryInline(getter, |
| 7652 0, | 7379 0, |
| 7653 NULL, | 7380 NULL, |
| 7654 ast_id, | 7381 ast_id, |
| 7655 return_id, | 7382 return_id, |
| 7656 GETTER_CALL_RETURN); | 7383 GETTER_CALL_RETURN); |
| 7657 } | 7384 } |
| 7658 | 7385 |
| 7659 | 7386 |
| 7660 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | 7387 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
| 7388 Handle<Map> receiver_map, |
| 7661 BailoutId id, | 7389 BailoutId id, |
| 7662 BailoutId assignment_id, | 7390 BailoutId assignment_id, |
| 7663 HValue* implicit_return_value) { | 7391 HValue* implicit_return_value) { |
| 7392 if (TryInlineApiSetter(setter, receiver_map, id)) return true; |
| 7664 return TryInline(setter, | 7393 return TryInline(setter, |
| 7665 1, | 7394 1, |
| 7666 implicit_return_value, | 7395 implicit_return_value, |
| 7667 id, assignment_id, | 7396 id, assignment_id, |
| 7668 SETTER_CALL_RETURN); | 7397 SETTER_CALL_RETURN); |
| 7669 } | 7398 } |
| 7670 | 7399 |
| 7671 | 7400 |
| 7672 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function, | 7401 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function, |
| 7673 Call* expr, | 7402 Call* expr, |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7854 | 7583 |
| 7855 length_checker.Else(); | 7584 length_checker.Else(); |
| 7856 HValue* elements = AddLoadElements(checked_object); | 7585 HValue* elements = AddLoadElements(checked_object); |
| 7857 // Ensure that we aren't popping from a copy-on-write array. | 7586 // Ensure that we aren't popping from a copy-on-write array. |
| 7858 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 7587 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
| 7859 elements = BuildCopyElementsOnWrite(checked_object, elements, | 7588 elements = BuildCopyElementsOnWrite(checked_object, elements, |
| 7860 elements_kind, length); | 7589 elements_kind, length); |
| 7861 } | 7590 } |
| 7862 reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1()); | 7591 reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1()); |
| 7863 result = AddElementAccess(elements, reduced_length, NULL, | 7592 result = AddElementAccess(elements, reduced_length, NULL, |
| 7864 bounds_check, elements_kind, false); | 7593 bounds_check, elements_kind, LOAD); |
| 7865 Factory* factory = isolate()->factory(); | 7594 Factory* factory = isolate()->factory(); |
| 7866 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 7595 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
| 7867 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 7596 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
| 7868 ? Add<HConstant>(factory->the_hole_value()) | 7597 ? Add<HConstant>(factory->the_hole_value()) |
| 7869 : Add<HConstant>(nan_double); | 7598 : Add<HConstant>(nan_double); |
| 7870 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 7599 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
| 7871 elements_kind = FAST_HOLEY_ELEMENTS; | 7600 elements_kind = FAST_HOLEY_ELEMENTS; |
| 7872 } | 7601 } |
| 7873 AddElementAccess( | 7602 AddElementAccess( |
| 7874 elements, reduced_length, hole, bounds_check, elements_kind, true); | 7603 elements, reduced_length, hole, bounds_check, elements_kind, STORE); |
| 7875 Add<HStoreNamedField>( | 7604 Add<HStoreNamedField>( |
| 7876 checked_object, HObjectAccess::ForArrayLength(elements_kind), | 7605 checked_object, HObjectAccess::ForArrayLength(elements_kind), |
| 7877 reduced_length, STORE_TO_INITIALIZED_ENTRY); | 7606 reduced_length, STORE_TO_INITIALIZED_ENTRY); |
| 7878 | 7607 |
| 7879 if (!ast_context()->IsEffect()) Push(result); | 7608 if (!ast_context()->IsEffect()) Push(result); |
| 7880 | 7609 |
| 7881 length_checker.End(); | 7610 length_checker.End(); |
| 7882 } | 7611 } |
| 7883 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); | 7612 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
| 7884 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 7613 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7923 default: | 7652 default: |
| 7924 // Not yet supported for inlining. | 7653 // Not yet supported for inlining. |
| 7925 break; | 7654 break; |
| 7926 } | 7655 } |
| 7927 return false; | 7656 return false; |
| 7928 } | 7657 } |
| 7929 | 7658 |
| 7930 | 7659 |
| 7931 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, | 7660 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, |
| 7932 HValue* receiver) { | 7661 HValue* receiver) { |
| 7933 return TryInlineApiCall( | 7662 Handle<JSFunction> function = expr->target(); |
| 7934 expr, receiver, Handle<Map>::null(), true); | 7663 int argc = expr->arguments()->length(); |
| 7664 SmallMapList receiver_maps; |
| 7665 return TryInlineApiCall(function, |
| 7666 receiver, |
| 7667 &receiver_maps, |
| 7668 argc, |
| 7669 expr->id(), |
| 7670 kCallApiFunction); |
| 7935 } | 7671 } |
| 7936 | 7672 |
| 7937 | 7673 |
| 7938 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr, | 7674 bool HOptimizedGraphBuilder::TryInlineApiMethodCall( |
| 7939 HValue* receiver, | 7675 Call* expr, |
| 7940 Handle<Map> receiver_map) { | 7676 HValue* receiver, |
| 7941 return TryInlineApiCall(expr, receiver, receiver_map, false); | 7677 SmallMapList* receiver_maps) { |
| 7678 Handle<JSFunction> function = expr->target(); |
| 7679 int argc = expr->arguments()->length(); |
| 7680 return TryInlineApiCall(function, |
| 7681 receiver, |
| 7682 receiver_maps, |
| 7683 argc, |
| 7684 expr->id(), |
| 7685 kCallApiMethod); |
| 7942 } | 7686 } |
| 7943 | 7687 |
| 7944 bool HOptimizedGraphBuilder::TryInlineApiCall(Call* expr, | 7688 |
| 7945 HValue* receiver, | 7689 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function, |
| 7946 Handle<Map> receiver_map, | 7690 Handle<Map> receiver_map, |
| 7947 bool is_function_call) { | 7691 BailoutId ast_id) { |
| 7948 if (!expr->IsMonomorphic()) return false; | 7692 SmallMapList receiver_maps(1, zone()); |
| 7949 CallOptimization optimization(expr->target()); | 7693 receiver_maps.Add(receiver_map, zone()); |
| 7694 return TryInlineApiCall(function, |
| 7695 NULL, // Receiver is on expression stack. |
| 7696 &receiver_maps, |
| 7697 0, |
| 7698 ast_id, |
| 7699 kCallApiGetter); |
| 7700 } |
| 7701 |
| 7702 |
| 7703 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function, |
| 7704 Handle<Map> receiver_map, |
| 7705 BailoutId ast_id) { |
| 7706 SmallMapList receiver_maps(1, zone()); |
| 7707 receiver_maps.Add(receiver_map, zone()); |
| 7708 return TryInlineApiCall(function, |
| 7709 NULL, // Receiver is on expression stack. |
| 7710 &receiver_maps, |
| 7711 1, |
| 7712 ast_id, |
| 7713 kCallApiSetter); |
| 7714 } |
| 7715 |
| 7716 |
| 7717 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function, |
| 7718 HValue* receiver, |
| 7719 SmallMapList* receiver_maps, |
| 7720 int argc, |
| 7721 BailoutId ast_id, |
| 7722 ApiCallType call_type) { |
| 7723 CallOptimization optimization(function); |
| 7950 if (!optimization.is_simple_api_call()) return false; | 7724 if (!optimization.is_simple_api_call()) return false; |
| 7951 Handle<Map> holder_map; | 7725 Handle<Map> holder_map; |
| 7952 if (is_function_call) { | 7726 if (call_type == kCallApiFunction) { |
| 7953 // Cannot embed a direct reference to the global proxy map | 7727 // Cannot embed a direct reference to the global proxy map |
| 7954 // as it maybe dropped on deserialization. | 7728 // as it maybe dropped on deserialization. |
| 7955 CHECK(!Serializer::enabled()); | 7729 CHECK(!Serializer::enabled()); |
| 7956 receiver_map = Handle<Map>( | 7730 ASSERT_EQ(0, receiver_maps->length()); |
| 7957 expr->target()->context()->global_object()->global_receiver()->map()); | 7731 receiver_maps->Add(handle( |
| 7732 function->context()->global_object()->global_receiver()->map()), |
| 7733 zone()); |
| 7958 } | 7734 } |
| 7959 CallOptimization::HolderLookup holder_lookup = | 7735 CallOptimization::HolderLookup holder_lookup = |
| 7960 CallOptimization::kHolderNotFound; | 7736 CallOptimization::kHolderNotFound; |
| 7961 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( | 7737 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( |
| 7962 receiver_map, &holder_lookup); | 7738 receiver_maps->first(), &holder_lookup); |
| 7963 if (holder_lookup == CallOptimization::kHolderNotFound) return false; | 7739 if (holder_lookup == CallOptimization::kHolderNotFound) return false; |
| 7964 | 7740 |
| 7965 if (FLAG_trace_inlining) { | 7741 if (FLAG_trace_inlining) { |
| 7966 PrintF("Inlining api function "); | 7742 PrintF("Inlining api function "); |
| 7967 expr->target()->ShortPrint(); | 7743 function->ShortPrint(); |
| 7968 PrintF("\n"); | 7744 PrintF("\n"); |
| 7969 } | 7745 } |
| 7970 | 7746 |
| 7971 const int argc = expr->arguments()->length(); | 7747 bool drop_extra = false; |
| 7972 // Includes receiver. | 7748 switch (call_type) { |
| 7973 PushArgumentsFromEnvironment(argc + 1); | 7749 case kCallApiFunction: |
| 7974 | 7750 case kCallApiMethod: |
| 7975 // Need to ensure the chain between receiver and api_holder is intact | 7751 // Need to check that none of the receiver maps could have changed. |
| 7976 AddCheckMap(receiver, receiver_map); | 7752 Add<HCheckMaps>(receiver, receiver_maps); |
| 7977 if (holder_lookup == CallOptimization::kHolderFound) { | 7753 // Need to ensure the chain between receiver and api_holder is intact. |
| 7978 AddCheckPrototypeMaps(api_holder, receiver_map); | 7754 if (holder_lookup == CallOptimization::kHolderFound) { |
| 7979 } else { | 7755 AddCheckPrototypeMaps(api_holder, receiver_maps->first()); |
| 7980 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); | 7756 } else { |
| 7757 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); |
| 7758 } |
| 7759 // Includes receiver. |
| 7760 PushArgumentsFromEnvironment(argc + 1); |
| 7761 // Drop function after call. |
| 7762 drop_extra = true; |
| 7763 break; |
| 7764 case kCallApiGetter: |
| 7765 // Receiver and prototype chain cannot have changed. |
| 7766 ASSERT_EQ(0, argc); |
| 7767 ASSERT_EQ(NULL, receiver); |
| 7768 // Receiver is on expression stack. |
| 7769 receiver = Pop(); |
| 7770 Add<HPushArgument>(receiver); |
| 7771 break; |
| 7772 case kCallApiSetter: |
| 7773 { |
| 7774 // Receiver and prototype chain cannot have changed. |
| 7775 ASSERT_EQ(1, argc); |
| 7776 ASSERT_EQ(NULL, receiver); |
| 7777 // Receiver and value are on expression stack. |
| 7778 HValue* value = Pop(); |
| 7779 receiver = Pop(); |
| 7780 Add<HPushArgument>(receiver); |
| 7781 Add<HPushArgument>(value); |
| 7782 break; |
| 7783 } |
| 7981 } | 7784 } |
| 7982 | 7785 |
| 7983 HValue* holder = NULL; | 7786 HValue* holder = NULL; |
| 7984 switch (holder_lookup) { | 7787 switch (holder_lookup) { |
| 7985 case CallOptimization::kHolderFound: | 7788 case CallOptimization::kHolderFound: |
| 7986 holder = Add<HConstant>(api_holder); | 7789 holder = Add<HConstant>(api_holder); |
| 7987 break; | 7790 break; |
| 7988 case CallOptimization::kHolderIsReceiver: | 7791 case CallOptimization::kHolderIsReceiver: |
| 7989 holder = receiver; | 7792 holder = receiver; |
| 7990 break; | 7793 break; |
| 7991 case CallOptimization::kHolderNotFound: | 7794 case CallOptimization::kHolderNotFound: |
| 7992 UNREACHABLE(); | 7795 UNREACHABLE(); |
| 7993 break; | 7796 break; |
| 7994 } | 7797 } |
| 7995 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 7798 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 7996 Handle<Object> call_data_obj(api_call_info->data(), isolate()); | 7799 Handle<Object> call_data_obj(api_call_info->data(), isolate()); |
| 7997 bool call_data_is_undefined = call_data_obj->IsUndefined(); | 7800 bool call_data_is_undefined = call_data_obj->IsUndefined(); |
| 7998 HValue* call_data = Add<HConstant>(call_data_obj); | 7801 HValue* call_data = Add<HConstant>(call_data_obj); |
| 7999 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback())); | 7802 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback())); |
| 8000 ExternalReference ref = ExternalReference(&fun, | 7803 ExternalReference ref = ExternalReference(&fun, |
| 8001 ExternalReference::DIRECT_API_CALL, | 7804 ExternalReference::DIRECT_API_CALL, |
| 8002 isolate()); | 7805 isolate()); |
| 8003 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); | 7806 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); |
| 8004 | 7807 |
| 8005 HValue* op_vals[] = { | 7808 HValue* op_vals[] = { |
| 8006 // callee | 7809 Add<HConstant>(function), |
| 8007 Add<HConstant>(expr->target()), | |
| 8008 call_data, | 7810 call_data, |
| 8009 holder, | 7811 holder, |
| 8010 api_function_address, | 7812 api_function_address, |
| 8011 context() | 7813 context() |
| 8012 }; | 7814 }; |
| 8013 | 7815 |
| 8014 CallInterfaceDescriptor* descriptor = | 7816 CallInterfaceDescriptor* descriptor = |
| 8015 isolate()->call_descriptor(Isolate::ApiFunctionCall); | 7817 isolate()->call_descriptor(Isolate::ApiFunctionCall); |
| 8016 | 7818 |
| 8017 CallApiFunctionStub stub(true, call_data_is_undefined, argc); | 7819 CallApiFunctionStub stub(true, call_data_is_undefined, argc); |
| 8018 Handle<Code> code = stub.GetCode(isolate()); | 7820 Handle<Code> code = stub.GetCode(isolate()); |
| 8019 HConstant* code_value = Add<HConstant>(code); | 7821 HConstant* code_value = Add<HConstant>(code); |
| 8020 | 7822 |
| 8021 ASSERT((sizeof(op_vals) / kPointerSize) == | 7823 ASSERT((sizeof(op_vals) / kPointerSize) == |
| 8022 descriptor->environment_length()); | 7824 descriptor->environment_length()); |
| 8023 | 7825 |
| 8024 HInstruction* call = New<HCallWithDescriptor>( | 7826 HInstruction* call = New<HCallWithDescriptor>( |
| 8025 code_value, argc + 1, descriptor, | 7827 code_value, argc + 1, descriptor, |
| 8026 Vector<HValue*>(op_vals, descriptor->environment_length())); | 7828 Vector<HValue*>(op_vals, descriptor->environment_length())); |
| 8027 | 7829 |
| 8028 Drop(1); // Drop function. | 7830 if (drop_extra) Drop(1); // Drop function. |
| 8029 ast_context()->ReturnInstruction(call, expr->id()); | 7831 ast_context()->ReturnInstruction(call, ast_id); |
| 8030 return true; | 7832 return true; |
| 8031 } | 7833 } |
| 8032 | 7834 |
| 8033 | 7835 |
| 8034 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { | 7836 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { |
| 8035 ASSERT(expr->expression()->IsProperty()); | 7837 ASSERT(expr->expression()->IsProperty()); |
| 8036 | 7838 |
| 8037 if (!expr->IsMonomorphic()) { | 7839 if (!expr->IsMonomorphic()) { |
| 8038 return false; | 7840 return false; |
| 8039 } | 7841 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8125 Expression* callee = expr->expression(); | 7927 Expression* callee = expr->expression(); |
| 8126 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7928 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 8127 HInstruction* call = NULL; | 7929 HInstruction* call = NULL; |
| 8128 | 7930 |
| 8129 Property* prop = callee->AsProperty(); | 7931 Property* prop = callee->AsProperty(); |
| 8130 if (prop != NULL) { | 7932 if (prop != NULL) { |
| 8131 CHECK_ALIVE(VisitForValue(prop->obj())); | 7933 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 8132 HValue* receiver = Top(); | 7934 HValue* receiver = Top(); |
| 8133 | 7935 |
| 8134 SmallMapList* types; | 7936 SmallMapList* types; |
| 8135 ComputeReceiverTypes(expr, receiver, &types); | 7937 ComputeReceiverTypes(expr, receiver, &types, zone()); |
| 8136 | 7938 |
| 8137 if (prop->key()->IsPropertyName() && types->length() > 0) { | 7939 if (prop->key()->IsPropertyName() && types->length() > 0) { |
| 8138 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 7940 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 8139 PropertyAccessInfo info(this, IC::MapToType(types->first()), name); | 7941 PropertyAccessInfo info(this, LOAD, ToType(types->first()), name); |
| 8140 if (!info.CanLoadAsMonomorphic(types)) { | 7942 if (!info.CanAccessAsMonomorphic(types)) { |
| 8141 HandlePolymorphicCallNamed(expr, receiver, types, name); | 7943 HandlePolymorphicCallNamed(expr, receiver, types, name); |
| 8142 return; | 7944 return; |
| 8143 } | 7945 } |
| 8144 } | 7946 } |
| 8145 | 7947 |
| 8146 HValue* key = NULL; | 7948 HValue* key = NULL; |
| 8147 if (!prop->key()->IsPropertyName()) { | 7949 if (!prop->key()->IsPropertyName()) { |
| 8148 CHECK_ALIVE(VisitForValue(prop->key())); | 7950 CHECK_ALIVE(VisitForValue(prop->key())); |
| 8149 key = Pop(); | 7951 key = Pop(); |
| 8150 } | 7952 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 8168 | 7970 |
| 8169 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); | 7971 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); |
| 8170 if (TryInlineBuiltinMethodCall(expr, receiver, map)) { | 7972 if (TryInlineBuiltinMethodCall(expr, receiver, map)) { |
| 8171 if (FLAG_trace_inlining) { | 7973 if (FLAG_trace_inlining) { |
| 8172 PrintF("Inlining builtin "); | 7974 PrintF("Inlining builtin "); |
| 8173 known_function->ShortPrint(); | 7975 known_function->ShortPrint(); |
| 8174 PrintF("\n"); | 7976 PrintF("\n"); |
| 8175 } | 7977 } |
| 8176 return; | 7978 return; |
| 8177 } | 7979 } |
| 8178 if (TryInlineApiMethodCall(expr, receiver, map)) return; | 7980 if (TryInlineApiMethodCall(expr, receiver, types)) return; |
| 8179 | 7981 |
| 8180 // Wrap the receiver if necessary. | 7982 // Wrap the receiver if necessary. |
| 8181 if (NeedsWrappingFor(IC::MapToType(types->first()), known_function)) { | 7983 if (NeedsWrappingFor(ToType(types->first()), known_function)) { |
| 8182 // Since HWrapReceiver currently cannot actually wrap numbers and | 7984 // Since HWrapReceiver currently cannot actually wrap numbers and |
| 8183 // strings, use the regular CallFunctionStub for method calls to wrap | 7985 // strings, use the regular CallFunctionStub for method calls to wrap |
| 8184 // the receiver. | 7986 // the receiver. |
| 8185 // TODO(verwaest): Support creation of value wrappers directly in | 7987 // TODO(verwaest): Support creation of value wrappers directly in |
| 8186 // HWrapReceiver. | 7988 // HWrapReceiver. |
| 8187 call = New<HCallFunction>( | 7989 call = New<HCallFunction>( |
| 8188 function, argument_count, WRAP_AND_CALL); | 7990 function, argument_count, WRAP_AND_CALL); |
| 8189 } else if (TryInlineCall(expr)) { | 7991 } else if (TryInlineCall(expr)) { |
| 8190 return; | 7992 return; |
| 8191 } else { | 7993 } else { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 8207 } | 8009 } |
| 8208 | 8010 |
| 8209 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 8011 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
| 8210 if (global_call) { | 8012 if (global_call) { |
| 8211 Variable* var = proxy->var(); | 8013 Variable* var = proxy->var(); |
| 8212 bool known_global_function = false; | 8014 bool known_global_function = false; |
| 8213 // If there is a global property cell for the name at compile time and | 8015 // If there is a global property cell for the name at compile time and |
| 8214 // access check is not enabled we assume that the function will not change | 8016 // access check is not enabled we assume that the function will not change |
| 8215 // and generate optimized code for calling the function. | 8017 // and generate optimized code for calling the function. |
| 8216 LookupResult lookup(isolate()); | 8018 LookupResult lookup(isolate()); |
| 8217 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 8019 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, LOAD); |
| 8218 if (type == kUseCell && | 8020 if (type == kUseCell && |
| 8219 !current_info()->global_object()->IsAccessCheckNeeded()) { | 8021 !current_info()->global_object()->IsAccessCheckNeeded()) { |
| 8220 Handle<GlobalObject> global(current_info()->global_object()); | 8022 Handle<GlobalObject> global(current_info()->global_object()); |
| 8221 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 8023 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
| 8222 } | 8024 } |
| 8223 CHECK_ALIVE(VisitForValue(expr->expression())); | 8025 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8224 HValue* function = Top(); | 8026 HValue* function = Top(); |
| 8225 if (known_global_function) { | 8027 if (known_global_function) { |
| 8226 Add<HCheckValue>(function, expr->target()); | 8028 Add<HCheckValue>(function, expr->target()); |
| 8227 | 8029 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8350 // TODO(mvstanton): If all the arguments are constants in smi range, then | 8152 // TODO(mvstanton): If all the arguments are constants in smi range, then |
| 8351 // we could set fill_with_hole to false and save a few instructions. | 8153 // we could set fill_with_hole to false and save a few instructions. |
| 8352 JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind) | 8154 JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind) |
| 8353 ? JSArrayBuilder::FILL_WITH_HOLE | 8155 ? JSArrayBuilder::FILL_WITH_HOLE |
| 8354 : JSArrayBuilder::DONT_FILL_WITH_HOLE; | 8156 : JSArrayBuilder::DONT_FILL_WITH_HOLE; |
| 8355 new_object = array_builder.AllocateArray(length, length, fill_mode); | 8157 new_object = array_builder.AllocateArray(length, length, fill_mode); |
| 8356 HValue* elements = array_builder.GetElementsLocation(); | 8158 HValue* elements = array_builder.GetElementsLocation(); |
| 8357 for (int i = 0; i < argument_count; i++) { | 8159 for (int i = 0; i < argument_count; i++) { |
| 8358 HValue* value = environment()->ExpressionStackAt(argument_count - i - 1); | 8160 HValue* value = environment()->ExpressionStackAt(argument_count - i - 1); |
| 8359 HValue* constant_i = Add<HConstant>(i); | 8161 HValue* constant_i = Add<HConstant>(i); |
| 8360 Add<HStoreKeyed>(elements, constant_i, value, kind, INITIALIZING_STORE); | 8162 Add<HStoreKeyed>(elements, constant_i, value, kind); |
| 8361 } | 8163 } |
| 8362 } | 8164 } |
| 8363 | 8165 |
| 8364 Drop(argument_count + 1); // drop constructor and args. | 8166 Drop(argument_count + 1); // drop constructor and args. |
| 8365 ast_context()->ReturnValue(new_object); | 8167 ast_context()->ReturnValue(new_object); |
| 8366 } | 8168 } |
| 8367 | 8169 |
| 8368 | 8170 |
| 8369 // Checks whether allocation using the given constructor can be inlined. | 8171 // Checks whether allocation using the given constructor can be inlined. |
| 8370 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 8172 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8459 isolate()->heap()->GetPretenureMode() : NOT_TENURED; | 8261 isolate()->heap()->GetPretenureMode() : NOT_TENURED; |
| 8460 HAllocate* receiver = | 8262 HAllocate* receiver = |
| 8461 Add<HAllocate>(size_in_bytes, HType::JSObject(), pretenure_flag, | 8263 Add<HAllocate>(size_in_bytes, HType::JSObject(), pretenure_flag, |
| 8462 JS_OBJECT_TYPE); | 8264 JS_OBJECT_TYPE); |
| 8463 receiver->set_known_initial_map(initial_map); | 8265 receiver->set_known_initial_map(initial_map); |
| 8464 | 8266 |
| 8465 // Load the initial map from the constructor. | 8267 // Load the initial map from the constructor. |
| 8466 HValue* constructor_value = Add<HConstant>(constructor); | 8268 HValue* constructor_value = Add<HConstant>(constructor); |
| 8467 HValue* initial_map_value = | 8269 HValue* initial_map_value = |
| 8468 Add<HLoadNamedField>(constructor_value, static_cast<HValue*>(NULL), | 8270 Add<HLoadNamedField>(constructor_value, static_cast<HValue*>(NULL), |
| 8469 HObjectAccess::ForJSObjectOffset( | 8271 HObjectAccess::ForMapAndOffset( |
| 8272 handle(constructor->map()), |
| 8470 JSFunction::kPrototypeOrInitialMapOffset)); | 8273 JSFunction::kPrototypeOrInitialMapOffset)); |
| 8471 | 8274 |
| 8472 // Initialize map and fields of the newly allocated object. | 8275 // Initialize map and fields of the newly allocated object. |
| 8473 { NoObservableSideEffectsScope no_effects(this); | 8276 { NoObservableSideEffectsScope no_effects(this); |
| 8474 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | 8277 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); |
| 8475 Add<HStoreNamedField>(receiver, | 8278 Add<HStoreNamedField>(receiver, |
| 8476 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), | 8279 HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset), |
| 8477 initial_map_value, INITIALIZING_STORE); | 8280 initial_map_value); |
| 8478 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); | 8281 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); |
| 8479 Add<HStoreNamedField>(receiver, | 8282 Add<HStoreNamedField>(receiver, |
| 8480 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), | 8283 HObjectAccess::ForMapAndOffset(initial_map, |
| 8481 empty_fixed_array, INITIALIZING_STORE); | 8284 JSObject::kPropertiesOffset), |
| 8285 empty_fixed_array); |
| 8482 Add<HStoreNamedField>(receiver, | 8286 Add<HStoreNamedField>(receiver, |
| 8483 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), | 8287 HObjectAccess::ForMapAndOffset(initial_map, |
| 8484 empty_fixed_array, INITIALIZING_STORE); | 8288 JSObject::kElementsOffset), |
| 8289 empty_fixed_array); |
| 8485 if (initial_map->inobject_properties() != 0) { | 8290 if (initial_map->inobject_properties() != 0) { |
| 8486 HConstant* undefined = graph()->GetConstantUndefined(); | 8291 HConstant* undefined = graph()->GetConstantUndefined(); |
| 8487 for (int i = 0; i < initial_map->inobject_properties(); i++) { | 8292 for (int i = 0; i < initial_map->inobject_properties(); i++) { |
| 8488 int property_offset = JSObject::kHeaderSize + i * kPointerSize; | 8293 int property_offset = initial_map->GetInObjectPropertyOffset(i); |
| 8489 Add<HStoreNamedField>(receiver, | 8294 Add<HStoreNamedField>(receiver, |
| 8490 HObjectAccess::ForJSObjectOffset(property_offset), | 8295 HObjectAccess::ForMapAndOffset(initial_map, property_offset), |
| 8491 undefined, PREINITIALIZING_STORE); | 8296 undefined); |
| 8492 } | 8297 } |
| 8493 } | 8298 } |
| 8494 } | 8299 } |
| 8495 | 8300 |
| 8496 // Replace the constructor function with a newly allocated receiver using | 8301 // Replace the constructor function with a newly allocated receiver using |
| 8497 // the index of the receiver from the top of the expression stack. | 8302 // the index of the receiver from the top of the expression stack. |
| 8498 const int receiver_index = argument_count - 1; | 8303 const int receiver_index = argument_count - 1; |
| 8499 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); | 8304 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); |
| 8500 environment()->SetExpressionStackAt(receiver_index, receiver); | 8305 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 8501 | 8306 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8565 void HGraphBuilder::BuildArrayBufferViewInitialization( | 8370 void HGraphBuilder::BuildArrayBufferViewInitialization( |
| 8566 HValue* obj, | 8371 HValue* obj, |
| 8567 HValue* buffer, | 8372 HValue* buffer, |
| 8568 HValue* byte_offset, | 8373 HValue* byte_offset, |
| 8569 HValue* byte_length) { | 8374 HValue* byte_length) { |
| 8570 | 8375 |
| 8571 for (int offset = ViewClass::kSize; | 8376 for (int offset = ViewClass::kSize; |
| 8572 offset < ViewClass::kSizeWithInternalFields; | 8377 offset < ViewClass::kSizeWithInternalFields; |
| 8573 offset += kPointerSize) { | 8378 offset += kPointerSize) { |
| 8574 Add<HStoreNamedField>(obj, | 8379 Add<HStoreNamedField>(obj, |
| 8575 HObjectAccess::ForJSObjectOffset(offset), | 8380 HObjectAccess::ForObservableJSObjectOffset(offset), |
| 8576 graph()->GetConstant0(), INITIALIZING_STORE); | 8381 graph()->GetConstant0()); |
| 8577 } | 8382 } |
| 8578 | 8383 |
| 8579 Add<HStoreNamedField>( | 8384 Add<HStoreNamedField>( |
| 8580 obj, | 8385 obj, |
| 8581 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer, INITIALIZING_STORE); | 8386 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); |
| 8582 Add<HStoreNamedField>( | 8387 Add<HStoreNamedField>( |
| 8583 obj, | 8388 obj, |
| 8584 HObjectAccess::ForJSArrayBufferViewByteOffset(), | 8389 HObjectAccess::ForJSArrayBufferViewByteOffset(), |
| 8585 byte_offset, INITIALIZING_STORE); | 8390 byte_offset); |
| 8586 Add<HStoreNamedField>( | 8391 Add<HStoreNamedField>( |
| 8587 obj, | 8392 obj, |
| 8588 HObjectAccess::ForJSArrayBufferViewByteLength(), | 8393 HObjectAccess::ForJSArrayBufferViewByteLength(), |
| 8589 byte_length, INITIALIZING_STORE); | 8394 byte_length); |
| 8590 | 8395 |
| 8591 HObjectAccess weak_first_view_access = | 8396 HObjectAccess weak_first_view_access = |
| 8592 HObjectAccess::ForJSArrayBufferWeakFirstView(); | 8397 HObjectAccess::ForJSArrayBufferWeakFirstView(); |
| 8593 Add<HStoreNamedField>(obj, | 8398 Add<HStoreNamedField>(obj, |
| 8594 HObjectAccess::ForJSArrayBufferViewWeakNext(), | 8399 HObjectAccess::ForJSArrayBufferViewWeakNext(), |
| 8595 Add<HLoadNamedField>(buffer, static_cast<HValue*>(NULL), | 8400 Add<HLoadNamedField>(buffer, static_cast<HValue*>(NULL), |
| 8596 weak_first_view_access), | 8401 weak_first_view_access)); |
| 8597 INITIALIZING_STORE); | |
| 8598 Add<HStoreNamedField>( | 8402 Add<HStoreNamedField>( |
| 8599 buffer, weak_first_view_access, obj, INITIALIZING_STORE); | 8403 buffer, weak_first_view_access, obj); |
| 8600 } | 8404 } |
| 8601 | 8405 |
| 8602 | 8406 |
| 8603 void HOptimizedGraphBuilder::VisitDataViewInitialize( | 8407 void HOptimizedGraphBuilder::VisitDataViewInitialize( |
| 8604 CallRuntime* expr) { | 8408 CallRuntime* expr) { |
| 8605 ZoneList<Expression*>* arguments = expr->arguments(); | 8409 ZoneList<Expression*>* arguments = expr->arguments(); |
| 8606 | 8410 |
| 8607 NoObservableSideEffectsScope scope(this); | 8411 NoObservableSideEffectsScope scope(this); |
| 8608 ASSERT(arguments->length()== 4); | 8412 ASSERT(arguments->length()== 4); |
| 8609 CHECK_ALIVE(VisitForValue(arguments->at(0))); | 8413 CHECK_ALIVE(VisitForValue(arguments->at(0))); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8679 | 8483 |
| 8680 ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization. | 8484 ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization. |
| 8681 size_t element_size = 1; // Bogus initialization. | 8485 size_t element_size = 1; // Bogus initialization. |
| 8682 Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size); | 8486 Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size); |
| 8683 | 8487 |
| 8684 HInstruction* length = AddUncasted<HDiv>(byte_length, | 8488 HInstruction* length = AddUncasted<HDiv>(byte_length, |
| 8685 Add<HConstant>(static_cast<int32_t>(element_size))); | 8489 Add<HConstant>(static_cast<int32_t>(element_size))); |
| 8686 | 8490 |
| 8687 Add<HStoreNamedField>(obj, | 8491 Add<HStoreNamedField>(obj, |
| 8688 HObjectAccess::ForJSTypedArrayLength(), | 8492 HObjectAccess::ForJSTypedArrayLength(), |
| 8689 length, INITIALIZING_STORE); | 8493 length); |
| 8494 |
| 8495 Handle<Map> external_array_map( |
| 8496 isolate()->heap()->MapForExternalArrayType(array_type)); |
| 8690 | 8497 |
| 8691 HValue* elements = | 8498 HValue* elements = |
| 8692 Add<HAllocate>( | 8499 Add<HAllocate>( |
| 8693 Add<HConstant>(ExternalArray::kAlignedSize), | 8500 Add<HConstant>(ExternalArray::kAlignedSize), |
| 8694 HType::JSArray(), | 8501 HType::JSArray(), |
| 8695 NOT_TENURED, | 8502 NOT_TENURED, |
| 8696 static_cast<InstanceType>(FIRST_EXTERNAL_ARRAY_TYPE + array_type)); | 8503 external_array_map->instance_type()); |
| 8697 | 8504 |
| 8698 Handle<Map> external_array_map( | |
| 8699 isolate()->heap()->MapForExternalArrayType(array_type)); | |
| 8700 AddStoreMapConstant(elements, external_array_map); | 8505 AddStoreMapConstant(elements, external_array_map); |
| 8701 | 8506 |
| 8702 HValue* backing_store = Add<HLoadNamedField>( | 8507 HValue* backing_store = Add<HLoadNamedField>( |
| 8703 buffer, static_cast<HValue*>(NULL), | 8508 buffer, static_cast<HValue*>(NULL), |
| 8704 HObjectAccess::ForJSArrayBufferBackingStore()); | 8509 HObjectAccess::ForJSArrayBufferBackingStore()); |
| 8705 | 8510 |
| 8706 HValue* typed_array_start; | 8511 HValue* typed_array_start; |
| 8707 if (is_zero_byte_offset) { | 8512 if (is_zero_byte_offset) { |
| 8708 typed_array_start = backing_store; | 8513 typed_array_start = backing_store; |
| 8709 } else { | 8514 } else { |
| 8710 HInstruction* external_pointer = | 8515 HInstruction* external_pointer = |
| 8711 AddUncasted<HAdd>(backing_store, byte_offset); | 8516 AddUncasted<HAdd>(backing_store, byte_offset); |
| 8712 // Arguments are checked prior to call to TypedArrayInitialize, | 8517 // Arguments are checked prior to call to TypedArrayInitialize, |
| 8713 // including byte_offset. | 8518 // including byte_offset. |
| 8714 external_pointer->ClearFlag(HValue::kCanOverflow); | 8519 external_pointer->ClearFlag(HValue::kCanOverflow); |
| 8715 typed_array_start = external_pointer; | 8520 typed_array_start = external_pointer; |
| 8716 } | 8521 } |
| 8717 | 8522 |
| 8523 Add<HStoreNamedField>(elements, |
| 8524 HObjectAccess::ForExternalArrayExternalPointer(), |
| 8525 typed_array_start); |
| 8526 Add<HStoreNamedField>(elements, |
| 8527 HObjectAccess::ForFixedArrayLength(), |
| 8528 length); |
| 8718 Add<HStoreNamedField>( | 8529 Add<HStoreNamedField>( |
| 8719 elements, HObjectAccess::ForExternalArrayExternalPointer(), | 8530 obj, HObjectAccess::ForElementsPointer(), elements); |
| 8720 typed_array_start, INITIALIZING_STORE); | |
| 8721 Add<HStoreNamedField>( | |
| 8722 elements, HObjectAccess::ForFixedArrayLength(), length, | |
| 8723 INITIALIZING_STORE); | |
| 8724 Add<HStoreNamedField>( | |
| 8725 obj, HObjectAccess::ForElementsPointer(), elements, INITIALIZING_STORE); | |
| 8726 } | 8531 } |
| 8727 | 8532 |
| 8728 if (!is_zero_byte_offset) { | 8533 if (!is_zero_byte_offset) { |
| 8729 byte_offset_smi.Else(); | 8534 byte_offset_smi.Else(); |
| 8730 { // byte_offset is not Smi. | 8535 { // byte_offset is not Smi. |
| 8731 Push(Add<HPushArgument>(obj)); | 8536 Push(Add<HPushArgument>(obj)); |
| 8732 VisitArgument(arguments->at(kArrayIdArg)); | 8537 VisitArgument(arguments->at(kArrayIdArg)); |
| 8733 Push(Add<HPushArgument>(buffer)); | 8538 Push(Add<HPushArgument>(buffer)); |
| 8734 Push(Add<HPushArgument>(byte_offset)); | 8539 Push(Add<HPushArgument>(byte_offset)); |
| 8735 Push(Add<HPushArgument>(byte_length)); | 8540 Push(Add<HPushArgument>(byte_length)); |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9208 return value; | 9013 return value; |
| 9209 } | 9014 } |
| 9210 | 9015 |
| 9211 return value; | 9016 return value; |
| 9212 } | 9017 } |
| 9213 | 9018 |
| 9214 | 9019 |
| 9215 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( | 9020 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 9216 BinaryOperation* expr, | 9021 BinaryOperation* expr, |
| 9217 HValue* left, | 9022 HValue* left, |
| 9218 HValue* right) { | 9023 HValue* right, |
| 9024 PushBeforeSimulateBehavior push_sim_result) { |
| 9219 Type* left_type = expr->left()->bounds().lower; | 9025 Type* left_type = expr->left()->bounds().lower; |
| 9220 Type* right_type = expr->right()->bounds().lower; | 9026 Type* right_type = expr->right()->bounds().lower; |
| 9221 Type* result_type = expr->bounds().lower; | 9027 Type* result_type = expr->bounds().lower; |
| 9222 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 9028 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 9223 Handle<AllocationSite> allocation_site = expr->allocation_site(); | 9029 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
| 9224 | 9030 |
| 9225 PretenureFlag pretenure_flag = !FLAG_allocation_site_pretenuring ? | 9031 PretenureFlag pretenure_flag = !FLAG_allocation_site_pretenuring ? |
| 9226 isolate()->heap()->GetPretenureMode() : NOT_TENURED; | 9032 isolate()->heap()->GetPretenureMode() : NOT_TENURED; |
| 9227 | 9033 |
| 9228 HAllocationMode allocation_mode = | 9034 HAllocationMode allocation_mode = |
| 9229 FLAG_allocation_site_pretenuring | 9035 FLAG_allocation_site_pretenuring |
| 9230 ? (allocation_site.is_null() | 9036 ? (allocation_site.is_null() |
| 9231 ? HAllocationMode(NOT_TENURED) | 9037 ? HAllocationMode(NOT_TENURED) |
| 9232 : HAllocationMode(allocation_site)) | 9038 : HAllocationMode(allocation_site)) |
| 9233 : HAllocationMode(pretenure_flag); | 9039 : HAllocationMode(pretenure_flag); |
| 9234 | 9040 |
| 9235 HValue* result = HGraphBuilder::BuildBinaryOperation( | 9041 HValue* result = HGraphBuilder::BuildBinaryOperation( |
| 9236 expr->op(), left, right, left_type, right_type, result_type, | 9042 expr->op(), left, right, left_type, right_type, result_type, |
| 9237 fixed_right_arg, allocation_mode); | 9043 fixed_right_arg, allocation_mode); |
| 9238 // Add a simulate after instructions with observable side effects, and | 9044 // Add a simulate after instructions with observable side effects, and |
| 9239 // after phis, which are the result of BuildBinaryOperation when we | 9045 // after phis, which are the result of BuildBinaryOperation when we |
| 9240 // inlined some complex subgraph. | 9046 // inlined some complex subgraph. |
| 9241 if (result->HasObservableSideEffects() || result->IsPhi()) { | 9047 if (result->HasObservableSideEffects() || result->IsPhi()) { |
| 9242 Push(result); | 9048 if (push_sim_result == NO_PUSH_BEFORE_SIMULATE) { |
| 9243 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 9049 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 9244 Drop(1); | 9050 } else { |
| 9051 ASSERT(push_sim_result == PUSH_BEFORE_SIMULATE); |
| 9052 Push(result); |
| 9053 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 9054 Drop(1); |
| 9055 } |
| 9245 } | 9056 } |
| 9246 return result; | 9057 return result; |
| 9247 } | 9058 } |
| 9248 | 9059 |
| 9249 | 9060 |
| 9250 HValue* HGraphBuilder::BuildBinaryOperation( | 9061 HValue* HGraphBuilder::BuildBinaryOperation( |
| 9251 Token::Value op, | 9062 Token::Value op, |
| 9252 HValue* left, | 9063 HValue* left, |
| 9253 HValue* right, | 9064 HValue* right, |
| 9254 Type* left_type, | 9065 Type* left_type, |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9534 eval_right->SetJoinId(expr->RightId()); | 9345 eval_right->SetJoinId(expr->RightId()); |
| 9535 set_current_block(eval_right); | 9346 set_current_block(eval_right); |
| 9536 Visit(expr->right()); | 9347 Visit(expr->right()); |
| 9537 } | 9348 } |
| 9538 | 9349 |
| 9539 } else if (ast_context()->IsValue()) { | 9350 } else if (ast_context()->IsValue()) { |
| 9540 CHECK_ALIVE(VisitForValue(expr->left())); | 9351 CHECK_ALIVE(VisitForValue(expr->left())); |
| 9541 ASSERT(current_block() != NULL); | 9352 ASSERT(current_block() != NULL); |
| 9542 HValue* left_value = Top(); | 9353 HValue* left_value = Top(); |
| 9543 | 9354 |
| 9544 if (left_value->IsConstant()) { | 9355 // Short-circuit left values that always evaluate to the same boolean value. |
| 9545 HConstant* left_constant = HConstant::cast(left_value); | 9356 if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) { |
| 9546 if ((is_logical_and && left_constant->BooleanValue()) || | 9357 // l (evals true) && r -> r |
| 9547 (!is_logical_and && !left_constant->BooleanValue())) { | 9358 // l (evals true) || r -> l |
| 9548 Drop(1); // left_value. | 9359 // l (evals false) && r -> l |
| 9360 // l (evals false) || r -> r |
| 9361 if (is_logical_and == expr->left()->ToBooleanIsTrue()) { |
| 9362 Drop(1); |
| 9549 CHECK_ALIVE(VisitForValue(expr->right())); | 9363 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9550 } | 9364 } |
| 9551 return ast_context()->ReturnValue(Pop()); | 9365 return ast_context()->ReturnValue(Pop()); |
| 9552 } | 9366 } |
| 9553 | 9367 |
| 9554 // We need an extra block to maintain edge-split form. | 9368 // We need an extra block to maintain edge-split form. |
| 9555 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 9369 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
| 9556 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 9370 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| 9557 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); | 9371 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); |
| 9558 HBranch* test = is_logical_and | 9372 HBranch* test = is_logical_and |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9611 } | 9425 } |
| 9612 } | 9426 } |
| 9613 | 9427 |
| 9614 | 9428 |
| 9615 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 9429 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { |
| 9616 CHECK_ALIVE(VisitForValue(expr->left())); | 9430 CHECK_ALIVE(VisitForValue(expr->left())); |
| 9617 CHECK_ALIVE(VisitForValue(expr->right())); | 9431 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9618 SetSourcePosition(expr->position()); | 9432 SetSourcePosition(expr->position()); |
| 9619 HValue* right = Pop(); | 9433 HValue* right = Pop(); |
| 9620 HValue* left = Pop(); | 9434 HValue* left = Pop(); |
| 9621 HValue* result = BuildBinaryOperation(expr, left, right); | 9435 HValue* result = |
| 9436 BuildBinaryOperation(expr, left, right, |
| 9437 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE |
| 9438 : PUSH_BEFORE_SIMULATE); |
| 9622 if (FLAG_emit_opt_code_positions && result->IsBinaryOperation()) { | 9439 if (FLAG_emit_opt_code_positions && result->IsBinaryOperation()) { |
| 9623 HBinaryOperation::cast(result)->SetOperandPositions( | 9440 HBinaryOperation::cast(result)->SetOperandPositions( |
| 9624 zone(), expr->left()->position(), expr->right()->position()); | 9441 zone(), expr->left()->position(), expr->right()->position()); |
| 9625 } | 9442 } |
| 9626 return ast_context()->ReturnValue(result); | 9443 return ast_context()->ReturnValue(result); |
| 9627 } | 9444 } |
| 9628 | 9445 |
| 9629 | 9446 |
| 9630 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 9447 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
| 9631 Expression* sub_expr, | 9448 Expression* sub_expr, |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9918 | 9735 |
| 9919 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 9736 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
| 9920 int elements_size = (elements->length() > 0 && | 9737 int elements_size = (elements->length() > 0 && |
| 9921 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 9738 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
| 9922 elements->Size() : 0; | 9739 elements->Size() : 0; |
| 9923 | 9740 |
| 9924 HInstruction* object_elements = NULL; | 9741 HInstruction* object_elements = NULL; |
| 9925 if (elements_size > 0) { | 9742 if (elements_size > 0) { |
| 9926 HValue* object_elements_size = Add<HConstant>(elements_size); | 9743 HValue* object_elements_size = Add<HConstant>(elements_size); |
| 9927 if (boilerplate_object->HasFastDoubleElements()) { | 9744 if (boilerplate_object->HasFastDoubleElements()) { |
| 9745 // Allocation folding will not be able to fold |object| and |
| 9746 // |object_elements| together if they are pre-tenured. |
| 9747 if (pretenure_flag == TENURED) { |
| 9748 HConstant* empty_fixed_array = Add<HConstant>( |
| 9749 isolate()->factory()->empty_fixed_array()); |
| 9750 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 9751 empty_fixed_array); |
| 9752 } |
| 9928 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), | 9753 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), |
| 9929 pretenure_flag, FIXED_DOUBLE_ARRAY_TYPE, site_context->current()); | 9754 pretenure_flag, FIXED_DOUBLE_ARRAY_TYPE, site_context->current()); |
| 9930 } else { | 9755 } else { |
| 9931 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), | 9756 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), |
| 9932 pretenure_flag, FIXED_ARRAY_TYPE, site_context->current()); | 9757 pretenure_flag, FIXED_ARRAY_TYPE, site_context->current()); |
| 9933 } | 9758 } |
| 9934 } | 9759 } |
| 9935 BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements); | 9760 BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements); |
| 9936 | 9761 |
| 9937 // Copy object elements if non-COW. | 9762 // Copy object elements if non-COW. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 9955 ASSERT(boilerplate_object->properties()->length() == 0); | 9780 ASSERT(boilerplate_object->properties()->length() == 0); |
| 9956 | 9781 |
| 9957 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 9782 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
| 9958 AddStoreMapConstant(object, boilerplate_object_map); | 9783 AddStoreMapConstant(object, boilerplate_object_map); |
| 9959 | 9784 |
| 9960 Handle<Object> properties_field = | 9785 Handle<Object> properties_field = |
| 9961 Handle<Object>(boilerplate_object->properties(), isolate()); | 9786 Handle<Object>(boilerplate_object->properties(), isolate()); |
| 9962 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 9787 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
| 9963 HInstruction* properties = Add<HConstant>(properties_field); | 9788 HInstruction* properties = Add<HConstant>(properties_field); |
| 9964 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 9789 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 9965 Add<HStoreNamedField>(object, access, properties, INITIALIZING_STORE); | 9790 Add<HStoreNamedField>(object, access, properties); |
| 9966 | 9791 |
| 9967 if (boilerplate_object->IsJSArray()) { | 9792 if (boilerplate_object->IsJSArray()) { |
| 9968 Handle<JSArray> boilerplate_array = | 9793 Handle<JSArray> boilerplate_array = |
| 9969 Handle<JSArray>::cast(boilerplate_object); | 9794 Handle<JSArray>::cast(boilerplate_object); |
| 9970 Handle<Object> length_field = | 9795 Handle<Object> length_field = |
| 9971 Handle<Object>(boilerplate_array->length(), isolate()); | 9796 Handle<Object>(boilerplate_array->length(), isolate()); |
| 9972 HInstruction* length = Add<HConstant>(length_field); | 9797 HInstruction* length = Add<HConstant>(length_field); |
| 9973 | 9798 |
| 9974 ASSERT(boilerplate_array->length()->IsSmi()); | 9799 ASSERT(boilerplate_array->length()->IsSmi()); |
| 9975 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength( | 9800 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength( |
| 9976 boilerplate_array->GetElementsKind()), length, INITIALIZING_STORE); | 9801 boilerplate_array->GetElementsKind()), length); |
| 9977 } | 9802 } |
| 9978 } | 9803 } |
| 9979 | 9804 |
| 9980 | 9805 |
| 9981 void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader( | 9806 void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader( |
| 9982 Handle<JSObject> boilerplate_object, | 9807 Handle<JSObject> boilerplate_object, |
| 9983 HInstruction* object, | 9808 HInstruction* object, |
| 9984 HInstruction* object_elements) { | 9809 HInstruction* object_elements) { |
| 9985 ASSERT(boilerplate_object->properties()->length() == 0); | 9810 ASSERT(boilerplate_object->properties()->length() == 0); |
| 9986 if (object_elements == NULL) { | 9811 if (object_elements == NULL) { |
| 9987 Handle<Object> elements_field = | 9812 Handle<Object> elements_field = |
| 9988 Handle<Object>(boilerplate_object->elements(), isolate()); | 9813 Handle<Object>(boilerplate_object->elements(), isolate()); |
| 9989 object_elements = Add<HConstant>(elements_field); | 9814 object_elements = Add<HConstant>(elements_field); |
| 9990 } | 9815 } |
| 9991 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 9816 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 9992 object_elements, INITIALIZING_STORE); | 9817 object_elements); |
| 9993 } | 9818 } |
| 9994 | 9819 |
| 9995 | 9820 |
| 9996 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 9821 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| 9997 Handle<JSObject> boilerplate_object, | 9822 Handle<JSObject> boilerplate_object, |
| 9998 HInstruction* object, | 9823 HInstruction* object, |
| 9999 AllocationSiteUsageContext* site_context, | 9824 AllocationSiteUsageContext* site_context, |
| 10000 PretenureFlag pretenure_flag) { | 9825 PretenureFlag pretenure_flag) { |
| 10001 Handle<DescriptorArray> descriptors( | 9826 Handle<Map> boilerplate_map(boilerplate_object->map()); |
| 10002 boilerplate_object->map()->instance_descriptors()); | 9827 Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors()); |
| 10003 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); | 9828 int limit = boilerplate_map->NumberOfOwnDescriptors(); |
| 10004 | 9829 |
| 10005 int copied_fields = 0; | 9830 int copied_fields = 0; |
| 10006 for (int i = 0; i < limit; i++) { | 9831 for (int i = 0; i < limit; i++) { |
| 10007 PropertyDetails details = descriptors->GetDetails(i); | 9832 PropertyDetails details = descriptors->GetDetails(i); |
| 10008 if (details.type() != FIELD) continue; | 9833 if (details.type() != FIELD) continue; |
| 10009 copied_fields++; | 9834 copied_fields++; |
| 10010 int index = descriptors->GetFieldIndex(i); | 9835 int index = descriptors->GetFieldIndex(i); |
| 10011 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); | 9836 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); |
| 10012 Handle<Name> name(descriptors->GetKey(i)); | 9837 Handle<Name> name(descriptors->GetKey(i)); |
| 10013 Handle<Object> value = | 9838 Handle<Object> value = |
| 10014 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), | 9839 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), |
| 10015 isolate()); | 9840 isolate()); |
| 10016 | 9841 |
| 10017 // The access for the store depends on the type of the boilerplate. | 9842 // The access for the store depends on the type of the boilerplate. |
| 10018 HObjectAccess access = boilerplate_object->IsJSArray() ? | 9843 HObjectAccess access = boilerplate_object->IsJSArray() ? |
| 10019 HObjectAccess::ForJSArrayOffset(property_offset) : | 9844 HObjectAccess::ForJSArrayOffset(property_offset) : |
| 10020 HObjectAccess::ForJSObjectOffset(property_offset); | 9845 HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset); |
| 10021 | 9846 |
| 10022 if (value->IsJSObject()) { | 9847 if (value->IsJSObject()) { |
| 10023 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 9848 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 10024 Handle<AllocationSite> current_site = site_context->EnterNewScope(); | 9849 Handle<AllocationSite> current_site = site_context->EnterNewScope(); |
| 10025 HInstruction* result = | 9850 HInstruction* result = |
| 10026 BuildFastLiteral(value_object, site_context); | 9851 BuildFastLiteral(value_object, site_context); |
| 10027 site_context->ExitScope(current_site, value_object); | 9852 site_context->ExitScope(current_site, value_object); |
| 10028 Add<HStoreNamedField>(object, access, result, INITIALIZING_STORE); | 9853 Add<HStoreNamedField>(object, access, result); |
| 10029 } else { | 9854 } else { |
| 10030 Representation representation = details.representation(); | 9855 Representation representation = details.representation(); |
| 10031 HInstruction* value_instruction; | 9856 HInstruction* value_instruction; |
| 10032 | 9857 |
| 10033 if (representation.IsDouble()) { | 9858 if (representation.IsDouble()) { |
| 10034 // Allocate a HeapNumber box and store the value into it. | 9859 // Allocate a HeapNumber box and store the value into it. |
| 10035 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); | 9860 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); |
| 10036 // This heap number alloc does not have a corresponding | 9861 // This heap number alloc does not have a corresponding |
| 10037 // AllocationSite. That is okay because | 9862 // AllocationSite. That is okay because |
| 10038 // 1) it's a child object of another object with a valid allocation site | 9863 // 1) it's a child object of another object with a valid allocation site |
| 10039 // 2) we can just use the mode of the parent object for pretenuring | 9864 // 2) we can just use the mode of the parent object for pretenuring |
| 10040 HInstruction* double_box = | 9865 HInstruction* double_box = |
| 10041 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), | 9866 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), |
| 10042 pretenure_flag, HEAP_NUMBER_TYPE); | 9867 pretenure_flag, HEAP_NUMBER_TYPE); |
| 10043 AddStoreMapConstant(double_box, | 9868 AddStoreMapConstant(double_box, |
| 10044 isolate()->factory()->heap_number_map()); | 9869 isolate()->factory()->heap_number_map()); |
| 10045 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), | 9870 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), |
| 10046 Add<HConstant>(value), INITIALIZING_STORE); | 9871 Add<HConstant>(value)); |
| 10047 value_instruction = double_box; | 9872 value_instruction = double_box; |
| 10048 } else if (representation.IsSmi() && value->IsUninitialized()) { | 9873 } else if (representation.IsSmi() && value->IsUninitialized()) { |
| 10049 value_instruction = graph()->GetConstant0(); | 9874 value_instruction = graph()->GetConstant0(); |
| 10050 } else { | 9875 } else { |
| 10051 value_instruction = Add<HConstant>(value); | 9876 value_instruction = Add<HConstant>(value); |
| 10052 } | 9877 } |
| 10053 | 9878 |
| 10054 Add<HStoreNamedField>(object, access, value_instruction, | 9879 Add<HStoreNamedField>(object, access, value_instruction); |
| 10055 INITIALIZING_STORE); | |
| 10056 } | 9880 } |
| 10057 } | 9881 } |
| 10058 | 9882 |
| 10059 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 9883 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
| 10060 HInstruction* value_instruction = | 9884 HInstruction* value_instruction = |
| 10061 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 9885 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
| 10062 for (int i = copied_fields; i < inobject_properties; i++) { | 9886 for (int i = copied_fields; i < inobject_properties; i++) { |
| 10063 ASSERT(boilerplate_object->IsJSObject()); | 9887 ASSERT(boilerplate_object->IsJSObject()); |
| 10064 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 9888 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
| 10065 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 9889 HObjectAccess access = |
| 10066 Add<HStoreNamedField>(object, access, value_instruction, | 9890 HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset); |
| 10067 PREINITIALIZING_STORE); | 9891 Add<HStoreNamedField>(object, access, value_instruction); |
| 10068 } | 9892 } |
| 10069 } | 9893 } |
| 10070 | 9894 |
| 10071 | 9895 |
| 10072 void HOptimizedGraphBuilder::BuildEmitElements( | 9896 void HOptimizedGraphBuilder::BuildEmitElements( |
| 10073 Handle<JSObject> boilerplate_object, | 9897 Handle<JSObject> boilerplate_object, |
| 10074 Handle<FixedArrayBase> elements, | 9898 Handle<FixedArrayBase> elements, |
| 10075 HValue* object_elements, | 9899 HValue* object_elements, |
| 10076 AllocationSiteUsageContext* site_context) { | 9900 AllocationSiteUsageContext* site_context) { |
| 10077 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 9901 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 10097 HValue* object_elements) { | 9921 HValue* object_elements) { |
| 10098 HInstruction* boilerplate_elements = Add<HConstant>(elements); | 9922 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
| 10099 int elements_length = elements->length(); | 9923 int elements_length = elements->length(); |
| 10100 for (int i = 0; i < elements_length; i++) { | 9924 for (int i = 0; i < elements_length; i++) { |
| 10101 HValue* key_constant = Add<HConstant>(i); | 9925 HValue* key_constant = Add<HConstant>(i); |
| 10102 HInstruction* value_instruction = | 9926 HInstruction* value_instruction = |
| 10103 Add<HLoadKeyed>(boilerplate_elements, key_constant, | 9927 Add<HLoadKeyed>(boilerplate_elements, key_constant, |
| 10104 static_cast<HValue*>(NULL), kind, | 9928 static_cast<HValue*>(NULL), kind, |
| 10105 ALLOW_RETURN_HOLE); | 9929 ALLOW_RETURN_HOLE); |
| 10106 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant, | 9930 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant, |
| 10107 value_instruction, kind, | 9931 value_instruction, kind); |
| 10108 INITIALIZING_STORE); | |
| 10109 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 9932 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 10110 } | 9933 } |
| 10111 } | 9934 } |
| 10112 | 9935 |
| 10113 | 9936 |
| 10114 void HOptimizedGraphBuilder::BuildEmitFixedArray( | 9937 void HOptimizedGraphBuilder::BuildEmitFixedArray( |
| 10115 Handle<FixedArrayBase> elements, | 9938 Handle<FixedArrayBase> elements, |
| 10116 ElementsKind kind, | 9939 ElementsKind kind, |
| 10117 HValue* object_elements, | 9940 HValue* object_elements, |
| 10118 AllocationSiteUsageContext* site_context) { | 9941 AllocationSiteUsageContext* site_context) { |
| 10119 HInstruction* boilerplate_elements = Add<HConstant>(elements); | 9942 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
| 10120 int elements_length = elements->length(); | 9943 int elements_length = elements->length(); |
| 10121 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 9944 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 10122 for (int i = 0; i < elements_length; i++) { | 9945 for (int i = 0; i < elements_length; i++) { |
| 10123 Handle<Object> value(fast_elements->get(i), isolate()); | 9946 Handle<Object> value(fast_elements->get(i), isolate()); |
| 10124 HValue* key_constant = Add<HConstant>(i); | 9947 HValue* key_constant = Add<HConstant>(i); |
| 10125 if (value->IsJSObject()) { | 9948 if (value->IsJSObject()) { |
| 10126 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 9949 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 10127 Handle<AllocationSite> current_site = site_context->EnterNewScope(); | 9950 Handle<AllocationSite> current_site = site_context->EnterNewScope(); |
| 10128 HInstruction* result = | 9951 HInstruction* result = |
| 10129 BuildFastLiteral(value_object, site_context); | 9952 BuildFastLiteral(value_object, site_context); |
| 10130 site_context->ExitScope(current_site, value_object); | 9953 site_context->ExitScope(current_site, value_object); |
| 10131 Add<HStoreKeyed>(object_elements, key_constant, result, kind, | 9954 Add<HStoreKeyed>(object_elements, key_constant, result, kind); |
| 10132 INITIALIZING_STORE); | |
| 10133 } else { | 9955 } else { |
| 10134 HInstruction* value_instruction = | 9956 HInstruction* value_instruction = |
| 10135 Add<HLoadKeyed>(boilerplate_elements, key_constant, | 9957 Add<HLoadKeyed>(boilerplate_elements, key_constant, |
| 10136 static_cast<HValue*>(NULL), kind, | 9958 static_cast<HValue*>(NULL), kind, |
| 10137 ALLOW_RETURN_HOLE); | 9959 ALLOW_RETURN_HOLE); |
| 10138 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind, | 9960 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); |
| 10139 INITIALIZING_STORE); | |
| 10140 } | 9961 } |
| 10141 } | 9962 } |
| 10142 } | 9963 } |
| 10143 | 9964 |
| 10144 | 9965 |
| 10145 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 9966 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 10146 ASSERT(!HasStackOverflow()); | 9967 ASSERT(!HasStackOverflow()); |
| 10147 ASSERT(current_block() != NULL); | 9968 ASSERT(current_block() != NULL); |
| 10148 ASSERT(current_block()->HasPredecessor()); | 9969 ASSERT(current_block()->HasPredecessor()); |
| 10149 HInstruction* instr = BuildThisFunction(); | 9970 HInstruction* instr = BuildThisFunction(); |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10447 HValue* object = Pop(); | 10268 HValue* object = Pop(); |
| 10448 | 10269 |
| 10449 IfBuilder if_objectisvalue(this); | 10270 IfBuilder if_objectisvalue(this); |
| 10450 HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>( | 10271 HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>( |
| 10451 object, JS_VALUE_TYPE); | 10272 object, JS_VALUE_TYPE); |
| 10452 if_objectisvalue.Then(); | 10273 if_objectisvalue.Then(); |
| 10453 { | 10274 { |
| 10454 // Return the actual value. | 10275 // Return the actual value. |
| 10455 Push(Add<HLoadNamedField>( | 10276 Push(Add<HLoadNamedField>( |
| 10456 object, objectisvalue, | 10277 object, objectisvalue, |
| 10457 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset))); | 10278 HObjectAccess::ForObservableJSObjectOffset( |
| 10279 JSValue::kValueOffset))); |
| 10458 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 10280 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
| 10459 } | 10281 } |
| 10460 if_objectisvalue.Else(); | 10282 if_objectisvalue.Else(); |
| 10461 { | 10283 { |
| 10462 // If the object is not a value return the object. | 10284 // If the object is not a value return the object. |
| 10463 Push(object); | 10285 Push(object); |
| 10464 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 10286 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
| 10465 } | 10287 } |
| 10466 if_objectisvalue.End(); | 10288 if_objectisvalue.End(); |
| 10467 return ast_context()->ReturnValue(Pop()); | 10289 return ast_context()->ReturnValue(Pop()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10517 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 10339 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 10518 HValue* value = Pop(); | 10340 HValue* value = Pop(); |
| 10519 HValue* object = Pop(); | 10341 HValue* object = Pop(); |
| 10520 | 10342 |
| 10521 // Check if object is a JSValue. | 10343 // Check if object is a JSValue. |
| 10522 IfBuilder if_objectisvalue(this); | 10344 IfBuilder if_objectisvalue(this); |
| 10523 if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); | 10345 if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); |
| 10524 if_objectisvalue.Then(); | 10346 if_objectisvalue.Then(); |
| 10525 { | 10347 { |
| 10526 // Create in-object property store to kValueOffset. | 10348 // Create in-object property store to kValueOffset. |
| 10527 Add<HStoreNamedField>( | 10349 Add<HStoreNamedField>(object, |
| 10528 object, HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), | 10350 HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset), |
| 10529 value, INITIALIZING_STORE); | 10351 value); |
| 10530 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 10352 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
| 10531 } | 10353 } |
| 10532 if_objectisvalue.Else(); | 10354 if_objectisvalue.Else(); |
| 10533 { | 10355 { |
| 10534 // Nothing to do in this case. | 10356 // Nothing to do in this case. |
| 10535 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 10357 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
| 10536 } | 10358 } |
| 10537 if_objectisvalue.End(); | 10359 if_objectisvalue.End(); |
| 10538 return ast_context()->ReturnValue(value); | 10360 return ast_context()->ReturnValue(value); |
| 10539 } | 10361 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10672 int arg_count = call->arguments()->length() - 1; | 10494 int arg_count = call->arguments()->length() - 1; |
| 10673 ASSERT(arg_count >= 1); // There's always at least a receiver. | 10495 ASSERT(arg_count >= 1); // There's always at least a receiver. |
| 10674 | 10496 |
| 10675 for (int i = 0; i < arg_count; ++i) { | 10497 for (int i = 0; i < arg_count; ++i) { |
| 10676 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 10498 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); |
| 10677 } | 10499 } |
| 10678 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | 10500 CHECK_ALIVE(VisitForValue(call->arguments()->last())); |
| 10679 | 10501 |
| 10680 HValue* function = Pop(); | 10502 HValue* function = Pop(); |
| 10681 | 10503 |
| 10682 // Branch for function proxies, or other non-functions. | 10504 IfBuilder if_is_jsfunction(this); |
| 10683 HHasInstanceTypeAndBranch* typecheck = | 10505 if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); |
| 10684 New<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); | |
| 10685 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); | |
| 10686 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); | |
| 10687 HBasicBlock* join = graph()->CreateBasicBlock(); | |
| 10688 typecheck->SetSuccessorAt(0, if_jsfunction); | |
| 10689 typecheck->SetSuccessorAt(1, if_nonfunction); | |
| 10690 FinishCurrentBlock(typecheck); | |
| 10691 | 10506 |
| 10692 set_current_block(if_jsfunction); | 10507 if_is_jsfunction.Then(); |
| 10693 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count); | 10508 { |
| 10694 Drop(arg_count); | 10509 HInstruction* invoke_result = |
| 10695 Push(invoke_result); | 10510 Add<HInvokeFunction>(function, arg_count); |
| 10696 Goto(if_jsfunction, join); | 10511 Drop(arg_count); |
| 10512 if (!ast_context()->IsEffect()) { |
| 10513 Push(invoke_result); |
| 10514 } |
| 10515 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
| 10516 } |
| 10697 | 10517 |
| 10698 set_current_block(if_nonfunction); | 10518 if_is_jsfunction.Else(); |
| 10699 HInstruction* call_result = Add<HCallFunction>(function, arg_count); | 10519 { |
| 10700 Drop(arg_count); | 10520 HInstruction* call_result = |
| 10701 Push(call_result); | 10521 Add<HCallFunction>(function, arg_count); |
| 10702 Goto(if_nonfunction, join); | 10522 Drop(arg_count); |
| 10523 if (!ast_context()->IsEffect()) { |
| 10524 Push(call_result); |
| 10525 } |
| 10526 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
| 10527 } |
| 10528 if_is_jsfunction.End(); |
| 10703 | 10529 |
| 10704 set_current_block(join); | 10530 if (ast_context()->IsEffect()) { |
| 10705 join->SetJoinId(call->id()); | 10531 // EffectContext::ReturnValue ignores the value, so we can just pass |
| 10706 return ast_context()->ReturnValue(Pop()); | 10532 // 'undefined' (as we do not have the call result anymore). |
| 10533 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| 10534 } else { |
| 10535 return ast_context()->ReturnValue(Pop()); |
| 10536 } |
| 10707 } | 10537 } |
| 10708 | 10538 |
| 10709 | 10539 |
| 10710 // Fast call to math functions. | 10540 // Fast call to math functions. |
| 10711 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { | 10541 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { |
| 10712 ASSERT_EQ(2, call->arguments()->length()); | 10542 ASSERT_EQ(2, call->arguments()->length()); |
| 10713 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10543 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10714 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 10544 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 10715 HValue* right = Pop(); | 10545 HValue* right = Pop(); |
| 10716 HValue* left = Pop(); | 10546 HValue* left = Pop(); |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11384 if (ShouldProduceTraceOutput()) { | 11214 if (ShouldProduceTraceOutput()) { |
| 11385 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11215 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11386 } | 11216 } |
| 11387 | 11217 |
| 11388 #ifdef DEBUG | 11218 #ifdef DEBUG |
| 11389 graph_->Verify(false); // No full verify. | 11219 graph_->Verify(false); // No full verify. |
| 11390 #endif | 11220 #endif |
| 11391 } | 11221 } |
| 11392 | 11222 |
| 11393 } } // namespace v8::internal | 11223 } } // namespace v8::internal |
| OLD | NEW |