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) { | |
2419 return Add<HLoadNamedField>( | 2418 return Add<HLoadNamedField>( |
2420 object, dependency, HObjectAccess::ForElementsPointer()); | 2419 object, static_cast<HValue*>(NULL), HObjectAccess::ForElementsPointer()); |
2421 } | 2420 } |
2422 | 2421 |
2423 | 2422 |
2424 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength( | 2423 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
2425 HValue* array, | |
2426 HValue* dependency) { | |
2427 return Add<HLoadNamedField>( | 2424 return Add<HLoadNamedField>( |
2428 array, dependency, HObjectAccess::ForFixedArrayLength()); | 2425 object, static_cast<HValue*>(NULL), HObjectAccess::ForFixedArrayLength()); |
2429 } | 2426 } |
2430 | 2427 |
2431 | 2428 |
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 | |
2440 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { | 2429 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { |
2441 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity, | 2430 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity, |
2442 graph_->GetConstant1()); | 2431 graph_->GetConstant1()); |
2443 | 2432 |
2444 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity); | 2433 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity); |
2445 new_capacity->ClearFlag(HValue::kCanOverflow); | 2434 new_capacity->ClearFlag(HValue::kCanOverflow); |
2446 | 2435 |
2447 HValue* min_growth = Add<HConstant>(16); | 2436 HValue* min_growth = Add<HConstant>(16); |
2448 | 2437 |
2449 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth); | 2438 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth); |
(...skipping 17 matching lines...) Expand all Loading... |
2467 HValue* elements, | 2456 HValue* elements, |
2468 ElementsKind kind, | 2457 ElementsKind kind, |
2469 ElementsKind new_kind, | 2458 ElementsKind new_kind, |
2470 HValue* length, | 2459 HValue* length, |
2471 HValue* new_capacity) { | 2460 HValue* new_capacity) { |
2472 BuildNewSpaceArrayCheck(new_capacity, new_kind); | 2461 BuildNewSpaceArrayCheck(new_capacity, new_kind); |
2473 | 2462 |
2474 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 2463 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
2475 new_kind, new_capacity); | 2464 new_kind, new_capacity); |
2476 | 2465 |
2477 BuildCopyElements(object, elements, kind, new_elements, | 2466 BuildCopyElements(elements, kind, |
2478 new_kind, length, new_capacity); | 2467 new_elements, new_kind, |
| 2468 length, new_capacity); |
2479 | 2469 |
2480 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 2470 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
2481 new_elements); | 2471 new_elements); |
2482 | 2472 |
2483 return new_elements; | 2473 return new_elements; |
2484 } | 2474 } |
2485 | 2475 |
2486 | 2476 |
2487 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, | 2477 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, |
2488 ElementsKind elements_kind, | 2478 ElementsKind elements_kind, |
2489 HValue* from, | 2479 HValue* from, |
2490 HValue* to) { | 2480 HValue* to) { |
2491 // Fast elements kinds need to be initialized in case statements below cause a | 2481 // Fast elements kinds need to be initialized in case statements below cause |
2492 // garbage collection. | 2482 // a garbage collection. |
2493 Factory* factory = isolate()->factory(); | 2483 Factory* factory = isolate()->factory(); |
2494 | 2484 |
2495 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 2485 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
2496 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 2486 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
2497 ? Add<HConstant>(factory->the_hole_value()) | 2487 ? Add<HConstant>(factory->the_hole_value()) |
2498 : Add<HConstant>(nan_double); | 2488 : Add<HConstant>(nan_double); |
2499 | 2489 |
2500 // Special loop unfolding case | 2490 // Special loop unfolding case |
2501 static const int kLoopUnfoldLimit = 8; | 2491 static const int kLoopUnfoldLimit = 8; |
2502 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); | 2492 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); |
(...skipping 23 matching lines...) Expand all Loading... |
2526 | 2516 |
2527 HValue* key = builder.BeginBody(from, to, Token::LT); | 2517 HValue* key = builder.BeginBody(from, to, Token::LT); |
2528 | 2518 |
2529 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 2519 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
2530 | 2520 |
2531 builder.EndBody(); | 2521 builder.EndBody(); |
2532 } | 2522 } |
2533 } | 2523 } |
2534 | 2524 |
2535 | 2525 |
2536 void HGraphBuilder::BuildCopyElements(HValue* array, | 2526 void HGraphBuilder::BuildCopyElements(HValue* from_elements, |
2537 HValue* from_elements, | |
2538 ElementsKind from_elements_kind, | 2527 ElementsKind from_elements_kind, |
2539 HValue* to_elements, | 2528 HValue* to_elements, |
2540 ElementsKind to_elements_kind, | 2529 ElementsKind to_elements_kind, |
2541 HValue* length, | 2530 HValue* length, |
2542 HValue* capacity) { | 2531 HValue* capacity) { |
2543 int constant_capacity = -1; | 2532 bool pre_fill_with_holes = |
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 = | |
2564 IsFastDoubleElementsKind(from_elements_kind) && | 2533 IsFastDoubleElementsKind(from_elements_kind) && |
2565 IsFastObjectElementsKind(to_elements_kind); | 2534 IsFastObjectElementsKind(to_elements_kind); |
2566 | 2535 |
2567 if (pre_fill_with_holes) { | 2536 if (pre_fill_with_holes) { |
2568 // If the copy might trigger a GC, make sure that the FixedArray is | 2537 // If the copy might trigger a GC, make sure that the FixedArray is |
2569 // pre-initialized with holes to make sure that it's always in a | 2538 // pre-initialized with holes to make sure that it's always in a consistent |
2570 // consistent state. | 2539 // state. |
2571 BuildFillElementsWithHole(to_elements, to_elements_kind, | 2540 BuildFillElementsWithHole(to_elements, to_elements_kind, |
2572 graph()->GetConstant0(), capacity); | 2541 graph()->GetConstant0(), capacity); |
2573 } | 2542 } |
2574 | 2543 |
2575 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); | 2544 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
2576 | 2545 |
2577 // Be very careful to copy the elements up to length backwards down to | 2546 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); |
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 | 2547 |
2592 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && | 2548 HValue* element = Add<HLoadKeyed>(from_elements, key, |
2593 IsFastSmiElementsKind(to_elements_kind)) | 2549 static_cast<HValue*>(NULL), |
| 2550 from_elements_kind, |
| 2551 ALLOW_RETURN_HOLE); |
| 2552 |
| 2553 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && |
| 2554 IsFastSmiElementsKind(to_elements_kind)) |
2594 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 2555 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
2595 | 2556 |
2596 if (IsHoleyElementsKind(from_elements_kind) && | 2557 if (IsHoleyElementsKind(from_elements_kind) && |
2597 from_elements_kind != to_elements_kind) { | 2558 from_elements_kind != to_elements_kind) { |
2598 IfBuilder if_hole(this); | 2559 IfBuilder if_hole(this); |
2599 if_hole.If<HCompareHoleAndBranch>(element); | 2560 if_hole.If<HCompareHoleAndBranch>(element); |
2600 if_hole.Then(); | 2561 if_hole.Then(); |
2601 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) | 2562 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) |
2602 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) | 2563 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) |
2603 : graph()->GetConstantHole(); | 2564 : graph()->GetConstantHole(); |
2604 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); | 2565 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); |
2605 if_hole.Else(); | 2566 if_hole.Else(); |
2606 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | 2567 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
2607 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2568 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
2608 if_hole.End(); | 2569 if_hole.End(); |
2609 } else { | 2570 } else { |
2610 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | 2571 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
2611 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2572 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 } | |
2630 } | 2573 } |
2631 | 2574 |
2632 Counters* counters = isolate()->counters(); | 2575 builder.EndBody(); |
2633 AddIncrementCounter(counters->inlined_copyied_elements()); | 2576 |
| 2577 if (!pre_fill_with_holes && length != capacity) { |
| 2578 // Fill unused capacity with the hole. |
| 2579 BuildFillElementsWithHole(to_elements, to_elements_kind, |
| 2580 key, capacity); |
| 2581 } |
2634 } | 2582 } |
2635 | 2583 |
2636 HValue* HGraphBuilder::BuildCloneShallowArrayCommon( | 2584 |
2637 HValue* boilerplate, | 2585 HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, |
2638 HValue* allocation_site, | 2586 HValue* allocation_site, |
2639 HValue* extra_size, | 2587 AllocationSiteMode mode, |
2640 HValue** return_elements, | 2588 ElementsKind kind, |
2641 AllocationSiteMode mode) { | 2589 int length) { |
| 2590 NoObservableSideEffectsScope no_effects(this); |
| 2591 |
2642 // All sizes here are multiples of kPointerSize. | 2592 // All sizes here are multiples of kPointerSize. |
2643 int array_size = JSArray::kSize; | 2593 int size = JSArray::kSize; |
2644 if (mode == TRACK_ALLOCATION_SITE) { | 2594 if (mode == TRACK_ALLOCATION_SITE) { |
2645 array_size += AllocationMemento::kSize; | 2595 size += AllocationMemento::kSize; |
2646 } | 2596 } |
2647 | 2597 |
2648 HValue* size_in_bytes = Add<HConstant>(array_size); | 2598 HValue* size_in_bytes = Add<HConstant>(size); |
2649 if (extra_size != NULL) { | |
2650 size_in_bytes = AddUncasted<HAdd>(extra_size, size_in_bytes); | |
2651 size_in_bytes->ClearFlag(HValue::kCanOverflow); | |
2652 } | |
2653 | |
2654 HInstruction* object = Add<HAllocate>(size_in_bytes, | 2599 HInstruction* object = Add<HAllocate>(size_in_bytes, |
2655 HType::JSObject(), | 2600 HType::JSObject(), |
2656 NOT_TENURED, | 2601 NOT_TENURED, |
2657 JS_OBJECT_TYPE); | 2602 JS_OBJECT_TYPE); |
2658 | 2603 |
2659 // Copy the JS array part. | 2604 // Copy the JS array part. |
2660 HValue* map = Add<HLoadNamedField>(boilerplate, | 2605 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
2661 static_cast<HValue*>(NULL), HObjectAccess::ForMap()); | 2606 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
2662 Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(), | 2607 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
2663 Add<HConstant>(isolate()->factory()->empty_fixed_array()), | 2608 Add<HStoreNamedField>( |
2664 INITIALIZING_STORE); | 2609 object, access, Add<HLoadNamedField>( |
2665 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map, | 2610 boilerplate, static_cast<HValue*>(NULL), access)); |
2666 INITIALIZING_STORE); | 2611 } |
| 2612 } |
2667 | 2613 |
2668 // Create an allocation site info if requested. | 2614 // Create an allocation site info if requested. |
2669 if (mode == TRACK_ALLOCATION_SITE) { | 2615 if (mode == TRACK_ALLOCATION_SITE) { |
2670 BuildCreateAllocationMemento( | 2616 BuildCreateAllocationMemento( |
2671 object, Add<HConstant>(JSArray::kSize), allocation_site); | 2617 object, Add<HConstant>(JSArray::kSize), allocation_site); |
2672 } | 2618 } |
2673 | 2619 |
2674 if (extra_size != NULL) { | 2620 if (length > 0) { |
2675 HValue* elements = Add<HInnerAllocatedObject>(object, | 2621 // We have to initialize the elements pointer if allocation folding is |
2676 Add<HConstant>(array_size)); | 2622 // turned off. |
2677 if (return_elements != NULL) *return_elements = elements; | 2623 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { |
| 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 } |
2678 } | 2662 } |
2679 | 2663 |
2680 return object; | 2664 return object; |
2681 } | 2665 } |
2682 | 2666 |
2683 | 2667 |
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 | |
2765 void HGraphBuilder::BuildCompareNil( | 2668 void HGraphBuilder::BuildCompareNil( |
2766 HValue* value, | 2669 HValue* value, |
2767 Type* type, | 2670 Type* type, |
2768 HIfContinuation* continuation) { | 2671 HIfContinuation* continuation) { |
2769 IfBuilder if_nil(this); | 2672 IfBuilder if_nil(this); |
2770 bool some_case_handled = false; | 2673 bool some_case_handled = false; |
2771 bool some_case_missing = false; | 2674 bool some_case_missing = false; |
2772 | 2675 |
2773 if (type->Maybe(Type::Null())) { | 2676 if (type->Maybe(Type::Null())) { |
2774 if (some_case_handled) if_nil.Or(); | 2677 if (some_case_handled) if_nil.Or(); |
(...skipping 9003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11778 if (ShouldProduceTraceOutput()) { | 11681 if (ShouldProduceTraceOutput()) { |
11779 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11682 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11780 } | 11683 } |
11781 | 11684 |
11782 #ifdef DEBUG | 11685 #ifdef DEBUG |
11783 graph_->Verify(false); // No full verify. | 11686 graph_->Verify(false); // No full verify. |
11784 #endif | 11687 #endif |
11785 } | 11688 } |
11786 | 11689 |
11787 } } // namespace v8::internal | 11690 } } // namespace v8::internal |
OLD | NEW |