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 2370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2381 elements, checked_key, dependency, elements_kind, load_mode); | 2381 elements, checked_key, dependency, elements_kind, load_mode); |
2382 if (FLAG_opt_safe_uint32_operations && | 2382 if (FLAG_opt_safe_uint32_operations && |
2383 (elements_kind == EXTERNAL_UINT32_ELEMENTS || | 2383 (elements_kind == EXTERNAL_UINT32_ELEMENTS || |
2384 elements_kind == UINT32_ELEMENTS)) { | 2384 elements_kind == UINT32_ELEMENTS)) { |
2385 graph()->RecordUint32Instruction(load); | 2385 graph()->RecordUint32Instruction(load); |
2386 } | 2386 } |
2387 return load; | 2387 return load; |
2388 } | 2388 } |
2389 | 2389 |
2390 | 2390 |
2391 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 2391 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) { |
2392 HValue* dependency) { | |
2393 return Add<HLoadNamedField>( | 2392 return Add<HLoadNamedField>( |
2394 object, dependency, HObjectAccess::ForElementsPointer()); | 2393 object, static_cast<HValue*>(NULL), HObjectAccess::ForElementsPointer()); |
2395 } | 2394 } |
2396 | 2395 |
2397 | 2396 |
2398 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength( | 2397 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
2399 HValue* array, | |
2400 HValue* dependency) { | |
2401 return Add<HLoadNamedField>( | 2398 return Add<HLoadNamedField>( |
2402 array, dependency, HObjectAccess::ForFixedArrayLength()); | 2399 object, static_cast<HValue*>(NULL), HObjectAccess::ForFixedArrayLength()); |
2403 } | 2400 } |
2404 | 2401 |
2405 | 2402 |
2406 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array, | |
2407 ElementsKind kind, | |
2408 HValue* dependency) { | |
2409 return Add<HLoadNamedField>( | |
2410 array, dependency, HObjectAccess::ForArrayLength(kind)); | |
2411 } | |
2412 | |
2413 | |
2414 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { | 2403 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { |
2415 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity, | 2404 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity, |
2416 graph_->GetConstant1()); | 2405 graph_->GetConstant1()); |
2417 | 2406 |
2418 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity); | 2407 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity); |
2419 new_capacity->ClearFlag(HValue::kCanOverflow); | 2408 new_capacity->ClearFlag(HValue::kCanOverflow); |
2420 | 2409 |
2421 HValue* min_growth = Add<HConstant>(16); | 2410 HValue* min_growth = Add<HConstant>(16); |
2422 | 2411 |
2423 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth); | 2412 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth); |
2424 new_capacity->ClearFlag(HValue::kCanOverflow); | 2413 new_capacity->ClearFlag(HValue::kCanOverflow); |
2425 | 2414 |
2426 return new_capacity; | 2415 return new_capacity; |
2427 } | 2416 } |
2428 | 2417 |
2429 | 2418 |
2430 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 2419 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
2431 HValue* elements, | 2420 HValue* elements, |
2432 ElementsKind kind, | 2421 ElementsKind kind, |
2433 ElementsKind new_kind, | 2422 ElementsKind new_kind, |
2434 HValue* length, | 2423 HValue* length, |
2435 HValue* new_capacity) { | 2424 HValue* new_capacity) { |
2436 Add<HBoundsCheck>(new_capacity, Add<HConstant>( | 2425 Add<HBoundsCheck>(new_capacity, Add<HConstant>( |
2437 (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> | 2426 (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> |
2438 ElementsKindToShiftSize(kind))); | 2427 ElementsKindToShiftSize(kind))); |
2439 | 2428 |
2440 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 2429 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
2441 new_kind, new_capacity); | 2430 new_kind, new_capacity); |
2442 | 2431 |
2443 BuildCopyElements(object, elements, kind, new_elements, | 2432 BuildCopyElements(elements, kind, |
2444 new_kind, length, new_capacity); | 2433 new_elements, new_kind, |
| 2434 length, new_capacity); |
2445 | 2435 |
2446 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 2436 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
2447 new_elements); | 2437 new_elements); |
2448 | 2438 |
2449 return new_elements; | 2439 return new_elements; |
2450 } | 2440 } |
2451 | 2441 |
2452 | 2442 |
2453 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, | 2443 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, |
2454 ElementsKind elements_kind, | 2444 ElementsKind elements_kind, |
2455 HValue* from, | 2445 HValue* from, |
2456 HValue* to) { | 2446 HValue* to) { |
2457 // Fast elements kinds need to be initialized in case statements below cause a | 2447 // Fast elements kinds need to be initialized in case statements below cause |
2458 // garbage collection. | 2448 // a garbage collection. |
2459 Factory* factory = isolate()->factory(); | 2449 Factory* factory = isolate()->factory(); |
2460 | 2450 |
2461 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 2451 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
2462 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 2452 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
2463 ? Add<HConstant>(factory->the_hole_value()) | 2453 ? Add<HConstant>(factory->the_hole_value()) |
2464 : Add<HConstant>(nan_double); | 2454 : Add<HConstant>(nan_double); |
2465 | 2455 |
2466 if (to == NULL) { | |
2467 to = AddLoadFixedArrayLength(elements); | |
2468 } | |
2469 | |
2470 // Special loop unfolding case | 2456 // Special loop unfolding case |
2471 static const int kLoopUnfoldLimit = 8; | 2457 static const int kLoopUnfoldLimit = 8; |
2472 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); | 2458 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); |
2473 int initial_capacity = -1; | 2459 int initial_capacity = -1; |
2474 if (from->IsInteger32Constant() && to->IsInteger32Constant()) { | 2460 if (from->IsInteger32Constant() && to->IsInteger32Constant()) { |
2475 int constant_from = from->GetInteger32Constant(); | 2461 int constant_from = from->GetInteger32Constant(); |
2476 int constant_to = to->GetInteger32Constant(); | 2462 int constant_to = to->GetInteger32Constant(); |
2477 | 2463 |
2478 if (constant_from == 0 && constant_to <= kLoopUnfoldLimit) { | 2464 if (constant_from == 0 && constant_to <= kLoopUnfoldLimit) { |
2479 initial_capacity = constant_to; | 2465 initial_capacity = constant_to; |
2480 } | 2466 } |
2481 } | 2467 } |
2482 | 2468 |
2483 // Since we're about to store a hole value, the store instruction below must | 2469 // Since we're about to store a hole value, the store instruction below must |
2484 // assume an elements kind that supports heap object values. | 2470 // assume an elements kind that supports heap object values. |
2485 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 2471 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
2486 elements_kind = FAST_HOLEY_ELEMENTS; | 2472 elements_kind = FAST_HOLEY_ELEMENTS; |
2487 } | 2473 } |
2488 | 2474 |
2489 if (initial_capacity >= 0) { | 2475 if (initial_capacity >= 0) { |
2490 for (int i = 0; i < initial_capacity; i++) { | 2476 for (int i = 0; i < initial_capacity; i++) { |
2491 HInstruction* key = Add<HConstant>(i); | 2477 HInstruction* key = Add<HConstant>(i); |
2492 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 2478 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
2493 } | 2479 } |
2494 } else { | 2480 } else { |
2495 // Carefully loop backwards so that the "from" remains live through the loop | 2481 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
2496 // rather than the to. This often corresponds to keeping length live rather | |
2497 // then capacity, which helps register allocation, since length is used more | |
2498 // other than capacity after filling with holes. | |
2499 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); | |
2500 | 2482 |
2501 HValue* key = builder.BeginBody(to, from, Token::GT); | 2483 HValue* key = builder.BeginBody(from, to, Token::LT); |
2502 | 2484 |
2503 HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1()); | 2485 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
2504 adjusted_key->ClearFlag(HValue::kCanOverflow); | |
2505 | |
2506 Add<HStoreKeyed>(elements, adjusted_key, hole, elements_kind); | |
2507 | 2486 |
2508 builder.EndBody(); | 2487 builder.EndBody(); |
2509 } | 2488 } |
2510 } | 2489 } |
2511 | 2490 |
2512 | 2491 |
2513 void HGraphBuilder::BuildCopyElements(HValue* array, | 2492 void HGraphBuilder::BuildCopyElements(HValue* from_elements, |
2514 HValue* from_elements, | |
2515 ElementsKind from_elements_kind, | 2493 ElementsKind from_elements_kind, |
2516 HValue* to_elements, | 2494 HValue* to_elements, |
2517 ElementsKind to_elements_kind, | 2495 ElementsKind to_elements_kind, |
2518 HValue* length, | 2496 HValue* length, |
2519 HValue* capacity) { | 2497 HValue* capacity) { |
2520 int constant_capacity = -1; | 2498 bool pre_fill_with_holes = |
2521 if (capacity != NULL && | |
2522 capacity->IsConstant() && | |
2523 HConstant::cast(capacity)->HasInteger32Value()) { | |
2524 int constant_candidate = HConstant::cast(capacity)->Integer32Value(); | |
2525 if (constant_candidate <= | |
2526 FastCloneShallowArrayStub::kMaximumInlinedCloneLength) { | |
2527 constant_capacity = constant_candidate; | |
2528 } | |
2529 } | |
2530 | |
2531 if (constant_capacity != -1) { | |
2532 // Unroll the loop for small elements kinds. | |
2533 for (int i = 0; i < constant_capacity; i++) { | |
2534 HValue* key_constant = Add<HConstant>(i); | |
2535 HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant, | |
2536 static_cast<HValue*>(NULL), | |
2537 from_elements_kind); | |
2538 Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind); | |
2539 } | |
2540 } else { | |
2541 bool pre_fill_with_holes = | |
2542 IsFastDoubleElementsKind(from_elements_kind) && | 2499 IsFastDoubleElementsKind(from_elements_kind) && |
2543 IsFastObjectElementsKind(to_elements_kind); | 2500 IsFastObjectElementsKind(to_elements_kind); |
2544 | 2501 |
2545 if (pre_fill_with_holes) { | 2502 if (pre_fill_with_holes) { |
2546 // If the copy might trigger a GC, make sure that the FixedArray is | 2503 // If the copy might trigger a GC, make sure that the FixedArray is |
2547 // pre-initialized with holes to make sure that it's always in a | 2504 // pre-initialized with holes to make sure that it's always in a consistent |
2548 // consistent state. | 2505 // state. |
2549 BuildFillElementsWithHole(to_elements, to_elements_kind, | 2506 BuildFillElementsWithHole(to_elements, to_elements_kind, |
2550 graph()->GetConstant0(), NULL); | 2507 graph()->GetConstant0(), capacity); |
2551 } else if (capacity == NULL || !length->Equals(capacity)) { | 2508 } |
2552 BuildFillElementsWithHole(to_elements, to_elements_kind, | |
2553 length, NULL); | |
2554 } | |
2555 | 2509 |
2556 if (capacity == NULL) { | 2510 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
2557 capacity = AddLoadFixedArrayLength(to_elements); | |
2558 } | |
2559 | 2511 |
2560 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); | 2512 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); |
2561 | 2513 |
2562 HValue* key = builder.BeginBody(length, graph()->GetConstant0(), | 2514 HValue* element = Add<HLoadKeyed>(from_elements, key, |
2563 Token::GT); | 2515 static_cast<HValue*>(NULL), |
| 2516 from_elements_kind, |
| 2517 ALLOW_RETURN_HOLE); |
2564 | 2518 |
2565 key = AddUncasted<HSub>(key, graph()->GetConstant1()); | 2519 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && |
2566 key->ClearFlag(HValue::kCanOverflow); | 2520 IsFastSmiElementsKind(to_elements_kind)) |
2567 | |
2568 HValue* element = Add<HLoadKeyed>(from_elements, key, | |
2569 static_cast<HValue*>(NULL), | |
2570 from_elements_kind, | |
2571 ALLOW_RETURN_HOLE); | |
2572 | |
2573 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && | |
2574 IsFastSmiElementsKind(to_elements_kind)) | |
2575 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 2521 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
2576 | 2522 |
2577 if (IsHoleyElementsKind(from_elements_kind) && | 2523 if (IsHoleyElementsKind(from_elements_kind) && |
2578 from_elements_kind != to_elements_kind) { | 2524 from_elements_kind != to_elements_kind) { |
2579 IfBuilder if_hole(this); | 2525 IfBuilder if_hole(this); |
2580 if_hole.If<HCompareHoleAndBranch>(element); | 2526 if_hole.If<HCompareHoleAndBranch>(element); |
2581 if_hole.Then(); | 2527 if_hole.Then(); |
2582 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) | 2528 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) |
2583 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) | 2529 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) |
2584 : graph()->GetConstantHole(); | 2530 : graph()->GetConstantHole(); |
2585 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); | 2531 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); |
2586 if_hole.Else(); | 2532 if_hole.Else(); |
2587 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | 2533 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
2588 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2534 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
2589 if_hole.End(); | 2535 if_hole.End(); |
2590 } else { | 2536 } else { |
2591 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | 2537 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
2592 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2538 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
2593 } | |
2594 | |
2595 builder.EndBody(); | |
2596 } | 2539 } |
2597 | 2540 |
2598 Counters* counters = isolate()->counters(); | 2541 builder.EndBody(); |
2599 AddIncrementCounter(counters->inlined_copied_elements()); | 2542 |
| 2543 if (!pre_fill_with_holes && length != capacity) { |
| 2544 // Fill unused capacity with the hole. |
| 2545 BuildFillElementsWithHole(to_elements, to_elements_kind, |
| 2546 key, capacity); |
| 2547 } |
2600 } | 2548 } |
2601 | 2549 |
2602 HValue* HGraphBuilder::BuildCloneShallowArrayCommon( | 2550 |
2603 HValue* boilerplate, | 2551 HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, |
2604 HValue* allocation_site, | 2552 HValue* allocation_site, |
2605 HValue* extra_size, | 2553 AllocationSiteMode mode, |
2606 HValue** return_elements, | 2554 ElementsKind kind, |
2607 AllocationSiteMode mode) { | 2555 int length) { |
| 2556 NoObservableSideEffectsScope no_effects(this); |
| 2557 |
2608 // All sizes here are multiples of kPointerSize. | 2558 // All sizes here are multiples of kPointerSize. |
2609 int array_size = JSArray::kSize; | 2559 int size = JSArray::kSize; |
2610 if (mode == TRACK_ALLOCATION_SITE) { | 2560 if (mode == TRACK_ALLOCATION_SITE) { |
2611 array_size += AllocationMemento::kSize; | 2561 size += AllocationMemento::kSize; |
2612 } | 2562 } |
2613 | 2563 |
2614 HValue* size_in_bytes = Add<HConstant>(array_size); | 2564 HValue* size_in_bytes = Add<HConstant>(size); |
2615 if (extra_size != NULL) { | |
2616 size_in_bytes = AddUncasted<HAdd>(extra_size, size_in_bytes); | |
2617 size_in_bytes->ClearFlag(HValue::kCanOverflow); | |
2618 } | |
2619 | |
2620 HInstruction* object = Add<HAllocate>(size_in_bytes, | 2565 HInstruction* object = Add<HAllocate>(size_in_bytes, |
2621 HType::JSObject(), | 2566 HType::JSObject(), |
2622 NOT_TENURED, | 2567 NOT_TENURED, |
2623 JS_OBJECT_TYPE); | 2568 JS_OBJECT_TYPE); |
2624 | 2569 |
2625 // Copy the JS array part. | 2570 // Copy the JS array part. |
2626 HValue* map = Add<HLoadNamedField>(boilerplate, | 2571 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
2627 static_cast<HValue*>(NULL), HObjectAccess::ForMap()); | 2572 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
2628 Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(), | 2573 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
2629 Add<HConstant>(isolate()->factory()->empty_fixed_array()), | 2574 Add<HStoreNamedField>( |
2630 INITIALIZING_STORE); | 2575 object, access, Add<HLoadNamedField>( |
2631 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map, | 2576 boilerplate, static_cast<HValue*>(NULL), access)); |
2632 INITIALIZING_STORE); | 2577 } |
| 2578 } |
2633 | 2579 |
2634 // Create an allocation site info if requested. | 2580 // Create an allocation site info if requested. |
2635 if (mode == TRACK_ALLOCATION_SITE) { | 2581 if (mode == TRACK_ALLOCATION_SITE) { |
2636 BuildCreateAllocationMemento( | 2582 BuildCreateAllocationMemento( |
2637 object, Add<HConstant>(JSArray::kSize), allocation_site); | 2583 object, Add<HConstant>(JSArray::kSize), allocation_site); |
2638 } | 2584 } |
2639 | 2585 |
2640 if (extra_size != NULL) { | 2586 if (length > 0) { |
2641 HValue* elements = Add<HInnerAllocatedObject>(object, | 2587 // We have to initialize the elements pointer if allocation folding is |
2642 Add<HConstant>(array_size)); | 2588 // turned off. |
2643 if (return_elements != NULL) *return_elements = elements; | 2589 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { |
| 2590 HConstant* empty_fixed_array = Add<HConstant>( |
| 2591 isolate()->factory()->empty_fixed_array()); |
| 2592 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 2593 empty_fixed_array, INITIALIZING_STORE); |
| 2594 } |
| 2595 |
| 2596 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 2597 HValue* object_elements; |
| 2598 if (IsFastDoubleElementsKind(kind)) { |
| 2599 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); |
| 2600 object_elements = Add<HAllocate>(elems_size, HType::Tagged(), |
| 2601 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); |
| 2602 } else { |
| 2603 HValue* elems_size = Add<HConstant>(FixedArray::SizeFor(length)); |
| 2604 object_elements = Add<HAllocate>(elems_size, HType::Tagged(), |
| 2605 NOT_TENURED, FIXED_ARRAY_TYPE); |
| 2606 } |
| 2607 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 2608 object_elements); |
| 2609 |
| 2610 // Copy the elements array header. |
| 2611 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
| 2612 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
| 2613 Add<HStoreNamedField>( |
| 2614 object_elements, access, Add<HLoadNamedField>( |
| 2615 boilerplate_elements, static_cast<HValue*>(NULL), access)); |
| 2616 } |
| 2617 |
| 2618 // Copy the elements array contents. |
| 2619 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold |
| 2620 // copying loops with constant length up to a given boundary and use this |
| 2621 // helper here instead. |
| 2622 for (int i = 0; i < length; i++) { |
| 2623 HValue* key_constant = Add<HConstant>(i); |
| 2624 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, |
| 2625 static_cast<HValue*>(NULL), kind); |
| 2626 Add<HStoreKeyed>(object_elements, key_constant, value, kind); |
| 2627 } |
2644 } | 2628 } |
2645 | 2629 |
2646 return object; | 2630 return object; |
2647 } | 2631 } |
2648 | 2632 |
2649 | 2633 |
2650 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate, | |
2651 HValue* allocation_site, | |
2652 AllocationSiteMode mode, | |
2653 ElementsKind kind) { | |
2654 HValue* result = BuildCloneShallowArrayCommon(boilerplate, | |
2655 allocation_site, NULL, NULL, mode); | |
2656 | |
2657 HValue* elements = AddLoadElements(boilerplate); | |
2658 HObjectAccess access = HObjectAccess::ForElementsPointer(); | |
2659 Add<HStoreNamedField>(result, access, elements, INITIALIZING_STORE); | |
2660 | |
2661 HValue* length = AddLoadArrayLength(boilerplate, kind); | |
2662 access = HObjectAccess::ForArrayLength(kind); | |
2663 Add<HStoreNamedField>(result, access, length, INITIALIZING_STORE); | |
2664 | |
2665 return result; | |
2666 } | |
2667 | |
2668 | |
2669 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate, | |
2670 HValue* allocation_site, | |
2671 AllocationSiteMode mode) { | |
2672 HValue* result = BuildCloneShallowArrayCommon(boilerplate, | |
2673 allocation_site, NULL, NULL, mode); | |
2674 | |
2675 HObjectAccess access = HObjectAccess::ForArrayLength(FAST_ELEMENTS); | |
2676 Add<HStoreNamedField>(result, access, graph()->GetConstant0(), | |
2677 INITIALIZING_STORE); | |
2678 access = HObjectAccess::ForElementsPointer(); | |
2679 Add<HStoreNamedField>(result, access, | |
2680 Add<HConstant>(isolate()->factory()->empty_fixed_array()), | |
2681 INITIALIZING_STORE); | |
2682 | |
2683 return result; | |
2684 } | |
2685 | |
2686 | |
2687 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate, | |
2688 HValue* allocation_site, | |
2689 AllocationSiteMode mode, | |
2690 ElementsKind kind) { | |
2691 int elements_kind_size = IsFastDoubleElementsKind(kind) | |
2692 ? kDoubleSize : kPointerSize; | |
2693 | |
2694 HValue* boilerplate_elements = AddLoadElements(boilerplate); | |
2695 HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements); | |
2696 HValue* extra = AddUncasted<HMul>(capacity, | |
2697 Add<HConstant>(elements_kind_size)); | |
2698 extra->ClearFlag(HValue::kCanOverflow); | |
2699 extra = AddUncasted<HAdd>(extra, Add<HConstant>(FixedArray::kHeaderSize)); | |
2700 extra->ClearFlag(HValue::kCanOverflow); | |
2701 HValue* elements = NULL; | |
2702 HValue* result = BuildCloneShallowArrayCommon(boilerplate, | |
2703 allocation_site, extra, &elements, mode); | |
2704 Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), | |
2705 elements, INITIALIZING_STORE); | |
2706 | |
2707 // The allocation for the cloned array above causes register pressure on | |
2708 // machines with low register counts. Force a reload of the boilerplate | |
2709 // elements here to free up a register for the allocation to avoid unnecessary | |
2710 // spillage. | |
2711 boilerplate_elements = AddLoadElements(boilerplate); | |
2712 boilerplate_elements->SetFlag(HValue::kCantBeReplaced); | |
2713 | |
2714 // Copy the elements array header. | |
2715 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | |
2716 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | |
2717 Add<HStoreNamedField>(elements, access, | |
2718 Add<HLoadNamedField>(boilerplate_elements, | |
2719 static_cast<HValue*>(NULL), access), | |
2720 INITIALIZING_STORE); | |
2721 } | |
2722 | |
2723 // And the result of the length | |
2724 HValue* length = Add<HLoadNamedField>(boilerplate, static_cast<HValue*>(NULL), | |
2725 HObjectAccess::ForArrayLength(kind)); | |
2726 Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), | |
2727 length, INITIALIZING_STORE); | |
2728 | |
2729 BuildCopyElements(result, boilerplate_elements, kind, elements, | |
2730 kind, length, NULL); | |
2731 | |
2732 return result; | |
2733 } | |
2734 | |
2735 | |
2736 void HGraphBuilder::BuildCompareNil( | 2634 void HGraphBuilder::BuildCompareNil( |
2737 HValue* value, | 2635 HValue* value, |
2738 Type* type, | 2636 Type* type, |
2739 HIfContinuation* continuation) { | 2637 HIfContinuation* continuation) { |
2740 IfBuilder if_nil(this); | 2638 IfBuilder if_nil(this); |
2741 bool some_case_handled = false; | 2639 bool some_case_handled = false; |
2742 bool some_case_missing = false; | 2640 bool some_case_missing = false; |
2743 | 2641 |
2744 if (type->Maybe(Type::Null())) { | 2642 if (type->Maybe(Type::Null())) { |
2745 if (some_case_handled) if_nil.Or(); | 2643 if (some_case_handled) if_nil.Or(); |
(...skipping 9051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11797 if (ShouldProduceTraceOutput()) { | 11695 if (ShouldProduceTraceOutput()) { |
11798 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11696 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11799 } | 11697 } |
11800 | 11698 |
11801 #ifdef DEBUG | 11699 #ifdef DEBUG |
11802 graph_->Verify(false); // No full verify. | 11700 graph_->Verify(false); // No full verify. |
11803 #endif | 11701 #endif |
11804 } | 11702 } |
11805 | 11703 |
11806 } } // namespace v8::internal | 11704 } } // namespace v8::internal |
OLD | NEW |