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