| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
| (...skipping 3664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3675 } else { | 3675 } else { |
| 3676 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 3676 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
| 3677 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 3677 running_hash = StringHasher::ComputeRunningHash(running_hash, data, |
| 3678 raw_string->length()); | 3678 raw_string->length()); |
| 3679 } | 3679 } |
| 3680 } | 3680 } |
| 3681 | 3681 |
| 3682 return running_hash; | 3682 return running_hash; |
| 3683 } | 3683 } |
| 3684 | 3684 |
| 3685 namespace { | |
| 3686 | |
| 3687 bool OnlyLastArgIsSpread(ZoneList<Expression*>* args) { | |
| 3688 for (int i = 0; i < args->length() - 1; i++) { | |
| 3689 if (args->at(i)->IsSpread()) { | |
| 3690 return false; | |
| 3691 } | |
| 3692 } | |
| 3693 return args->at(args->length() - 1)->IsSpread(); | |
| 3694 } | |
| 3695 | |
| 3696 } // namespace | |
| 3697 | |
| 3698 ZoneList<Expression*>* Parser::PrepareSpreadArguments( | 3685 ZoneList<Expression*>* Parser::PrepareSpreadArguments( |
| 3699 ZoneList<Expression*>* list) { | 3686 ZoneList<Expression*>* list) { |
| 3700 // Here we only deal with multiple arguments where the spread is not at the | 3687 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); |
| 3701 // end, or there are multiple spreads. | 3688 if (list->length() == 1) { |
| 3702 DCHECK_GT(list->length(), 1); | 3689 // Spread-call with single spread argument produces an InternalArray |
| 3703 DCHECK(!OnlyLastArgIsSpread(list)); | 3690 // containing the values from the array. |
| 3691 // |
| 3692 // Function is called or constructed with the produced array of arguments |
| 3693 // |
| 3694 // EG: Apply(Func, Spread(spread0)) |
| 3695 ZoneList<Expression*>* spread_list = |
| 3696 new (zone()) ZoneList<Expression*>(0, zone()); |
| 3697 spread_list->Add(list->at(0)->AsSpread()->expression(), zone()); |
| 3698 args->Add(factory()->NewCallRuntime(Runtime::kSpreadIterablePrepare, |
| 3699 spread_list, kNoSourcePosition), |
| 3700 zone()); |
| 3701 return args; |
| 3702 } else { |
| 3703 // Spread-call with multiple arguments produces array literals for each |
| 3704 // sequences of unspread arguments, and converts each spread iterable to |
| 3705 // an Internal array. Finally, all of these produced arrays are flattened |
| 3706 // into a single InternalArray, containing the arguments for the call. |
| 3707 // |
| 3708 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0), |
| 3709 // Spread(spread1), [unspread2, unspread3])) |
| 3710 int i = 0; |
| 3711 int n = list->length(); |
| 3712 while (i < n) { |
| 3713 if (!list->at(i)->IsSpread()) { |
| 3714 ZoneList<Expression*>* unspread = |
| 3715 new (zone()) ZoneList<Expression*>(1, zone()); |
| 3704 | 3716 |
| 3705 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); | 3717 // Push array of unspread parameters |
| 3706 // Spread-call with multiple arguments produces array literals for each | 3718 while (i < n && !list->at(i)->IsSpread()) { |
| 3707 // sequences of unspread arguments, and converts each spread iterable to | 3719 unspread->Add(list->at(i++), zone()); |
| 3708 // an Internal array. Finally, all of these produced arrays are flattened | 3720 } |
| 3709 // into a single InternalArray, containing the arguments for the call. | 3721 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
| 3710 // | 3722 args->Add(factory()->NewArrayLiteral(unspread, literal_index, |
| 3711 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0), | 3723 kNoSourcePosition), |
| 3712 // Spread(spread1), [unspread2, unspread3])) | 3724 zone()); |
| 3713 int i = 0; | 3725 |
| 3714 int n = list->length(); | 3726 if (i == n) break; |
| 3715 while (i < n) { | 3727 } |
| 3716 if (!list->at(i)->IsSpread()) { | 3728 |
| 3717 ZoneList<Expression*>* unspread = | 3729 // Push eagerly spread argument |
| 3730 ZoneList<Expression*>* spread_list = |
| 3718 new (zone()) ZoneList<Expression*>(1, zone()); | 3731 new (zone()) ZoneList<Expression*>(1, zone()); |
| 3719 | 3732 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone()); |
| 3720 // Push array of unspread parameters | 3733 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX, |
| 3721 while (i < n && !list->at(i)->IsSpread()) { | 3734 spread_list, kNoSourcePosition), |
| 3722 unspread->Add(list->at(i++), zone()); | |
| 3723 } | |
| 3724 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
| 3725 args->Add(factory()->NewArrayLiteral(unspread, literal_index, | |
| 3726 kNoSourcePosition), | |
| 3727 zone()); | 3735 zone()); |
| 3728 | |
| 3729 if (i == n) break; | |
| 3730 } | 3736 } |
| 3731 | 3737 |
| 3732 // Push eagerly spread argument | 3738 list = new (zone()) ZoneList<Expression*>(1, zone()); |
| 3733 ZoneList<Expression*>* spread_list = | 3739 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args, |
| 3734 new (zone()) ZoneList<Expression*>(1, zone()); | 3740 kNoSourcePosition), |
| 3735 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone()); | |
| 3736 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX, | |
| 3737 spread_list, kNoSourcePosition), | |
| 3738 zone()); | 3741 zone()); |
| 3742 return list; |
| 3739 } | 3743 } |
| 3740 | 3744 UNREACHABLE(); |
| 3741 list = new (zone()) ZoneList<Expression*>(1, zone()); | |
| 3742 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args, | |
| 3743 kNoSourcePosition), | |
| 3744 zone()); | |
| 3745 return list; | |
| 3746 } | 3745 } |
| 3747 | 3746 |
| 3748 Expression* Parser::SpreadCall(Expression* function, | 3747 Expression* Parser::SpreadCall(Expression* function, |
| 3749 ZoneList<Expression*>* args, int pos, | 3748 ZoneList<Expression*>* args, int pos) { |
| 3750 Call::PossiblyEval is_possibly_eval) { | |
| 3751 // Handle these cases in BytecodeGenerator. | |
| 3752 if (OnlyLastArgIsSpread(args)) { | |
| 3753 if (function->IsSuperCallReference()) { | |
| 3754 function = NewSuperCallReference(pos); | |
| 3755 } | |
| 3756 return factory()->NewCall(function, args, pos); | |
| 3757 } | |
| 3758 | |
| 3759 if (function->IsSuperCallReference()) { | 3749 if (function->IsSuperCallReference()) { |
| 3760 // Super calls | 3750 // Super calls |
| 3761 // $super_constructor = %_GetSuperConstructor(<this-function>) | 3751 // $super_constructor = %_GetSuperConstructor(<this-function>) |
| 3762 // %reflect_construct($super_constructor, args, new.target) | 3752 // %reflect_construct($super_constructor, args, new.target) |
| 3763 | 3753 |
| 3754 bool only_last_arg_is_spread = false; |
| 3755 for (int i = 0; i < args->length(); i++) { |
| 3756 if (args->at(i)->IsSpread()) { |
| 3757 if (i == args->length() - 1) { |
| 3758 only_last_arg_is_spread = true; |
| 3759 } |
| 3760 break; |
| 3761 } |
| 3762 } |
| 3763 |
| 3764 if (only_last_arg_is_spread) { |
| 3765 // Handle in BytecodeGenerator. |
| 3766 Expression* super_call_ref = NewSuperCallReference(pos); |
| 3767 return factory()->NewCall(super_call_ref, args, pos); |
| 3768 } |
| 3764 args = PrepareSpreadArguments(args); | 3769 args = PrepareSpreadArguments(args); |
| 3765 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); | 3770 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); |
| 3766 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); | 3771 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); |
| 3767 Expression* super_constructor = factory()->NewCallRuntime( | 3772 Expression* super_constructor = factory()->NewCallRuntime( |
| 3768 Runtime::kInlineGetSuperConstructor, tmp, pos); | 3773 Runtime::kInlineGetSuperConstructor, tmp, pos); |
| 3769 args->InsertAt(0, super_constructor, zone()); | 3774 args->InsertAt(0, super_constructor, zone()); |
| 3770 args->Add(function->AsSuperCallReference()->new_target_var(), zone()); | 3775 args->Add(function->AsSuperCallReference()->new_target_var(), zone()); |
| 3771 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, | 3776 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, |
| 3772 pos); | 3777 pos); |
| 3773 } else { | 3778 } else { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3795 args->InsertAt(0, function, zone()); | 3800 args->InsertAt(0, function, zone()); |
| 3796 args->InsertAt(1, factory()->NewUndefinedLiteral(kNoSourcePosition), | 3801 args->InsertAt(1, factory()->NewUndefinedLiteral(kNoSourcePosition), |
| 3797 zone()); | 3802 zone()); |
| 3798 } | 3803 } |
| 3799 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos); | 3804 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos); |
| 3800 } | 3805 } |
| 3801 } | 3806 } |
| 3802 | 3807 |
| 3803 Expression* Parser::SpreadCallNew(Expression* function, | 3808 Expression* Parser::SpreadCallNew(Expression* function, |
| 3804 ZoneList<Expression*>* args, int pos) { | 3809 ZoneList<Expression*>* args, int pos) { |
| 3805 if (OnlyLastArgIsSpread(args)) { | |
| 3806 // Handle in BytecodeGenerator. | |
| 3807 return factory()->NewCallNew(function, args, pos); | |
| 3808 } | |
| 3809 args = PrepareSpreadArguments(args); | 3810 args = PrepareSpreadArguments(args); |
| 3810 args->InsertAt(0, function, zone()); | 3811 args->InsertAt(0, function, zone()); |
| 3811 | 3812 |
| 3812 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); | 3813 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); |
| 3813 } | 3814 } |
| 3814 | 3815 |
| 3815 | 3816 |
| 3816 void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) { | 3817 void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) { |
| 3817 v8::Isolate::UseCounterFeature feature; | 3818 v8::Isolate::UseCounterFeature feature; |
| 3818 if (is_sloppy(mode)) | 3819 if (is_sloppy(mode)) |
| (...skipping 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5115 | 5116 |
| 5116 return final_loop; | 5117 return final_loop; |
| 5117 } | 5118 } |
| 5118 | 5119 |
| 5119 #undef CHECK_OK | 5120 #undef CHECK_OK |
| 5120 #undef CHECK_OK_VOID | 5121 #undef CHECK_OK_VOID |
| 5121 #undef CHECK_FAILED | 5122 #undef CHECK_FAILED |
| 5122 | 5123 |
| 5123 } // namespace internal | 5124 } // namespace internal |
| 5124 } // namespace v8 | 5125 } // namespace v8 |
| OLD | NEW |