Revision: 13215
Author:   [email protected]
Date:     Thu Dec 13 05:20:46 2012
Log:      Merged r13161 into 3.14 branch.

Allow lazy compilation (and thus optimisation) of functions inside eval.

BUG=v8:2315

[email protected]

Review URL: https://codereview.chromium.org/11564012
http://code.google.com/p/v8/source/detail?r=13215

Added:
 /branches/3.14/test/mjsunit/regress/regress-2315.js
Modified:
 /branches/3.14/src/contexts.h
 /branches/3.14/src/lithium.h
 /branches/3.14/src/parser.cc
 /branches/3.14/src/preparser.h
 /branches/3.14/src/scopes.cc
 /branches/3.14/src/version.cc
 /branches/3.14/test/mjsunit/regress/regress-492.js
 /branches/3.14/test/mjsunit/regress/regress-crbug-135066.js

=======================================
--- /dev/null
+++ /branches/3.14/test/mjsunit/regress/regress-2315.js Thu Dec 13 05:20:46 2012
@@ -0,0 +1,40 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+var foo = (function() {
+  return eval("(function bar() { return 1; })");
+})();
+
+foo();
+foo();
+%OptimizeFunctionOnNextCall(foo);
+foo();
+
+// Function should be optimized now.
+assertTrue(%GetOptimizationStatus(foo) != 2);
=======================================
--- /branches/3.14/src/contexts.h       Thu Sep 20 05:51:09 2012
+++ /branches/3.14/src/contexts.h       Thu Dec 13 05:20:46 2012
@@ -344,9 +344,13 @@
   // Compute the native context by traversing the context chain.
   Context* native_context();

-  // Predicates for context types.  IsNativeContext is defined on Object
+ // Predicates for context types. IsNativeContext is also defined on Object
   // because we frequently have to know if arbitrary objects are natives
   // contexts.
+  bool IsNativeContext() {
+    Map* map = this->map();
+    return map == map->GetHeap()->native_context_map();
+  }
   bool IsFunctionContext() {
     Map* map = this->map();
     return map == map->GetHeap()->function_context_map();
=======================================
--- /branches/3.14/src/lithium.h        Wed Oct 10 10:07:22 2012
+++ /branches/3.14/src/lithium.h        Thu Dec 13 05:20:46 2012
@@ -156,8 +156,8 @@
   };

   static const int kMaxVirtualRegisters = 1 << kVirtualRegisterWidth;
-  static const int kMaxFixedIndex = (1 << kFixedIndexWidth) - 1;
-  static const int kMinFixedIndex = -(1 << kFixedIndexWidth);
+  static const int kMaxFixedIndex = (1 << (kFixedIndexWidth - 1)) - 1;
+  static const int kMinFixedIndex = -(1 << (kFixedIndexWidth - 1));

   bool HasAnyPolicy() const {
     return policy() == ANY;
=======================================
--- /branches/3.14/src/parser.cc        Wed Oct 10 10:07:22 2012
+++ /branches/3.14/src/parser.cc        Thu Dec 13 05:20:46 2012
@@ -614,11 +614,6 @@
   ASSERT(target_stack_ == NULL);
   if (pre_data_ != NULL) pre_data_->Initialize();

-  // Compute the parsing mode.
-  Mode mode = (FLAG_lazy && allow_lazy_) ? PARSE_LAZILY : PARSE_EAGERLY;
-  if (allow_natives_syntax_ || extension_ != NULL) mode = PARSE_EAGERLY;
-  ParsingModeScope parsing_mode(this, mode);
-
   Handle<String> no_name = isolate()->factory()->empty_symbol();

   FunctionLiteral* result = NULL;
@@ -637,6 +632,13 @@
     scope->set_start_position(0);
     scope->set_end_position(source->length());

+    // Compute the parsing mode.
+    Mode mode = (FLAG_lazy && allow_lazy_) ? PARSE_LAZILY : PARSE_EAGERLY;
+ if (allow_natives_syntax_ || extension_ != NULL || scope->is_eval_scope()) {
+      mode = PARSE_EAGERLY;
+    }
+    ParsingModeScope parsing_mode(this, mode);
+
FunctionState function_state(this, scope, isolate()); // Enters 'scope'.
     top_scope_->SetLanguageMode(info->language_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
@@ -1059,12 +1061,14 @@
// as specified in ES5 10.4.2(3). The correct fix would be to always // add this scope in DoParseProgram(), but that requires adaptations
           // all over the code base, so we go with a quick-fix for now.
+          // In the same manner, we have to patch the parsing mode.
           if (is_eval && !top_scope_->is_eval_scope()) {
             ASSERT(top_scope_->is_global_scope());
             Scope* scope = NewScope(top_scope_, EVAL_SCOPE);
             scope->set_start_position(top_scope_->start_position());
             scope->set_end_position(top_scope_->end_position());
             top_scope_ = scope;
+            mode_ = PARSE_EAGERLY;
           }
           // TODO(ES6): Fix entering extended mode, once it is specified.
           top_scope_->SetLanguageMode(FLAG_harmony_scoping
=======================================
--- /branches/3.14/src/preparser.h      Thu May  3 02:06:43 2012
+++ /branches/3.14/src/preparser.h      Thu Dec 13 05:20:46 2012
@@ -150,11 +150,11 @@

   // Parses a single function literal, from the opening parentheses before
   // parameters to the closing brace after the body.
-  // Returns a FunctionEntry describing the body of the funciton in enough
+  // Returns a FunctionEntry describing the body of the function in enough
   // detail that it can be lazily compiled.
   // The scanner is expected to have matched the "function" keyword and
   // parameters, and have consumed the initial '{'.
- // At return, unless an error occured, the scanner is positioned before the + // At return, unless an error occurred, the scanner is positioned before the
   // the final '}'.
   PreParseResult PreParseLazyFunction(i::LanguageMode mode,
                                       i::ParserRecorder* log);
=======================================
--- /branches/3.14/src/scopes.cc        Wed Aug 29 08:32:24 2012
+++ /branches/3.14/src/scopes.cc        Thu Dec 13 05:20:46 2012
@@ -702,17 +702,12 @@
 bool Scope::HasLazyCompilableOuterContext() const {
   Scope* outer = outer_scope_;
   if (outer == NULL) return true;
-  // There are several reasons that prevent lazy compilation:
-  // - This scope is inside a with scope and all declaration scopes between
-  //   them have empty contexts. Such declaration scopes become invisible
-  //   during scope info deserialization.
-  // - This scope is inside a strict eval scope with variables that are
-  //   potentially context allocated in an artificial function scope that
-  //   is not deserialized correctly.
+ // We have to prevent lazy compilation if this scope is inside a with scope
+  // and all declaration scopes between them have empty contexts. Such
+ // declaration scopes may become invisible during scope info deserialization.
   outer = outer->DeclarationScope();
   bool found_non_trivial_declarations = false;
for (const Scope* scope = outer; scope != NULL; scope = scope->outer_scope_) {
-    if (scope->is_eval_scope()) return false;
if (scope->is_with_scope() && !found_non_trivial_declarations) return false;
     if (scope->is_declaration_scope() && scope->num_heap_slots() > 0) {
       found_non_trivial_declarations = true;
=======================================
--- /branches/3.14/src/version.cc       Tue Nov 20 01:11:03 2012
+++ /branches/3.14/src/version.cc       Thu Dec 13 05:20:46 2012
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     14
 #define BUILD_NUMBER      5
-#define PATCH_LEVEL       2
+#define PATCH_LEVEL       3
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
=======================================
--- /branches/3.14/test/mjsunit/regress/regress-492.js Wed Nov 18 06:12:51 2009 +++ /branches/3.14/test/mjsunit/regress/regress-492.js Thu Dec 13 05:20:46 2012
@@ -29,7 +29,7 @@
 // This should not hit any asserts in debug mode on ARM.

 function function_with_n_args(n) {
-  var source = '(function f(';
+  var source = '(function f' + n + '(';
   for (var arg = 0; arg < n; arg++) {
     if (arg != 0) source += ',';
     source += 'arg' + arg;
@@ -50,3 +50,41 @@
 for (args = 1019; args < 1041; args++) {
   function_with_n_args(args);
 }
+
+
+function foo(
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
+  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
+) {}
+
+for (var i = 0; i < 10000; ++i) foo();
=======================================
--- /branches/3.14/test/mjsunit/regress/regress-crbug-135066.js Tue Jul 3 03:03:19 2012 +++ /branches/3.14/test/mjsunit/regress/regress-crbug-135066.js Thu Dec 13 05:20:46 2012
@@ -29,25 +29,27 @@
 var filler = "//" + new Array(1024).join('x');

 // Test strict eval in global context.
-eval(
+assertEquals(23, eval(
   "'use strict';" +
   "var x = 23;" +
   "var f = function bozo1() {" +
   "  return x;" +
   "};" +
   "assertSame(23, f());" +
+  "f;" +
   filler
-);
+)());

 // Test default eval in strict context.
-(function() {
+assertEquals(42, (function() {
   "use strict";
-  eval(
+  return eval(
     "var y = 42;" +
     "var g = function bozo2() {" +
     "  return y;" +
     "};" +
     "assertSame(42, g());" +
+    "g;" +
     filler
-  );
-})();
+  )();
+})());

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to