Reviewers: adamk,

Description:
[es6] Use strict arguments objects for destructured parameters

Plus some renaming for consistency.

[email protected]
BUG=v8:811
LOG=N

Please review this at https://codereview.chromium.org/1278783002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+57, -31 lines):
  M src/compiler.h
  M src/compiler.cc
  M src/factory.cc
  M src/full-codegen/full-codegen.h
  M src/full-codegen/ia32/full-codegen-ia32.cc
  M src/objects.h
  M src/objects-inl.h
  M src/parser.cc
  M src/runtime/runtime-scopes.cc
  M src/scopeinfo.cc
  M src/scopes.h
  M src/scopes.cc
  M test/mjsunit/harmony/destructuring.js


Index: src/compiler.cc
diff --git a/src/compiler.cc b/src/compiler.cc
index ccf41716f6c9e9cb3a2237066421c8b3c7868d36..ede006c04cf27d7cfb4709a31c554efb809a2bc0 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -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: src/compiler.h
diff --git a/src/compiler.h b/src/compiler.h
index df81a4f5d27790dbdef89c20e013c29c08ceaf0a..78ae812970ca19658b8e67c5fac62effed7dfa21 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -400,7 +400,7 @@ class CompilationInfo {
   void PrintAstForTesting();
 #endif

-  bool is_simple_parameter_list();
+  bool has_simple_parameters();

   Handle<Code> GenerateCodeStub();

Index: src/factory.cc
diff --git a/src/factory.cc b/src/factory.cc
index 8944905d96190d991e4051306a471ae43cc17d91..05cb259602edb00bcc9427dd75e69b82f9e30d55 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -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: src/full-codegen/full-codegen.h
diff --git a/src/full-codegen/full-codegen.h b/src/full-codegen/full-codegen.h index 6761bda27192f84fc25199a5ab5c010449d5dda0..5406ccd1fc1150d4fc29c39101476ebda97cb6ec 100644
--- a/src/full-codegen/full-codegen.h
+++ b/src/full-codegen/full-codegen.h
@@ -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: src/full-codegen/ia32/full-codegen-ia32.cc
diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc index 6c1ac09969f99a4b59893ce23b36882d9a830c0c..d9ca3bd0c4d74bbf5141997438d4a7420ae99838 100644
--- a/src/full-codegen/ia32/full-codegen-ia32.cc
+++ b/src/full-codegen/ia32/full-codegen-ia32.cc
@@ -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: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 3a9fe2991decc352c34f79a0635ce1968a57539f..d8175c79812c8948f9bc450f4cf72721f13af075 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -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: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 6d052ef3a6d43cb43a2e874393298c7897e2bfe3..e3a8e03d4a891de8c7751e865ca7eb79d7deb440 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -3884,8 +3884,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.
@@ -4084,10 +4084,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.
@@ -6628,7 +6628,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,
@@ -7143,7 +7143,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: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 6a0838e067091c62390bc5412631004cf15857f2..45202cb3a82b922c7d487061cfff03578cc3a3c9 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -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: src/runtime/runtime-scopes.cc
diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc
index ff7e783393081cbe731a8d5f265a5b0fa852b773..be13a14d4f078f419db5f8045f3c794f6078ab57 100644
--- a/src/runtime/runtime-scopes.cc
+++ b/src/runtime/runtime-scopes.cc
@@ -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: src/scopeinfo.cc
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index e490fd9ce48f11eff84aa20f143f852dfea3d7ac..e53f36d27439aef1874b1be7df1637225dffa33f 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -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: src/scopes.cc
diff --git a/src/scopes.cc b/src/scopes.cc
index 319aca518ed69187dc29cc817c58f9266b2a8700..8ce28bd6aba130598ff24eb39df95f3967a37e4d 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -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: src/scopes.h
diff --git a/src/scopes.h b/src/scopes.h
index f48b3ae7111a1c6c841d641d671dff7622f1fac8..acfad4cf1605ac1f4b152636093841a303846147 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -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: test/mjsunit/harmony/destructuring.js
diff --git a/test/mjsunit/harmony/destructuring.js b/test/mjsunit/harmony/destructuring.js index 0bbaf26285932fd527cedad0c058fab591eae9e4..2a525faccbeab5ed5c3b3ccd95c23092677286f0 100644
--- a/test/mjsunit/harmony/destructuring.js
+++ b/test/mjsunit/harmony/destructuring.js
@@ -918,6 +918,27 @@
 }());


+(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);


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to