| 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) { | |
| 2393 return Add<HLoadNamedField>( | 2392 return Add<HLoadNamedField>( |
| 2394 object, dependency, HObjectAccess::ForElementsPointer()); | 2393 object, static_cast<HValue*>(NULL), HObjectAccess::ForElementsPointer()); |
| 2395 } | 2394 } |
| 2396 | 2395 |
| 2397 | 2396 |
| 2398 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength( | 2397 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
| 2399 HValue* array, | |
| 2400 HValue* dependency) { | |
| 2401 return Add<HLoadNamedField>( | 2398 return Add<HLoadNamedField>( |
| 2402 array, dependency, HObjectAccess::ForFixedArrayLength()); | 2399 object, static_cast<HValue*>(NULL), HObjectAccess::ForFixedArrayLength()); |
| 2403 } | 2400 } |
| 2404 | 2401 |
| 2405 | 2402 |
| 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 | |
| 2414 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { | 2403 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { |
| 2415 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity, | 2404 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity, |
| 2416 graph_->GetConstant1()); | 2405 graph_->GetConstant1()); |
| 2417 | 2406 |
| 2418 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity); | 2407 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity); |
| 2419 new_capacity->ClearFlag(HValue::kCanOverflow); | 2408 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 2420 | 2409 |
| 2421 HValue* min_growth = Add<HConstant>(16); | 2410 HValue* min_growth = Add<HConstant>(16); |
| 2422 | 2411 |
| 2423 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth); | 2412 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth); |
| 2424 new_capacity->ClearFlag(HValue::kCanOverflow); | 2413 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 2425 | 2414 |
| 2426 return new_capacity; | 2415 return new_capacity; |
| 2427 } | 2416 } |
| 2428 | 2417 |
| 2429 | 2418 |
| 2430 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 2419 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
| 2431 HValue* elements, | 2420 HValue* elements, |
| 2432 ElementsKind kind, | 2421 ElementsKind kind, |
| 2433 ElementsKind new_kind, | 2422 ElementsKind new_kind, |
| 2434 HValue* length, | 2423 HValue* length, |
| 2435 HValue* new_capacity) { | 2424 HValue* new_capacity) { |
| 2436 Add<HBoundsCheck>(new_capacity, Add<HConstant>( | 2425 Add<HBoundsCheck>(new_capacity, Add<HConstant>( |
| 2437 (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> | 2426 (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> |
| 2438 ElementsKindToShiftSize(kind))); | 2427 ElementsKindToShiftSize(kind))); |
| 2439 | 2428 |
| 2440 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 2429 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
| 2441 new_kind, new_capacity); | 2430 new_kind, new_capacity); |
| 2442 | 2431 |
| 2443 BuildCopyElements(object, elements, kind, new_elements, | 2432 BuildCopyElements(elements, kind, |
| 2444 new_kind, length, new_capacity); | 2433 new_elements, new_kind, |
| 2434 length, new_capacity); |
| 2445 | 2435 |
| 2446 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 2436 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 2447 new_elements); | 2437 new_elements); |
| 2448 | 2438 |
| 2449 return new_elements; | 2439 return new_elements; |
| 2450 } | 2440 } |
| 2451 | 2441 |
| 2452 | 2442 |
| 2453 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, | 2443 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, |
| 2454 ElementsKind elements_kind, | 2444 ElementsKind elements_kind, |
| 2455 HValue* from, | 2445 HValue* from, |
| 2456 HValue* to) { | 2446 HValue* to) { |
| 2457 // Fast elements kinds need to be initialized in case statements below cause a | 2447 // Fast elements kinds need to be initialized in case statements below cause |
| 2458 // garbage collection. | 2448 // a garbage collection. |
| 2459 Factory* factory = isolate()->factory(); | 2449 Factory* factory = isolate()->factory(); |
| 2460 | 2450 |
| 2461 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 2451 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
| 2462 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 2452 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
| 2463 ? Add<HConstant>(factory->the_hole_value()) | 2453 ? Add<HConstant>(factory->the_hole_value()) |
| 2464 : Add<HConstant>(nan_double); | 2454 : Add<HConstant>(nan_double); |
| 2465 | 2455 |
| 2466 if (to == NULL) { | |
| 2467 to = AddLoadFixedArrayLength(elements); | |
| 2468 } | |
| 2469 | |
| 2470 // Special loop unfolding case | 2456 // Special loop unfolding case |
| 2471 static const int kLoopUnfoldLimit = 8; | 2457 static const int kLoopUnfoldLimit = 8; |
| 2472 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); | 2458 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); |
| 2473 int initial_capacity = -1; | 2459 int initial_capacity = -1; |
| 2474 if (from->IsInteger32Constant() && to->IsInteger32Constant()) { | 2460 if (from->IsInteger32Constant() && to->IsInteger32Constant()) { |
| 2475 int constant_from = from->GetInteger32Constant(); | 2461 int constant_from = from->GetInteger32Constant(); |
| 2476 int constant_to = to->GetInteger32Constant(); | 2462 int constant_to = to->GetInteger32Constant(); |
| 2477 | 2463 |
| 2478 if (constant_from == 0 && constant_to <= kLoopUnfoldLimit) { | 2464 if (constant_from == 0 && constant_to <= kLoopUnfoldLimit) { |
| 2479 initial_capacity = constant_to; | 2465 initial_capacity = constant_to; |
| 2480 } | 2466 } |
| 2481 } | 2467 } |
| 2482 | 2468 |
| 2483 // Since we're about to store a hole value, the store instruction below must | 2469 // Since we're about to store a hole value, the store instruction below must |
| 2484 // assume an elements kind that supports heap object values. | 2470 // assume an elements kind that supports heap object values. |
| 2485 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 2471 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
| 2486 elements_kind = FAST_HOLEY_ELEMENTS; | 2472 elements_kind = FAST_HOLEY_ELEMENTS; |
| 2487 } | 2473 } |
| 2488 | 2474 |
| 2489 if (initial_capacity >= 0) { | 2475 if (initial_capacity >= 0) { |
| 2490 for (int i = 0; i < initial_capacity; i++) { | 2476 for (int i = 0; i < initial_capacity; i++) { |
| 2491 HInstruction* key = Add<HConstant>(i); | 2477 HInstruction* key = Add<HConstant>(i); |
| 2492 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 2478 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
| 2493 } | 2479 } |
| 2494 } else { | 2480 } else { |
| 2495 // Carefully loop backwards so that the "from" remains live through the loop | 2481 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
| 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); | |
| 2500 | 2482 |
| 2501 HValue* key = builder.BeginBody(to, from, Token::GT); | 2483 HValue* key = builder.BeginBody(from, to, Token::LT); |
| 2502 | 2484 |
| 2503 HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1()); | 2485 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
| 2504 adjusted_key->ClearFlag(HValue::kCanOverflow); | |
| 2505 | |
| 2506 Add<HStoreKeyed>(elements, adjusted_key, hole, elements_kind); | |
| 2507 | 2486 |
| 2508 builder.EndBody(); | 2487 builder.EndBody(); |
| 2509 } | 2488 } |
| 2510 } | 2489 } |
| 2511 | 2490 |
| 2512 | 2491 |
| 2513 void HGraphBuilder::BuildCopyElements(HValue* array, | 2492 void HGraphBuilder::BuildCopyElements(HValue* from_elements, |
| 2514 HValue* from_elements, | |
| 2515 ElementsKind from_elements_kind, | 2493 ElementsKind from_elements_kind, |
| 2516 HValue* to_elements, | 2494 HValue* to_elements, |
| 2517 ElementsKind to_elements_kind, | 2495 ElementsKind to_elements_kind, |
| 2518 HValue* length, | 2496 HValue* length, |
| 2519 HValue* capacity) { | 2497 HValue* capacity) { |
| 2520 int constant_capacity = -1; | 2498 bool pre_fill_with_holes = |
| 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. | |
| 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 = | |
| 2542 IsFastDoubleElementsKind(from_elements_kind) && | 2499 IsFastDoubleElementsKind(from_elements_kind) && |
| 2543 IsFastObjectElementsKind(to_elements_kind); | 2500 IsFastObjectElementsKind(to_elements_kind); |
| 2544 | 2501 |
| 2545 if (pre_fill_with_holes) { | 2502 if (pre_fill_with_holes) { |
| 2546 // If the copy might trigger a GC, make sure that the FixedArray is | 2503 // If the copy might trigger a GC, make sure that the FixedArray is |
| 2547 // pre-initialized with holes to make sure that it's always in a | 2504 // pre-initialized with holes to make sure that it's always in a consistent |
| 2548 // consistent state. | 2505 // state. |
| 2549 BuildFillElementsWithHole(to_elements, to_elements_kind, | 2506 BuildFillElementsWithHole(to_elements, to_elements_kind, |
| 2550 graph()->GetConstant0(), NULL); | 2507 graph()->GetConstant0(), capacity); |
| 2551 } else if (capacity == NULL || !length->Equals(capacity)) { | 2508 } |
| 2552 BuildFillElementsWithHole(to_elements, to_elements_kind, | |
| 2553 length, NULL); | |
| 2554 } | |
| 2555 | 2509 |
| 2556 if (capacity == NULL) { | 2510 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
| 2557 capacity = AddLoadFixedArrayLength(to_elements); | |
| 2558 } | |
| 2559 | 2511 |
| 2560 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); | 2512 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); |
| 2561 | 2513 |
| 2562 HValue* key = builder.BeginBody(length, graph()->GetConstant0(), | 2514 HValue* element = Add<HLoadKeyed>(from_elements, key, |
| 2563 Token::GT); | 2515 static_cast<HValue*>(NULL), |
| 2516 from_elements_kind, |
| 2517 ALLOW_RETURN_HOLE); |
| 2564 | 2518 |
| 2565 key = AddUncasted<HSub>(key, graph()->GetConstant1()); | 2519 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && |
| 2566 key->ClearFlag(HValue::kCanOverflow); | 2520 IsFastSmiElementsKind(to_elements_kind)) |
| 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; | 2521 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
| 2576 | 2522 |
| 2577 if (IsHoleyElementsKind(from_elements_kind) && | 2523 if (IsHoleyElementsKind(from_elements_kind) && |
| 2578 from_elements_kind != to_elements_kind) { | 2524 from_elements_kind != to_elements_kind) { |
| 2579 IfBuilder if_hole(this); | 2525 IfBuilder if_hole(this); |
| 2580 if_hole.If<HCompareHoleAndBranch>(element); | 2526 if_hole.If<HCompareHoleAndBranch>(element); |
| 2581 if_hole.Then(); | 2527 if_hole.Then(); |
| 2582 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) | 2528 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) |
| 2583 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) | 2529 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) |
| 2584 : graph()->GetConstantHole(); | 2530 : graph()->GetConstantHole(); |
| 2585 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); | 2531 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); |
| 2586 if_hole.Else(); | 2532 if_hole.Else(); |
| 2587 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | 2533 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
| 2588 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2534 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 2589 if_hole.End(); | 2535 if_hole.End(); |
| 2590 } else { | 2536 } else { |
| 2591 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | 2537 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); |
| 2592 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 2538 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 2593 } | |
| 2594 | |
| 2595 builder.EndBody(); | |
| 2596 } | 2539 } |
| 2597 | 2540 |
| 2598 Counters* counters = isolate()->counters(); | 2541 builder.EndBody(); |
| 2599 AddIncrementCounter(counters->inlined_copied_elements()); | 2542 |
| 2543 if (!pre_fill_with_holes && length != capacity) { |
| 2544 // Fill unused capacity with the hole. |
| 2545 BuildFillElementsWithHole(to_elements, to_elements_kind, |
| 2546 key, capacity); |
| 2547 } |
| 2600 } | 2548 } |
| 2601 | 2549 |
| 2602 HValue* HGraphBuilder::BuildCloneShallowArrayCommon( | 2550 |
| 2603 HValue* boilerplate, | 2551 HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, |
| 2604 HValue* allocation_site, | 2552 HValue* allocation_site, |
| 2605 HValue* extra_size, | 2553 AllocationSiteMode mode, |
| 2606 HValue** return_elements, | 2554 ElementsKind kind, |
| 2607 AllocationSiteMode mode) { | 2555 int length) { |
| 2556 NoObservableSideEffectsScope no_effects(this); |
| 2557 |
| 2608 // All sizes here are multiples of kPointerSize. | 2558 // All sizes here are multiples of kPointerSize. |
| 2609 int array_size = JSArray::kSize; | 2559 int size = JSArray::kSize; |
| 2610 if (mode == TRACK_ALLOCATION_SITE) { | 2560 if (mode == TRACK_ALLOCATION_SITE) { |
| 2611 array_size += AllocationMemento::kSize; | 2561 size += AllocationMemento::kSize; |
| 2612 } | 2562 } |
| 2613 | 2563 |
| 2614 HValue* size_in_bytes = Add<HConstant>(array_size); | 2564 HValue* size_in_bytes = Add<HConstant>(size); |
| 2615 if (extra_size != NULL) { | |
| 2616 size_in_bytes = AddUncasted<HAdd>(extra_size, size_in_bytes); | |
| 2617 size_in_bytes->ClearFlag(HValue::kCanOverflow); | |
| 2618 } | |
| 2619 | |
| 2620 HInstruction* object = Add<HAllocate>(size_in_bytes, | 2565 HInstruction* object = Add<HAllocate>(size_in_bytes, |
| 2621 HType::JSObject(), | 2566 HType::JSObject(), |
| 2622 NOT_TENURED, | 2567 NOT_TENURED, |
| 2623 JS_OBJECT_TYPE); | 2568 JS_OBJECT_TYPE); |
| 2624 | 2569 |
| 2625 // Copy the JS array part. | 2570 // Copy the JS array part. |
| 2626 HValue* map = Add<HLoadNamedField>(boilerplate, | 2571 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 2627 static_cast<HValue*>(NULL), HObjectAccess::ForMap()); | 2572 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
| 2628 Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(), | 2573 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
| 2629 Add<HConstant>(isolate()->factory()->empty_fixed_array()), | 2574 Add<HStoreNamedField>( |
| 2630 INITIALIZING_STORE); | 2575 object, access, Add<HLoadNamedField>( |
| 2631 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map, | 2576 boilerplate, static_cast<HValue*>(NULL), access)); |
| 2632 INITIALIZING_STORE); | 2577 } |
| 2578 } |
| 2633 | 2579 |
| 2634 // Create an allocation site info if requested. | 2580 // Create an allocation site info if requested. |
| 2635 if (mode == TRACK_ALLOCATION_SITE) { | 2581 if (mode == TRACK_ALLOCATION_SITE) { |
| 2636 BuildCreateAllocationMemento( | 2582 BuildCreateAllocationMemento( |
| 2637 object, Add<HConstant>(JSArray::kSize), allocation_site); | 2583 object, Add<HConstant>(JSArray::kSize), allocation_site); |
| 2638 } | 2584 } |
| 2639 | 2585 |
| 2640 if (extra_size != NULL) { | 2586 if (length > 0) { |
| 2641 HValue* elements = Add<HInnerAllocatedObject>(object, | 2587 // We have to initialize the elements pointer if allocation folding is |
| 2642 Add<HConstant>(array_size)); | 2588 // turned off. |
| 2643 if (return_elements != NULL) *return_elements = elements; | 2589 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { |
| 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 } |
| 2644 } | 2628 } |
| 2645 | 2629 |
| 2646 return object; | 2630 return object; |
| 2647 } | 2631 } |
| 2648 | 2632 |
| 2649 | 2633 |
| 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 | |
| 2736 void HGraphBuilder::BuildCompareNil( | 2634 void HGraphBuilder::BuildCompareNil( |
| 2737 HValue* value, | 2635 HValue* value, |
| 2738 Type* type, | 2636 Type* type, |
| 2739 HIfContinuation* continuation) { | 2637 HIfContinuation* continuation) { |
| 2740 IfBuilder if_nil(this); | 2638 IfBuilder if_nil(this); |
| 2741 bool some_case_handled = false; | 2639 bool some_case_handled = false; |
| 2742 bool some_case_missing = false; | 2640 bool some_case_missing = false; |
| 2743 | 2641 |
| 2744 if (type->Maybe(Type::Null())) { | 2642 if (type->Maybe(Type::Null())) { |
| 2745 if (some_case_handled) if_nil.Or(); | 2643 if (some_case_handled) if_nil.Or(); |
| (...skipping 9051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11797 if (ShouldProduceTraceOutput()) { | 11695 if (ShouldProduceTraceOutput()) { |
| 11798 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11696 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11799 } | 11697 } |
| 11800 | 11698 |
| 11801 #ifdef DEBUG | 11699 #ifdef DEBUG |
| 11802 graph_->Verify(false); // No full verify. | 11700 graph_->Verify(false); // No full verify. |
| 11803 #endif | 11701 #endif |
| 11804 } | 11702 } |
| 11805 | 11703 |
| 11806 } } // namespace v8::internal | 11704 } } // namespace v8::internal |
| OLD | NEW |