Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: src/hydrogen.cc

Issue 149403003: A64: Synchronize with r19234. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-check-elimination.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-check-elimination.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698