| Index: src/parser.cc | 
| diff --git a/src/parser.cc b/src/parser.cc | 
| index 4412b8a98cdca5618ec0b7caf1a77caf246718b3..0dc013202f857d8398a72fb599c2b6daadc94ce1 100644 | 
| --- a/src/parser.cc | 
| +++ b/src/parser.cc | 
| @@ -877,6 +877,7 @@ Parser::Parser(ParseInfo* info) | 
| set_allow_harmony_computed_property_names( | 
| FLAG_harmony_computed_property_names); | 
| set_allow_harmony_rest_params(FLAG_harmony_rest_parameters); | 
| +  set_allow_harmony_spreadcalls(FLAG_harmony_spreadcalls); | 
| set_allow_strong_mode(FLAG_strong_mode); | 
| for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; | 
| ++feature) { | 
| @@ -4231,6 +4232,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 
| allow_harmony_computed_property_names()); | 
| reusable_preparser_->set_allow_harmony_rest_params( | 
| allow_harmony_rest_params()); | 
| +    reusable_preparser_->set_allow_harmony_spreadcalls( | 
| +        allow_harmony_spreadcalls()); | 
| reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); | 
| } | 
| PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 
| @@ -4349,7 +4352,10 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { | 
| Expect(Token::MOD, CHECK_OK); | 
| // Allow "eval" or "arguments" for backward compatibility. | 
| const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); | 
| -  ZoneList<Expression*>* args = ParseArguments(CHECK_OK); | 
| +  Scanner::Location spread_pos; | 
| +  ZoneList<Expression*>* args = ParseArguments(&spread_pos, CHECK_OK); | 
| + | 
| +  DCHECK(!spread_pos.IsValid()); | 
|  | 
| if (extension_ != NULL) { | 
| // The extension structures are only accessible while parsing the | 
| @@ -5614,4 +5620,121 @@ uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) { | 
|  | 
| return running_hash; | 
| } | 
| + | 
| + | 
| +ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments( | 
| +    ZoneList<v8::internal::Expression*>* list) { | 
| +  ZoneList<v8::internal::Expression*>* args = | 
| +      new (zone()) ZoneList<v8::internal::Expression*>(1, zone()); | 
| +  if (list->length() == 1) { | 
| +    // Spread-call with single spread argument produces an InternalArray | 
| +    // containing the values from the array. | 
| +    // | 
| +    // Function is called or constructed with the produced array of arguments | 
| +    // | 
| +    // EG: Apply(Func, Spread(spread0)) | 
| +    ZoneList<Expression*>* spread_list = | 
| +        new (zone()) ZoneList<Expression*>(0, zone()); | 
| +    spread_list->Add(list->at(0)->AsSpread()->expression(), zone()); | 
| +    args->Add( | 
| +        factory()->NewCallRuntime(ast_value_factory()->spread_iterable_string(), | 
| +                                  NULL, spread_list, RelocInfo::kNoPosition), | 
| +        zone()); | 
| +    return args; | 
| +  } else { | 
| +    // Spread-call with multiple arguments produces array literals for each | 
| +    // sequences of unspread arguments, and converts each spread iterable to | 
| +    // an Internal array. Finally, all of these produced arrays are flattened | 
| +    // into a single InternalArray, containing the arguments for the call. | 
| +    // | 
| +    // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0), | 
| +    //                         Spread(spread1), [unspread2, unspread3])) | 
| +    int i = 0; | 
| +    int n = list->length(); | 
| +    while (i < n) { | 
| +      if (!list->at(i)->IsSpread()) { | 
| +        ZoneList<v8::internal::Expression*>* unspread = | 
| +            new (zone()) ZoneList<v8::internal::Expression*>(1, zone()); | 
| + | 
| +        // Push array of unspread parameters | 
| +        while (i < n && !list->at(i)->IsSpread()) { | 
| +          unspread->Add(list->at(i++), zone()); | 
| +        } | 
| +        int literal_index = function_state_->NextMaterializedLiteralIndex(); | 
| +        args->Add(factory()->NewArrayLiteral(unspread, literal_index, | 
| +                                             RelocInfo::kNoPosition), | 
| +                  zone()); | 
| + | 
| +        if (i == n) break; | 
| +      } | 
| + | 
| +      // Push eagerly spread argument | 
| +      ZoneList<v8::internal::Expression*>* spread_list = | 
| +          new (zone()) ZoneList<v8::internal::Expression*>(1, zone()); | 
| +      spread_list->Add(list->at(i++)->AsSpread()->expression(), zone()); | 
| +      args->Add(factory()->NewCallRuntime( | 
| +                    ast_value_factory()->spread_iterable_string(), NULL, | 
| +                    spread_list, RelocInfo::kNoPosition), | 
| +                zone()); | 
| +    } | 
| + | 
| +    list = new (zone()) ZoneList<v8::internal::Expression*>(1, zone()); | 
| +    list->Add(factory()->NewCallRuntime( | 
| +                  ast_value_factory()->spread_arguments_string(), NULL, args, | 
| +                  RelocInfo::kNoPosition), | 
| +              zone()); | 
| +    return list; | 
| +  } | 
| +  UNREACHABLE(); | 
| +} | 
| + | 
| + | 
| +Expression* Parser::SpreadCall(Expression* function, | 
| +                               ZoneList<v8::internal::Expression*>* args, | 
| +                               int pos) { | 
| +  if (function->IsSuperReference()) { | 
| +    // Super calls | 
| +    args->InsertAt(0, function, zone()); | 
| +    args->Add(factory()->NewVariableProxy(scope_->new_target_var()), zone()); | 
| +    Expression* result = factory()->NewCallRuntime( | 
| +        ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 
| +    args = new (zone()) ZoneList<Expression*>(0, zone()); | 
| +    args->Add(result, zone()); | 
| +    return factory()->NewCallRuntime( | 
| +        ast_value_factory()->empty_string(), | 
| +        Runtime::FunctionForId(Runtime::kInlineCallSuperWithSpread), args, pos); | 
| +  } else { | 
| +    if (function->IsProperty()) { | 
| +      // Method calls | 
| +      Variable* temp = | 
| +          scope_->NewTemporary(ast_value_factory()->empty_string()); | 
| +      VariableProxy* obj = factory()->NewVariableProxy(temp); | 
| +      Assignment* assign_obj = factory()->NewAssignment( | 
| +          Token::ASSIGN, obj, function->AsProperty()->obj(), | 
| +          RelocInfo::kNoPosition); | 
| +      function = factory()->NewProperty( | 
| +          assign_obj, function->AsProperty()->key(), RelocInfo::kNoPosition); | 
| +      args->InsertAt(0, function, zone()); | 
| +      obj = factory()->NewVariableProxy(temp); | 
| +      args->InsertAt(1, obj, zone()); | 
| +    } else { | 
| +      // Non-method calls | 
| +      args->InsertAt(0, function, zone()); | 
| +      args->InsertAt(1, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | 
| +                     zone()); | 
| +    } | 
| +    return factory()->NewCallRuntime( | 
| +        ast_value_factory()->reflect_apply_string(), NULL, args, pos); | 
| +  } | 
| +} | 
| + | 
| + | 
| +Expression* Parser::SpreadCallNew(Expression* function, | 
| +                                  ZoneList<v8::internal::Expression*>* args, | 
| +                                  int pos) { | 
| +  args->InsertAt(0, function, zone()); | 
| + | 
| +  return factory()->NewCallRuntime( | 
| +      ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 
| +} | 
| } }  // namespace v8::internal | 
|  |