Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/hydrogen.cc

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

Powered by Google App Engine
This is Rietveld 408576698