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); |
2542 } | 2573 } |
2543 | 2574 |
2544 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); | 2575 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); |
2545 | 2576 |
2546 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); | 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 | |
mvstanton
2014/04/25 08:25:17
Nice!
| |
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); | |
2547 | 2591 |
2548 HValue* element = Add<HLoadKeyed>(from_elements, key, | 2592 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && |
2549 static_cast<HValue*>(NULL), | 2593 IsFastSmiElementsKind(to_elements_kind)) |
2550 from_elements_kind, | |
2551 ALLOW_RETURN_HOLE); | |
2552 | |
2553 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && | |
2554 IsFastSmiElementsKind(to_elements_kind)) | |
2555 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 2594 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
2556 | 2595 |
2557 if (IsHoleyElementsKind(from_elements_kind) && | 2596 if (IsHoleyElementsKind(from_elements_kind) && |
2558 from_elements_kind != to_elements_kind) { | 2597 from_elements_kind != to_elements_kind) { |
2559 IfBuilder if_hole(this); | 2598 IfBuilder if_hole(this); |
2560 if_hole.If<HCompareHoleAndBranch>(element); | 2599 if_hole.If<HCompareHoleAndBranch>(element); |
2561 if_hole.Then(); | 2600 if_hole.Then(); |
2562 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) | 2601 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) |
2563 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) | 2602 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) |
2564 : graph()->GetConstantHole(); | 2603 : graph()->GetConstantHole(); |
2565 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); | 2604 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); |
2566 if_hole.Else(); | 2605 if_hole.Else(); |
2567 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | 2606 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
2568 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2607 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
2569 if_hole.End(); | 2608 if_hole.End(); |
2570 } else { | 2609 } else { |
2571 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | 2610 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
2572 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2611 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
2573 } | 2612 } |
2574 | 2613 |
2575 builder.EndBody(); | 2614 builder.EndBody(); |
2576 | 2615 |
2577 if (!pre_fill_with_holes && length != capacity) { | 2616 if (!pre_fill_with_holes && !length->Equals(capacity)) { |
2578 // Fill unused capacity with the hole. | 2617 // Force an explicit reload of capacity and length from locations where we |
2579 BuildFillElementsWithHole(to_elements, to_elements_kind, | 2618 // know they are available. This caps their live ranges before entering |
2580 key, capacity); | 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 } | |
2581 } | 2630 } |
2582 } | 2631 } |
2583 | 2632 |
2584 | 2633 HValue* HGraphBuilder::BuildCloneShallowArrayNoElements( |
mvstanton
2014/04/25 08:25:17
I don't like the name that much, it surprises me t
danno
2014/04/25 16:56:43
Done.
| |
2585 HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, | 2634 HValue* boilerplate, |
2586 HValue* allocation_site, | 2635 HValue* allocation_site, |
2587 AllocationSiteMode mode, | 2636 HValue* extra_size, |
2588 ElementsKind kind, | 2637 HValue** return_elements, |
2589 int length) { | 2638 AllocationSiteMode mode) { |
2590 NoObservableSideEffectsScope no_effects(this); | |
2591 | |
2592 // All sizes here are multiples of kPointerSize. | 2639 // All sizes here are multiples of kPointerSize. |
2593 int size = JSArray::kSize; | 2640 int array_size = JSArray::kSize; |
2594 if (mode == TRACK_ALLOCATION_SITE) { | 2641 if (mode == TRACK_ALLOCATION_SITE) { |
2595 size += AllocationMemento::kSize; | 2642 array_size += AllocationMemento::kSize; |
2596 } | 2643 } |
2597 | 2644 |
2598 HValue* size_in_bytes = Add<HConstant>(size); | 2645 HValue* size_in_bytes = Add<HConstant>(array_size); |
2646 if (extra_size != NULL) { | |
2647 size_in_bytes = AddUncasted<HAdd>(extra_size, size_in_bytes); | |
2648 size_in_bytes->ClearFlag(HValue::kCanOverflow); | |
2649 } | |
2650 | |
2599 HInstruction* object = Add<HAllocate>(size_in_bytes, | 2651 HInstruction* object = Add<HAllocate>(size_in_bytes, |
2600 HType::JSObject(), | 2652 HType::JSObject(), |
2601 NOT_TENURED, | 2653 NOT_TENURED, |
2602 JS_OBJECT_TYPE); | 2654 JS_OBJECT_TYPE); |
2603 | 2655 |
2604 // Copy the JS array part. | 2656 // Copy the JS array part. |
2605 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 2657 for (int i = 0; i < JSArray::kElementsOffset; i += kPointerSize) { |
mvstanton
2014/04/25 08:25:17
This is simply a map store, can we eliminate the l
danno
2014/04/25 16:56:43
Done.
| |
2606 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 2658 if (i != JSArray::kElementsOffset) { |
mvstanton
2014/04/25 08:25:17
As written, this check would always succeed.
danno
2014/04/25 16:56:43
Done.
| |
2607 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 2659 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
2608 Add<HStoreNamedField>( | 2660 Add<HStoreNamedField>( |
2609 object, access, Add<HLoadNamedField>( | 2661 object, access, Add<HLoadNamedField>( |
2610 boilerplate, static_cast<HValue*>(NULL), access)); | 2662 boilerplate, static_cast<HValue*>(NULL), access)); |
2611 } | 2663 } |
2612 } | 2664 } |
2613 | 2665 |
2614 // Create an allocation site info if requested. | 2666 // Create an allocation site info if requested. |
2615 if (mode == TRACK_ALLOCATION_SITE) { | 2667 if (mode == TRACK_ALLOCATION_SITE) { |
2616 BuildCreateAllocationMemento( | 2668 BuildCreateAllocationMemento( |
2617 object, Add<HConstant>(JSArray::kSize), allocation_site); | 2669 object, Add<HConstant>(JSArray::kSize), allocation_site); |
2618 } | 2670 } |
2619 | 2671 |
2620 if (length > 0) { | 2672 if (extra_size != NULL) { |
2621 // We have to initialize the elements pointer if allocation folding is | 2673 HValue* elements = Add<HInnerAllocatedObject>(object, |
2622 // turned off. | 2674 Add<HConstant>(array_size)); |
2623 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { | 2675 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 } | 2676 } |
2663 | 2677 |
2664 return object; | 2678 return object; |
2665 } | 2679 } |
2666 | 2680 |
2667 | 2681 |
2682 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate, | |
2683 HValue* allocation_site, | |
2684 AllocationSiteMode mode, | |
2685 ElementsKind kind) { | |
2686 HValue* result = BuildCloneShallowArrayNoElements(boilerplate, | |
2687 allocation_site, NULL, NULL, mode); | |
2688 | |
2689 HValue* length = AddLoadArrayLength(boilerplate, kind); | |
2690 HValue* elements = AddLoadElements(boilerplate); | |
2691 HObjectAccess access1 = HObjectAccess::ForArrayLength(kind); | |
2692 HObjectAccess access2 = HObjectAccess::ForElementsPointer(); | |
2693 Add<HStoreNamedField>(result, access1, length, INITIALIZING_STORE); | |
2694 Add<HStoreNamedField>(result, access2, elements, INITIALIZING_STORE); | |
2695 | |
2696 return result; | |
2697 } | |
2698 | |
2699 | |
2700 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate, | |
2701 HValue* allocation_site, | |
2702 AllocationSiteMode mode) { | |
2703 HValue* result = BuildCloneShallowArrayNoElements(boilerplate, | |
2704 allocation_site, NULL, NULL, mode); | |
2705 | |
2706 HObjectAccess access = HObjectAccess::ForArrayLength(FAST_ELEMENTS); | |
2707 Add<HStoreNamedField>(result, access, graph()->GetConstant0(), | |
2708 INITIALIZING_STORE); | |
2709 access = HObjectAccess::ForElementsPointer(); | |
2710 Add<HStoreNamedField>(result, access, | |
2711 Add<HConstant>(isolate()->factory()->empty_fixed_array()), | |
2712 INITIALIZING_STORE); | |
2713 | |
2714 return result; | |
2715 } | |
2716 | |
2717 | |
2718 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate, | |
2719 HValue* allocation_site, | |
2720 AllocationSiteMode mode, | |
2721 ElementsKind kind) { | |
2722 int elements_kind_size = IsFastDoubleElementsKind(kind) | |
2723 ? kDoubleSize : kPointerSize; | |
2724 | |
2725 HValue* boilerplate_elements = AddLoadElements(boilerplate); | |
2726 HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements); | |
2727 HValue* extra = AddUncasted<HMul>(capacity, | |
2728 Add<HConstant>(elements_kind_size)); | |
2729 extra->ClearFlag(HValue::kCanOverflow); | |
2730 extra = AddUncasted<HAdd>(extra, Add<HConstant>(FixedArray::kHeaderSize)); | |
2731 extra->ClearFlag(HValue::kCanOverflow); | |
2732 HValue* elements = NULL; | |
2733 HValue* result = BuildCloneShallowArrayNoElements(boilerplate, | |
2734 allocation_site, extra, &elements, mode); | |
2735 | |
2736 // Explicitly reload the boilerplate's elements. This frees up a register | |
2737 // during the allocation which otherwise causes spillage in many common code | |
2738 // sequences on platforms with tight register constraints. | |
2739 boilerplate_elements = AddLoadElements(boilerplate); | |
2740 boilerplate_elements->ClearFlag(HValue::kUseGVN); | |
2741 HValue* length = Add<HLoadNamedField>(boilerplate, static_cast<HValue*>(NULL), | |
2742 HObjectAccess::ForArrayLength(kind)); | |
2743 Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), | |
2744 elements, INITIALIZING_STORE); | |
2745 Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), | |
2746 length, INITIALIZING_STORE); | |
2747 | |
2748 // Copy the elements array header. | |
2749 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | |
2750 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | |
2751 Add<HStoreNamedField>(elements, access, | |
2752 Add<HLoadNamedField>(boilerplate_elements, | |
2753 static_cast<HValue*>(NULL), access)); | |
2754 } | |
2755 | |
2756 BuildCopyElements(result, boilerplate_elements, kind, elements, | |
2757 kind, length, capacity); | |
2758 | |
2759 return result; | |
2760 } | |
2761 | |
2762 | |
2668 void HGraphBuilder::BuildCompareNil( | 2763 void HGraphBuilder::BuildCompareNil( |
2669 HValue* value, | 2764 HValue* value, |
2670 Type* type, | 2765 Type* type, |
2671 HIfContinuation* continuation) { | 2766 HIfContinuation* continuation) { |
2672 IfBuilder if_nil(this); | 2767 IfBuilder if_nil(this); |
2673 bool some_case_handled = false; | 2768 bool some_case_handled = false; |
2674 bool some_case_missing = false; | 2769 bool some_case_missing = false; |
2675 | 2770 |
2676 if (type->Maybe(Type::Null())) { | 2771 if (type->Maybe(Type::Null())) { |
2677 if (some_case_handled) if_nil.Or(); | 2772 if (some_case_handled) if_nil.Or(); |
(...skipping 8994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11672 if (ShouldProduceTraceOutput()) { | 11767 if (ShouldProduceTraceOutput()) { |
11673 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11768 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11674 } | 11769 } |
11675 | 11770 |
11676 #ifdef DEBUG | 11771 #ifdef DEBUG |
11677 graph_->Verify(false); // No full verify. | 11772 graph_->Verify(false); // No full verify. |
11678 #endif | 11773 #endif |
11679 } | 11774 } |
11680 | 11775 |
11681 } } // namespace v8::internal | 11776 } } // namespace v8::internal |
OLD | NEW |