| 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 |