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

Side by Side Diff: src/crankshaft/hydrogen.cc

Issue 2117383002: Cleanup array constructor inlining in crankshaft (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments Created 4 years, 5 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
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | no next file » | 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 "src/crankshaft/hydrogen.h" 5 #include "src/crankshaft/hydrogen.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "src/allocation-site-scopes.h" 9 #include "src/allocation-site-scopes.h"
10 #include "src/ast/ast-numbering.h" 10 #include "src/ast/ast-numbering.h"
(...skipping 2862 matching lines...) Expand 10 before | Expand all | Expand 10 after
2873 elements, isolate()->factory()->fixed_array_map()); 2873 elements, isolate()->factory()->fixed_array_map());
2874 check_cow_map->ClearDependsOnFlag(kElementsKind); 2874 check_cow_map->ClearDependsOnFlag(kElementsKind);
2875 } 2875 }
2876 } 2876 }
2877 } 2877 }
2878 return AddElementAccess(elements, checked_key, val, checked_object, nullptr, 2878 return AddElementAccess(elements, checked_key, val, checked_object, nullptr,
2879 elements_kind, access_type, load_mode); 2879 elements_kind, access_type, load_mode);
2880 } 2880 }
2881 2881
2882 2882
2883 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2884 JSArrayBuilder* array_builder,
2885 HValue* length_argument) {
2886 if (length_argument->IsConstant() &&
2887 HConstant::cast(length_argument)->HasSmiValue()) {
2888 int array_length = HConstant::cast(length_argument)->Integer32Value();
2889 if (array_length == 0) {
2890 return array_builder->AllocateEmptyArray();
2891 } else {
2892 return array_builder->AllocateArray(length_argument,
2893 length_argument);
2894 }
2895 }
2896
2897 HValue* constant_zero = graph()->GetConstant0();
2898 HConstant* max_alloc_length =
2899 Add<HConstant>(JSArray::kInitialMaxFastElementArray);
2900 HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
2901 max_alloc_length);
2902 IfBuilder if_builder(this);
2903 if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
2904 Token::EQ);
2905 if_builder.Then();
2906 const int initial_capacity = JSArray::kPreallocatedArrayElements;
2907 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
2908 Push(initial_capacity_node); // capacity
2909 Push(constant_zero); // length
2910 if_builder.Else();
2911 if (!(top_info()->IsStub()) &&
2912 IsFastPackedElementsKind(array_builder->kind())) {
2913 // We'll come back later with better (holey) feedback.
2914 if_builder.Deopt(
2915 Deoptimizer::kHoleyArrayDespitePackedElements_kindFeedback);
2916 } else {
2917 Push(checked_length); // capacity
2918 Push(checked_length); // length
2919 }
2920 if_builder.End();
2921
2922 // Figure out total size
2923 HValue* length = Pop();
2924 HValue* capacity = Pop();
2925 return array_builder->AllocateArray(capacity, length);
2926 }
2927
2928
2929 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind, 2883 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
2930 HValue* capacity) { 2884 HValue* capacity) {
2931 int elements_size = IsFastDoubleElementsKind(kind) 2885 int elements_size = IsFastDoubleElementsKind(kind)
2932 ? kDoubleSize 2886 ? kDoubleSize
2933 : kPointerSize; 2887 : kPointerSize;
2934 2888
2935 HConstant* elements_size_value = Add<HConstant>(elements_size); 2889 HConstant* elements_size_value = Add<HConstant>(elements_size);
2936 HInstruction* mul = 2890 HInstruction* mul =
2937 HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(), 2891 HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(),
2938 elements_size_value); 2892 elements_size_value);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3009 2963
3010 void HGraphBuilder::BuildJSArrayHeader(HValue* array, 2964 void HGraphBuilder::BuildJSArrayHeader(HValue* array,
3011 HValue* array_map, 2965 HValue* array_map,
3012 HValue* elements, 2966 HValue* elements,
3013 AllocationSiteMode mode, 2967 AllocationSiteMode mode,
3014 ElementsKind elements_kind, 2968 ElementsKind elements_kind,
3015 HValue* allocation_site_payload, 2969 HValue* allocation_site_payload,
3016 HValue* length_field) { 2970 HValue* length_field) {
3017 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map); 2971 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
3018 2972
3019 HConstant* empty_fixed_array = 2973 HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
3020 Add<HConstant>(isolate()->factory()->empty_fixed_array());
3021 2974
3022 Add<HStoreNamedField>( 2975 Add<HStoreNamedField>(
3023 array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array); 2976 array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
3024 2977
3025 Add<HStoreNamedField>( 2978 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(),
3026 array, HObjectAccess::ForElementsPointer(), 2979 elements != nullptr ? elements : empty_fixed_array);
3027 elements != NULL ? elements : empty_fixed_array);
3028 2980
3029 Add<HStoreNamedField>( 2981 Add<HStoreNamedField>(
3030 array, HObjectAccess::ForArrayLength(elements_kind), length_field); 2982 array, HObjectAccess::ForArrayLength(elements_kind), length_field);
3031 2983
3032 if (mode == TRACK_ALLOCATION_SITE) { 2984 if (mode == TRACK_ALLOCATION_SITE) {
3033 BuildCreateAllocationMemento( 2985 BuildCreateAllocationMemento(
3034 array, Add<HConstant>(JSArray::kSize), allocation_site_payload); 2986 array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
3035 } 2987 }
3036 } 2988 }
3037 2989
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
3528 was_neutered_test, graph()->GetConstant0(), Token::NE); 3480 was_neutered_test, graph()->GetConstant0(), Token::NE);
3529 if_was_neutered.Then(); 3481 if_was_neutered.Then();
3530 Push(graph()->GetConstant0()); 3482 Push(graph()->GetConstant0());
3531 if_was_neutered.Else(); 3483 if_was_neutered.Else();
3532 Push(field); 3484 Push(field);
3533 if_was_neutered.End(); 3485 if_was_neutered.End();
3534 3486
3535 return Pop(); 3487 return Pop();
3536 } 3488 }
3537 3489
3538
3539 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3540 ElementsKind kind,
3541 HValue* allocation_site_payload,
3542 HValue* constructor_function,
3543 AllocationSiteOverrideMode override_mode) :
3544 builder_(builder),
3545 kind_(kind),
3546 allocation_site_payload_(allocation_site_payload),
3547 constructor_function_(constructor_function) {
3548 DCHECK(!allocation_site_payload->IsConstant() ||
3549 HConstant::cast(allocation_site_payload)->handle(
3550 builder_->isolate())->IsAllocationSite());
3551 mode_ = override_mode == DISABLE_ALLOCATION_SITES
3552 ? DONT_TRACK_ALLOCATION_SITE
3553 : AllocationSite::GetMode(kind);
3554 }
3555
3556
3557 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3558 ElementsKind kind,
3559 HValue* constructor_function) :
3560 builder_(builder),
3561 kind_(kind),
3562 mode_(DONT_TRACK_ALLOCATION_SITE),
3563 allocation_site_payload_(NULL),
3564 constructor_function_(constructor_function) {
3565 }
3566
3567
3568 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
3569 if (!builder()->top_info()->IsStub()) {
3570 // A constant map is fine.
3571 Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
3572 builder()->isolate());
3573 return builder()->Add<HConstant>(map);
3574 }
3575
3576 if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
3577 // No need for a context lookup if the kind_ matches the initial
3578 // map, because we can just load the map in that case.
3579 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3580 return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
3581 access);
3582 }
3583
3584 // TODO(mvstanton): we should always have a constructor function if we
3585 // are creating a stub.
3586 HInstruction* native_context = constructor_function_ != NULL
3587 ? builder()->BuildGetNativeContext(constructor_function_)
3588 : builder()->BuildGetNativeContext();
3589
3590 HObjectAccess access =
3591 HObjectAccess::ForContextSlot(Context::ArrayMapIndex(kind_));
3592 return builder()->Add<HLoadNamedField>(native_context, nullptr, access);
3593 }
3594
3595
3596 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
3597 // Find the map near the constructor function
3598 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3599 return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
3600 access);
3601 }
3602
3603
3604 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
3605 HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
3606 return AllocateArray(capacity,
3607 builder()->graph()->GetConstant0());
3608 }
3609
3610
3611 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3612 HValue* capacity,
3613 HValue* length_field,
3614 FillMode fill_mode) {
3615 // These HForceRepresentations are because we store these as fields in the
3616 // objects we construct, and an int32-to-smi HChange could deopt. Accept
3617 // the deopt possibility now, before allocation occurs.
3618 capacity =
3619 builder()->AddUncasted<HForceRepresentation>(capacity,
3620 Representation::Smi());
3621 length_field =
3622 builder()->AddUncasted<HForceRepresentation>(length_field,
3623 Representation::Smi());
3624
3625 // Generate size calculation code here in order to make it dominate
3626 // the JSArray allocation.
3627 HValue* elements_size =
3628 builder()->BuildCalculateElementsSize(kind_, capacity);
3629
3630 // Bail out for large objects.
3631 HValue* max_regular_heap_object_size =
3632 builder()->Add<HConstant>(Page::kMaxRegularHeapObjectSize);
3633 builder()->Add<HBoundsCheck>(elements_size, max_regular_heap_object_size);
3634
3635 // Allocate (dealing with failure appropriately)
3636 HAllocate* array_object = builder()->AllocateJSArrayObject(mode_);
3637
3638 // Fill in the fields: map, properties, length
3639 HValue* map;
3640 if (allocation_site_payload_ == NULL) {
3641 map = EmitInternalMapCode();
3642 } else {
3643 map = EmitMapCode();
3644 }
3645
3646 builder()->BuildJSArrayHeader(array_object,
3647 map,
3648 NULL, // set elements to empty fixed array
3649 mode_,
3650 kind_,
3651 allocation_site_payload_,
3652 length_field);
3653
3654 // Allocate and initialize the elements
3655 elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);
3656
3657 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
3658
3659 // Set the elements
3660 builder()->Add<HStoreNamedField>(
3661 array_object, HObjectAccess::ForElementsPointer(), elements_location_);
3662
3663 if (fill_mode == FILL_WITH_HOLE) {
3664 builder()->BuildFillElementsWithHole(elements_location_, kind_,
3665 graph()->GetConstant0(), capacity);
3666 }
3667
3668 return array_object;
3669 }
3670
3671
3672 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) { 3490 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) {
3673 HValue* native_context = BuildGetNativeContext(); 3491 HValue* native_context = BuildGetNativeContext();
3674 HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index); 3492 HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index);
3675 return Add<HLoadNamedField>(native_context, nullptr, function_access); 3493 return Add<HLoadNamedField>(native_context, nullptr, function_access);
3676 } 3494 }
3677 3495
3678 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) 3496 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
3679 : HGraphBuilder(info, CallInterfaceDescriptor()), 3497 : HGraphBuilder(info, CallInterfaceDescriptor()),
3680 function_state_(NULL), 3498 function_state_(NULL),
3681 initial_function_state_(this, info, NORMAL_RETURN, 0, 3499 initial_function_state_(this, info, NORMAL_RETURN, 0,
(...skipping 6015 matching lines...) Expand 10 before | Expand all | Expand 10 after
9697 // Cannot embed a direct reference to the global proxy 9515 // Cannot embed a direct reference to the global proxy
9698 // as is it dropped on deserialization. 9516 // as is it dropped on deserialization.
9699 CHECK(!isolate()->serializer_enabled()); 9517 CHECK(!isolate()->serializer_enabled());
9700 Handle<JSObject> global_proxy(target->context()->global_proxy()); 9518 Handle<JSObject> global_proxy(target->context()->global_proxy());
9701 return Add<HConstant>(global_proxy); 9519 return Add<HConstant>(global_proxy);
9702 } 9520 }
9703 return graph()->GetConstantUndefined(); 9521 return graph()->GetConstantUndefined();
9704 } 9522 }
9705 9523
9706 9524
9707 void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
9708 int arguments_count,
9709 HValue* function,
9710 Handle<AllocationSite> site) {
9711 Add<HCheckValue>(function, array_function());
9712
9713 if (IsCallArrayInlineable(arguments_count, site)) {
9714 BuildInlinedCallArray(expression, arguments_count, site);
9715 return;
9716 }
9717
9718 HInstruction* call = PreProcessCall(New<HCallNewArray>(
9719 function, arguments_count + 1, site->GetElementsKind(), site));
9720 if (expression->IsCall()) {
9721 Drop(1);
9722 }
9723 ast_context()->ReturnInstruction(call, expression->id());
9724 }
9725
9726
9727 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver, 9525 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
9728 HValue* search_element, 9526 HValue* search_element,
9729 ElementsKind kind, 9527 ElementsKind kind,
9730 ArrayIndexOfMode mode) { 9528 ArrayIndexOfMode mode) {
9731 DCHECK(IsFastElementsKind(kind)); 9529 DCHECK(IsFastElementsKind(kind));
9732 9530
9733 NoObservableSideEffectsScope no_effects(this); 9531 NoObservableSideEffectsScope no_effects(this);
9734 9532
9735 HValue* elements = AddLoadElements(receiver); 9533 HValue* elements = AddLoadElements(receiver);
9736 HValue* length = AddLoadArrayLength(receiver, kind); 9534 HValue* length = AddLoadArrayLength(receiver, kind);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
9863 loop.EndBody(); 9661 loop.EndBody();
9864 } 9662 }
9865 if_isnumber.End(); 9663 if_isnumber.End();
9866 } 9664 }
9867 if_isstring.End(); 9665 if_isstring.End();
9868 } 9666 }
9869 9667
9870 return Pop(); 9668 return Pop();
9871 } 9669 }
9872 9670
9873 9671 template <class T>
9874 bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) { 9672 bool HOptimizedGraphBuilder::TryHandleArrayCall(T* expr, HValue* function) {
9875 if (!array_function().is_identical_to(expr->target())) { 9673 if (!array_function().is_identical_to(expr->target())) {
9876 return false; 9674 return false;
9877 } 9675 }
9878 9676
9879 Handle<AllocationSite> site = expr->allocation_site(); 9677 Handle<AllocationSite> site = expr->allocation_site();
9880 if (site.is_null()) return false; 9678 if (site.is_null()) return false;
9881 9679
9882 BuildArrayCall(expr, 9680 Add<HCheckValue>(function, array_function());
9883 expr->arguments()->length(), 9681
9884 function, 9682 int arguments_count = expr->arguments()->length();
9885 site); 9683 if (TryInlineArrayCall(expr, arguments_count, site)) return true;
9684
9685 HInstruction* call = PreProcessCall(New<HCallNewArray>(
9686 function, arguments_count + 1, site->GetElementsKind(), site));
9687 if (expr->IsCall()) Drop(1);
9688 ast_context()->ReturnInstruction(call, expr->id());
9689
9886 return true; 9690 return true;
9887 } 9691 }
9888 9692
9889
9890 bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
9891 HValue* function) {
9892 if (!array_function().is_identical_to(expr->target())) {
9893 return false;
9894 }
9895
9896 Handle<AllocationSite> site = expr->allocation_site();
9897 if (site.is_null()) return false;
9898
9899 BuildArrayCall(expr, expr->arguments()->length(), function, site);
9900 return true;
9901 }
9902
9903 9693
9904 bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) { 9694 bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) {
9905 ZoneList<Expression*>* args = expr->arguments(); 9695 ZoneList<Expression*>* args = expr->arguments();
9906 if (args->length() != 2) return false; 9696 if (args->length() != 2) return false;
9907 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 9697 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
9908 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 9698 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
9909 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); 9699 HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
9910 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 9700 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
9911 return true; 9701 return true;
9912 } 9702 }
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
10075 function, argument_count, syntactic_tail_call_mode, 9865 function, argument_count, syntactic_tail_call_mode,
10076 ConvertReceiverMode::kNullOrUndefined, tail_call_mode); 9866 ConvertReceiverMode::kNullOrUndefined, tail_call_mode);
10077 } 9867 }
10078 } 9868 }
10079 } 9869 }
10080 9870
10081 Drop(1); // Drop the function. 9871 Drop(1); // Drop the function.
10082 return ast_context()->ReturnInstruction(call, expr->id()); 9872 return ast_context()->ReturnInstruction(call, expr->id());
10083 } 9873 }
10084 9874
9875 bool HOptimizedGraphBuilder::TryInlineArrayCall(Expression* expression,
9876 int argument_count,
9877 Handle<AllocationSite> site) {
9878 Handle<JSFunction> caller = current_info()->closure();
9879 Handle<JSFunction> target = array_function();
10085 9880
10086 void HOptimizedGraphBuilder::BuildInlinedCallArray( 9881 if (!site->CanInlineCall()) {
10087 Expression* expression, 9882 TraceInline(target, caller, "AllocationSite requested no inlining.");
10088 int argument_count, 9883 return false;
10089 Handle<AllocationSite> site) { 9884 }
10090 DCHECK(!site.is_null()); 9885
10091 DCHECK(argument_count >= 0 && argument_count <= 1); 9886 if (argument_count > 1) {
9887 TraceInline(target, caller, "Too many arguments to inline.");
9888 return false;
9889 }
9890
9891 int array_length = 0;
9892 // Do not inline if the constant length argument is not a smi or outside the
9893 // valid range for unrolled loop initialization.
9894 if (argument_count == 1) {
9895 HValue* argument = Top();
9896 if (!argument->IsConstant()) {
9897 TraceInline(target, caller,
9898 "Dont inline [new] Array(n) where n isn't constant.");
9899 return false;
9900 }
9901
9902 HConstant* constant_argument = HConstant::cast(argument);
9903 if (!constant_argument->HasSmiValue()) {
9904 TraceInline(target, caller,
9905 "Constant length outside of valid inlining range.");
9906 return false;
9907 }
9908 array_length = constant_argument->Integer32Value();
9909 if (array_length < 0 || array_length > kElementLoopUnrollThreshold) {
9910 TraceInline(target, caller,
9911 "Constant length outside of valid inlining range.");
9912 return false;
9913 }
9914 }
9915
9916 TraceInline(target, caller, NULL);
9917
10092 NoObservableSideEffectsScope no_effects(this); 9918 NoObservableSideEffectsScope no_effects(this);
10093 9919
10094 // We should at least have the constructor on the expression stack.
10095 HValue* constructor = environment()->ExpressionStackAt(argument_count);
10096
10097 // Register on the site for deoptimization if the transition feedback changes. 9920 // Register on the site for deoptimization if the transition feedback changes.
10098 top_info()->dependencies()->AssumeTransitionStable(site); 9921 top_info()->dependencies()->AssumeTransitionStable(site);
9922
9923 // Build the array.
10099 ElementsKind kind = site->GetElementsKind(); 9924 ElementsKind kind = site->GetElementsKind();
10100 HInstruction* site_instruction = Add<HConstant>(site); 9925 HValue* capacity;
10101 9926 HValue* length;
10102 // In the single constant argument case, we may have to adjust elements kind 9927 if (array_length == 0) {
10103 // to avoid creating a packed non-empty array. 9928 STATIC_ASSERT(0 < JSArray::kPreallocatedArrayElements);
10104 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { 9929 const int initial_capacity = JSArray::kPreallocatedArrayElements;
10105 HValue* argument = environment()->Top(); 9930 capacity = Add<HConstant>(initial_capacity);
10106 if (argument->IsConstant()) { 9931 length = graph()->GetConstant0();
10107 HConstant* constant_argument = HConstant::cast(argument); 9932 } else {
10108 DCHECK(constant_argument->HasSmiValue()); 9933 length = Top();
10109 int constant_array_size = constant_argument->Integer32Value(); 9934 capacity = length;
10110 if (constant_array_size != 0) { 9935 kind = GetHoleyElementsKind(kind);
10111 kind = GetHoleyElementsKind(kind);
10112 }
10113 }
10114 } 9936 }
10115 9937
10116 // Build the array. 9938 // These HForceRepresentations are because we store these as fields in the
10117 JSArrayBuilder array_builder(this, 9939 // objects we construct, and an int32-to-smi HChange could deopt. Accept
10118 kind, 9940 // the deopt possibility now, before allocation occurs.
10119 site_instruction, 9941 length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
10120 constructor, 9942 capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
10121 DISABLE_ALLOCATION_SITES); 9943
10122 HValue* new_object = argument_count == 0 9944 // Generate size calculation code here in order to make it dominate
10123 ? array_builder.AllocateEmptyArray() 9945 // the JSArray allocation.
10124 : BuildAllocateArrayFromLength(&array_builder, Top()); 9946 HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
9947
9948 // Bail out for large objects.
9949 HValue* max_size = Add<HConstant>(Page::kMaxRegularHeapObjectSize);
9950 Add<HBoundsCheck>(elements_size, max_size);
9951
9952 // Allocate (dealing with failure appropriately).
9953 AllocationSiteMode mode = DONT_TRACK_ALLOCATION_SITE;
9954 HAllocate* new_object = AllocateJSArrayObject(mode);
9955
9956 // Fill in the fields: map, properties, length.
9957 Handle<Map> map_constant(isolate()->get_initial_js_array_map(kind));
9958 HValue* map = Add<HConstant>(map_constant);
9959
9960 BuildJSArrayHeader(new_object, map,
9961 nullptr, // set elements to empty fixed array
9962 mode, kind, nullptr, length);
9963
9964 // Allocate and initialize the elements.
9965 HAllocate* elements = BuildAllocateElements(kind, elements_size);
9966 BuildInitializeElementsHeader(elements, kind, capacity);
9967 BuildFillElementsWithHole(elements, kind, graph()->GetConstant0(), capacity);
9968
9969 // Set the elements.
9970 Add<HStoreNamedField>(new_object, HObjectAccess::ForElementsPointer(),
9971 elements);
10125 9972
10126 int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1); 9973 int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
10127 Drop(args_to_drop); 9974 Drop(args_to_drop);
10128 ast_context()->ReturnValue(new_object); 9975 ast_context()->ReturnValue(new_object);
9976 return true;
10129 } 9977 }
10130 9978
10131 9979
10132 // Checks whether allocation using the given constructor can be inlined. 9980 // Checks whether allocation using the given constructor can be inlined.
10133 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { 9981 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
10134 return constructor->has_initial_map() && 9982 return constructor->has_initial_map() &&
10135 !IsSubclassConstructor(constructor->shared()->kind()) && 9983 !IsSubclassConstructor(constructor->shared()->kind()) &&
10136 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && 9984 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
10137 constructor->initial_map()->instance_size() < 9985 constructor->initial_map()->instance_size() <
10138 HAllocate::kMaxInlineSize; 9986 HAllocate::kMaxInlineSize;
10139 } 9987 }
10140 9988
10141
10142 bool HOptimizedGraphBuilder::IsCallArrayInlineable(
10143 int argument_count,
10144 Handle<AllocationSite> site) {
10145 Handle<JSFunction> caller = current_info()->closure();
10146 Handle<JSFunction> target = array_function();
10147 // We should have the function plus array arguments on the environment stack.
10148 DCHECK(environment()->length() >= (argument_count + 1));
10149 DCHECK(!site.is_null());
10150
10151 bool inline_ok = false;
10152 if (site->CanInlineCall()) {
10153 // We also want to avoid inlining in certain 1 argument scenarios.
10154 if (argument_count == 1) {
10155 HValue* argument = Top();
10156 if (argument->IsConstant()) {
10157 // Do not inline if the constant length argument is not a smi or
10158 // outside the valid range for unrolled loop initialization.
10159 HConstant* constant_argument = HConstant::cast(argument);
10160 if (constant_argument->HasSmiValue()) {
10161 int value = constant_argument->Integer32Value();
10162 inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
10163 if (!inline_ok) {
10164 TraceInline(target, caller,
10165 "Constant length outside of valid inlining range.");
10166 }
10167 }
10168 } else {
10169 TraceInline(target, caller,
10170 "Dont inline [new] Array(n) where n isn't constant.");
10171 }
10172 } else if (argument_count == 0) {
10173 inline_ok = true;
10174 } else {
10175 TraceInline(target, caller, "Too many arguments to inline.");
10176 }
10177 } else {
10178 TraceInline(target, caller, "AllocationSite requested no inlining.");
10179 }
10180
10181 if (inline_ok) {
10182 TraceInline(target, caller, NULL);
10183 }
10184 return inline_ok;
10185 }
10186
10187
10188 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { 9989 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
10189 DCHECK(!HasStackOverflow()); 9990 DCHECK(!HasStackOverflow());
10190 DCHECK(current_block() != NULL); 9991 DCHECK(current_block() != NULL);
10191 DCHECK(current_block()->HasPredecessor()); 9992 DCHECK(current_block()->HasPredecessor());
10192 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); 9993 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
10193 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 9994 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
10194 Factory* factory = isolate()->factory(); 9995 Factory* factory = isolate()->factory();
10195 9996
10196 // The constructor function is on the stack in the unoptimized code 9997 // The constructor function is on the stack in the unoptimized code
10197 // during evaluation of the arguments. 9998 // during evaluation of the arguments.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
10271 HInstruction* instr = current_block()->last(); 10072 HInstruction* instr = current_block()->last();
10272 do { 10073 do {
10273 HInstruction* prev_instr = instr->previous(); 10074 HInstruction* prev_instr = instr->previous();
10274 instr->DeleteAndReplaceWith(NULL); 10075 instr->DeleteAndReplaceWith(NULL);
10275 instr = prev_instr; 10076 instr = prev_instr;
10276 } while (instr != check); 10077 } while (instr != check);
10277 environment()->SetExpressionStackAt(receiver_index, function); 10078 environment()->SetExpressionStackAt(receiver_index, function);
10278 } else { 10079 } else {
10279 // The constructor function is both an operand to the instruction and an 10080 // The constructor function is both an operand to the instruction and an
10280 // argument to the construct call. 10081 // argument to the construct call.
10281 if (TryHandleArrayCallNew(expr, function)) return; 10082 if (TryHandleArrayCall(expr, function)) return;
10282 } 10083 }
10283 10084
10284 HValue* arity = Add<HConstant>(argument_count - 1); 10085 HValue* arity = Add<HConstant>(argument_count - 1);
10285 HValue* op_vals[] = {context(), function, function, arity}; 10086 HValue* op_vals[] = {context(), function, function, arity};
10286 Callable callable = CodeFactory::Construct(isolate()); 10087 Callable callable = CodeFactory::Construct(isolate());
10287 HConstant* stub = Add<HConstant>(callable.code()); 10088 HConstant* stub = Add<HConstant>(callable.code());
10288 PushArgumentsFromEnvironment(argument_count); 10089 PushArgumentsFromEnvironment(argument_count);
10289 HInstruction* construct = New<HCallWithDescriptor>( 10090 HInstruction* construct = New<HCallWithDescriptor>(
10290 stub, argument_count, callable.descriptor(), ArrayVector(op_vals)); 10091 stub, argument_count, callable.descriptor(), ArrayVector(op_vals));
10291 return ast_context()->ReturnInstruction(construct, expr->id()); 10092 return ast_context()->ReturnInstruction(construct, expr->id());
(...skipping 3335 matching lines...) Expand 10 before | Expand all | Expand 10 after
13627 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 13428 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
13628 } 13429 }
13629 13430
13630 #ifdef DEBUG 13431 #ifdef DEBUG
13631 graph_->Verify(false); // No full verify. 13432 graph_->Verify(false); // No full verify.
13632 #endif 13433 #endif
13633 } 13434 }
13634 13435
13635 } // namespace internal 13436 } // namespace internal
13636 } // namespace v8 13437 } // namespace v8
OLDNEW
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698