Revision: 11947
Author:   [email protected]
Date:     Thu Jun 28 08:04:22 2012
Log:      Version 3.12.5

Fixed lazy parsing heuristics to respect outer scope. (Chromium issue 135008)

Allow using test-wrapper-gypbuild.py on Windows when no python interpreter is registered.

Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=11947

Added:
 /trunk/test/mjsunit/regress/regress-crbug-135008.js
Modified:
 /trunk/ChangeLog
 /trunk/src/arm/lithium-codegen-arm.cc
 /trunk/src/ast.cc
 /trunk/src/hydrogen-instructions.h
 /trunk/src/hydrogen.cc
 /trunk/src/ia32/assembler-ia32.cc
 /trunk/src/ia32/lithium-codegen-ia32.cc
 /trunk/src/mips/lithium-codegen-mips.cc
 /trunk/src/objects-printer.cc
 /trunk/src/parser.cc
 /trunk/src/version.cc
 /trunk/src/x64/assembler-x64.cc
 /trunk/src/x64/lithium-codegen-x64.cc
 /trunk/test/mjsunit/compiler/inline-literals.js
 /trunk/tools/test-wrapper-gypbuild.py

=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-crbug-135008.js Thu Jun 28 08:04:22 2012
@@ -0,0 +1,45 @@
+// 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.
+
+// Filler long enough to trigger lazy parsing.
+var filler = "//" + new Array(1024).join('x');
+
+var scope = { x:23 };
+
+with(scope) {
+  eval(
+    "scope.f = (function outer() {" +
+    "  function inner() {" +
+    "    return x;" +
+    "  }" +
+    "  return inner;" +
+    "})();" +
+    filler
+  );
+};
+
+assertSame(23, scope.f());
=======================================
--- /trunk/ChangeLog    Wed Jun 27 04:12:38 2012
+++ /trunk/ChangeLog    Thu Jun 28 08:04:22 2012
@@ -1,3 +1,14 @@
+2012-06-28: Version 3.12.5
+
+        Fixed lazy parsing heuristics to respect outer scope.
+        (Chromium issue 135008)
+
+        Allow using test-wrapper-gypbuild.py on Windows when no python
+        interpreter is registered.
+
+        Performance and stability improvements on all platforms.
+
+
 2012-06-27: Version 3.12.4

         Removed -fomit-frame-pointer flag from Release builds to make
=======================================
--- /trunk/src/arm/lithium-codegen-arm.cc       Fri Jun 22 06:44:28 2012
+++ /trunk/src/arm/lithium-codegen-arm.cc       Thu Jun 28 08:04:22 2012
@@ -4754,7 +4754,7 @@


 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
-  Heap* heap = isolate()->heap();
+  Handle<FixedArray> literals(instr->environment()->closure()->literals());
   ElementsKind boilerplate_elements_kind =
       instr->hydrogen()->boilerplate_elements_kind();

@@ -4774,12 +4774,12 @@
     DeoptimizeIf(ne, instr->environment());
   }

-  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
+  // Set up the parameters to the stub/runtime call.
+  __ LoadHeapObject(r3, literals);
   __ mov(r2, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
   // Boilerplate already exists, constant elements are never accessed.
   // Pass an empty fixed array.
-  __ mov(r1, Operand(Handle<FixedArray>(heap->empty_fixed_array())));
+  __ mov(r1, Operand(isolate()->factory()->empty_fixed_array()));
   __ Push(r3, r2, r1);

   // Pick the right runtime function or stub to call.
@@ -4987,15 +4987,13 @@
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   Label materialized;
   // Registers will be used as follows:
-  // r3 = JS function.
   // r7 = literals array.
   // r1 = regexp literal.
   // r0 = regexp literal clone.
   // r2 and r4-r6 are used as temporaries.
-  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ ldr(r7, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
-  int literal_offset = FixedArray::kHeaderSize +
-      instr->hydrogen()->literal_index() * kPointerSize;
+  int literal_offset =
+      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
+  __ LoadHeapObject(r7, instr->hydrogen()->literals());
   __ ldr(r1, FieldMemOperand(r7, literal_offset));
   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   __ cmp(r1, ip);
=======================================
--- /trunk/src/ast.cc   Wed Jun 27 04:12:38 2012
+++ /trunk/src/ast.cc   Thu Jun 28 08:04:22 2012
@@ -1047,6 +1047,8 @@
 REGULAR_NODE(Conditional)
 REGULAR_NODE(Literal)
 REGULAR_NODE(ObjectLiteral)
+REGULAR_NODE(RegExpLiteral)
+REGULAR_NODE(ArrayLiteral)
 REGULAR_NODE(Assignment)
 REGULAR_NODE(Throw)
 REGULAR_NODE(Property)
@@ -1077,8 +1079,6 @@
 DONT_OPTIMIZE_NODE(SharedFunctionInfoLiteral)

 DONT_INLINE_NODE(FunctionLiteral)
-DONT_INLINE_NODE(RegExpLiteral) // TODO(1322): Allow materialized literals.
-DONT_INLINE_NODE(ArrayLiteral)  // TODO(1322): Allow materialized literals.

 DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
 DONT_SELFOPTIMIZE_NODE(WhileStatement)
=======================================
--- /trunk/src/hydrogen-instructions.h  Thu Jun 21 04:16:20 2012
+++ /trunk/src/hydrogen-instructions.h  Thu Jun 28 08:04:22 2012
@@ -4792,10 +4792,12 @@
 class HRegExpLiteral: public HMaterializedLiteral<1> {
  public:
   HRegExpLiteral(HValue* context,
+                 Handle<FixedArray> literals,
                  Handle<String> pattern,
                  Handle<String> flags,
                  int literal_index)
       : HMaterializedLiteral<1>(literal_index, 0),
+        literals_(literals),
         pattern_(pattern),
         flags_(flags) {
     SetOperandAt(0, context);
@@ -4803,6 +4805,7 @@
   }

   HValue* context() { return OperandAt(0); }
+  Handle<FixedArray> literals() { return literals_; }
   Handle<String> pattern() { return pattern_; }
   Handle<String> flags() { return flags_; }

@@ -4814,6 +4817,7 @@
   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)

  private:
+  Handle<FixedArray> literals_;
   Handle<String> pattern_;
   Handle<String> flags_;
 };
=======================================
--- /trunk/src/hydrogen.cc      Fri Jun 22 06:44:28 2012
+++ /trunk/src/hydrogen.cc      Thu Jun 28 08:04:22 2012
@@ -4646,9 +4646,12 @@
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
+ Handle<JSFunction> closure = function_state()->compilation_info()->closure();
+  Handle<FixedArray> literals(closure->literals());
   HValue* context = environment()->LookupContext();

   HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
+                                                     literals,
                                                      expr->pattern(),
                                                      expr->flags(),
expr->literal_index());
=======================================
--- /trunk/src/ia32/assembler-ia32.cc   Thu Feb 16 07:33:53 2012
+++ /trunk/src/ia32/assembler-ia32.cc   Thu Jun 28 08:04:22 2012
@@ -1373,7 +1373,7 @@
     ASSERT(offset_to_next <= 0);
     // Relative address, relative to point after address.
     int disp = pos - fixup_pos - sizeof(int8_t);
-    ASSERT(0 <= disp && disp <= 127);
+    CHECK(0 <= disp && disp <= 127);
     set_byte_at(fixup_pos, disp);
     if (offset_to_next < 0) {
       L->link_to(fixup_pos + offset_to_next, Label::kNear);
=======================================
--- /trunk/src/ia32/lithium-codegen-ia32.cc     Wed Jun 27 04:12:38 2012
+++ /trunk/src/ia32/lithium-codegen-ia32.cc     Thu Jun 28 08:04:22 2012
@@ -4685,7 +4685,7 @@

 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
   ASSERT(ToRegister(instr->context()).is(esi));
-  Heap* heap = isolate()->heap();
+  Handle<FixedArray> literals(instr->environment()->closure()->literals());
   ElementsKind boilerplate_elements_kind =
       instr->hydrogen()->boilerplate_elements_kind();

@@ -4706,12 +4706,11 @@
   }

   // Set up the parameters to the stub/runtime call.
-  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  __ push(FieldOperand(eax, JSFunction::kLiteralsOffset));
+  __ PushHeapObject(literals);
   __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
   // Boilerplate already exists, constant elements are never accessed.
   // Pass an empty fixed array.
-  __ push(Immediate(Handle<FixedArray>(heap->empty_fixed_array())));
+  __ push(Immediate(isolate()->factory()->empty_fixed_array()));

   // Pick the right runtime function or stub to call.
   int length = instr->hydrogen()->length();
@@ -4930,15 +4929,13 @@
   ASSERT(ToRegister(instr->context()).is(esi));
   Label materialized;
   // Registers will be used as follows:
-  // edi = JS function.
   // ecx = literals array.
   // ebx = regexp literal.
   // eax = regexp literal clone.
   // esi = context.
-  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
-  int literal_offset = FixedArray::kHeaderSize +
-      instr->hydrogen()->literal_index() * kPointerSize;
+  int literal_offset =
+      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
+  __ LoadHeapObject(ecx, instr->hydrogen()->literals());
   __ mov(ebx, FieldOperand(ecx, literal_offset));
   __ cmp(ebx, factory()->undefined_value());
   __ j(not_equal, &materialized, Label::kNear);
=======================================
--- /trunk/src/mips/lithium-codegen-mips.cc     Fri Jun 22 06:44:28 2012
+++ /trunk/src/mips/lithium-codegen-mips.cc     Thu Jun 28 08:04:22 2012
@@ -4522,7 +4522,7 @@


 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
-  Heap* heap = isolate()->heap();
+  Handle<FixedArray> literals(instr->environment()->closure()->literals());
   ElementsKind boilerplate_elements_kind =
       instr->hydrogen()->boilerplate_elements_kind();

@@ -4543,12 +4543,13 @@
                  a2,
                  Operand(boilerplate_elements_kind));
   }
-  __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
+
+  // Set up the parameters to the stub/runtime call.
+  __ LoadHeapObject(a3, literals);
   __ li(a2, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
   // Boilerplate already exists, constant elements are never accessed.
   // Pass an empty fixed array.
-  __ li(a1, Operand(Handle<FixedArray>(heap->empty_fixed_array())));
+  __ li(a1, Operand(isolate()->factory()->empty_fixed_array()));
   __ Push(a3, a2, a1);

   // Pick the right runtime function or stub to call.
@@ -4759,15 +4760,13 @@
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   Label materialized;
   // Registers will be used as follows:
-  // a3 = JS function.
   // t3 = literals array.
   // a1 = regexp literal.
   // a0 = regexp literal clone.
   // a2 and t0-t2 are used as temporaries.
-  __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ lw(t3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
-  int literal_offset = FixedArray::kHeaderSize +
-      instr->hydrogen()->literal_index() * kPointerSize;
+  int literal_offset =
+      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
+  __ LoadHeapObject(t3, instr->hydrogen()->literals());
   __ lw(a1, FieldMemOperand(t3, literal_offset));
   __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
   __ Branch(&materialized, ne, a1, Operand(at));
=======================================
--- /trunk/src/objects-printer.cc       Wed Jun 27 04:12:38 2012
+++ /trunk/src/objects-printer.cc       Thu Jun 28 08:04:22 2012
@@ -739,6 +739,8 @@
   shared()->name()->Print(out);
   PrintF(out, "\n - context = ");
   unchecked_context()->ShortPrint(out);
+  PrintF(out, "\n - literals = ");
+  literals()->ShortPrint(out);
   PrintF(out, "\n - code = ");
   code()->ShortPrint(out);
   PrintF(out, "\n");
=======================================
--- /trunk/src/parser.cc        Thu Jun 21 04:16:20 2012
+++ /trunk/src/parser.cc        Thu Jun 28 08:04:22 2012
@@ -4521,6 +4521,7 @@
     // The heuristics are:
// - It must not have been prohibited by the caller to Parse (some callers
     //   need a full AST).
+    // - The outer scope must allow lazy compilation of inner functions.
// - The function mustn't be a function expression with an open parenthesis
     //   before; we consider that a hint that the function will be called
     //   immediately, and it would be a waste of time to make it lazily
@@ -4528,6 +4529,7 @@
// These are all things we can know at this point, without looking at the
     // function itself.
     bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
+                               top_scope_->AllowsLazyCompilation() &&
                                !parenthesized_function_);
parenthesized_function_ = false; // The bit was set for this function only.

=======================================
--- /trunk/src/version.cc       Wed Jun 27 04:12:38 2012
+++ /trunk/src/version.cc       Thu Jun 28 08:04:22 2012
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     12
-#define BUILD_NUMBER      4
+#define BUILD_NUMBER      5
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
=======================================
--- /trunk/src/x64/assembler-x64.cc     Fri Mar 23 08:11:57 2012
+++ /trunk/src/x64/assembler-x64.cc     Thu Jun 28 08:04:22 2012
@@ -467,7 +467,7 @@
         static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
     ASSERT(offset_to_next <= 0);
     int disp = pos - (fixup_pos + sizeof(int8_t));
-    ASSERT(is_int8(disp));
+    CHECK(is_int8(disp));
     set_byte_at(fixup_pos, disp);
     if (offset_to_next < 0) {
       L->link_to(fixup_pos + offset_to_next, Label::kNear);
=======================================
--- /trunk/src/x64/lithium-codegen-x64.cc       Wed Jun 27 04:12:38 2012
+++ /trunk/src/x64/lithium-codegen-x64.cc       Thu Jun 28 08:04:22 2012
@@ -4401,7 +4401,7 @@


 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
-  Heap* heap = isolate()->heap();
+  Handle<FixedArray> literals(instr->environment()->closure()->literals());
   ElementsKind boilerplate_elements_kind =
       instr->hydrogen()->boilerplate_elements_kind();

@@ -4422,12 +4422,11 @@
   }

   // Set up the parameters to the stub/runtime call.
-  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-  __ push(FieldOperand(rax, JSFunction::kLiteralsOffset));
+  __ PushHeapObject(literals);
   __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
   // Boilerplate already exists, constant elements are never accessed.
   // Pass an empty fixed array.
-  __ Push(Handle<FixedArray>(heap->empty_fixed_array()));
+  __ Push(isolate()->factory()->empty_fixed_array());

   // Pick the right runtime function or stub to call.
   int length = instr->hydrogen()->length();
@@ -4630,14 +4629,12 @@
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   Label materialized;
   // Registers will be used as follows:
-  // rdi = JS function.
   // rcx = literals array.
   // rbx = regexp literal.
   // rax = regexp literal clone.
-  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-  __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
-  int literal_offset = FixedArray::kHeaderSize +
-      instr->hydrogen()->literal_index() * kPointerSize;
+  int literal_offset =
+      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
+  __ LoadHeapObject(rcx, instr->hydrogen()->literals());
   __ movq(rbx, FieldOperand(rcx, literal_offset));
   __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
   __ j(not_equal, &materialized, Label::kNear);
=======================================
--- /trunk/test/mjsunit/compiler/inline-literals.js     Tue Feb 21 02:08:21 2012
+++ /trunk/test/mjsunit/compiler/inline-literals.js     Thu Jun 28 08:04:22 2012
@@ -29,6 +29,26 @@

 // Test that we can inline functions containing materialized literals.

+function a2(b, c) {
+  return [b, c, b + c];
+}
+
+function a1(a, b, c) {
+  return [a, a2(b, c)];
+}
+
+function TestArrayLiteral(a, b, c) {
+  var expected = [a, [b, c, b + c]];
+  var result = a1(a, b, c);
+  assertEquals(expected, result, "TestArrayLiteral");
+}
+
+TestArrayLiteral(1, 2, 3);
+TestArrayLiteral(1, 2, 3);
+%OptimizeFunctionOnNextCall(TestArrayLiteral);
+TestArrayLiteral(1, 2, 3);
+TestArrayLiteral('a', 'b', 'c');
+
 function o2(b, c) {
   return { 'b':b, 'c':c, 'y':b + c };
 }
@@ -48,3 +68,22 @@
 %OptimizeFunctionOnNextCall(TestObjectLiteral);
 TestObjectLiteral(1, 2, 3);
 TestObjectLiteral('a', 'b', 'c');
+
+function r2(s, x, y) {
+  return s.replace(/a/, x + y);
+}
+
+function r1(s, x, y) {
+  return r2(s, x, y).replace(/b/, y + x);
+}
+
+function TestRegExpLiteral(s, x, y, expected) {
+  var result = r1(s, x, y);
+  assertEquals(expected, result, "TestRegExpLiteral");
+}
+
+TestRegExpLiteral("a-", "reg", "exp", "regexp-");
+TestRegExpLiteral("-b", "reg", "exp", "-expreg");
+%OptimizeFunctionOnNextCall(TestRegExpLiteral);
+TestRegExpLiteral("ab", "reg", "exp", "regexpexpreg");
+TestRegExpLiteral("ab", 12345, 54321, "6666666666");
=======================================
--- /trunk/tools/test-wrapper-gypbuild.py       Wed Jun 13 04:51:58 2012
+++ /trunk/tools/test-wrapper-gypbuild.py       Thu Jun 28 08:04:22 2012
@@ -217,9 +217,10 @@

   if not options.no_presubmit:
     print ">>> running presubmit tests"
-    returncodes += subprocess.call([workspace + '/tools/presubmit.py'])
-
-  args_for_children = ['python']
+    returncodes += subprocess.call([sys.executable,
+                                    workspace + '/tools/presubmit.py'])
+
+  args_for_children = [sys.executable]
args_for_children += [workspace + '/tools/test.py'] + PassOnOptions(options)
   args_for_children += ['--no-build', '--build-system=gyp']
   for arg in args:

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

Reply via email to