[es6] Use strict arguments objects for destructured parameters
authorrossberg <rossberg@chromium.org>
Fri, 7 Aug 2015 11:38:20 +0000 (04:38 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 7 Aug 2015 11:38:39 +0000 (11:38 +0000)
Plus some renaming for consistency.

R=adamk@chromium.org
BUG=v8:811
LOG=N

Review URL: https://codereview.chromium.org/1278783002

Cr-Commit-Position: refs/heads/master@{#30064}

20 files changed:
src/compiler.cc
src/compiler.h
src/factory.cc
src/full-codegen/arm/full-codegen-arm.cc
src/full-codegen/arm64/full-codegen-arm64.cc
src/full-codegen/full-codegen.h
src/full-codegen/ia32/full-codegen-ia32.cc
src/full-codegen/mips/full-codegen-mips.cc
src/full-codegen/mips64/full-codegen-mips64.cc
src/full-codegen/ppc/full-codegen-ppc.cc
src/full-codegen/x64/full-codegen-x64.cc
src/full-codegen/x87/full-codegen-x87.cc
src/objects-inl.h
src/objects.h
src/parser.cc
src/runtime/runtime-scopes.cc
src/scopeinfo.cc
src/scopes.cc
src/scopes.h
test/mjsunit/harmony/destructuring.js

index ccf41716f6c9e9cb3a2237066421c8b3c7868d36..ede006c04cf27d7cfb4709a31c554efb809a2bc0 100644 (file)
@@ -222,8 +222,8 @@ void CompilationInfo::EnsureFeedbackVector() {
 }
 
 
-bool CompilationInfo::is_simple_parameter_list() {
-  return scope()->is_simple_parameter_list();
+bool CompilationInfo::has_simple_parameters() {
+  return scope()->has_simple_parameters();
 }
 
 
index df81a4f5d27790dbdef89c20e013c29c08ceaf0a..78ae812970ca19658b8e67c5fac62effed7dfa21 100644 (file)
@@ -400,7 +400,7 @@ class CompilationInfo {
   void PrintAstForTesting();
 #endif
 
-  bool is_simple_parameter_list();
+  bool has_simple_parameters();
 
   Handle<Code> GenerateCodeStub();
 
index 8944905d96190d991e4051306a471ae43cc17d91..05cb259602edb00bcc9427dd75e69b82f9e30d55 100644 (file)
@@ -2348,10 +2348,9 @@ Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
 Handle<JSObject> Factory::NewArgumentsObject(Handle<JSFunction> callee,
                                              int length) {
   bool strict_mode_callee = is_strict(callee->shared()->language_mode()) ||
-                            !callee->is_simple_parameter_list();
+                            !callee->has_simple_parameters();
   Handle<Map> map = strict_mode_callee ? isolate()->strict_arguments_map()
                                        : isolate()->sloppy_arguments_map();
-
   AllocationSiteUsageContext context(isolate(), Handle<AllocationSite>(),
                                      false);
   DCHECK(!isolate()->has_pending_exception());
index 0e6d4c04edf5263e6116d87383b54ae4dee0f38a..7ebf078f7ecf24e6f8df0cd3909d18d1c5593a4f 100644 (file)
@@ -318,7 +318,7 @@ void FullCodeGenerator::Generate() {
     // The stub will rewrite receiver and parameter count if the previous
     // stack frame was an arguments adapter frame.
     ArgumentsAccessStub::Type type;
-    if (is_strict(language_mode()) || !is_simple_parameter_list()) {
+    if (is_strict(language_mode()) || !has_simple_parameters()) {
       type = ArgumentsAccessStub::NEW_STRICT;
     } else if (function()->has_duplicate_parameters()) {
       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
index 678471d0c996747b5d3f806af1b57134a22b3d65..a90019ea431fd935f396287dc182cc4f311b535a 100644 (file)
@@ -324,7 +324,7 @@ void FullCodeGenerator::Generate() {
     // The stub will rewrite receiver and parameter count if the previous
     // stack frame was an arguments adapter frame.
     ArgumentsAccessStub::Type type;
-    if (is_strict(language_mode()) || !is_simple_parameter_list()) {
+    if (is_strict(language_mode()) || !has_simple_parameters()) {
       type = ArgumentsAccessStub::NEW_STRICT;
     } else if (function()->has_duplicate_parameters()) {
       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
index 6761bda27192f84fc25199a5ab5c010449d5dda0..5406ccd1fc1150d4fc29c39101476ebda97cb6ec 100644 (file)
@@ -700,7 +700,7 @@ class FullCodeGenerator: public AstVisitor {
   bool is_eval() { return info_->is_eval(); }
   bool is_native() { return info_->is_native(); }
   LanguageMode language_mode() { return function()->language_mode(); }
-  bool is_simple_parameter_list() { return info_->is_simple_parameter_list(); }
+  bool has_simple_parameters() { return info_->has_simple_parameters(); }
   FunctionLiteral* function() { return info_->function(); }
   Scope* scope() { return scope_; }
 
index 6c1ac09969f99a4b59893ce23b36882d9a830c0c..d9ca3bd0c4d74bbf5141997438d4a7420ae99838 100644 (file)
@@ -320,7 +320,7 @@ void FullCodeGenerator::Generate() {
     // The stub will rewrite receiver and parameter count if the previous
     // stack frame was an arguments adapter frame.
     ArgumentsAccessStub::Type type;
-    if (is_strict(language_mode()) || !is_simple_parameter_list()) {
+    if (is_strict(language_mode()) || !has_simple_parameters()) {
       type = ArgumentsAccessStub::NEW_STRICT;
     } else if (function()->has_duplicate_parameters()) {
       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
index cef99aba65af9fd0582ecd1c9d38e28d64e5f00e..a63f954c5a6fa7fd215dfd060042a829f89f9b72 100644 (file)
@@ -337,7 +337,7 @@ void FullCodeGenerator::Generate() {
     // The stub will rewrite receiever and parameter count if the previous
     // stack frame was an arguments adapter frame.
     ArgumentsAccessStub::Type type;
-    if (is_strict(language_mode()) || !is_simple_parameter_list()) {
+    if (is_strict(language_mode()) || !has_simple_parameters()) {
       type = ArgumentsAccessStub::NEW_STRICT;
     } else if (function()->has_duplicate_parameters()) {
       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
index 8075822fe5c83f42e5620d90055848659aaee843..2f3f11502da024ddd2c4e8e02b69f19a8f7d48aa 100644 (file)
@@ -333,7 +333,7 @@ void FullCodeGenerator::Generate() {
     // The stub will rewrite receiever and parameter count if the previous
     // stack frame was an arguments adapter frame.
     ArgumentsAccessStub::Type type;
-    if (is_strict(language_mode()) || !is_simple_parameter_list()) {
+    if (is_strict(language_mode()) || !has_simple_parameters()) {
       type = ArgumentsAccessStub::NEW_STRICT;
     } else if (function()->has_duplicate_parameters()) {
       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
index e20f36719af48f4b565017b14ff5f53313900bbd..841077cede7cd0242b76a24735fe90d5ad0d7501 100644 (file)
@@ -330,7 +330,7 @@ void FullCodeGenerator::Generate() {
     // The stub will rewrite receiver and parameter count if the previous
     // stack frame was an arguments adapter frame.
     ArgumentsAccessStub::Type type;
-    if (is_strict(language_mode()) || !is_simple_parameter_list()) {
+    if (is_strict(language_mode()) || !has_simple_parameters()) {
       type = ArgumentsAccessStub::NEW_STRICT;
     } else if (function()->has_duplicate_parameters()) {
       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
index 65c0456dc70c32da4a18bfa18f326be43ec30a2c..206048f36986b8472d0a1037a449ddf26d70ff0a 100644 (file)
@@ -319,7 +319,7 @@ void FullCodeGenerator::Generate() {
     // stack frame was an arguments adapter frame.
 
     ArgumentsAccessStub::Type type;
-    if (is_strict(language_mode()) || !is_simple_parameter_list()) {
+    if (is_strict(language_mode()) || !has_simple_parameters()) {
       type = ArgumentsAccessStub::NEW_STRICT;
     } else if (function()->has_duplicate_parameters()) {
       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
index f1848c9e06167bdb161a90ec389005d31998680c..38702e53aa55f9928b032cb359905fdf11bcd5b8 100644 (file)
@@ -317,7 +317,7 @@ void FullCodeGenerator::Generate() {
     // The stub will rewrite receiver and parameter count if the previous
     // stack frame was an arguments adapter frame.
     ArgumentsAccessStub::Type type;
-    if (is_strict(language_mode()) || !is_simple_parameter_list()) {
+    if (is_strict(language_mode()) || !has_simple_parameters()) {
       type = ArgumentsAccessStub::NEW_STRICT;
     } else if (function()->has_duplicate_parameters()) {
       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
index 3a9fe2991decc352c34f79a0635ce1968a57539f..d8175c79812c8948f9bc450f4cf72721f13af075 100644 (file)
@@ -5378,8 +5378,8 @@ bool SharedFunctionInfo::is_compiled() {
 }
 
 
-bool SharedFunctionInfo::is_simple_parameter_list() {
-  return scope_info()->IsSimpleParameterList();
+bool SharedFunctionInfo::has_simple_parameters() {
+  return scope_info()->HasSimpleParameters();
 }
 
 
@@ -5685,8 +5685,8 @@ bool JSFunction::is_compiled() {
 }
 
 
-bool JSFunction::is_simple_parameter_list() {
-  return shared()->is_simple_parameter_list();
+bool JSFunction::has_simple_parameters() {
+  return shared()->has_simple_parameters();
 }
 
 
index 257f0e54c35d198f2c6ee16d605e961702edf4f7..8e64fe38da799f8c772a11ccda4977442703d94f 100644 (file)
@@ -3886,8 +3886,8 @@ class ScopeInfo : public FixedArray {
   // Return if this is a nested function within an asm module scope.
   bool IsAsmFunction() { return AsmFunctionField::decode(Flags()); }
 
-  bool IsSimpleParameterList() {
-    return IsSimpleParameterListField::decode(Flags());
+  bool HasSimpleParameters() {
+    return HasSimpleParametersField::decode(Flags());
   }
 
   // Return the function_name if present.
@@ -4086,10 +4086,10 @@ class ScopeInfo : public FixedArray {
   class AsmModuleField : public BitField<bool, FunctionVariableMode::kNext, 1> {
   };
   class AsmFunctionField : public BitField<bool, AsmModuleField::kNext, 1> {};
-  class IsSimpleParameterListField
+  class HasSimpleParametersField
       : public BitField<bool, AsmFunctionField::kNext, 1> {};
   class FunctionKindField
-      : public BitField<FunctionKind, IsSimpleParameterListField::kNext, 8> {};
+      : public BitField<FunctionKind, HasSimpleParametersField::kNext, 8> {};
 
   // BitFields representing the encoded information for context locals in the
   // ContextLocalInfoEntries part.
@@ -6630,7 +6630,7 @@ class SharedFunctionInfo: public HeapObject {
   // Calculate the number of in-object properties.
   int CalculateInObjectProperties();
 
-  inline bool is_simple_parameter_list();
+  inline bool has_simple_parameters();
 
   // Initialize a SharedFunctionInfo from a parsed function literal.
   static void InitFromFunctionLiteral(Handle<SharedFunctionInfo> shared_info,
@@ -7145,7 +7145,7 @@ class JSFunction: public JSObject {
   // Returns `false` if formal parameters include rest parameters, optional
   // parameters, or destructuring parameters.
   // TODO(caitp): make this a flag set during parsing
-  inline bool is_simple_parameter_list();
+  inline bool has_simple_parameters();
 
   // [next_function_link]: Links functions into various lists, e.g. the list
   // of optimized functions hanging off the native_context. The CodeFlusher
index 6a0838e067091c62390bc5412631004cf15857f2..45202cb3a82b922c7d487061cfff03578cc3a3c9 100644 (file)
@@ -3926,6 +3926,7 @@ void ParserTraits::ParseArrowFunctionFormalParameterList(
       *duplicate_loc = classifier.duplicate_formal_parameter_error().location;
     }
   }
+  DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
 }
 
 
index ff7e783393081cbe731a8d5f265a5b0fa852b773..be13a14d4f078f419db5f8045f3c794f6078ab57 100644 (file)
@@ -397,7 +397,7 @@ static Handle<JSObject> NewSloppyArguments(Isolate* isolate,
                                            Object** parameters,
                                            int argument_count) {
   CHECK(!IsSubclassConstructor(callee->shared()->kind()));
-  DCHECK(callee->is_simple_parameter_list());
+  DCHECK(callee->has_simple_parameters());
   Handle<JSObject> result =
       isolate->factory()->NewArgumentsObject(callee, argument_count);
 
@@ -518,7 +518,7 @@ RUNTIME_FUNCTION(Runtime_NewArguments) {
   Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1));
 
   return (is_strict(callee->shared()->language_mode()) ||
-             !callee->is_simple_parameter_list())
+             !callee->has_simple_parameters())
              ? *NewStrictArguments(isolate, callee, parameters, argument_count)
              : *NewSloppyArguments(isolate, callee, parameters, argument_count);
 }
index e490fd9ce48f11eff84aa20f143f852dfea3d7ac..e53f36d27439aef1874b1be7df1637225dffa33f 100644 (file)
@@ -34,9 +34,6 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
   DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
   DCHECK_EQ(scope->ContextGlobalCount(), context_global_count);
 
-  bool simple_parameter_list =
-      scope->is_function_scope() ? scope->is_simple_parameter_list() : true;
-
   // Determine use and location of the "this" binding if it is present.
   VariableAllocationInfo receiver_info;
   if (scope->has_this_declaration()) {
@@ -85,6 +82,9 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
   Factory* factory = isolate->factory();
   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
 
+  bool has_simple_parameters =
+      scope->is_function_scope() && scope->has_simple_parameters();
+
   // Encode the flags.
   int flags = ScopeTypeField::encode(scope->scope_type()) |
               CallsEvalField::encode(scope->calls_eval()) |
@@ -94,7 +94,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
               FunctionVariableMode::encode(function_variable_mode) |
               AsmModuleField::encode(scope->asm_module()) |
               AsmFunctionField::encode(scope->asm_function()) |
-              IsSimpleParameterListField::encode(simple_parameter_list) |
+              HasSimpleParametersField::encode(has_simple_parameters) |
               FunctionKindField::encode(scope->function_kind());
   scope_info->SetFlags(flags);
   scope_info->SetParameterCount(parameter_count);
@@ -224,7 +224,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
   const int context_local_count = 1;
   const int context_global_count = 0;
   const int strong_mode_free_variable_count = 0;
-  const bool simple_parameter_list = true;
+  const bool has_simple_parameters = true;
   const VariableAllocationInfo receiver_info = CONTEXT;
   const VariableAllocationInfo function_name_info = NONE;
   const VariableMode function_variable_mode = VAR;
@@ -248,7 +248,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
               FunctionVariableField::encode(function_name_info) |
               FunctionVariableMode::encode(function_variable_mode) |
               AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
-              IsSimpleParameterListField::encode(simple_parameter_list) |
+              HasSimpleParametersField::encode(has_simple_parameters) |
               FunctionKindField::encode(FunctionKind::kNormalFunction);
   scope_info->SetFlags(flags);
   scope_info->SetParameterCount(parameter_count);
index 319aca518ed69187dc29cc817c58f9266b2a8700..8ce28bd6aba130598ff24eb39df95f3967a37e4d 100644 (file)
@@ -180,7 +180,8 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
   num_heap_slots_ = 0;
   num_global_slots_ = 0;
   num_modules_ = 0;
-  module_var_ = NULL,
+  module_var_ = NULL;
+  has_simple_parameters_ = true;
   rest_parameter_ = NULL;
   rest_index_ = -1;
   scope_info_ = scope_info;
@@ -468,6 +469,7 @@ Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode,
   Variable* var;
   if (mode == TEMPORARY) {
     var = NewTemporary(name);
+    has_simple_parameters_ = false;
   } else {
     var = variables_.Declare(this, name, mode, Variable::NORMAL,
                              kCreatedInitialized);
@@ -478,6 +480,7 @@ Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode,
     DCHECK_NULL(rest_parameter_);
     rest_parameter_ = var;
     rest_index_ = num_parameters();
+    has_simple_parameters_ = false;
   }
   params_.Add(var, zone());
   return var;
@@ -1399,7 +1402,9 @@ void Scope::AllocateParameterLocals(Isolate* isolate) {
     // In strict mode 'arguments' does not alias formal parameters.
     // Therefore in strict mode we allocate parameters as if 'arguments'
     // were not used.
-    uses_sloppy_arguments = is_sloppy(language_mode());
+    // If the parameter list is not simple, arguments isn't sloppy either.
+    uses_sloppy_arguments =
+        is_sloppy(language_mode()) && has_simple_parameters();
   }
 
   if (rest_parameter_ && !MustAllocate(rest_parameter_)) {
index f48b3ae7111a1c6c841d641d671dff7622f1fac8..acfad4cf1605ac1f4b152636093841a303846147 100644 (file)
@@ -389,10 +389,9 @@ class Scope: public ZoneObject {
     return rest_index_ >= 0;
   }
 
-  bool is_simple_parameter_list() const {
+  bool has_simple_parameters() const {
     DCHECK(is_function_scope());
-    if (rest_index_ >= 0) return false;
-    return true;
+    return has_simple_parameters_;
   }
 
   // The local variable 'arguments' if we need to allocate it; NULL otherwise.
@@ -632,7 +631,8 @@ class Scope: public ZoneObject {
   // For module scopes, the host scope's temporary variable binding this module.
   Variable* module_var_;
 
-  // Rest parameter
+  // Info about the parameter list of a function.
+  bool has_simple_parameters_;
   Variable* rest_parameter_;
   int rest_index_;
 
index 0bbaf26285932fd527cedad0c058fab591eae9e4..2a525faccbeab5ed5c3b3ccd95c23092677286f0 100644 (file)
 }());
 
 
+(function TestArgumentsForNonSimpleParameters() {
+  function f1({}, x) { arguments[1] = 0; return x }
+  assertEquals(6, f1({}, 6));
+  function f2({}, x) { x = 2; return arguments[1] }
+  assertEquals(7, f2({}, 7));
+  function f3(x, {}) { arguments[0] = 0; return x }
+  assertEquals(6, f3(6, {}));
+  function f4(x, {}) { x = 2; return arguments[0] }
+  assertEquals(7, f4(7, {}));
+  function f5(x, ...a) { arguments[0] = 0; return x }
+  assertEquals(6, f5(6, {}));
+  function f6(x, ...a) { x = 2; return arguments[0] }
+  assertEquals(6, f6(6, {}));
+  function f7({a: x}) { x = 2; return arguments[0].a }
+  assertEquals(5, f7({a: 5}));
+  function f8(x, ...a) { a = []; return arguments[1] }
+  assertEquals(6, f8(5, 6));
+  // TODO(caitp, rossberg): add cases for default parameters.
+}());
+
+
 (function TestForInOfTDZ() {
   assertThrows("'use strict'; let x = {}; for (let [x, y] of {x});", ReferenceError);
   assertThrows("'use strict'; let x = {}; for (let [y, x] of {x});", ReferenceError);