OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |