[compiler] Allow optimization of top-level eval code.
This allows for top-level eval code to be parsed properly before doing optimization. It uses the same kind of re-parsing we already perform when compiling code for debugging. R=bmeurer@chromium.org Review-Url: https://codereview.chromium.org/1884143003 Cr-Commit-Position: refs/heads/master@{#36014}
This commit is contained in:
parent
0322c20d17
commit
22b4db544c
@ -418,6 +418,12 @@ void CompilationJob::RecordOptimizationStats() {
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
|
||||
return shared->is_toplevel() && shared->script()->IsScript() &&
|
||||
Script::cast(shared->script())->compilation_type() ==
|
||||
Script::COMPILATION_TYPE_EVAL;
|
||||
}
|
||||
|
||||
void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
|
||||
CompilationInfo* info) {
|
||||
// Log the code generation. If source information is available include
|
||||
@ -765,12 +771,6 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
|
||||
shared->code()->set_profiler_ticks(0);
|
||||
}
|
||||
|
||||
// TODO(mstarzinger): We cannot properly deserialize a scope chain containing
|
||||
// an eval scope and hence would fail at parsing the eval source again.
|
||||
if (shared->disable_optimization_reason() == kEval) {
|
||||
return MaybeHandle<Code>();
|
||||
}
|
||||
|
||||
VMState<COMPILER> state(isolate);
|
||||
DCHECK(!isolate->has_pending_exception());
|
||||
PostponeInterruptsScope postpone(isolate);
|
||||
@ -779,6 +779,7 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
|
||||
use_turbofan ? compiler::Pipeline::NewCompilationJob(function)
|
||||
: new HCompilationJob(function));
|
||||
CompilationInfo* info = job->info();
|
||||
ParseInfo* parse_info = info->parse_info();
|
||||
|
||||
info->SetOptimizingForOsr(osr_ast_id);
|
||||
|
||||
@ -813,6 +814,14 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
|
||||
info->MarkAsOptimizeFromBytecode();
|
||||
}
|
||||
|
||||
if (IsEvalToplevel(shared)) {
|
||||
parse_info->set_eval();
|
||||
if (function->context()->IsNativeContext()) parse_info->set_global();
|
||||
parse_info->set_toplevel();
|
||||
parse_info->set_allow_lazy_parsing(false);
|
||||
parse_info->set_lazy(false);
|
||||
}
|
||||
|
||||
if (mode == Compiler::CONCURRENT) {
|
||||
if (GetOptimizedCodeLater(job.get())) {
|
||||
job.Detach(); // The background recompile job owns this now.
|
||||
@ -1001,12 +1010,6 @@ MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
|
||||
}
|
||||
|
||||
|
||||
inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
|
||||
return shared->is_toplevel() && shared->script()->IsScript() &&
|
||||
Script::cast(shared->script())->compilation_type() ==
|
||||
Script::COMPILATION_TYPE_EVAL;
|
||||
}
|
||||
|
||||
Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
|
||||
Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) {
|
||||
Handle<Code> code = isolate->builtins()->CompileLazy();
|
||||
|
@ -492,6 +492,12 @@ Node* AstGraphBuilder::GetFunctionClosureForContext() {
|
||||
// Contexts nested in the native context have a canonical empty function as
|
||||
// their closure, not the anonymous closure containing the global code.
|
||||
return BuildLoadNativeContextField(Context::CLOSURE_INDEX);
|
||||
} else if (closure_scope->is_eval_scope()) {
|
||||
// Contexts nested inside eval code have the same closure as the context
|
||||
// calling eval, not the anonymous closure containing the eval code.
|
||||
const Operator* op =
|
||||
javascript()->LoadContext(0, Context::CLOSURE_INDEX, false);
|
||||
return NewNode(op, current_context());
|
||||
} else {
|
||||
DCHECK(closure_scope->is_function_scope());
|
||||
return GetFunctionClosure();
|
||||
@ -1109,7 +1115,9 @@ void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
|
||||
}
|
||||
break;
|
||||
case VariableLocation::LOOKUP:
|
||||
UNIMPLEMENTED();
|
||||
// TODO(mstarzinger): Implement this case.
|
||||
SetStackOverflow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1142,7 +1150,9 @@ void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
|
||||
break;
|
||||
}
|
||||
case VariableLocation::LOOKUP:
|
||||
UNIMPLEMENTED();
|
||||
// TODO(mstarzinger): Implement this case.
|
||||
SetStackOverflow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3185,7 +3195,7 @@ Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
|
||||
|
||||
|
||||
Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
|
||||
DCHECK(scope->is_function_scope());
|
||||
DCHECK(scope->is_function_scope() || scope->is_eval_scope());
|
||||
|
||||
// Allocate a new local context.
|
||||
int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
|
||||
|
@ -12355,7 +12355,11 @@ MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
|
||||
SharedFunctionInfo* shared;
|
||||
while ((shared = iterator.Next<SharedFunctionInfo>())) {
|
||||
if (fun->function_token_position() == shared->function_token_position() &&
|
||||
fun->start_position() == shared->start_position()) {
|
||||
fun->start_position() == shared->start_position() &&
|
||||
fun->end_position() == shared->end_position()) {
|
||||
// This method is not used to find top-level SharedFunctionInfo objects,
|
||||
// verify that above checks are sufficient to distinguish top-level code.
|
||||
DCHECK(!shared->is_toplevel());
|
||||
return Handle<SharedFunctionInfo>(shared);
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,8 @@
|
||||
'js1_5/Regress/regress-111557': [PASS, NO_VARIANTS],
|
||||
'js1_5/Regress/regress-155081': [PASS, NO_VARIANTS],
|
||||
'js1_5/Regress/regress-155081-2': [PASS, NO_VARIANTS],
|
||||
'js1_5/Regress/regress-159334': [PASS, NO_VARIANTS],
|
||||
'js1_5/Regress/regress-321971': [PASS, NO_VARIANTS],
|
||||
'js1_5/Regress/regress-451322': [PASS, NO_VARIANTS],
|
||||
|
||||
# TODO(turbofan): Large switch statements crash.
|
||||
|
Loading…
Reference in New Issue
Block a user