Reviewers: Rico,

Message:
PTAL.

Description:
Make sure reparse in ScopeIterator is equivalent to initial parse.

This CL adapts the ScopeIterator to run the preparser over global code
first, so that it matches the behaviour an initial parse with preparsing.

TEST=mjsunit/debug-stepout-scope.js


Please review this at http://codereview.chromium.org/8590027/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/compiler.cc
  M src/parser.h
  M src/parser.cc
  M src/runtime.cc
  M test/cctest/test-parsing.cc
  M test/mjsunit/debug-stepout-scope.js


Index: src/compiler.cc
diff --git a/src/compiler.cc b/src/compiler.cc
index 8b34f022fc53d4f3d4858dfbbeb94835f291c66c..e4d278d2e1b3c743a517d01a28fdc94c7b3f695d 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -488,14 +488,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
     }
     if (pre_data == NULL
         && source_length >= FLAG_min_preparse_length) {
-      if (source->IsExternalTwoByteString()) {
-        ExternalTwoByteStringUC16CharacterStream stream(
- Handle<ExternalTwoByteString>::cast(source), 0, source->length());
-        pre_data = ParserApi::PartialPreParse(&stream, extension, flags);
-      } else {
- GenericStringUC16CharacterStream stream(source, 0, source->length());
-        pre_data = ParserApi::PartialPreParse(&stream, extension, flags);
-      }
+      pre_data = ParserApi::PartialPreParse(source, extension, flags);
     }

     // Create a script object describing the script to be compiled.
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index e19af1cd5cd3dd265633660544b675246588c17b..2780a8789d8d25daf455a5f4b2d24fbd9c4ac112 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -5374,7 +5374,7 @@ static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,

 // Preparse, but only collect data that is immediately useful,
 // even if the preparser data is only used once.
-ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
+ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
                                            v8::Extension* extension,
                                            int flags) {
   bool allow_lazy = FLAG_lazy && (extension == NULL);
@@ -5385,7 +5385,15 @@ ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
   }
   flags |= kAllowLazy;
   PartialParserRecorder recorder;
-  return DoPreParse(source, flags, &recorder);
+  int source_length = source->length();
+  if (source->IsExternalTwoByteString()) {
+    ExternalTwoByteStringUC16CharacterStream stream(
+        Handle<ExternalTwoByteString>::cast(source), 0, source_length);
+    return DoPreParse(&stream, flags, &recorder);
+  } else {
+    GenericStringUC16CharacterStream stream(source, 0, source_length);
+    return DoPreParse(&stream, flags, &recorder);
+  }
 }


Index: src/parser.h
diff --git a/src/parser.h b/src/parser.h
index 1436bf9066c5d50b11c91ec44d1481fd0434d2a4..c17fe756a600f18650fcd228cb2977096df41f3c 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -174,7 +174,7 @@ class ParserApi {

   // Preparser that only does preprocessing that makes sense if only used
   // immediately after.
-  static ScriptDataImpl* PartialPreParse(UC16CharacterStream* source,
+  static ScriptDataImpl* PartialPreParse(Handle<String> source,
                                          v8::Extension* extension,
                                          int flags);
 };
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index 46bb5dc1c668104b03def8bd12cbb9546c6dbeaa..31fbaf7697300da4d1253ddb7bd431c203929bc6 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -11234,8 +11234,19 @@ class ScopeIterator {
     if (scope_info->Type() != FUNCTION_SCOPE) {
       // Global or eval code.
       CompilationInfo info(script);
+      ScriptDataImpl* pre_data = NULL;
+      int flags = kNoParsingFlags;
+      if (info.is_native() || FLAG_allow_natives_syntax) {
+        flags |= kAllowNativesSyntax;
+      }
+      if (!info.is_native() && FLAG_harmony_scoping){
+        flags |= kHarmonyScoping;
+      }
       if (scope_info->Type() == GLOBAL_SCOPE) {
+        Handle<String> source(String::cast(script->source()));
+        pre_data = ParserApi::PartialPreParse(source, NULL, flags);
         info.MarkAsGlobal();
+        info.SetPreParseData(pre_data);
       } else {
         ASSERT(scope_info->Type() == EVAL_SCOPE);
         info.MarkAsEval();
@@ -11244,6 +11255,10 @@ class ScopeIterator {
       CHECK(ParserApi::Parse(&info));
       CHECK(Scope::Analyze(&info));
       scope = info.function()->scope();
+      // Delete preparse data again.
+      if (pre_data != NULL) {
+        delete pre_data;
+      }
     } else {
       // Function code
       CompilationInfo info(shared_info);
Index: test/cctest/test-parsing.cc
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 7901edc91a79b2c4883d66c344626d085c7d6ef9..6dd744502f1365936714e85136190f301783ca30 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -349,10 +349,10 @@ TEST(Regress928) {
       "try { } catch (e) { var foo = function () { /* first */ } }"
       "var bar = function () { /* second */ }";

- i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(program), - static_cast<unsigned>(strlen(program)));
-  i::ScriptDataImpl* data =
-      i::ParserApi::PartialPreParse(&stream, NULL, false);
+  v8::HandleScope handles;
+  i::Handle<i::String> source(
+      FACTORY->NewStringFromAscii(i::CStrVector(program)));
+ i::ScriptDataImpl* data = i::ParserApi::PartialPreParse(source, NULL, false);
   CHECK(!data->HasError());

   data->Initialize();
Index: test/mjsunit/debug-stepout-scope.js
diff --git a/test/mjsunit/debug-stepout-scope.js b/test/mjsunit/debug-stepout-scope.js index b06ec1a83b38ae5cbbe737524b948ef66f375e0b..2e1f0de7c46287354cbbedc05d2bddb4156e471e 100644
--- a/test/mjsunit/debug-stepout-scope.js
+++ b/test/mjsunit/debug-stepout-scope.js
@@ -166,5 +166,15 @@ eval(pre + "1");
 eval(pre + "try { throw 'stuff' } catch (e) { e = 1; }");


+// The following function can be preparsed, but not parsed because
+// it contains an invalid break target. This is to make sure that
+// when a script is preparsed, the ScopeIterator will reparse it in
+// the same way.
+function lazy_parsed_but_never_called() {
+  while (true) {
+    break invalid_break_label;
+  }
+}
+
 // With block as the last(!) statement in global code.
 with ({}) { debugger; }
\ No newline at end of file


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

Reply via email to