Index: src/compiler.cc |
diff --git a/src/compiler.cc b/src/compiler.cc |
index bfb2e21beac2ace9de56707a84f238dd312a6054..127f6d544ee5754e975fb2d4e5b5d0727add106e 100755 |
--- a/src/compiler.cc |
+++ b/src/compiler.cc |
@@ -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(); |