OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2407 elements, checked_key, dependency, elements_kind, load_mode); | 2407 elements, checked_key, dependency, elements_kind, load_mode); |
2408 if (FLAG_opt_safe_uint32_operations && | 2408 if (FLAG_opt_safe_uint32_operations && |
2409 (elements_kind == EXTERNAL_UINT32_ELEMENTS || | 2409 (elements_kind == EXTERNAL_UINT32_ELEMENTS || |
2410 elements_kind == UINT32_ELEMENTS)) { | 2410 elements_kind == UINT32_ELEMENTS)) { |
2411 graph()->RecordUint32Instruction(load); | 2411 graph()->RecordUint32Instruction(load); |
2412 } | 2412 } |
2413 return load; | 2413 return load; |
2414 } | 2414 } |
2415 | 2415 |
2416 | 2416 |
2417 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) { | 2417 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
| 2418 HValue* dependency) { |
2418 return Add<HLoadNamedField>( | 2419 return Add<HLoadNamedField>( |
2419 object, static_cast<HValue*>(NULL), HObjectAccess::ForElementsPointer()); | 2420 object, dependency, HObjectAccess::ForElementsPointer()); |
2420 } | 2421 } |
2421 | 2422 |
2422 | 2423 |
2423 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { | 2424 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength( |
| 2425 HValue* array, |
| 2426 HValue* dependency) { |
2424 return Add<HLoadNamedField>( | 2427 return Add<HLoadNamedField>( |
2425 object, static_cast<HValue*>(NULL), HObjectAccess::ForFixedArrayLength()); | 2428 array, dependency, HObjectAccess::ForFixedArrayLength()); |
2426 } | 2429 } |
2427 | 2430 |
2428 | 2431 |
| 2432 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array, |
| 2433 ElementsKind kind, |
| 2434 HValue* dependency) { |
| 2435 return Add<HLoadNamedField>( |
| 2436 array, dependency, HObjectAccess::ForArrayLength(kind)); |
| 2437 } |
| 2438 |
| 2439 |
2429 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { | 2440 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { |
2430 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity, | 2441 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity, |
2431 graph_->GetConstant1()); | 2442 graph_->GetConstant1()); |
2432 | 2443 |
2433 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity); | 2444 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity); |
2434 new_capacity->ClearFlag(HValue::kCanOverflow); | 2445 new_capacity->ClearFlag(HValue::kCanOverflow); |
2435 | 2446 |
2436 HValue* min_growth = Add<HConstant>(16); | 2447 HValue* min_growth = Add<HConstant>(16); |
2437 | 2448 |
2438 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth); | 2449 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth); |
(...skipping 17 matching lines...) Expand all Loading... |
2456 HValue* elements, | 2467 HValue* elements, |
2457 ElementsKind kind, | 2468 ElementsKind kind, |
2458 ElementsKind new_kind, | 2469 ElementsKind new_kind, |
2459 HValue* length, | 2470 HValue* length, |
2460 HValue* new_capacity) { | 2471 HValue* new_capacity) { |
2461 BuildNewSpaceArrayCheck(new_capacity, new_kind); | 2472 BuildNewSpaceArrayCheck(new_capacity, new_kind); |
2462 | 2473 |
2463 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 2474 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
2464 new_kind, new_capacity); | 2475 new_kind, new_capacity); |
2465 | 2476 |
2466 BuildCopyElements(elements, kind, | 2477 BuildCopyElements(object, elements, kind, new_elements, |
2467 new_elements, new_kind, | 2478 new_kind, length, new_capacity); |
2468 length, new_capacity); | |
2469 | 2479 |
2470 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 2480 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
2471 new_elements); | 2481 new_elements); |
2472 | 2482 |
2473 return new_elements; | 2483 return new_elements; |
2474 } | 2484 } |
2475 | 2485 |
2476 | 2486 |
2477 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, | 2487 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, |
2478 ElementsKind elements_kind, | 2488 ElementsKind elements_kind, |
2479 HValue* from, | 2489 HValue* from, |
2480 HValue* to) { | 2490 HValue* to) { |
2481 // Fast elements kinds need to be initialized in case statements below cause | 2491 // Fast elements kinds need to be initialized in case statements below cause a |
2482 // a garbage collection. | 2492 // garbage collection. |
2483 Factory* factory = isolate()->factory(); | 2493 Factory* factory = isolate()->factory(); |
2484 | 2494 |
2485 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 2495 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
2486 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 2496 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
2487 ? Add<HConstant>(factory->the_hole_value()) | 2497 ? Add<HConstant>(factory->the_hole_value()) |
2488 : Add<HConstant>(nan_double); | 2498 : Add<HConstant>(nan_double); |
2489 | 2499 |
2490 // Special loop unfolding case | 2500 // Special loop unfolding case |
2491 static const int kLoopUnfoldLimit = 8; | 2501 static const int kLoopUnfoldLimit = 8; |
2492 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); | 2502 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); |
(...skipping 23 matching lines...) Expand all Loading... |
2516 | 2526 |
2517 HValue* key = builder.BeginBody(from, to, Token::LT); | 2527 HValue* key = builder.BeginBody(from, to, Token::LT); |
2518 | 2528 |
2519 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 2529 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
2520 | 2530 |
2521 builder.EndBody(); | 2531 builder.EndBody(); |
2522 } | 2532 } |
2523 } | 2533 } |
2524 | 2534 |
2525 | 2535 |
2526 void HGraphBuilder::BuildCopyElements(HValue* from_elements, | 2536 void HGraphBuilder::BuildCopyElements(HValue* array, |
| 2537 HValue* from_elements, |
2527 ElementsKind from_elements_kind, | 2538 ElementsKind from_elements_kind, |
2528 HValue* to_elements, | 2539 HValue* to_elements, |
2529 ElementsKind to_elements_kind, | 2540 ElementsKind to_elements_kind, |
2530 HValue* length, | 2541 HValue* length, |
2531 HValue* capacity) { | 2542 HValue* capacity) { |
2532 bool pre_fill_with_holes = | 2543 int constant_capacity = -1; |
| 2544 if (capacity->IsConstant() && |
| 2545 HConstant::cast(capacity)->HasInteger32Value()) { |
| 2546 int constant_candidate = HConstant::cast(capacity)->Integer32Value(); |
| 2547 if (constant_candidate <= |
| 2548 FastCloneShallowArrayStub::kMaximumInlinedCloneLength) { |
| 2549 constant_capacity = constant_candidate; |
| 2550 } |
| 2551 } |
| 2552 |
| 2553 if (constant_capacity != -1) { |
| 2554 // Unroll the loop for small elements kinds. |
| 2555 for (int i = 0; i < constant_capacity; i++) { |
| 2556 HValue* key_constant = Add<HConstant>(i); |
| 2557 HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant, |
| 2558 static_cast<HValue*>(NULL), |
| 2559 from_elements_kind); |
| 2560 Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind); |
| 2561 } |
| 2562 } else { |
| 2563 bool pre_fill_with_holes = |
2533 IsFastDoubleElementsKind(from_elements_kind) && | 2564 IsFastDoubleElementsKind(from_elements_kind) && |
2534 IsFastObjectElementsKind(to_elements_kind); | 2565 IsFastObjectElementsKind(to_elements_kind); |
2535 | 2566 |
2536 if (pre_fill_with_holes) { | 2567 if (pre_fill_with_holes) { |
2537 // If the copy might trigger a GC, make sure that the FixedArray is | 2568 // If the copy might trigger a GC, make sure that the FixedArray is |
2538 // pre-initialized with holes to make sure that it's always in a consistent | 2569 // pre-initialized with holes to make sure that it's always in a |
2539 // state. | 2570 // consistent state. |
2540 BuildFillElementsWithHole(to_elements, to_elements_kind, | 2571 BuildFillElementsWithHole(to_elements, to_elements_kind, |
2541 graph()->GetConstant0(), capacity); | 2572 graph()->GetConstant0(), capacity); |
| 2573 } |
| 2574 |
| 2575 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); |
| 2576 |
| 2577 // Be very careful to copy the elements up to length backwards down to |
| 2578 // zero. This eliminates the need to keep length alive through the loop, |
| 2579 // since the termination condition compares to a constant. This reduces |
| 2580 // register pressure in code stubs that otherwise would spill and create |
| 2581 // a stack frame. |
| 2582 HValue* decremented_length = AddUncasted<HSub>(length, |
| 2583 graph()->GetConstant1()); |
| 2584 decremented_length->ClearFlag(HValue::kCanOverflow); |
| 2585 HValue* key = builder.BeginBody(decremented_length, Add<HConstant>(-1), |
| 2586 Token::NE); |
| 2587 HValue* element = Add<HLoadKeyed>(from_elements, key, |
| 2588 static_cast<HValue*>(NULL), |
| 2589 from_elements_kind, |
| 2590 ALLOW_RETURN_HOLE); |
| 2591 |
| 2592 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && |
| 2593 IsFastSmiElementsKind(to_elements_kind)) |
| 2594 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
| 2595 |
| 2596 if (IsHoleyElementsKind(from_elements_kind) && |
| 2597 from_elements_kind != to_elements_kind) { |
| 2598 IfBuilder if_hole(this); |
| 2599 if_hole.If<HCompareHoleAndBranch>(element); |
| 2600 if_hole.Then(); |
| 2601 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) |
| 2602 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) |
| 2603 : graph()->GetConstantHole(); |
| 2604 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); |
| 2605 if_hole.Else(); |
| 2606 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
| 2607 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 2608 if_hole.End(); |
| 2609 } else { |
| 2610 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
| 2611 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 2612 } |
| 2613 |
| 2614 builder.EndBody(); |
| 2615 |
| 2616 if (!pre_fill_with_holes && !length->Equals(capacity)) { |
| 2617 // Force an explicit reload of capacity and length from locations where we |
| 2618 // know they are available. This caps their live ranges before entering |
| 2619 // the the element copy loop above, reducing register pressure enough to |
| 2620 // not spill and create stack frames for performance-critical array stubs |
| 2621 // on platforms with a small register set. |
| 2622 capacity = AddLoadFixedArrayLength(to_elements); |
| 2623 capacity->ClearFlag(HValue::kUseGVN); |
| 2624 length = AddLoadArrayLength(array, to_elements_kind); |
| 2625 length->ClearFlag(HValue::kUseGVN); |
| 2626 // Fill unused capacity with the hole. |
| 2627 BuildFillElementsWithHole(to_elements, to_elements_kind, |
| 2628 length, capacity); |
| 2629 } |
2542 } | 2630 } |
2543 | 2631 |
2544 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); | 2632 Counters* counters = isolate()->counters(); |
| 2633 AddIncrementCounter(counters->inlined_copyied_elements()); |
| 2634 } |
2545 | 2635 |
2546 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); | 2636 HValue* HGraphBuilder::BuildCloneShallowArrayCommon( |
2547 | 2637 HValue* boilerplate, |
2548 HValue* element = Add<HLoadKeyed>(from_elements, key, | 2638 HValue* allocation_site, |
2549 static_cast<HValue*>(NULL), | 2639 HValue* extra_size, |
2550 from_elements_kind, | 2640 HValue** return_elements, |
2551 ALLOW_RETURN_HOLE); | 2641 AllocationSiteMode mode) { |
2552 | 2642 // All sizes here are multiples of kPointerSize. |
2553 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && | 2643 int array_size = JSArray::kSize; |
2554 IsFastSmiElementsKind(to_elements_kind)) | 2644 if (mode == TRACK_ALLOCATION_SITE) { |
2555 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 2645 array_size += AllocationMemento::kSize; |
2556 | |
2557 if (IsHoleyElementsKind(from_elements_kind) && | |
2558 from_elements_kind != to_elements_kind) { | |
2559 IfBuilder if_hole(this); | |
2560 if_hole.If<HCompareHoleAndBranch>(element); | |
2561 if_hole.Then(); | |
2562 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) | |
2563 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) | |
2564 : graph()->GetConstantHole(); | |
2565 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); | |
2566 if_hole.Else(); | |
2567 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | |
2568 store->SetFlag(HValue::kAllowUndefinedAsNaN); | |
2569 if_hole.End(); | |
2570 } else { | |
2571 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | |
2572 store->SetFlag(HValue::kAllowUndefinedAsNaN); | |
2573 } | 2646 } |
2574 | 2647 |
2575 builder.EndBody(); | 2648 HValue* size_in_bytes = Add<HConstant>(array_size); |
2576 | 2649 if (extra_size != NULL) { |
2577 if (!pre_fill_with_holes && length != capacity) { | 2650 size_in_bytes = AddUncasted<HAdd>(extra_size, size_in_bytes); |
2578 // Fill unused capacity with the hole. | 2651 size_in_bytes->ClearFlag(HValue::kCanOverflow); |
2579 BuildFillElementsWithHole(to_elements, to_elements_kind, | |
2580 key, capacity); | |
2581 } | |
2582 } | |
2583 | |
2584 | |
2585 HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, | |
2586 HValue* allocation_site, | |
2587 AllocationSiteMode mode, | |
2588 ElementsKind kind, | |
2589 int length) { | |
2590 NoObservableSideEffectsScope no_effects(this); | |
2591 | |
2592 // All sizes here are multiples of kPointerSize. | |
2593 int size = JSArray::kSize; | |
2594 if (mode == TRACK_ALLOCATION_SITE) { | |
2595 size += AllocationMemento::kSize; | |
2596 } | 2652 } |
2597 | 2653 |
2598 HValue* size_in_bytes = Add<HConstant>(size); | |
2599 HInstruction* object = Add<HAllocate>(size_in_bytes, | 2654 HInstruction* object = Add<HAllocate>(size_in_bytes, |
2600 HType::JSObject(), | 2655 HType::JSObject(), |
2601 NOT_TENURED, | 2656 NOT_TENURED, |
2602 JS_OBJECT_TYPE); | 2657 JS_OBJECT_TYPE); |
2603 | 2658 |
2604 // Copy the JS array part. | 2659 // Copy the JS array part. |
2605 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 2660 HValue* map = Add<HLoadNamedField>(boilerplate, |
2606 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 2661 static_cast<HValue*>(NULL), HObjectAccess::ForMap()); |
2607 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 2662 Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(), |
2608 Add<HStoreNamedField>( | 2663 Add<HConstant>(isolate()->factory()->empty_fixed_array()), |
2609 object, access, Add<HLoadNamedField>( | 2664 INITIALIZING_STORE); |
2610 boilerplate, static_cast<HValue*>(NULL), access)); | 2665 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map, |
2611 } | 2666 INITIALIZING_STORE); |
2612 } | |
2613 | 2667 |
2614 // Create an allocation site info if requested. | 2668 // Create an allocation site info if requested. |
2615 if (mode == TRACK_ALLOCATION_SITE) { | 2669 if (mode == TRACK_ALLOCATION_SITE) { |
2616 BuildCreateAllocationMemento( | 2670 BuildCreateAllocationMemento( |
2617 object, Add<HConstant>(JSArray::kSize), allocation_site); | 2671 object, Add<HConstant>(JSArray::kSize), allocation_site); |
2618 } | 2672 } |
2619 | 2673 |
2620 if (length > 0) { | 2674 if (extra_size != NULL) { |
2621 // We have to initialize the elements pointer if allocation folding is | 2675 HValue* elements = Add<HInnerAllocatedObject>(object, |
2622 // turned off. | 2676 Add<HConstant>(array_size)); |
2623 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { | 2677 if (return_elements != NULL) *return_elements = elements; |
2624 HConstant* empty_fixed_array = Add<HConstant>( | |
2625 isolate()->factory()->empty_fixed_array()); | |
2626 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | |
2627 empty_fixed_array, INITIALIZING_STORE); | |
2628 } | |
2629 | |
2630 HValue* boilerplate_elements = AddLoadElements(boilerplate); | |
2631 HValue* object_elements; | |
2632 if (IsFastDoubleElementsKind(kind)) { | |
2633 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); | |
2634 object_elements = Add<HAllocate>(elems_size, HType::Tagged(), | |
2635 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); | |
2636 } else { | |
2637 HValue* elems_size = Add<HConstant>(FixedArray::SizeFor(length)); | |
2638 object_elements = Add<HAllocate>(elems_size, HType::Tagged(), | |
2639 NOT_TENURED, FIXED_ARRAY_TYPE); | |
2640 } | |
2641 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | |
2642 object_elements); | |
2643 | |
2644 // Copy the elements array header. | |
2645 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | |
2646 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | |
2647 Add<HStoreNamedField>( | |
2648 object_elements, access, Add<HLoadNamedField>( | |
2649 boilerplate_elements, static_cast<HValue*>(NULL), access)); | |
2650 } | |
2651 | |
2652 // Copy the elements array contents. | |
2653 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold | |
2654 // copying loops with constant length up to a given boundary and use this | |
2655 // helper here instead. | |
2656 for (int i = 0; i < length; i++) { | |
2657 HValue* key_constant = Add<HConstant>(i); | |
2658 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, | |
2659 static_cast<HValue*>(NULL), kind); | |
2660 Add<HStoreKeyed>(object_elements, key_constant, value, kind); | |
2661 } | |
2662 } | 2678 } |
2663 | 2679 |
2664 return object; | 2680 return object; |
2665 } | 2681 } |
2666 | 2682 |
2667 | 2683 |
| 2684 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate, |
| 2685 HValue* allocation_site, |
| 2686 AllocationSiteMode mode, |
| 2687 ElementsKind kind) { |
| 2688 HValue* result = BuildCloneShallowArrayCommon(boilerplate, |
| 2689 allocation_site, NULL, NULL, mode); |
| 2690 |
| 2691 HValue* length = AddLoadArrayLength(boilerplate, kind); |
| 2692 HValue* elements = AddLoadElements(boilerplate); |
| 2693 HObjectAccess access1 = HObjectAccess::ForArrayLength(kind); |
| 2694 HObjectAccess access2 = HObjectAccess::ForElementsPointer(); |
| 2695 Add<HStoreNamedField>(result, access1, length, INITIALIZING_STORE); |
| 2696 Add<HStoreNamedField>(result, access2, elements, INITIALIZING_STORE); |
| 2697 |
| 2698 return result; |
| 2699 } |
| 2700 |
| 2701 |
| 2702 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate, |
| 2703 HValue* allocation_site, |
| 2704 AllocationSiteMode mode) { |
| 2705 HValue* result = BuildCloneShallowArrayCommon(boilerplate, |
| 2706 allocation_site, NULL, NULL, mode); |
| 2707 |
| 2708 HObjectAccess access = HObjectAccess::ForArrayLength(FAST_ELEMENTS); |
| 2709 Add<HStoreNamedField>(result, access, graph()->GetConstant0(), |
| 2710 INITIALIZING_STORE); |
| 2711 access = HObjectAccess::ForElementsPointer(); |
| 2712 Add<HStoreNamedField>(result, access, |
| 2713 Add<HConstant>(isolate()->factory()->empty_fixed_array()), |
| 2714 INITIALIZING_STORE); |
| 2715 |
| 2716 return result; |
| 2717 } |
| 2718 |
| 2719 |
| 2720 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate, |
| 2721 HValue* allocation_site, |
| 2722 AllocationSiteMode mode, |
| 2723 ElementsKind kind) { |
| 2724 int elements_kind_size = IsFastDoubleElementsKind(kind) |
| 2725 ? kDoubleSize : kPointerSize; |
| 2726 |
| 2727 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 2728 HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements); |
| 2729 HValue* extra = AddUncasted<HMul>(capacity, |
| 2730 Add<HConstant>(elements_kind_size)); |
| 2731 extra->ClearFlag(HValue::kCanOverflow); |
| 2732 extra = AddUncasted<HAdd>(extra, Add<HConstant>(FixedArray::kHeaderSize)); |
| 2733 extra->ClearFlag(HValue::kCanOverflow); |
| 2734 HValue* elements = NULL; |
| 2735 HValue* result = BuildCloneShallowArrayCommon(boilerplate, |
| 2736 allocation_site, extra, &elements, mode); |
| 2737 |
| 2738 // Explicitly reload the boilerplate's elements. This frees up a register |
| 2739 // during the allocation which otherwise causes spillage in many common code |
| 2740 // sequences on platforms with tight register constraints. |
| 2741 boilerplate_elements = AddLoadElements(boilerplate); |
| 2742 boilerplate_elements->ClearFlag(HValue::kUseGVN); |
| 2743 HValue* length = Add<HLoadNamedField>(boilerplate, static_cast<HValue*>(NULL), |
| 2744 HObjectAccess::ForArrayLength(kind)); |
| 2745 Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), |
| 2746 elements, INITIALIZING_STORE); |
| 2747 Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), |
| 2748 length, INITIALIZING_STORE); |
| 2749 |
| 2750 // Copy the elements array header. |
| 2751 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
| 2752 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
| 2753 Add<HStoreNamedField>(elements, access, |
| 2754 Add<HLoadNamedField>(boilerplate_elements, |
| 2755 static_cast<HValue*>(NULL), access)); |
| 2756 } |
| 2757 |
| 2758 BuildCopyElements(result, boilerplate_elements, kind, elements, |
| 2759 kind, length, capacity); |
| 2760 |
| 2761 return result; |
| 2762 } |
| 2763 |
| 2764 |
2668 void HGraphBuilder::BuildCompareNil( | 2765 void HGraphBuilder::BuildCompareNil( |
2669 HValue* value, | 2766 HValue* value, |
2670 Type* type, | 2767 Type* type, |
2671 HIfContinuation* continuation) { | 2768 HIfContinuation* continuation) { |
2672 IfBuilder if_nil(this); | 2769 IfBuilder if_nil(this); |
2673 bool some_case_handled = false; | 2770 bool some_case_handled = false; |
2674 bool some_case_missing = false; | 2771 bool some_case_missing = false; |
2675 | 2772 |
2676 if (type->Maybe(Type::Null())) { | 2773 if (type->Maybe(Type::Null())) { |
2677 if (some_case_handled) if_nil.Or(); | 2774 if (some_case_handled) if_nil.Or(); |
(...skipping 9003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11681 if (ShouldProduceTraceOutput()) { | 11778 if (ShouldProduceTraceOutput()) { |
11682 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11779 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11683 } | 11780 } |
11684 | 11781 |
11685 #ifdef DEBUG | 11782 #ifdef DEBUG |
11686 graph_->Verify(false); // No full verify. | 11783 graph_->Verify(false); // No full verify. |
11687 #endif | 11784 #endif |
11688 } | 11785 } |
11689 | 11786 |
11690 } } // namespace v8::internal | 11787 } } // namespace v8::internal |
OLD | NEW |