Chromium Code Reviews| 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); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 2430 HValue* elements, | 2441 HValue* elements, |
| 2431 ElementsKind kind, | 2442 ElementsKind kind, |
| 2432 ElementsKind new_kind, | 2443 ElementsKind new_kind, |
| 2433 HValue* length, | 2444 HValue* length, |
| 2434 HValue* new_capacity) { | 2445 HValue* new_capacity) { |
| 2435 BuildNewSpaceArrayCheck(new_capacity, new_kind); | 2446 BuildNewSpaceArrayCheck(new_capacity, new_kind); |
| 2436 | 2447 |
| 2437 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 2448 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
| 2438 new_kind, new_capacity); | 2449 new_kind, new_capacity); |
| 2439 | 2450 |
| 2440 BuildCopyElements(elements, kind, | 2451 BuildCopyElements(object, elements, kind, new_elements, |
| 2441 new_elements, new_kind, | 2452 new_kind, length, new_capacity); |
| 2442 length, new_capacity); | |
| 2443 | 2453 |
| 2444 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 2454 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 2445 new_elements); | 2455 new_elements); |
| 2446 | 2456 |
| 2447 return new_elements; | 2457 return new_elements; |
| 2448 } | 2458 } |
| 2449 | 2459 |
| 2450 | 2460 |
| 2451 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, | 2461 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, |
| 2452 ElementsKind elements_kind, | 2462 ElementsKind elements_kind, |
| 2453 HValue* from, | 2463 HValue* from, |
| 2454 HValue* to) { | 2464 HValue* to) { |
| 2455 // Fast elements kinds need to be initialized in case statements below cause | 2465 // Fast elements kinds need to be initialized in case statements below cause a |
| 2456 // a garbage collection. | 2466 // garbage collection. |
| 2457 Factory* factory = isolate()->factory(); | 2467 Factory* factory = isolate()->factory(); |
| 2458 | 2468 |
| 2459 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 2469 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
| 2460 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 2470 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
| 2461 ? Add<HConstant>(factory->the_hole_value()) | 2471 ? Add<HConstant>(factory->the_hole_value()) |
| 2462 : Add<HConstant>(nan_double); | 2472 : Add<HConstant>(nan_double); |
| 2463 | 2473 |
| 2474 if (to == NULL) to = AddLoadFixedArrayLength(elements); | |
|
mvstanton
2014/05/09 13:16:49
nit: I'd rather see a { } around the assignment, t
danno
2014/05/09 15:51:25
Done.
danno
2014/05/09 15:51:25
Done.
| |
| 2475 | |
| 2464 // Special loop unfolding case | 2476 // Special loop unfolding case |
| 2465 static const int kLoopUnfoldLimit = 8; | 2477 static const int kLoopUnfoldLimit = 8; |
| 2466 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); | 2478 STATIC_ASSERT(JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit); |
| 2467 int initial_capacity = -1; | 2479 int initial_capacity = -1; |
| 2468 if (from->IsInteger32Constant() && to->IsInteger32Constant()) { | 2480 if (from->IsInteger32Constant() && to->IsInteger32Constant()) { |
| 2469 int constant_from = from->GetInteger32Constant(); | 2481 int constant_from = from->GetInteger32Constant(); |
| 2470 int constant_to = to->GetInteger32Constant(); | 2482 int constant_to = to->GetInteger32Constant(); |
| 2471 | 2483 |
| 2472 if (constant_from == 0 && constant_to <= kLoopUnfoldLimit) { | 2484 if (constant_from == 0 && constant_to <= kLoopUnfoldLimit) { |
| 2473 initial_capacity = constant_to; | 2485 initial_capacity = constant_to; |
| 2474 } | 2486 } |
| 2475 } | 2487 } |
| 2476 | 2488 |
| 2477 // Since we're about to store a hole value, the store instruction below must | 2489 // Since we're about to store a hole value, the store instruction below must |
| 2478 // assume an elements kind that supports heap object values. | 2490 // assume an elements kind that supports heap object values. |
| 2479 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 2491 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
| 2480 elements_kind = FAST_HOLEY_ELEMENTS; | 2492 elements_kind = FAST_HOLEY_ELEMENTS; |
| 2481 } | 2493 } |
| 2482 | 2494 |
| 2483 if (initial_capacity >= 0) { | 2495 if (initial_capacity >= 0) { |
| 2484 for (int i = 0; i < initial_capacity; i++) { | 2496 for (int i = 0; i < initial_capacity; i++) { |
| 2485 HInstruction* key = Add<HConstant>(i); | 2497 HInstruction* key = Add<HConstant>(i); |
| 2486 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 2498 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
| 2487 } | 2499 } |
| 2488 } else { | 2500 } else { |
| 2489 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); | 2501 // Carefully loop backwards so that the "from" remains live through the loop |
| 2502 // rather than the to. This often corresponds to keeping length live rather | |
| 2503 // then capacity, which helps register allocation, since length is used more | |
| 2504 // other than capacity after filling with holes. | |
| 2505 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); | |
| 2490 | 2506 |
| 2491 HValue* key = builder.BeginBody(from, to, Token::LT); | 2507 HValue* key = builder.BeginBody(to, from, Token::GT); |
| 2492 | 2508 |
| 2493 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 2509 HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1()); |
| 2510 adjusted_key->ClearFlag(HValue::kCanOverflow); | |
| 2511 | |
| 2512 Add<HStoreKeyed>(elements, adjusted_key, hole, elements_kind); | |
| 2494 | 2513 |
| 2495 builder.EndBody(); | 2514 builder.EndBody(); |
| 2496 } | 2515 } |
| 2497 } | 2516 } |
| 2498 | 2517 |
| 2499 | 2518 |
| 2500 void HGraphBuilder::BuildCopyElements(HValue* from_elements, | 2519 void HGraphBuilder::BuildCopyElements(HValue* array, |
| 2520 HValue* from_elements, | |
| 2501 ElementsKind from_elements_kind, | 2521 ElementsKind from_elements_kind, |
| 2502 HValue* to_elements, | 2522 HValue* to_elements, |
| 2503 ElementsKind to_elements_kind, | 2523 ElementsKind to_elements_kind, |
| 2504 HValue* length, | 2524 HValue* length, |
| 2505 HValue* capacity) { | 2525 HValue* capacity) { |
| 2506 bool pre_fill_with_holes = | 2526 int constant_capacity = -1; |
| 2527 if (capacity != NULL && | |
| 2528 capacity->IsConstant() && | |
| 2529 HConstant::cast(capacity)->HasInteger32Value()) { | |
| 2530 int constant_candidate = HConstant::cast(capacity)->Integer32Value(); | |
| 2531 if (constant_candidate <= | |
| 2532 FastCloneShallowArrayStub::kMaximumInlinedCloneLength) { | |
| 2533 constant_capacity = constant_candidate; | |
| 2534 } | |
| 2535 } | |
| 2536 | |
| 2537 if (constant_capacity != -1) { | |
| 2538 // Unroll the loop for small elements kinds. | |
| 2539 for (int i = 0; i < constant_capacity; i++) { | |
| 2540 HValue* key_constant = Add<HConstant>(i); | |
| 2541 HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant, | |
| 2542 static_cast<HValue*>(NULL), | |
| 2543 from_elements_kind); | |
| 2544 Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind); | |
| 2545 } | |
| 2546 } else { | |
| 2547 bool pre_fill_with_holes = | |
| 2507 IsFastDoubleElementsKind(from_elements_kind) && | 2548 IsFastDoubleElementsKind(from_elements_kind) && |
| 2508 IsFastObjectElementsKind(to_elements_kind); | 2549 IsFastObjectElementsKind(to_elements_kind); |
| 2509 | 2550 |
| 2510 if (pre_fill_with_holes) { | 2551 if (pre_fill_with_holes) { |
| 2511 // If the copy might trigger a GC, make sure that the FixedArray is | 2552 // If the copy might trigger a GC, make sure that the FixedArray is |
| 2512 // pre-initialized with holes to make sure that it's always in a consistent | 2553 // pre-initialized with holes to make sure that it's always in a |
| 2513 // state. | 2554 // consistent state. |
| 2514 BuildFillElementsWithHole(to_elements, to_elements_kind, | 2555 BuildFillElementsWithHole(to_elements, to_elements_kind, |
| 2515 graph()->GetConstant0(), capacity); | 2556 graph()->GetConstant0(), NULL); |
| 2557 } else if (capacity == NULL || !length->Equals(capacity)) { | |
| 2558 BuildFillElementsWithHole(to_elements, to_elements_kind, | |
| 2559 length, NULL); | |
| 2560 } | |
| 2561 | |
| 2562 if (capacity == NULL) capacity = AddLoadFixedArrayLength(to_elements); | |
|
mvstanton
2014/05/09 13:16:49
nit: same here.
danno
2014/05/09 15:51:25
Done.
| |
| 2563 | |
| 2564 LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement); | |
| 2565 | |
| 2566 HValue* key = builder.BeginBody(length, graph()->GetConstant0(), | |
| 2567 Token::GT); | |
| 2568 | |
| 2569 key = AddUncasted<HSub>(key, graph()->GetConstant1()); | |
| 2570 key->ClearFlag(HValue::kCanOverflow); | |
| 2571 | |
| 2572 HValue* element = Add<HLoadKeyed>(from_elements, key, | |
| 2573 static_cast<HValue*>(NULL), | |
| 2574 from_elements_kind, | |
| 2575 ALLOW_RETURN_HOLE); | |
| 2576 | |
| 2577 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && | |
| 2578 IsFastSmiElementsKind(to_elements_kind)) | |
| 2579 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | |
| 2580 | |
| 2581 if (IsHoleyElementsKind(from_elements_kind) && | |
| 2582 from_elements_kind != to_elements_kind) { | |
| 2583 IfBuilder if_hole(this); | |
| 2584 if_hole.If<HCompareHoleAndBranch>(element); | |
| 2585 if_hole.Then(); | |
| 2586 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) | |
| 2587 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) | |
| 2588 : graph()->GetConstantHole(); | |
| 2589 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); | |
| 2590 if_hole.Else(); | |
| 2591 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | |
| 2592 store->SetFlag(HValue::kAllowUndefinedAsNaN); | |
| 2593 if_hole.End(); | |
| 2594 } else { | |
| 2595 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | |
| 2596 store->SetFlag(HValue::kAllowUndefinedAsNaN); | |
| 2597 } | |
| 2598 | |
| 2599 builder.EndBody(); | |
| 2516 } | 2600 } |
| 2517 | 2601 |
| 2518 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); | 2602 Counters* counters = isolate()->counters(); |
| 2603 AddIncrementCounter(counters->inlined_copyied_elements()); | |
| 2604 } | |
| 2519 | 2605 |
| 2520 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); | 2606 HValue* HGraphBuilder::BuildCloneShallowArrayCommon( |
| 2521 | 2607 HValue* boilerplate, |
| 2522 HValue* element = Add<HLoadKeyed>(from_elements, key, | 2608 HValue* allocation_site, |
| 2523 static_cast<HValue*>(NULL), | 2609 HValue* extra_size, |
| 2524 from_elements_kind, | 2610 HValue** return_elements, |
| 2525 ALLOW_RETURN_HOLE); | 2611 AllocationSiteMode mode) { |
| 2526 | 2612 // All sizes here are multiples of kPointerSize. |
| 2527 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) && | 2613 int array_size = JSArray::kSize; |
| 2528 IsFastSmiElementsKind(to_elements_kind)) | 2614 if (mode == TRACK_ALLOCATION_SITE) { |
| 2529 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 2615 array_size += AllocationMemento::kSize; |
| 2530 | |
| 2531 if (IsHoleyElementsKind(from_elements_kind) && | |
| 2532 from_elements_kind != to_elements_kind) { | |
| 2533 IfBuilder if_hole(this); | |
| 2534 if_hole.If<HCompareHoleAndBranch>(element); | |
| 2535 if_hole.Then(); | |
| 2536 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) | |
| 2537 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double()) | |
| 2538 : graph()->GetConstantHole(); | |
| 2539 Add<HStoreKeyed>(to_elements, key, hole_constant, kind); | |
| 2540 if_hole.Else(); | |
| 2541 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | |
| 2542 store->SetFlag(HValue::kAllowUndefinedAsNaN); | |
| 2543 if_hole.End(); | |
| 2544 } else { | |
| 2545 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind); | |
| 2546 store->SetFlag(HValue::kAllowUndefinedAsNaN); | |
| 2547 } | 2616 } |
| 2548 | 2617 |
| 2549 builder.EndBody(); | 2618 HValue* size_in_bytes = Add<HConstant>(array_size); |
| 2550 | 2619 if (extra_size != NULL) { |
| 2551 if (!pre_fill_with_holes && length != capacity) { | 2620 size_in_bytes = AddUncasted<HAdd>(extra_size, size_in_bytes); |
| 2552 // Fill unused capacity with the hole. | 2621 size_in_bytes->ClearFlag(HValue::kCanOverflow); |
| 2553 BuildFillElementsWithHole(to_elements, to_elements_kind, | |
| 2554 key, capacity); | |
| 2555 } | |
| 2556 } | |
| 2557 | |
| 2558 | |
| 2559 HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, | |
| 2560 HValue* allocation_site, | |
| 2561 AllocationSiteMode mode, | |
| 2562 ElementsKind kind, | |
| 2563 int length) { | |
| 2564 NoObservableSideEffectsScope no_effects(this); | |
| 2565 | |
| 2566 // All sizes here are multiples of kPointerSize. | |
| 2567 int size = JSArray::kSize; | |
| 2568 if (mode == TRACK_ALLOCATION_SITE) { | |
| 2569 size += AllocationMemento::kSize; | |
| 2570 } | 2622 } |
| 2571 | 2623 |
| 2572 HValue* size_in_bytes = Add<HConstant>(size); | |
| 2573 HInstruction* object = Add<HAllocate>(size_in_bytes, | 2624 HInstruction* object = Add<HAllocate>(size_in_bytes, |
| 2574 HType::JSObject(), | 2625 HType::JSObject(), |
| 2575 NOT_TENURED, | 2626 NOT_TENURED, |
| 2576 JS_OBJECT_TYPE); | 2627 JS_OBJECT_TYPE); |
| 2577 | 2628 |
| 2578 // Copy the JS array part. | 2629 // Copy the JS array part. |
| 2579 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 2630 HValue* map = Add<HLoadNamedField>(boilerplate, |
| 2580 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 2631 static_cast<HValue*>(NULL), HObjectAccess::ForMap()); |
| 2581 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 2632 Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(), |
| 2582 Add<HStoreNamedField>( | 2633 Add<HConstant>(isolate()->factory()->empty_fixed_array()), |
| 2583 object, access, Add<HLoadNamedField>( | 2634 INITIALIZING_STORE); |
| 2584 boilerplate, static_cast<HValue*>(NULL), access)); | 2635 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map, |
| 2585 } | 2636 INITIALIZING_STORE); |
| 2586 } | |
| 2587 | 2637 |
| 2588 // Create an allocation site info if requested. | 2638 // Create an allocation site info if requested. |
| 2589 if (mode == TRACK_ALLOCATION_SITE) { | 2639 if (mode == TRACK_ALLOCATION_SITE) { |
| 2590 BuildCreateAllocationMemento( | 2640 BuildCreateAllocationMemento( |
| 2591 object, Add<HConstant>(JSArray::kSize), allocation_site); | 2641 object, Add<HConstant>(JSArray::kSize), allocation_site); |
| 2592 } | 2642 } |
| 2593 | 2643 |
| 2594 if (length > 0) { | 2644 if (extra_size != NULL) { |
| 2595 // We have to initialize the elements pointer if allocation folding is | 2645 HValue* elements = Add<HInnerAllocatedObject>(object, |
| 2596 // turned off. | 2646 Add<HConstant>(array_size)); |
| 2597 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { | 2647 if (return_elements != NULL) *return_elements = elements; |
| 2598 HConstant* empty_fixed_array = Add<HConstant>( | |
| 2599 isolate()->factory()->empty_fixed_array()); | |
| 2600 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | |
| 2601 empty_fixed_array, INITIALIZING_STORE); | |
| 2602 } | |
| 2603 | |
| 2604 HValue* boilerplate_elements = AddLoadElements(boilerplate); | |
| 2605 HValue* object_elements; | |
| 2606 if (IsFastDoubleElementsKind(kind)) { | |
| 2607 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); | |
| 2608 object_elements = Add<HAllocate>(elems_size, HType::Tagged(), | |
| 2609 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); | |
| 2610 } else { | |
| 2611 HValue* elems_size = Add<HConstant>(FixedArray::SizeFor(length)); | |
| 2612 object_elements = Add<HAllocate>(elems_size, HType::Tagged(), | |
| 2613 NOT_TENURED, FIXED_ARRAY_TYPE); | |
| 2614 } | |
| 2615 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | |
| 2616 object_elements); | |
| 2617 | |
| 2618 // Copy the elements array header. | |
| 2619 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | |
| 2620 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | |
| 2621 Add<HStoreNamedField>( | |
| 2622 object_elements, access, Add<HLoadNamedField>( | |
| 2623 boilerplate_elements, static_cast<HValue*>(NULL), access)); | |
| 2624 } | |
| 2625 | |
| 2626 // Copy the elements array contents. | |
| 2627 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold | |
| 2628 // copying loops with constant length up to a given boundary and use this | |
| 2629 // helper here instead. | |
| 2630 for (int i = 0; i < length; i++) { | |
| 2631 HValue* key_constant = Add<HConstant>(i); | |
| 2632 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, | |
| 2633 static_cast<HValue*>(NULL), kind); | |
| 2634 Add<HStoreKeyed>(object_elements, key_constant, value, kind); | |
| 2635 } | |
| 2636 } | 2648 } |
| 2637 | 2649 |
| 2638 return object; | 2650 return object; |
| 2639 } | 2651 } |
| 2640 | 2652 |
| 2641 | 2653 |
| 2654 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate, | |
| 2655 HValue* allocation_site, | |
| 2656 AllocationSiteMode mode, | |
| 2657 ElementsKind kind) { | |
| 2658 HValue* result = BuildCloneShallowArrayCommon(boilerplate, | |
| 2659 allocation_site, NULL, NULL, mode); | |
| 2660 | |
| 2661 HValue* elements = AddLoadElements(boilerplate); | |
| 2662 HObjectAccess access = HObjectAccess::ForElementsPointer(); | |
| 2663 Add<HStoreNamedField>(result, access, elements, INITIALIZING_STORE); | |
| 2664 | |
| 2665 HValue* length = AddLoadArrayLength(boilerplate, kind); | |
| 2666 access = HObjectAccess::ForArrayLength(kind); | |
| 2667 Add<HStoreNamedField>(result, access, length, INITIALIZING_STORE); | |
| 2668 | |
| 2669 return result; | |
| 2670 } | |
| 2671 | |
| 2672 | |
| 2673 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate, | |
| 2674 HValue* allocation_site, | |
| 2675 AllocationSiteMode mode) { | |
| 2676 HValue* result = BuildCloneShallowArrayCommon(boilerplate, | |
| 2677 allocation_site, NULL, NULL, mode); | |
| 2678 | |
| 2679 HObjectAccess access = HObjectAccess::ForArrayLength(FAST_ELEMENTS); | |
| 2680 Add<HStoreNamedField>(result, access, graph()->GetConstant0(), | |
| 2681 INITIALIZING_STORE); | |
| 2682 access = HObjectAccess::ForElementsPointer(); | |
| 2683 Add<HStoreNamedField>(result, access, | |
| 2684 Add<HConstant>(isolate()->factory()->empty_fixed_array()), | |
| 2685 INITIALIZING_STORE); | |
| 2686 | |
| 2687 return result; | |
| 2688 } | |
| 2689 | |
| 2690 | |
| 2691 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate, | |
| 2692 HValue* allocation_site, | |
| 2693 AllocationSiteMode mode, | |
| 2694 ElementsKind kind) { | |
| 2695 int elements_kind_size = IsFastDoubleElementsKind(kind) | |
| 2696 ? kDoubleSize : kPointerSize; | |
| 2697 | |
| 2698 HValue* boilerplate_elements = AddLoadElements(boilerplate); | |
| 2699 HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements); | |
| 2700 HValue* extra = AddUncasted<HMul>(capacity, | |
| 2701 Add<HConstant>(elements_kind_size)); | |
| 2702 extra->ClearFlag(HValue::kCanOverflow); | |
| 2703 extra = AddUncasted<HAdd>(extra, Add<HConstant>(FixedArray::kHeaderSize)); | |
| 2704 extra->ClearFlag(HValue::kCanOverflow); | |
| 2705 HValue* elements = NULL; | |
| 2706 HValue* result = BuildCloneShallowArrayCommon(boilerplate, | |
| 2707 allocation_site, extra, &elements, mode); | |
| 2708 Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), | |
| 2709 elements, INITIALIZING_STORE); | |
| 2710 | |
| 2711 boilerplate_elements = AddLoadElements(boilerplate); | |
| 2712 boilerplate_elements->SetFlag(HValue::kCantBeReplaced); | |
|
mvstanton
2014/05/09 13:16:49
Can you comment the motivation for using kCantBeRe
danno
2014/05/09 15:51:25
Done.
| |
| 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 | |
| 2642 void HGraphBuilder::BuildCompareNil( | 2736 void HGraphBuilder::BuildCompareNil( |
| 2643 HValue* value, | 2737 HValue* value, |
| 2644 Type* type, | 2738 Type* type, |
| 2645 HIfContinuation* continuation) { | 2739 HIfContinuation* continuation) { |
| 2646 IfBuilder if_nil(this); | 2740 IfBuilder if_nil(this); |
| 2647 bool some_case_handled = false; | 2741 bool some_case_handled = false; |
| 2648 bool some_case_missing = false; | 2742 bool some_case_missing = false; |
| 2649 | 2743 |
| 2650 if (type->Maybe(Type::Null())) { | 2744 if (type->Maybe(Type::Null())) { |
| 2651 if (some_case_handled) if_nil.Or(); | 2745 if (some_case_handled) if_nil.Or(); |
| (...skipping 9021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11673 if (ShouldProduceTraceOutput()) { | 11767 if (ShouldProduceTraceOutput()) { |
| 11674 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11768 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11675 } | 11769 } |
| 11676 | 11770 |
| 11677 #ifdef DEBUG | 11771 #ifdef DEBUG |
| 11678 graph_->Verify(false); // No full verify. | 11772 graph_->Verify(false); // No full verify. |
| 11679 #endif | 11773 #endif |
| 11680 } | 11774 } |
| 11681 | 11775 |
| 11682 } } // namespace v8::internal | 11776 } } // namespace v8::internal |
| OLD | NEW |