From 3d85b86e238d1aaabc241a175b50324bb3c82fd8 Mon Sep 17 00:00:00 2001 From: "marja@chromium.org" Date: Mon, 24 Feb 2014 17:48:09 +0000 Subject: [PATCH] Lazy preparsing vs. lazy parsing fix. Preparsing is always maximally lazy (every function that can be lazy is preparsed lazily), but Parser has more complicated laziness logic. If we're going to parse eagerly, and we have preparse data from lazy preparsing, we're gonna have a bad time. The symbol stream won't contain symbols inside lazy functions, and when the Parser parses them eagerly, it will consume symbols from the symbol stream, and everything will go wrong. This bug was hidden because the symbol cache was not used for real (see https://codereview.chromium.org/172753002/ ). R=ulan@chromium.org BUG=346207 LOG=Y Review URL: https://codereview.chromium.org/177973002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19532 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler.cc | 7 +++++++ test/cctest/test-debug.cc | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/compiler.cc b/src/compiler.cc index d466778..743d333 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -789,6 +789,13 @@ static Handle CompileToplevel(CompilationInfo* info) { String::cast(script->source())->length() > FLAG_min_preparse_length) && !DebuggerWantsEagerCompilation(info); + if (!parse_allow_lazy && info->pre_parse_data() != NULL) { + // We are going to parse eagerly, but we have preparse data produced by lazy + // preparsing. We cannot use it, since it won't contain all the symbols we + // need for eager parsing. + info->SetPreParseData(NULL); + } + Handle result; { VMState state(info->isolate()); diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc index 67ef885..8077979 100644 --- a/test/cctest/test-debug.cc +++ b/test/cctest/test-debug.cc @@ -7700,4 +7700,39 @@ TEST(LiveEditDisabled) { } +TEST(PrecompiledFunction) { + // Regression test for crbug.com/346207. If we have preparse data, parsing the + // function in the presence of the debugger (and breakpoints) should still + // succeed. The bug was that preparsing was done lazily and parsing was done + // eagerly, so, the symbol streams didn't match. + DebugLocalContext env; + v8::HandleScope scope(env->GetIsolate()); + env.ExposeDebug(); + v8::Debug::SetDebugEventListener2(DebugBreakInlineListener); + + v8::Local break_here = + CompileFunction(&env, "function break_here(){}", "break_here"); + SetBreakPoint(break_here, 0); + + const char* source = + "var a = b = c = 1; \n" + "function this_is_lazy() { \n" + // This symbol won't appear in the preparse data. + " var a; \n" + "} \n" + "function bar() { \n" + " return \"bar\"; \n" + "}; \n" + "a = b = c = 2; \n" + "bar(); \n"; + v8::Local result = PreCompileCompileRun(source); + CHECK(result->IsString()); + v8::String::Utf8Value utf8(result); + CHECK_EQ("bar", *utf8); + + v8::Debug::SetDebugEventListener2(NULL); + CheckDebuggerUnloaded(); +} + + #endif // ENABLE_DEBUGGER_SUPPORT -- 2.7.4