OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "hydrogen.h" | 5 #include "hydrogen.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "v8.h" | 9 #include "v8.h" |
10 #include "allocation-site-scopes.h" | 10 #include "allocation-site-scopes.h" |
(...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1528 | 1528 |
1529 return BuildUncheckedDictionaryElementLoadHelper(elements, key, | 1529 return BuildUncheckedDictionaryElementLoadHelper(elements, key, |
1530 hash, mask, 0); | 1530 hash, mask, 0); |
1531 } | 1531 } |
1532 | 1532 |
1533 | 1533 |
1534 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length, | 1534 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length, |
1535 HValue* index, | 1535 HValue* index, |
1536 HValue* input) { | 1536 HValue* input) { |
1537 NoObservableSideEffectsScope scope(this); | 1537 NoObservableSideEffectsScope scope(this); |
| 1538 HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray); |
| 1539 Add<HBoundsCheck>(length, max_length); |
1538 | 1540 |
1539 // Compute the size of the RegExpResult followed by FixedArray with length. | 1541 // Generate size calculation code here in order to make it dominate |
1540 HValue* size = length; | 1542 // the JSRegExpResult allocation. |
1541 // Make sure size does not exceed max regular heap object size. | 1543 ElementsKind elements_kind = FAST_ELEMENTS; |
1542 const int kHeaderSize = JSRegExpResult::kSize + FixedArray::kHeaderSize; | 1544 HValue* size = BuildCalculateElementsSize(elements_kind, length); |
1543 const int kMaxLength = | |
1544 (Page::kMaxRegularHeapObjectSize - kHeaderSize) >> kPointerSizeLog2; | |
1545 Add<HBoundsCheck>(size, Add<HConstant>(kMaxLength)); | |
1546 | |
1547 size = AddUncasted<HShl>(size, Add<HConstant>(kPointerSizeLog2)); | |
1548 size = AddUncasted<HAdd>(size, Add<HConstant>(kHeaderSize)); | |
1549 | 1545 |
1550 // Allocate the JSRegExpResult and the FixedArray in one step. | 1546 // Allocate the JSRegExpResult and the FixedArray in one step. |
1551 HValue* result = Add<HAllocate>( | 1547 HValue* result = Add<HAllocate>( |
1552 size, HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); | 1548 Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(), |
1553 | 1549 NOT_TENURED, JS_ARRAY_TYPE); |
1554 // Determine the elements FixedArray. | |
1555 HValue* elements = Add<HInnerAllocatedObject>( | |
1556 result, Add<HConstant>(JSRegExpResult::kSize), HType::HeapObject()); | |
1557 | 1550 |
1558 // Initialize the JSRegExpResult header. | 1551 // Initialize the JSRegExpResult header. |
1559 HValue* global_object = Add<HLoadNamedField>( | 1552 HValue* global_object = Add<HLoadNamedField>( |
1560 context(), static_cast<HValue*>(NULL), | 1553 context(), static_cast<HValue*>(NULL), |
1561 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 1554 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
1562 HValue* native_context = Add<HLoadNamedField>( | 1555 HValue* native_context = Add<HLoadNamedField>( |
1563 global_object, static_cast<HValue*>(NULL), | 1556 global_object, static_cast<HValue*>(NULL), |
1564 HObjectAccess::ForGlobalObjectNativeContext()); | 1557 HObjectAccess::ForGlobalObjectNativeContext()); |
1565 Add<HStoreNamedField>( | 1558 Add<HStoreNamedField>( |
1566 result, HObjectAccess::ForMap(), | 1559 result, HObjectAccess::ForMap(), |
1567 Add<HLoadNamedField>( | 1560 Add<HLoadNamedField>( |
1568 native_context, static_cast<HValue*>(NULL), | 1561 native_context, static_cast<HValue*>(NULL), |
1569 HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX))); | 1562 HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX))); |
| 1563 HConstant* empty_fixed_array = |
| 1564 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
1570 Add<HStoreNamedField>( | 1565 Add<HStoreNamedField>( |
1571 result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset), | 1566 result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset), |
1572 Add<HConstant>(isolate()->factory()->empty_fixed_array())); | 1567 empty_fixed_array); |
1573 Add<HStoreNamedField>( | 1568 Add<HStoreNamedField>( |
1574 result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset), | 1569 result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset), |
1575 elements); | 1570 empty_fixed_array); |
1576 Add<HStoreNamedField>( | 1571 Add<HStoreNamedField>( |
1577 result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length); | 1572 result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length); |
1578 | 1573 |
1579 // Initialize the additional fields. | 1574 // Initialize the additional fields. |
1580 Add<HStoreNamedField>( | 1575 Add<HStoreNamedField>( |
1581 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset), | 1576 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset), |
1582 index); | 1577 index); |
1583 Add<HStoreNamedField>( | 1578 Add<HStoreNamedField>( |
1584 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset), | 1579 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset), |
1585 input); | 1580 input); |
1586 | 1581 |
1587 // Initialize the elements header. | 1582 // Allocate and initialize the elements header. |
1588 AddStoreMapConstant(elements, isolate()->factory()->fixed_array_map()); | 1583 HAllocate* elements = BuildAllocateElements(elements_kind, size); |
1589 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), length); | 1584 BuildInitializeElementsHeader(elements, elements_kind, length); |
| 1585 |
| 1586 HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize( |
| 1587 elements_kind, max_length->Integer32Value()); |
| 1588 elements->set_size_upper_bound(size_in_bytes_upper_bound); |
| 1589 |
| 1590 Add<HStoreNamedField>( |
| 1591 result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset), |
| 1592 elements); |
1590 | 1593 |
1591 // Initialize the elements contents with undefined. | 1594 // Initialize the elements contents with undefined. |
1592 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); | 1595 BuildFillElementsWithValue( |
1593 index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1596 elements, elements_kind, graph()->GetConstant0(), length, |
1594 { | 1597 graph()->GetConstantUndefined()); |
1595 Add<HStoreKeyed>(elements, index, graph()->GetConstantUndefined(), | |
1596 FAST_ELEMENTS); | |
1597 } | |
1598 loop.EndBody(); | |
1599 | 1598 |
1600 return result; | 1599 return result; |
1601 } | 1600 } |
1602 | 1601 |
1603 | 1602 |
1604 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) { | 1603 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) { |
1605 NoObservableSideEffectsScope scope(this); | 1604 NoObservableSideEffectsScope scope(this); |
1606 | 1605 |
1607 // Convert constant numbers at compile time. | 1606 // Convert constant numbers at compile time. |
1608 if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) { | 1607 if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) { |
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2221 elements, isolate()->factory()->fixed_array_map()); | 2220 elements, isolate()->factory()->fixed_array_map()); |
2222 check_cow_map->ClearDependsOnFlag(kElementsKind); | 2221 check_cow_map->ClearDependsOnFlag(kElementsKind); |
2223 } | 2222 } |
2224 } | 2223 } |
2225 } | 2224 } |
2226 return AddElementAccess(elements, checked_key, val, checked_object, | 2225 return AddElementAccess(elements, checked_key, val, checked_object, |
2227 elements_kind, access_type, load_mode); | 2226 elements_kind, access_type, load_mode); |
2228 } | 2227 } |
2229 | 2228 |
2230 | 2229 |
2231 | |
2232 HValue* HGraphBuilder::BuildAllocateArrayFromLength( | 2230 HValue* HGraphBuilder::BuildAllocateArrayFromLength( |
2233 JSArrayBuilder* array_builder, | 2231 JSArrayBuilder* array_builder, |
2234 HValue* length_argument) { | 2232 HValue* length_argument) { |
2235 if (length_argument->IsConstant() && | 2233 if (length_argument->IsConstant() && |
2236 HConstant::cast(length_argument)->HasSmiValue()) { | 2234 HConstant::cast(length_argument)->HasSmiValue()) { |
2237 int array_length = HConstant::cast(length_argument)->Integer32Value(); | 2235 int array_length = HConstant::cast(length_argument)->Integer32Value(); |
2238 HValue* new_object = array_length == 0 | 2236 if (array_length == 0) { |
2239 ? array_builder->AllocateEmptyArray() | 2237 return array_builder->AllocateEmptyArray(); |
2240 : array_builder->AllocateArray(length_argument, length_argument); | 2238 } else { |
2241 return new_object; | 2239 return array_builder->AllocateArray(length_argument, |
| 2240 array_length, |
| 2241 length_argument); |
| 2242 } |
2242 } | 2243 } |
2243 | 2244 |
2244 HValue* constant_zero = graph()->GetConstant0(); | 2245 HValue* constant_zero = graph()->GetConstant0(); |
2245 HConstant* max_alloc_length = | 2246 HConstant* max_alloc_length = |
2246 Add<HConstant>(JSObject::kInitialMaxFastElementArray); | 2247 Add<HConstant>(JSObject::kInitialMaxFastElementArray); |
2247 HInstruction* checked_length = Add<HBoundsCheck>(length_argument, | 2248 HInstruction* checked_length = Add<HBoundsCheck>(length_argument, |
2248 max_alloc_length); | 2249 max_alloc_length); |
2249 IfBuilder if_builder(this); | 2250 IfBuilder if_builder(this); |
2250 if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero, | 2251 if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero, |
2251 Token::EQ); | 2252 Token::EQ); |
2252 if_builder.Then(); | 2253 if_builder.Then(); |
2253 const int initial_capacity = JSArray::kPreallocatedArrayElements; | 2254 const int initial_capacity = JSArray::kPreallocatedArrayElements; |
2254 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity); | 2255 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity); |
2255 Push(initial_capacity_node); // capacity | 2256 Push(initial_capacity_node); // capacity |
2256 Push(constant_zero); // length | 2257 Push(constant_zero); // length |
2257 if_builder.Else(); | 2258 if_builder.Else(); |
2258 if (!(top_info()->IsStub()) && | 2259 if (!(top_info()->IsStub()) && |
2259 IsFastPackedElementsKind(array_builder->kind())) { | 2260 IsFastPackedElementsKind(array_builder->kind())) { |
2260 // We'll come back later with better (holey) feedback. | 2261 // We'll come back later with better (holey) feedback. |
2261 if_builder.Deopt("Holey array despite packed elements_kind feedback"); | 2262 if_builder.Deopt("Holey array despite packed elements_kind feedback"); |
2262 } else { | 2263 } else { |
2263 Push(checked_length); // capacity | 2264 Push(checked_length); // capacity |
2264 Push(checked_length); // length | 2265 Push(checked_length); // length |
2265 } | 2266 } |
2266 if_builder.End(); | 2267 if_builder.End(); |
2267 | 2268 |
2268 // Figure out total size | 2269 // Figure out total size |
2269 HValue* length = Pop(); | 2270 HValue* length = Pop(); |
2270 HValue* capacity = Pop(); | 2271 HValue* capacity = Pop(); |
2271 return array_builder->AllocateArray(capacity, length); | 2272 return array_builder->AllocateArray(capacity, max_alloc_length, length); |
2272 } | 2273 } |
2273 | 2274 |
2274 | 2275 |
2275 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, | 2276 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind, |
2276 HValue* capacity) { | 2277 HValue* capacity) { |
2277 int elements_size; | 2278 int elements_size = IsFastDoubleElementsKind(kind) |
2278 InstanceType instance_type; | 2279 ? kDoubleSize |
2279 | 2280 : kPointerSize; |
2280 if (IsFastDoubleElementsKind(kind)) { | |
2281 elements_size = kDoubleSize; | |
2282 instance_type = FIXED_DOUBLE_ARRAY_TYPE; | |
2283 } else { | |
2284 elements_size = kPointerSize; | |
2285 instance_type = FIXED_ARRAY_TYPE; | |
2286 } | |
2287 | 2281 |
2288 HConstant* elements_size_value = Add<HConstant>(elements_size); | 2282 HConstant* elements_size_value = Add<HConstant>(elements_size); |
2289 HValue* mul = AddUncasted<HMul>(capacity, elements_size_value); | 2283 HInstruction* mul = HMul::NewImul(zone(), context(), |
| 2284 capacity->ActualValue(), |
| 2285 elements_size_value); |
| 2286 AddInstruction(mul); |
2290 mul->ClearFlag(HValue::kCanOverflow); | 2287 mul->ClearFlag(HValue::kCanOverflow); |
2291 | 2288 |
| 2289 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); |
| 2290 |
2292 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); | 2291 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); |
2293 HValue* total_size = AddUncasted<HAdd>(mul, header_size); | 2292 HValue* total_size = AddUncasted<HAdd>(mul, header_size); |
2294 total_size->ClearFlag(HValue::kCanOverflow); | 2293 total_size->ClearFlag(HValue::kCanOverflow); |
| 2294 return total_size; |
| 2295 } |
2295 | 2296 |
2296 return Add<HAllocate>(total_size, HType::HeapObject(), NOT_TENURED, | 2297 |
| 2298 HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) { |
| 2299 int base_size = JSArray::kSize; |
| 2300 if (mode == TRACK_ALLOCATION_SITE) { |
| 2301 base_size += AllocationMemento::kSize; |
| 2302 } |
| 2303 HConstant* size_in_bytes = Add<HConstant>(base_size); |
| 2304 return Add<HAllocate>( |
| 2305 size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE); |
| 2306 } |
| 2307 |
| 2308 |
| 2309 HConstant* HGraphBuilder::EstablishElementsAllocationSize( |
| 2310 ElementsKind kind, |
| 2311 int capacity) { |
| 2312 int base_size = IsFastDoubleElementsKind(kind) |
| 2313 ? FixedDoubleArray::SizeFor(capacity) |
| 2314 : FixedArray::SizeFor(capacity); |
| 2315 |
| 2316 return Add<HConstant>(base_size); |
| 2317 } |
| 2318 |
| 2319 |
| 2320 HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind, |
| 2321 HValue* size_in_bytes) { |
| 2322 InstanceType instance_type = IsFastDoubleElementsKind(kind) |
| 2323 ? FIXED_DOUBLE_ARRAY_TYPE |
| 2324 : FIXED_ARRAY_TYPE; |
| 2325 |
| 2326 return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED, |
2297 instance_type); | 2327 instance_type); |
2298 } | 2328 } |
2299 | 2329 |
2300 | 2330 |
2301 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 2331 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
2302 ElementsKind kind, | 2332 ElementsKind kind, |
2303 HValue* capacity) { | 2333 HValue* capacity) { |
2304 Factory* factory = isolate()->factory(); | 2334 Factory* factory = isolate()->factory(); |
2305 Handle<Map> map = IsFastDoubleElementsKind(kind) | 2335 Handle<Map> map = IsFastDoubleElementsKind(kind) |
2306 ? factory->fixed_double_array_map() | 2336 ? factory->fixed_double_array_map() |
2307 : factory->fixed_array_map(); | 2337 : factory->fixed_array_map(); |
2308 | 2338 |
2309 Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map)); | 2339 Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map)); |
2310 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), | 2340 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), |
2311 capacity); | 2341 capacity); |
2312 } | 2342 } |
2313 | 2343 |
2314 | 2344 |
2315 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( | 2345 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
2316 ElementsKind kind, | 2346 ElementsKind kind, |
2317 HValue* capacity) { | 2347 HValue* capacity) { |
2318 // The HForceRepresentation is to prevent possible deopt on int-smi | 2348 // The HForceRepresentation is to prevent possible deopt on int-smi |
2319 // conversion after allocation but before the new object fields are set. | 2349 // conversion after allocation but before the new object fields are set. |
2320 capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi()); | 2350 capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi()); |
2321 HValue* new_elements = BuildAllocateElements(kind, capacity); | 2351 HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity); |
| 2352 HValue* new_elements = BuildAllocateElements(kind, size_in_bytes); |
2322 BuildInitializeElementsHeader(new_elements, kind, capacity); | 2353 BuildInitializeElementsHeader(new_elements, kind, capacity); |
2323 return new_elements; | 2354 return new_elements; |
2324 } | 2355 } |
2325 | 2356 |
2326 | 2357 |
2327 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 2358 void HGraphBuilder::BuildJSArrayHeader(HValue* array, |
2328 HValue* array_map, | 2359 HValue* array_map, |
2329 AllocationSiteMode mode, | 2360 HValue* elements, |
2330 ElementsKind elements_kind, | 2361 AllocationSiteMode mode, |
2331 HValue* allocation_site_payload, | 2362 ElementsKind elements_kind, |
2332 HValue* length_field) { | 2363 HValue* allocation_site_payload, |
2333 | 2364 HValue* length_field) { |
2334 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map); | 2365 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map); |
2335 | 2366 |
2336 HConstant* empty_fixed_array = | 2367 HConstant* empty_fixed_array = |
2337 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 2368 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
2338 | 2369 |
2339 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 2370 Add<HStoreNamedField>( |
2340 Add<HStoreNamedField>(array, access, empty_fixed_array); | 2371 array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array); |
2341 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), | 2372 |
2342 length_field); | 2373 Add<HStoreNamedField>( |
| 2374 array, HObjectAccess::ForElementsPointer(), |
| 2375 elements != NULL ? elements : empty_fixed_array); |
| 2376 |
| 2377 Add<HStoreNamedField>( |
| 2378 array, HObjectAccess::ForArrayLength(elements_kind), length_field); |
2343 | 2379 |
2344 if (mode == TRACK_ALLOCATION_SITE) { | 2380 if (mode == TRACK_ALLOCATION_SITE) { |
2345 BuildCreateAllocationMemento( | 2381 BuildCreateAllocationMemento( |
2346 array, Add<HConstant>(JSArray::kSize), allocation_site_payload); | 2382 array, Add<HConstant>(JSArray::kSize), allocation_site_payload); |
2347 } | 2383 } |
2348 | |
2349 int elements_location = JSArray::kSize; | |
2350 if (mode == TRACK_ALLOCATION_SITE) { | |
2351 elements_location += AllocationMemento::kSize; | |
2352 } | |
2353 | |
2354 HInnerAllocatedObject* elements = Add<HInnerAllocatedObject>( | |
2355 array, Add<HConstant>(elements_location), HType::HeapObject()); | |
2356 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); | |
2357 return elements; | |
2358 } | 2384 } |
2359 | 2385 |
2360 | 2386 |
2361 HInstruction* HGraphBuilder::AddElementAccess( | 2387 HInstruction* HGraphBuilder::AddElementAccess( |
2362 HValue* elements, | 2388 HValue* elements, |
2363 HValue* checked_key, | 2389 HValue* checked_key, |
2364 HValue* val, | 2390 HValue* val, |
2365 HValue* dependency, | 2391 HValue* dependency, |
2366 ElementsKind elements_kind, | 2392 ElementsKind elements_kind, |
2367 PropertyAccessType access_type, | 2393 PropertyAccessType access_type, |
(...skipping 16 matching lines...) Expand all Loading... |
2384 elements, checked_key, dependency, elements_kind, load_mode); | 2410 elements, checked_key, dependency, elements_kind, load_mode); |
2385 if (FLAG_opt_safe_uint32_operations && | 2411 if (FLAG_opt_safe_uint32_operations && |
2386 (elements_kind == EXTERNAL_UINT32_ELEMENTS || | 2412 (elements_kind == EXTERNAL_UINT32_ELEMENTS || |
2387 elements_kind == UINT32_ELEMENTS)) { | 2413 elements_kind == UINT32_ELEMENTS)) { |
2388 graph()->RecordUint32Instruction(load); | 2414 graph()->RecordUint32Instruction(load); |
2389 } | 2415 } |
2390 return load; | 2416 return load; |
2391 } | 2417 } |
2392 | 2418 |
2393 | 2419 |
| 2420 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object, |
| 2421 HValue* dependency) { |
| 2422 return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap()); |
| 2423 } |
| 2424 |
| 2425 |
2394 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 2426 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
2395 HValue* dependency) { | 2427 HValue* dependency) { |
2396 return Add<HLoadNamedField>( | 2428 return Add<HLoadNamedField>( |
2397 object, dependency, HObjectAccess::ForElementsPointer()); | 2429 object, dependency, HObjectAccess::ForElementsPointer()); |
2398 } | 2430 } |
2399 | 2431 |
2400 | 2432 |
2401 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength( | 2433 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength( |
2402 HValue* array, | 2434 HValue* array, |
2403 HValue* dependency) { | 2435 HValue* dependency) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2436 ElementsKind new_kind, | 2468 ElementsKind new_kind, |
2437 HValue* length, | 2469 HValue* length, |
2438 HValue* new_capacity) { | 2470 HValue* new_capacity) { |
2439 Add<HBoundsCheck>(new_capacity, Add<HConstant>( | 2471 Add<HBoundsCheck>(new_capacity, Add<HConstant>( |
2440 (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> | 2472 (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> |
2441 ElementsKindToShiftSize(kind))); | 2473 ElementsKindToShiftSize(kind))); |
2442 | 2474 |
2443 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 2475 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
2444 new_kind, new_capacity); | 2476 new_kind, new_capacity); |
2445 | 2477 |
2446 BuildCopyElements(object, elements, kind, new_elements, | 2478 BuildCopyElements(elements, kind, new_elements, |
2447 new_kind, length, new_capacity); | 2479 new_kind, length, new_capacity); |
2448 | 2480 |
2449 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 2481 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
2450 new_elements); | 2482 new_elements); |
2451 | 2483 |
2452 return new_elements; | 2484 return new_elements; |
2453 } | 2485 } |
2454 | 2486 |
2455 | 2487 |
2456 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, | 2488 void HGraphBuilder::BuildFillElementsWithValue(HValue* elements, |
2457 ElementsKind elements_kind, | 2489 ElementsKind elements_kind, |
2458 HValue* from, | 2490 HValue* from, |
2459 HValue* to) { | 2491 HValue* to, |
2460 // Fast elements kinds need to be initialized in case statements below cause a | 2492 HValue* value) { |
2461 // garbage collection. | |
2462 Factory* factory = isolate()->factory(); | |
2463 | |
2464 double nan_double = FixedDoubleArray::hole_nan_as_double(); | |
2465 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | |
2466 ? Add<HConstant>(factory->the_hole_value()) | |
2467 : Add<HConstant>(nan_double); | |
2468 | |
2469 if (to == NULL) { | 2493 if (to == NULL) { |
2470 to = AddLoadFixedArrayLength(elements); | 2494 to = AddLoadFixedArrayLength(elements); |
2471 } | 2495 } |
2472 | 2496 |
2473 // Special loop unfolding case | 2497 // Special loop unfolding case |
2474 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= | 2498 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= |
2475 kElementLoopUnrollThreshold); | 2499 kElementLoopUnrollThreshold); |
2476 int initial_capacity = -1; | 2500 int initial_capacity = -1; |
2477 if (from->IsInteger32Constant() && to->IsInteger32Constant()) { | 2501 if (from->IsInteger32Constant() && to->IsInteger32Constant()) { |
2478 int constant_from = from->GetInteger32Constant(); | 2502 int constant_from = from->GetInteger32Constant(); |
2479 int constant_to = to->GetInteger32Constant(); | 2503 int constant_to = to->GetInteger32Constant(); |
2480 | 2504 |
2481 if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) { | 2505 if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) { |
2482 initial_capacity = constant_to; | 2506 initial_capacity = constant_to; |
2483 } | 2507 } |
2484 } | 2508 } |
2485 | 2509 |
2486 // Since we're about to store a hole value, the store instruction below must | 2510 // Since we're about to store a hole value, the store instruction below must |
2487 // assume an elements kind that supports heap object values. | 2511 // assume an elements kind that supports heap object values. |
2488 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 2512 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
2489 elements_kind = FAST_HOLEY_ELEMENTS; | 2513 elements_kind = FAST_HOLEY_ELEMENTS; |
2490 } | 2514 } |
2491 | 2515 |
2492 if (initial_capacity >= 0) { | 2516 if (initial_capacity >= 0) { |
2493 for (int i = 0; i < initial_capacity; i++) { | 2517 for (int i = 0; i < initial_capacity; i++) { |
2494 HInstruction* key = Add<HConstant>(i); | 2518 HInstruction* key = Add<HConstant>(i); |
2495 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 2519 Add<HStoreKeyed>(elements, key, value, elements_kind); |
2496 } | 2520 } |
2497 } else { | 2521 } else { |
2498 // Carefully loop backwards so that the "from" remains live through the loop | 2522 // Carefully loop backwards so that the "from" remains live through the loop |
2499 // rather than the to. This often corresponds to keeping length live rather | 2523 // rather than the to. This often corresponds to keeping length live rather |
2500 // then capacity, which helps register allocation, since length is used more | 2524 // then capacity, which helps register allocation, since length is used more |
2501 // other than capacity after filling with holes. | 2525 // other than capacity after filling with holes. |
2502 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); | 2526 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); |
2503 | 2527 |
2504 HValue* key = builder.BeginBody(to, from, Token::GT); | 2528 HValue* key = builder.BeginBody(to, from, Token::GT); |
2505 | 2529 |
2506 HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1()); | 2530 HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1()); |
2507 adjusted_key->ClearFlag(HValue::kCanOverflow); | 2531 adjusted_key->ClearFlag(HValue::kCanOverflow); |
2508 | 2532 |
2509 Add<HStoreKeyed>(elements, adjusted_key, hole, elements_kind); | 2533 Add<HStoreKeyed>(elements, adjusted_key, value, elements_kind); |
2510 | 2534 |
2511 builder.EndBody(); | 2535 builder.EndBody(); |
2512 } | 2536 } |
2513 } | 2537 } |
2514 | 2538 |
2515 | 2539 |
2516 void HGraphBuilder::BuildCopyElements(HValue* array, | 2540 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, |
2517 HValue* from_elements, | 2541 ElementsKind elements_kind, |
| 2542 HValue* from, |
| 2543 HValue* to) { |
| 2544 // Fast elements kinds need to be initialized in case statements below cause a |
| 2545 // garbage collection. |
| 2546 Factory* factory = isolate()->factory(); |
| 2547 |
| 2548 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
| 2549 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
| 2550 ? Add<HConstant>(factory->the_hole_value()) |
| 2551 : Add<HConstant>(nan_double); |
| 2552 |
| 2553 BuildFillElementsWithValue(elements, elements_kind, from, to, hole); |
| 2554 } |
| 2555 |
| 2556 |
| 2557 void HGraphBuilder::BuildCopyElements(HValue* from_elements, |
2518 ElementsKind from_elements_kind, | 2558 ElementsKind from_elements_kind, |
2519 HValue* to_elements, | 2559 HValue* to_elements, |
2520 ElementsKind to_elements_kind, | 2560 ElementsKind to_elements_kind, |
2521 HValue* length, | 2561 HValue* length, |
2522 HValue* capacity) { | 2562 HValue* capacity) { |
2523 int constant_capacity = -1; | 2563 int constant_capacity = -1; |
2524 if (capacity != NULL && | 2564 if (capacity != NULL && |
2525 capacity->IsConstant() && | 2565 capacity->IsConstant() && |
2526 HConstant::cast(capacity)->HasInteger32Value()) { | 2566 HConstant::cast(capacity)->HasInteger32Value()) { |
2527 int constant_candidate = HConstant::cast(capacity)->Integer32Value(); | 2567 int constant_candidate = HConstant::cast(capacity)->Integer32Value(); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2594 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2634 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
2595 } | 2635 } |
2596 | 2636 |
2597 builder.EndBody(); | 2637 builder.EndBody(); |
2598 } | 2638 } |
2599 | 2639 |
2600 Counters* counters = isolate()->counters(); | 2640 Counters* counters = isolate()->counters(); |
2601 AddIncrementCounter(counters->inlined_copied_elements()); | 2641 AddIncrementCounter(counters->inlined_copied_elements()); |
2602 } | 2642 } |
2603 | 2643 |
2604 HValue* HGraphBuilder::BuildCloneShallowArrayCommon( | |
2605 HValue* boilerplate, | |
2606 HValue* allocation_site, | |
2607 HValue* extra_size, | |
2608 HValue** return_elements, | |
2609 AllocationSiteMode mode) { | |
2610 // All sizes here are multiples of kPointerSize. | |
2611 int array_size = JSArray::kSize; | |
2612 if (mode == TRACK_ALLOCATION_SITE) { | |
2613 array_size += AllocationMemento::kSize; | |
2614 } | |
2615 | |
2616 HValue* size_in_bytes = Add<HConstant>(array_size); | |
2617 if (extra_size != NULL) { | |
2618 size_in_bytes = AddUncasted<HAdd>(extra_size, size_in_bytes); | |
2619 size_in_bytes->ClearFlag(HValue::kCanOverflow); | |
2620 } | |
2621 | |
2622 HInstruction* object = Add<HAllocate>(size_in_bytes, | |
2623 HType::JSObject(), | |
2624 NOT_TENURED, | |
2625 JS_OBJECT_TYPE); | |
2626 | |
2627 // Copy the JS array part. | |
2628 HValue* map = Add<HLoadNamedField>(boilerplate, | |
2629 static_cast<HValue*>(NULL), HObjectAccess::ForMap()); | |
2630 Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(), | |
2631 Add<HConstant>(isolate()->factory()->empty_fixed_array()), | |
2632 INITIALIZING_STORE); | |
2633 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map, | |
2634 INITIALIZING_STORE); | |
2635 | |
2636 // Create an allocation site info if requested. | |
2637 if (mode == TRACK_ALLOCATION_SITE) { | |
2638 BuildCreateAllocationMemento( | |
2639 object, Add<HConstant>(JSArray::kSize), allocation_site); | |
2640 } | |
2641 | |
2642 if (extra_size != NULL) { | |
2643 HValue* elements = Add<HInnerAllocatedObject>(object, | |
2644 Add<HConstant>(array_size), HType::HeapObject()); | |
2645 if (return_elements != NULL) *return_elements = elements; | |
2646 } | |
2647 | |
2648 return object; | |
2649 } | |
2650 | |
2651 | 2644 |
2652 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate, | 2645 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate, |
2653 HValue* allocation_site, | 2646 HValue* allocation_site, |
2654 AllocationSiteMode mode, | 2647 AllocationSiteMode mode, |
2655 ElementsKind kind) { | 2648 ElementsKind kind) { |
2656 HValue* result = BuildCloneShallowArrayCommon(boilerplate, | 2649 HAllocate* array = AllocateJSArrayObject(mode); |
2657 allocation_site, NULL, NULL, mode); | |
2658 | 2650 |
| 2651 HValue* map = AddLoadMap(boilerplate); |
2659 HValue* elements = AddLoadElements(boilerplate); | 2652 HValue* elements = AddLoadElements(boilerplate); |
2660 HObjectAccess access = HObjectAccess::ForElementsPointer(); | 2653 HValue* length = AddLoadArrayLength(boilerplate, kind); |
2661 Add<HStoreNamedField>(result, access, elements, INITIALIZING_STORE); | |
2662 | 2654 |
2663 HValue* length = AddLoadArrayLength(boilerplate, kind); | 2655 BuildJSArrayHeader(array, |
2664 access = HObjectAccess::ForArrayLength(kind); | 2656 map, |
2665 Add<HStoreNamedField>(result, access, length, INITIALIZING_STORE); | 2657 elements, |
2666 | 2658 mode, |
2667 return result; | 2659 FAST_ELEMENTS, |
| 2660 allocation_site, |
| 2661 length); |
| 2662 return array; |
2668 } | 2663 } |
2669 | 2664 |
2670 | 2665 |
2671 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate, | 2666 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate, |
2672 HValue* allocation_site, | 2667 HValue* allocation_site, |
2673 AllocationSiteMode mode) { | 2668 AllocationSiteMode mode) { |
2674 HValue* result = BuildCloneShallowArrayCommon(boilerplate, | 2669 HAllocate* array = AllocateJSArrayObject(mode); |
2675 allocation_site, NULL, NULL, mode); | |
2676 | 2670 |
2677 HObjectAccess access = HObjectAccess::ForArrayLength(FAST_ELEMENTS); | 2671 HValue* map = AddLoadMap(boilerplate); |
2678 Add<HStoreNamedField>(result, access, graph()->GetConstant0(), | |
2679 INITIALIZING_STORE); | |
2680 access = HObjectAccess::ForElementsPointer(); | |
2681 Add<HStoreNamedField>(result, access, | |
2682 Add<HConstant>(isolate()->factory()->empty_fixed_array()), | |
2683 INITIALIZING_STORE); | |
2684 | 2672 |
2685 return result; | 2673 BuildJSArrayHeader(array, |
| 2674 map, |
| 2675 NULL, // set elements to empty fixed array |
| 2676 mode, |
| 2677 FAST_ELEMENTS, |
| 2678 allocation_site, |
| 2679 graph()->GetConstant0()); |
| 2680 return array; |
2686 } | 2681 } |
2687 | 2682 |
2688 | 2683 |
2689 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate, | 2684 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate, |
2690 HValue* allocation_site, | 2685 HValue* allocation_site, |
2691 AllocationSiteMode mode, | 2686 AllocationSiteMode mode, |
2692 ElementsKind kind) { | 2687 ElementsKind kind) { |
2693 int elements_kind_size = IsFastDoubleElementsKind(kind) | |
2694 ? kDoubleSize : kPointerSize; | |
2695 | |
2696 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 2688 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
2697 HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements); | 2689 HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements); |
2698 HValue* extra = AddUncasted<HMul>(capacity, | 2690 |
2699 Add<HConstant>(elements_kind_size)); | 2691 // Generate size calculation code here in order to make it dominate |
2700 extra->ClearFlag(HValue::kCanOverflow); | 2692 // the JSArray allocation. |
2701 extra = AddUncasted<HAdd>(extra, Add<HConstant>(FixedArray::kHeaderSize)); | 2693 HValue* elements_size = BuildCalculateElementsSize(kind, capacity); |
2702 extra->ClearFlag(HValue::kCanOverflow); | 2694 |
| 2695 // Create empty JSArray object for now, store elimination should remove |
| 2696 // redundant initialization of elements and length fields and at the same |
| 2697 // time the object will be fully prepared for GC if it happens during |
| 2698 // elements allocation. |
| 2699 HValue* result = BuildCloneShallowArrayEmpty( |
| 2700 boilerplate, allocation_site, mode); |
| 2701 |
| 2702 HAllocate* elements = BuildAllocateElements(kind, elements_size); |
| 2703 |
2703 // This function implicitly relies on the fact that the | 2704 // This function implicitly relies on the fact that the |
2704 // FastCloneShallowArrayStub is called only for literals shorter than | 2705 // FastCloneShallowArrayStub is called only for literals shorter than |
2705 // JSObject::kInitialMaxFastElementArray and therefore the size of the | 2706 // JSObject::kInitialMaxFastElementArray. |
2706 // resulting folded allocation will always be in allowed range. | |
2707 // Can't add HBoundsCheck here because otherwise the stub will eager a frame. | 2707 // Can't add HBoundsCheck here because otherwise the stub will eager a frame. |
| 2708 HConstant* size_upper_bound = EstablishElementsAllocationSize( |
| 2709 kind, JSObject::kInitialMaxFastElementArray); |
| 2710 elements->set_size_upper_bound(size_upper_bound); |
2708 | 2711 |
2709 HValue* elements = NULL; | 2712 Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements); |
2710 HValue* result = BuildCloneShallowArrayCommon(boilerplate, | |
2711 allocation_site, extra, &elements, mode); | |
2712 Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), | |
2713 elements, INITIALIZING_STORE); | |
2714 | 2713 |
2715 // The allocation for the cloned array above causes register pressure on | 2714 // The allocation for the cloned array above causes register pressure on |
2716 // machines with low register counts. Force a reload of the boilerplate | 2715 // machines with low register counts. Force a reload of the boilerplate |
2717 // elements here to free up a register for the allocation to avoid unnecessary | 2716 // elements here to free up a register for the allocation to avoid unnecessary |
2718 // spillage. | 2717 // spillage. |
2719 boilerplate_elements = AddLoadElements(boilerplate); | 2718 boilerplate_elements = AddLoadElements(boilerplate); |
2720 boilerplate_elements->SetFlag(HValue::kCantBeReplaced); | 2719 boilerplate_elements->SetFlag(HValue::kCantBeReplaced); |
2721 | 2720 |
2722 // Copy the elements array header. | 2721 // Copy the elements array header. |
2723 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 2722 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
2724 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | 2723 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
2725 Add<HStoreNamedField>(elements, access, | 2724 Add<HStoreNamedField>(elements, access, |
2726 Add<HLoadNamedField>(boilerplate_elements, | 2725 Add<HLoadNamedField>(boilerplate_elements, |
2727 static_cast<HValue*>(NULL), access), | 2726 static_cast<HValue*>(NULL), access)); |
2728 INITIALIZING_STORE); | |
2729 } | 2727 } |
2730 | 2728 |
2731 // And the result of the length | 2729 // And the result of the length |
2732 HValue* length = Add<HLoadNamedField>(boilerplate, static_cast<HValue*>(NULL), | 2730 HValue* length = AddLoadArrayLength(boilerplate, kind); |
2733 HObjectAccess::ForArrayLength(kind)); | 2731 Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), length); |
2734 Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), | |
2735 length, INITIALIZING_STORE); | |
2736 | 2732 |
2737 BuildCopyElements(result, boilerplate_elements, kind, elements, | 2733 BuildCopyElements(boilerplate_elements, kind, elements, |
2738 kind, length, NULL); | 2734 kind, length, NULL); |
2739 | |
2740 return result; | 2735 return result; |
2741 } | 2736 } |
2742 | 2737 |
2743 | 2738 |
2744 void HGraphBuilder::BuildCompareNil( | 2739 void HGraphBuilder::BuildCompareNil( |
2745 HValue* value, | 2740 HValue* value, |
2746 Type* type, | 2741 Type* type, |
2747 HIfContinuation* continuation) { | 2742 HIfContinuation* continuation) { |
2748 IfBuilder if_nil(this); | 2743 IfBuilder if_nil(this); |
2749 bool some_case_handled = false; | 2744 bool some_case_handled = false; |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2924 | 2919 |
2925 | 2920 |
2926 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 2921 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
2927 // Find the map near the constructor function | 2922 // Find the map near the constructor function |
2928 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 2923 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
2929 return builder()->Add<HLoadNamedField>( | 2924 return builder()->Add<HLoadNamedField>( |
2930 constructor_function_, static_cast<HValue*>(NULL), access); | 2925 constructor_function_, static_cast<HValue*>(NULL), access); |
2931 } | 2926 } |
2932 | 2927 |
2933 | 2928 |
2934 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 2929 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { |
2935 HValue* length_node) { | |
2936 ASSERT(length_node != NULL); | |
2937 | |
2938 int base_size = JSArray::kSize; | |
2939 if (mode_ == TRACK_ALLOCATION_SITE) { | |
2940 base_size += AllocationMemento::kSize; | |
2941 } | |
2942 | |
2943 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); | |
2944 base_size += FixedArray::kHeaderSize; | |
2945 | |
2946 HInstruction* elements_size_value = | |
2947 builder()->Add<HConstant>(elements_size()); | |
2948 HInstruction* mul = HMul::NewImul(builder()->zone(), builder()->context(), | |
2949 length_node, elements_size_value); | |
2950 builder()->AddInstruction(mul); | |
2951 HInstruction* base = builder()->Add<HConstant>(base_size); | |
2952 HInstruction* total_size = HAdd::New(builder()->zone(), builder()->context(), | |
2953 base, mul); | |
2954 total_size->ClearFlag(HValue::kCanOverflow); | |
2955 builder()->AddInstruction(total_size); | |
2956 return total_size; | |
2957 } | |
2958 | |
2959 | |
2960 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { | |
2961 int base_size = JSArray::kSize; | |
2962 if (mode_ == TRACK_ALLOCATION_SITE) { | |
2963 base_size += AllocationMemento::kSize; | |
2964 } | |
2965 | |
2966 base_size += IsFastDoubleElementsKind(kind_) | |
2967 ? FixedDoubleArray::SizeFor(initial_capacity()) | |
2968 : FixedArray::SizeFor(initial_capacity()); | |
2969 | |
2970 return builder()->Add<HConstant>(base_size); | |
2971 } | |
2972 | |
2973 | |
2974 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { | |
2975 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); | |
2976 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); | 2930 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); |
2977 return AllocateArray(size_in_bytes, | 2931 return AllocateArray(capacity, |
2978 capacity, | 2932 capacity, |
2979 builder()->graph()->GetConstant0()); | 2933 builder()->graph()->GetConstant0()); |
2980 } | 2934 } |
2981 | 2935 |
2982 | 2936 |
2983 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, | 2937 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray( |
2984 HValue* length_field, | 2938 HValue* capacity, |
2985 FillMode fill_mode) { | 2939 HConstant* capacity_upper_bound, |
2986 HValue* size_in_bytes = EstablishAllocationSize(capacity); | 2940 HValue* length_field, |
2987 return AllocateArray(size_in_bytes, capacity, length_field, fill_mode); | 2941 FillMode fill_mode) { |
| 2942 return AllocateArray(capacity, |
| 2943 capacity_upper_bound->GetInteger32Constant(), |
| 2944 length_field, |
| 2945 fill_mode); |
2988 } | 2946 } |
2989 | 2947 |
2990 | 2948 |
2991 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, | 2949 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray( |
2992 HValue* capacity, | 2950 HValue* capacity, |
2993 HValue* length_field, | 2951 int capacity_upper_bound, |
2994 FillMode fill_mode) { | 2952 HValue* length_field, |
| 2953 FillMode fill_mode) { |
| 2954 HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant() |
| 2955 ? HConstant::cast(capacity) |
| 2956 : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound); |
| 2957 |
| 2958 HAllocate* array = AllocateArray(capacity, length_field, fill_mode); |
| 2959 if (!elements_location_->has_size_upper_bound()) { |
| 2960 elements_location_->set_size_upper_bound(elememts_size_upper_bound); |
| 2961 } |
| 2962 return array; |
| 2963 } |
| 2964 |
| 2965 |
| 2966 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray( |
| 2967 HValue* capacity, |
| 2968 HValue* length_field, |
| 2969 FillMode fill_mode) { |
2995 // These HForceRepresentations are because we store these as fields in the | 2970 // These HForceRepresentations are because we store these as fields in the |
2996 // objects we construct, and an int32-to-smi HChange could deopt. Accept | 2971 // objects we construct, and an int32-to-smi HChange could deopt. Accept |
2997 // the deopt possibility now, before allocation occurs. | 2972 // the deopt possibility now, before allocation occurs. |
2998 capacity = | 2973 capacity = |
2999 builder()->AddUncasted<HForceRepresentation>(capacity, | 2974 builder()->AddUncasted<HForceRepresentation>(capacity, |
3000 Representation::Smi()); | 2975 Representation::Smi()); |
3001 length_field = | 2976 length_field = |
3002 builder()->AddUncasted<HForceRepresentation>(length_field, | 2977 builder()->AddUncasted<HForceRepresentation>(length_field, |
3003 Representation::Smi()); | 2978 Representation::Smi()); |
| 2979 |
| 2980 // Generate size calculation code here in order to make it dominate |
| 2981 // the JSArray allocation. |
| 2982 HValue* elements_size = |
| 2983 builder()->BuildCalculateElementsSize(kind_, capacity); |
| 2984 |
3004 // Allocate (dealing with failure appropriately) | 2985 // Allocate (dealing with failure appropriately) |
3005 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, | 2986 HAllocate* array_object = builder()->AllocateJSArrayObject(mode_); |
3006 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); | |
3007 | |
3008 // Folded array allocation should be aligned if it has fast double elements. | |
3009 if (IsFastDoubleElementsKind(kind_)) { | |
3010 new_object->MakeDoubleAligned(); | |
3011 } | |
3012 | 2987 |
3013 // Fill in the fields: map, properties, length | 2988 // Fill in the fields: map, properties, length |
3014 HValue* map; | 2989 HValue* map; |
3015 if (allocation_site_payload_ == NULL) { | 2990 if (allocation_site_payload_ == NULL) { |
3016 map = EmitInternalMapCode(); | 2991 map = EmitInternalMapCode(); |
3017 } else { | 2992 } else { |
3018 map = EmitMapCode(); | 2993 map = EmitMapCode(); |
3019 } | 2994 } |
3020 elements_location_ = builder()->BuildJSArrayHeader(new_object, | |
3021 map, | |
3022 mode_, | |
3023 kind_, | |
3024 allocation_site_payload_, | |
3025 length_field); | |
3026 | 2995 |
3027 // Initialize the elements | 2996 builder()->BuildJSArrayHeader(array_object, |
| 2997 map, |
| 2998 NULL, // set elements to empty fixed array |
| 2999 mode_, |
| 3000 kind_, |
| 3001 allocation_site_payload_, |
| 3002 length_field); |
| 3003 |
| 3004 // Allocate and initialize the elements |
| 3005 elements_location_ = builder()->BuildAllocateElements(kind_, elements_size); |
| 3006 |
3028 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); | 3007 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); |
3029 | 3008 |
| 3009 // Set the elements |
| 3010 builder()->Add<HStoreNamedField>( |
| 3011 array_object, HObjectAccess::ForElementsPointer(), elements_location_); |
| 3012 |
3030 if (fill_mode == FILL_WITH_HOLE) { | 3013 if (fill_mode == FILL_WITH_HOLE) { |
3031 builder()->BuildFillElementsWithHole(elements_location_, kind_, | 3014 builder()->BuildFillElementsWithHole(elements_location_, kind_, |
3032 graph()->GetConstant0(), capacity); | 3015 graph()->GetConstant0(), capacity); |
3033 } | 3016 } |
3034 | 3017 |
3035 return new_object; | 3018 return array_object; |
3036 } | 3019 } |
3037 | 3020 |
3038 | 3021 |
3039 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) { | 3022 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) { |
3040 HValue* global_object = Add<HLoadNamedField>( | 3023 HValue* global_object = Add<HLoadNamedField>( |
3041 context(), static_cast<HValue*>(NULL), | 3024 context(), static_cast<HValue*>(NULL), |
3042 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 3025 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
3043 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset( | 3026 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset( |
3044 GlobalObject::kBuiltinsOffset); | 3027 GlobalObject::kBuiltinsOffset); |
3045 HValue* builtins = Add<HLoadNamedField>( | 3028 HValue* builtins = Add<HLoadNamedField>( |
(...skipping 7194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10240 HInstruction* object = Add<HAllocate>(object_size_constant, type, | 10223 HInstruction* object = Add<HAllocate>(object_size_constant, type, |
10241 pretenure_flag, instance_type, site_context->current()); | 10224 pretenure_flag, instance_type, site_context->current()); |
10242 | 10225 |
10243 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the | 10226 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the |
10244 // elements array may not get folded into the object. Hence, we set the | 10227 // elements array may not get folded into the object. Hence, we set the |
10245 // elements pointer to empty fixed array and let store elimination remove | 10228 // elements pointer to empty fixed array and let store elimination remove |
10246 // this store in the folding case. | 10229 // this store in the folding case. |
10247 HConstant* empty_fixed_array = Add<HConstant>( | 10230 HConstant* empty_fixed_array = Add<HConstant>( |
10248 isolate()->factory()->empty_fixed_array()); | 10231 isolate()->factory()->empty_fixed_array()); |
10249 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 10232 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
10250 empty_fixed_array, INITIALIZING_STORE); | 10233 empty_fixed_array); |
10251 | 10234 |
10252 BuildEmitObjectHeader(boilerplate_object, object); | 10235 BuildEmitObjectHeader(boilerplate_object, object); |
10253 | 10236 |
10254 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 10237 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
10255 int elements_size = (elements->length() > 0 && | 10238 int elements_size = (elements->length() > 0 && |
10256 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 10239 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
10257 elements->Size() : 0; | 10240 elements->Size() : 0; |
10258 | 10241 |
10259 if (pretenure_flag == TENURED && | 10242 if (pretenure_flag == TENURED && |
10260 elements->map() == isolate()->heap()->fixed_cow_array_map() && | 10243 elements->map() == isolate()->heap()->fixed_cow_array_map() && |
(...skipping 1527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11788 if (ShouldProduceTraceOutput()) { | 11771 if (ShouldProduceTraceOutput()) { |
11789 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11772 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11790 } | 11773 } |
11791 | 11774 |
11792 #ifdef DEBUG | 11775 #ifdef DEBUG |
11793 graph_->Verify(false); // No full verify. | 11776 graph_->Verify(false); // No full verify. |
11794 #endif | 11777 #endif |
11795 } | 11778 } |
11796 | 11779 |
11797 } } // namespace v8::internal | 11780 } } // namespace v8::internal |
OLD | NEW |