Begin a more aggressive refactoring of the Compiler interface.

The plan is to use the CompilationInfo class to communicate inputs and
outputs to compilation pipeline phases, which each return a boolean
success/failure flag.

The intent is to make it easier to compose small pieces of the
pipeline without having to grow a custom function each time, each
taking a half dozen arguments.

This change modifies the very front end (the parser).

Review URL: http://codereview.chromium.org/3586006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5581 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2010-10-04 11:35:46 +00:00
parent 26163835a7
commit bef3ae07db
9 changed files with 212 additions and 239 deletions

View File

@ -175,7 +175,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_);
loop_nesting_ = info->loop_nesting();
loop_nesting_ = info->is_in_loop() ? 1 : 0;
{
CodeGenState state(this);
@ -339,7 +339,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
}
// Adjust for function-level loop nesting.
ASSERT(loop_nesting_ == info->loop_nesting());
ASSERT(loop_nesting_ == info->is_in_loop()? 1 : 0);
loop_nesting_ = 0;
// Code generation state must be reset.

View File

@ -45,6 +45,40 @@
namespace v8 {
namespace internal {
CompilationInfo::CompilationInfo(Handle<Script> script)
: flags_(0),
function_(NULL),
scope_(NULL),
script_(script),
extension_(NULL),
pre_parse_data_(NULL) {
}
CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
: flags_(IsLazy::encode(true)),
function_(NULL),
scope_(NULL),
shared_info_(shared_info),
script_(Handle<Script>(Script::cast(shared_info->script()))),
extension_(NULL),
pre_parse_data_(NULL) {
}
CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
: flags_(IsLazy::encode(true)),
function_(NULL),
scope_(NULL),
closure_(closure),
shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
script_(Handle<Script>(Script::cast(shared_info_->script()))),
extension_(NULL),
pre_parse_data_(NULL) {
}
// For normal operation the syntax checker is used to determine whether to
// use the full compiler for top level code or not. However if the flag
// --always-full-compiler is specified or debugging is active the full
@ -131,30 +165,25 @@ Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
#endif
static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
bool is_eval,
Compiler::ValidationState validate,
Handle<Script> script,
Handle<Context> context,
v8::Extension* extension,
ScriptDataImpl* pre_data) {
static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info,
Handle<Context> context) {
CompilationZoneScope zone_scope(DELETE_ON_EXIT);
PostponeInterruptsScope postpone;
ASSERT(!i::Top::global_context().is_null());
Handle<Script> script = info->script();
script->set_context_data((*i::Top::global_context())->data());
bool is_json = (validate == Compiler::VALIDATE_JSON);
#ifdef ENABLE_DEBUGGER_SUPPORT
if (is_eval || is_json) {
Script::CompilationType compilation_type = is_json
if (info->is_eval() || info->is_json()) {
Script::CompilationType compilation_type = info->is_json()
? Script::COMPILATION_TYPE_JSON
: Script::COMPILATION_TYPE_EVAL;
script->set_compilation_type(Smi::FromInt(compilation_type));
// For eval scripts add information on the function from which eval was
// called.
if (is_eval) {
if (info->is_eval()) {
StackTraceFrameIterator it;
if (!it.done()) {
script->set_eval_from_shared(
@ -171,31 +200,22 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
#endif
// Only allow non-global compiles for eval.
ASSERT(is_eval || is_global);
ASSERT(info->is_eval() || info->is_global());
// Build AST.
EagerCompilationInfo info(script, is_eval);
FunctionLiteral* lit =
Parser::MakeAST(is_global, script, extension, pre_data, is_json);
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
return Handle<SharedFunctionInfo>::null();
}
info.set_function(lit);
if (!Parser::Parse(info)) return Handle<SharedFunctionInfo>::null();
// Measure how long it takes to do the compilation; only take the
// rest of the function into account to avoid overlap with the
// parsing statistics.
HistogramTimer* rate = is_eval
HistogramTimer* rate = info->is_eval()
? &Counters::compile_eval
: &Counters::compile;
HistogramTimerScope timer(rate);
// Compile the code.
FunctionLiteral* lit = info->function();
LiveEditFunctionTracker live_edit_tracker(lit);
Handle<Code> code = MakeCode(context, &info);
Handle<Code> code = MakeCode(context, info);
// Check for stack-overflow exceptions.
if (code.is_null()) {
@ -205,18 +225,22 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
if (script->name()->IsString()) {
PROFILE(CodeCreateEvent(
is_eval ? Logger::EVAL_TAG :
Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*code, String::cast(script->name())));
info->is_eval()
? Logger::EVAL_TAG
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*code,
String::cast(script->name())));
OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
code->instruction_start(),
code->instruction_size()));
} else {
PROFILE(CodeCreateEvent(
is_eval ? Logger::EVAL_TAG :
Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*code, ""));
OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
info->is_eval()
? Logger::EVAL_TAG
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*code,
""));
OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
code->instruction_start(),
code->instruction_size()));
}
@ -227,7 +251,7 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
lit->name(),
lit->materialized_literal_count(),
code,
SerializedScopeInfo::Create(info.scope()));
SerializedScopeInfo::Create(info->scope()));
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Compiler::SetFunctionInfo(result, lit, true, script);
@ -303,13 +327,11 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
: *script_data);
// Compile the function and add it to the cache.
result = MakeFunctionInfo(true,
false,
DONT_VALIDATE_JSON,
script,
Handle<Context>::null(),
extension,
pre_data);
CompilationInfo info(script);
info.MarkAsGlobal();
info.SetExtension(extension);
info.SetPreParseData(pre_data);
result = MakeFunctionInfo(&info, Handle<Context>::null());
if (extension == NULL && !result.is_null()) {
CompilationCache::PutScript(source, result);
}
@ -329,9 +351,10 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
ValidationState validate) {
// Note that if validation is required then no path through this
// function is allowed to return a value without validating that
// the input is legal json.
// Note that if validation is required then no path through this function
// is allowed to return a value without validating that the input is legal
// json.
bool is_json = (validate == VALIDATE_JSON);
int source_length = source->length();
Counters::total_eval_size.Increment(source_length);
@ -340,27 +363,26 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
// The VM is in the COMPILER state until exiting this function.
VMState state(COMPILER);
// Do a lookup in the compilation cache; if the entry is not there,
// invoke the compiler and add the result to the cache. If we're
// evaluating json we bypass the cache since we can't be sure a
// potential value in the cache has been validated.
// Do a lookup in the compilation cache; if the entry is not there, invoke
// the compiler and add the result to the cache. If we're evaluating json
// we bypass the cache since we can't be sure a potential value in the
// cache has been validated.
Handle<SharedFunctionInfo> result;
if (validate == DONT_VALIDATE_JSON)
if (!is_json) {
result = CompilationCache::LookupEval(source, context, is_global);
}
if (result.is_null()) {
// Create a script object describing the script to be compiled.
Handle<Script> script = Factory::NewScript(source);
result = MakeFunctionInfo(is_global,
true,
validate,
script,
context,
NULL,
NULL);
if (!result.is_null() && validate != VALIDATE_JSON) {
// For json it's unlikely that we'll ever see exactly the same
// string again so we don't use the compilation cache.
CompilationInfo info(script);
info.MarkAsEval();
if (is_global) info.MarkAsGlobal();
if (is_json) info.MarkAsJson();
result = MakeFunctionInfo(&info, context);
if (!result.is_null() && !is_json) {
// For json it's unlikely that we'll ever see exactly the same string
// again so we don't use the compilation cache.
CompilationCache::PutEval(source, context, is_global, result);
}
}
@ -382,16 +404,8 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
int compiled_size = shared->end_position() - shared->start_position();
Counters::total_compile_size.Increment(compiled_size);
// Generate the AST for the lazily compiled function. The AST may be
// NULL in case of parser stack overflow.
FunctionLiteral* lit = Parser::MakeLazyAST(shared);
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
return false;
}
info->set_function(lit);
// Generate the AST for the lazily compiled function.
if (!Parser::Parse(info)) return false;
// Measure how long it takes to do the lazy compilation; only take
// the rest of the function into account to avoid overlap with the
@ -428,6 +442,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
}
// Set the expected number of properties for instances.
FunctionLiteral* lit = info->function();
SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
// Set the optimication hints after performing lazy compilation, as these are
@ -477,8 +492,8 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
// Generate code and return it. The way that the compilation mode
// is controlled by the command-line flags is described in
// the static helper function MakeCode.
EagerCompilationInfo info(script, false);
info.set_function(literal);
CompilationInfo info(script);
info.SetFunction(literal);
bool is_run_once = literal->try_full_codegen();
bool use_full = FLAG_full_compiler && !literal->contains_loops();

View File

@ -42,112 +42,84 @@ class ScriptDataImpl;
// is constructed based on the resources available at compile-time.
class CompilationInfo BASE_EMBEDDED {
public:
virtual ~CompilationInfo() {}
explicit CompilationInfo(Handle<Script> script);
explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
explicit CompilationInfo(Handle<JSFunction> closure);
// Dispatched behavior.
virtual Handle<SharedFunctionInfo> shared_info() const = 0;
bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
bool is_json() const { return (flags_ & IsJson::mask()) != 0; }
bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
FunctionLiteral* function() const { return function_; }
Scope* scope() const { return function_->scope(); }
Handle<JSFunction> closure() const { return closure_; }
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
Handle<Script> script() const { return script_; }
v8::Extension* extension() const { return extension_; }
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
virtual Handle<Script> script() const {
return Handle<Script>(Script::cast(shared_info()->script()));
void MarkAsEval() {
ASSERT(!is_lazy());
flags_ |= IsEval::encode(true);
}
virtual Handle<JSFunction> closure() const {
return Handle<JSFunction>::null();
void MarkAsGlobal() {
ASSERT(!is_lazy());
flags_ |= IsGlobal::encode(true);
}
void MarkAsJson() {
ASSERT(!is_lazy());
flags_ |= IsJson::encode(true);
}
void MarkAsInLoop() {
ASSERT(is_lazy());
flags_ |= IsInLoop::encode(true);
}
void SetFunction(FunctionLiteral* literal) {
ASSERT(function_ == NULL);
function_ = literal;
}
void SetExtension(v8::Extension* extension) {
ASSERT(!is_lazy());
extension_ = extension;
}
void SetPreParseData(ScriptDataImpl* pre_parse_data) {
ASSERT(!is_lazy());
pre_parse_data_ = pre_parse_data;
}
virtual bool is_eval() const { return false; }
virtual int loop_nesting() const { return 0; }
virtual bool has_global_object() const { return false; }
virtual GlobalObject* global_object() const { return NULL; }
// There should always be a function literal, but it may be set after
// construction (for lazy compilation).
FunctionLiteral* function() { return function_; }
void set_function(FunctionLiteral* literal) { function_ = literal; }
// Derived accessors.
Scope* scope() { return function()->scope(); }
protected:
CompilationInfo() : function_(NULL) {}
private:
// Flags using template class BitField<type, start, length>. All are
// false by default.
//
// Compilation is either eager or lazy.
class IsLazy: public BitField<bool, 0, 1> {};
// Flags that can be set for eager compilation.
class IsEval: public BitField<bool, 1, 1> {};
class IsGlobal: public BitField<bool, 2, 1> {};
class IsJson: public BitField<bool, 3, 1> {};
// Flags that can be set for lazy compilation.
class IsInLoop: public BitField<bool, 4, 1> {};
unsigned flags_;
// Fields filled in by the compilation pipeline.
FunctionLiteral* function_;
Scope* scope_;
// Possible initial inputs to the compilation process.
Handle<JSFunction> closure_;
Handle<SharedFunctionInfo> shared_info_;
Handle<Script> script_;
// Fields possibly needed for eager compilation, NULL by default.
v8::Extension* extension_;
ScriptDataImpl* pre_parse_data_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
class EagerCompilationInfo: public CompilationInfo {
public:
EagerCompilationInfo(Handle<Script> script, bool is_eval)
: script_(script), is_eval_(is_eval) {
ASSERT(!script.is_null());
}
// Overridden functions from the base class.
virtual Handle<SharedFunctionInfo> shared_info() const {
return Handle<SharedFunctionInfo>::null();
}
virtual Handle<Script> script() const { return script_; }
virtual bool is_eval() const { return is_eval_; }
private:
Handle<Script> script_;
bool is_eval_;
};
class LazySharedCompilationInfo: public CompilationInfo {
public:
explicit LazySharedCompilationInfo(Handle<SharedFunctionInfo> shared_info)
: shared_info_(shared_info) {
ASSERT(!shared_info.is_null());
}
// Overridden functions from the base class.
virtual Handle<SharedFunctionInfo> shared_info() const {
return shared_info_;
}
private:
Handle<SharedFunctionInfo> shared_info_;
};
class LazyFunctionCompilationInfo: public CompilationInfo {
public:
LazyFunctionCompilationInfo(Handle<JSFunction> closure,
int loop_nesting)
: closure_(closure), loop_nesting_(loop_nesting) {
ASSERT(!closure.is_null());
}
// Overridden functions from the base class.
virtual Handle<SharedFunctionInfo> shared_info() const {
return Handle<SharedFunctionInfo>(closure_->shared());
}
virtual int loop_nesting() const { return loop_nesting_; }
virtual bool has_global_object() const {
return closure_->context()->global() != NULL;
}
virtual GlobalObject* global_object() const {
return closure_->context()->global();
}
private:
Handle<JSFunction> closure_;
int loop_nesting_;
};
// The V8 compiler
//
// General strategy: Source code is translated into an anonymous function w/o
@ -161,7 +133,7 @@ class LazyFunctionCompilationInfo: public CompilationInfo {
class Compiler : public AllStatic {
public:
enum ValidationState { VALIDATE_JSON, DONT_VALIDATE_JSON };
enum ValidationState { DONT_VALIDATE_JSON, VALIDATE_JSON };
// All routines return a JSFunction.
// If an error occurs an exception is raised and

View File

@ -779,7 +779,7 @@ static bool CompileLazyHelper(CompilationInfo* info,
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) {
LazySharedCompilationInfo info(shared);
CompilationInfo info(shared);
return CompileLazyHelper(&info, flag);
}
@ -791,7 +791,7 @@ bool CompileLazy(Handle<JSFunction> function,
function->shared()->set_code_age(0);
return true;
} else {
LazyFunctionCompilationInfo info(function, 0);
CompilationInfo info(function);
bool result = CompileLazyHelper(&info, flag);
PROFILE(FunctionCreateEvent(*function));
return result;
@ -806,7 +806,8 @@ bool CompileLazyInLoop(Handle<JSFunction> function,
function->shared()->set_code_age(0);
return true;
} else {
LazyFunctionCompilationInfo info(function, 1);
CompilationInfo info(function);
info.MarkAsInLoop();
bool result = CompileLazyHelper(&info, flag);
PROFILE(FunctionCreateEvent(*function));
return result;

View File

@ -179,7 +179,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_);
loop_nesting_ = info->loop_nesting();
loop_nesting_ = info->is_in_loop() ? 1 : 0;
JumpTarget::set_compiling_deferred_code(false);
@ -358,7 +358,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
}
// Adjust for function-level loop nesting.
ASSERT_EQ(loop_nesting_, info->loop_nesting());
ASSERT_EQ(loop_nesting_, info->is_in_loop() ? 1 : 0);
loop_nesting_ = 0;
// Code generation state must be reset.

View File

@ -398,31 +398,16 @@ Handle<JSArray> LiveEdit::CompareStringsLinewise(Handle<String> s1,
static void CompileScriptForTracker(Handle<Script> script) {
const bool is_eval = false;
const bool is_global = true;
// TODO(635): support extensions.
Extension* extension = NULL;
PostponeInterruptsScope postpone;
// Only allow non-global compiles for eval.
ASSERT(is_eval || is_global);
// Build AST.
ScriptDataImpl* pre_data = NULL;
EagerCompilationInfo info(script, is_eval);
FunctionLiteral* lit =
Parser::MakeAST(is_global, script, extension, pre_data);
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
return;
}
info.set_function(lit);
CompilationInfo info(script);
info.MarkAsGlobal();
if (!Parser::Parse(&info)) return;
// Compile the code.
LiveEditFunctionTracker tracker(lit);
LiveEditFunctionTracker tracker(info.function());
Handle<Code> code = MakeCodeForLiveEdit(&info);
// Check for stack-overflow exceptions.
@ -433,11 +418,13 @@ static void CompileScriptForTracker(Handle<Script> script) {
tracker.RecordRootFunctionInfo(code);
}
// Unwraps JSValue object, returning its field "value"
static Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
return Handle<Object>(jsValue->value());
}
// Wraps any object into a OpaqueReference, that will hide the object
// from JavaScript.
static Handle<JSValue> WrapInJSValue(Object* object) {
@ -448,6 +435,7 @@ static Handle<JSValue> WrapInJSValue(Object* object) {
return result;
}
// Simple helper class that creates more or less typed structures over
// JSArray object. This is an adhoc method of passing structures from C++
// to JavaScript.
@ -468,6 +456,7 @@ class JSArrayBasedStruct {
Handle<JSArray> GetJSArray() {
return array_;
}
protected:
void SetField(int field_position, Handle<Object> value) {
SetElement(array_, field_position, value);
@ -482,6 +471,7 @@ class JSArrayBasedStruct {
Object* res = GetField(field_position);
return Smi::cast(res)->value();
}
private:
Handle<JSArray> array_;
};
@ -554,6 +544,7 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
friend class JSArrayBasedStruct<FunctionInfoWrapper>;
};
// Wraps SharedFunctionInfo along with some of its fields for passing it
// back to JavaScript. SharedFunctionInfo object itself is additionally
// wrapped into BlindReference for sanitizing reasons.
@ -594,6 +585,7 @@ class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
friend class JSArrayBasedStruct<SharedInfoWrapper>;
};
class FunctionInfoListener {
public:
FunctionInfoListener() {
@ -620,7 +612,6 @@ class FunctionInfoListener {
current_parent_index_ = info.GetParentIndex();
}
public:
// Saves only function code, because for a script function we
// may never create a SharedFunctionInfo object.
void FunctionCode(Handle<Code> function_code) {
@ -708,6 +699,7 @@ class FunctionInfoListener {
int current_parent_index_;
};
static FunctionInfoListener* active_function_info_listener = NULL;
JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,

View File

@ -5344,14 +5344,19 @@ bool Parser::ParseRegExp(FlatStringReader* input,
}
FunctionLiteral* Parser::MakeAST(bool compile_in_global_context,
Handle<Script> script,
v8::Extension* extension,
ScriptDataImpl* pre_data,
bool is_json) {
bool Parser::Parse(CompilationInfo* info) {
ASSERT(info->function() == NULL);
FunctionLiteral* result = NULL;
Handle<Script> script = info->script();
if (info->is_lazy()) {
AstBuildingParser parser(script, true, NULL, NULL);
result = parser.ParseLazy(info->shared_info());
} else {
bool allow_natives_syntax =
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
AstBuildingParser parser(script, allow_natives_syntax, extension, pre_data);
ScriptDataImpl* pre_data = info->pre_parse_data();
AstBuildingParser parser(script, allow_natives_syntax, info->extension(),
pre_data);
if (pre_data != NULL && pre_data->has_error()) {
Scanner::Location loc = pre_data->MessageLocation();
const char* message = pre_data->BuildMessage();
@ -5362,25 +5367,19 @@ FunctionLiteral* Parser::MakeAST(bool compile_in_global_context,
DeleteArray(args[i]);
}
DeleteArray(args.start());
return NULL;
}
Handle<String> source = Handle<String>(String::cast(script->source()));
FunctionLiteral* result;
if (is_json) {
ASSERT(compile_in_global_context);
result = parser.ParseJson(source);
ASSERT(Top::has_pending_exception());
} else {
result = parser.ParseProgram(source, compile_in_global_context);
Handle<String> source = Handle<String>(String::cast(script->source()));
// JSON is always global.
ASSERT(!info->is_json() || info->is_global());
result = info->is_json()
? parser.ParseJson(source)
: parser.ParseProgram(source, info->is_global());
}
}
return result;
}
FunctionLiteral* Parser::MakeLazyAST(Handle<SharedFunctionInfo> info) {
Handle<Script> script(Script::cast(info->script()));
AstBuildingParser parser(script, true, NULL, NULL);
FunctionLiteral* result = parser.ParseLazy(info);
return result;
info->SetFunction(result);
return (result != NULL);
}
#undef NEW

View File

@ -35,6 +35,7 @@
namespace v8 {
namespace internal {
class CompilationInfo;
class FuncNameInferrer;
class ParserFactory;
class ParserLog;
@ -183,17 +184,10 @@ class Parser {
ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
virtual ~Parser() { }
// Takes a script and and context information, and builds a
// FunctionLiteral AST node. Returns NULL and deallocates any allocated
// AST nodes if parsing failed.
static FunctionLiteral* MakeAST(bool compile_in_global_context,
Handle<Script> script,
v8::Extension* extension,
ScriptDataImpl* pre_data,
bool is_json = false);
// Support for doing lazy compilation.
static FunctionLiteral* MakeLazyAST(Handle<SharedFunctionInfo> info);
// Parses the source code represented by the compilation info and sets its
// function literal. Returns false (and deallocates any allocated AST
// nodes) if parsing failed.
static bool Parse(CompilationInfo* info);
// Generic preparser generating full preparse data.
static ScriptDataImpl* PreParse(Handle<String> source,

View File

@ -178,7 +178,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_);
loop_nesting_ = info->loop_nesting();
loop_nesting_ = info->is_in_loop() ? 1 : 0;
JumpTarget::set_compiling_deferred_code(false);
@ -356,7 +356,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
}
// Adjust for function-level loop nesting.
ASSERT_EQ(loop_nesting_, info->loop_nesting());
ASSERT_EQ(loop_nesting_, info->is_in_loop() ? 1 : 0);
loop_nesting_ = 0;
// Code generation state must be reset.