diff options
Diffstat (limited to 'deps/v8/src/compiler.cc')
-rw-r--r-- | deps/v8/src/compiler.cc | 219 |
1 files changed, 136 insertions, 83 deletions
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index d55bf33bab..307b3b0e42 100644 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -6,7 +6,10 @@ #include <algorithm> -#include "src/ast-numbering.h" +#include "src/ast/ast-numbering.h" +#include "src/ast/prettyprinter.h" +#include "src/ast/scopeinfo.h" +#include "src/ast/scopes.h" #include "src/bootstrapper.h" #include "src/codegen.h" #include "src/compilation-cache.h" @@ -23,14 +26,11 @@ #include "src/isolate-inl.h" #include "src/log-inl.h" #include "src/messages.h" -#include "src/parser.h" -#include "src/prettyprinter.h" +#include "src/parsing/parser.h" +#include "src/parsing/rewriter.h" +#include "src/parsing/scanner-character-streams.h" #include "src/profiler/cpu-profiler.h" -#include "src/rewriter.h" #include "src/runtime-profiler.h" -#include "src/scanner-character-streams.h" -#include "src/scopeinfo.h" -#include "src/scopes.h" #include "src/snapshot/serialize.h" #include "src/vm-state-inl.h" @@ -178,7 +178,6 @@ CompilationInfo::CompilationInfo(ParseInfo* parse_info, CodeStub* code_stub, parameter_count_(0), optimization_id_(-1), osr_expr_stack_height_(0), - function_type_(nullptr), debug_name_(debug_name) { // Parameter count is number of stack parameters. if (code_stub_ != NULL) { @@ -205,14 +204,6 @@ CompilationInfo::~CompilationInfo() { } -void CompilationInfo::SetStub(CodeStub* code_stub) { - SetMode(STUB); - code_stub_ = code_stub; - debug_name_ = CodeStub::MajorName(code_stub->MajorKey()); - set_output_code_kind(code_stub->GetCodeKind()); -} - - int CompilationInfo::num_parameters() const { return has_scope() ? scope()->num_parameters() : parameter_count_; } @@ -420,12 +411,29 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { DCHECK(info()->shared_info()->has_deoptimization_support()); DCHECK(!info()->is_first_compile()); - // Check the enabling conditions for TurboFan. + bool optimization_disabled = info()->shared_info()->optimization_disabled(); bool dont_crankshaft = info()->shared_info()->dont_crankshaft(); - if (((FLAG_turbo_asm && info()->shared_info()->asm_function()) || - (dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0) || - info()->closure()->PassesFilter(FLAG_turbo_filter)) && - (FLAG_turbo_osr || !info()->is_osr())) { + + // Check the enabling conditions for Turbofan. + // 1. "use asm" code. + bool is_turbofanable_asm = FLAG_turbo_asm && + info()->shared_info()->asm_function() && + !optimization_disabled; + + // 2. Fallback for features unsupported by Crankshaft. + bool is_unsupported_by_crankshaft_but_turbofanable = + dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 && + !optimization_disabled; + + // 3. Explicitly enabled by the command-line filter. + bool passes_turbo_filter = info()->closure()->PassesFilter(FLAG_turbo_filter); + + // If this is OSR request, OSR must be enabled by Turbofan. + bool passes_osr_test = FLAG_turbo_osr || !info()->is_osr(); + + if ((is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable || + passes_turbo_filter) && + passes_osr_test) { // Use TurboFan for the compilation. if (FLAG_trace_opt) { OFStream os(stdout); @@ -553,6 +561,61 @@ OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() { } +namespace { + +void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, + Handle<Code> code) { + Handle<WeakCell> cell = Code::WeakCellFor(code); + Heap* heap = isolate->heap(); + Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); + dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell); + heap->AddWeakObjectToCodeDependency(object, dep); +} + + +void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) { + // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. + Isolate* const isolate = code->GetIsolate(); + DCHECK(code->is_optimized_code()); + std::vector<Handle<Map>> maps; + std::vector<Handle<HeapObject>> objects; + { + DisallowHeapAllocation no_gc; + int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | + RelocInfo::ModeMask(RelocInfo::CELL); + for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { + RelocInfo::Mode mode = it.rinfo()->rmode(); + if (mode == RelocInfo::CELL && + code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) { + objects.push_back(handle(it.rinfo()->target_cell(), isolate)); + } else if (mode == RelocInfo::EMBEDDED_OBJECT && + code->IsWeakObjectInOptimizedCode( + it.rinfo()->target_object())) { + Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()), + isolate); + if (object->IsMap()) { + maps.push_back(Handle<Map>::cast(object)); + } else { + objects.push_back(object); + } + } + } + } + for (Handle<Map> map : maps) { + if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) { + isolate->heap()->AddRetainedMap(map); + } + Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); + } + for (Handle<HeapObject> object : objects) { + AddWeakObjectToCodeDependency(isolate, object, code); + } + code->set_can_have_weak_objects(true); +} + +} // namespace + + OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { DCHECK(last_status() == SUCCEEDED); // TODO(turbofan): Currently everything is done in the first phase. @@ -561,6 +624,7 @@ OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { if (info()->is_deoptimization_enabled()) { info()->parse_info()->context()->native_context()->AddOptimizedCode( *info()->code()); + RegisterWeakObjectsInOptimizedCode(info()->code()); } RecordOptimizationStats(); return last_status(); @@ -585,6 +649,7 @@ OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { } return SetLastStatus(BAILED_OUT); } + RegisterWeakObjectsInOptimizedCode(optimized_code); info()->SetCode(optimized_code); } RecordOptimizationStats(); @@ -706,8 +771,6 @@ static bool CompileUnoptimizedCode(CompilationInfo* info) { // TODO(rmcilroy): Remove this temporary work-around when ignition supports // catch and eval. static bool IgnitionShouldFallbackToFullCodeGen(Scope* scope) { - if (!FLAG_ignition_fallback_on_eval_and_catch) return false; - if (scope->is_eval_scope() || scope->is_catch_scope() || scope->calls_eval()) { return true; @@ -719,21 +782,46 @@ static bool IgnitionShouldFallbackToFullCodeGen(Scope* scope) { } -static bool GenerateBytecode(CompilationInfo* info) { - DCHECK(AllowCompilation::IsAllowed(info->isolate())); - bool success = false; - if (Compiler::Analyze(info->parse_info())) { - if (IgnitionShouldFallbackToFullCodeGen(info->scope())) { - success = FullCodeGenerator::MakeCode(info); - } else { - success = interpreter::Interpreter::MakeBytecode(info); - } +static bool UseIgnition(CompilationInfo* info) { + // Cannot use Ignition when the {function_data} is already used. + if (info->has_shared_info() && info->shared_info()->HasBuiltinFunctionId()) { + return false; + } + + // Checks whether the scope chain is supported. + if (FLAG_ignition_fallback_on_eval_and_catch && + IgnitionShouldFallbackToFullCodeGen(info->scope())) { + return false; + } + + // Checks whether top level functions should be passed by the filter. + if (info->closure().is_null()) { + Vector<const char> filter = CStrVector(FLAG_ignition_filter); + return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); } - if (!success) { + + // Finally respect the filter. + return info->closure()->PassesFilter(FLAG_ignition_filter); +} + + +static bool GenerateBaselineCode(CompilationInfo* info) { + if (FLAG_ignition && UseIgnition(info)) { + return interpreter::Interpreter::MakeBytecode(info); + } else { + return FullCodeGenerator::MakeCode(info); + } +} + + +static bool CompileBaselineCode(CompilationInfo* info) { + DCHECK(AllowCompilation::IsAllowed(info->isolate())); + if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) { Isolate* isolate = info->isolate(); if (!isolate->has_pending_exception()) isolate->StackOverflow(); + return false; } - return success; + return true; } @@ -746,19 +834,13 @@ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); Handle<SharedFunctionInfo> shared = info->shared_info(); FunctionLiteral* lit = info->literal(); - shared->set_language_mode(lit->language_mode()); + DCHECK_EQ(shared->language_mode(), lit->language_mode()); SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); MaybeDisableOptimization(shared, lit->dont_optimize_reason()); - if (FLAG_ignition && !shared->HasBuiltinFunctionId() && - info->closure()->PassesFilter(FLAG_ignition_filter)) { - // Compile bytecode for the interpreter. - if (!GenerateBytecode(info)) return MaybeHandle<Code>(); - } else { - // Compile unoptimized code. - if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); - - CHECK_EQ(Code::FUNCTION, info->code()->kind()); + // Compile either unoptimized code or bytecode for the interpreter. + if (!CompileBaselineCode(info)) return MaybeHandle<Code>(); + if (info->code()->kind() == Code::FUNCTION) { // Only for full code. RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); } @@ -807,11 +889,8 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { // Frame specialization implies function context specialization. DCHECK(!info->is_frame_specializing()); - // Do not cache bound functions. - Handle<JSFunction> function = info->closure(); - if (function->shared()->bound()) return; - // Cache optimized context-specific code. + Handle<JSFunction> function = info->closure(); Handle<SharedFunctionInfo> shared(function->shared()); Handle<LiteralsArray> literals(function->literals()); Handle<Context> native_context(function->context()->native_context()); @@ -998,23 +1077,6 @@ MaybeHandle<Code> Compiler::GetLazyCode(Handle<JSFunction> function) { } -MaybeHandle<Code> Compiler::GetStubCode(Handle<JSFunction> function, - CodeStub* stub) { - // Build a "hybrid" CompilationInfo for a JSFunction/CodeStub pair. - Zone zone; - ParseInfo parse_info(&zone, function); - CompilationInfo info(&parse_info); - info.SetFunctionType(stub->GetCallInterfaceDescriptor().GetFunctionType()); - info.MarkAsFunctionContextSpecializing(); - info.MarkAsDeoptimizationEnabled(); - info.SetStub(stub); - - // Run a "mini pipeline", extracted from compiler.cc. - if (!ParseAndAnalyze(&parse_info)) return MaybeHandle<Code>(); - return compiler::Pipeline(&info).GenerateCode(); -} - - bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) { if (function->is_compiled()) return true; MaybeHandle<Code> maybe_code = Compiler::GetLazyCode(function); @@ -1162,6 +1224,7 @@ void Compiler::CompileForLiveEdit(Handle<Script> script) { // Get rid of old list of shared function infos. info.MarkAsFirstCompile(); + info.MarkAsDebug(); info.parse_info()->set_global(); if (!Parser::ParseStatic(info.parse_info())) return; @@ -1176,13 +1239,6 @@ void Compiler::CompileForLiveEdit(Handle<Script> script) { } -// Checks whether top level functions should be passed by {raw_filter}. -static bool TopLevelFunctionPassesFilter(const char* raw_filter) { - Vector<const char> filter = CStrVector(raw_filter); - return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); -} - - static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { Isolate* isolate = info->isolate(); PostponeInterruptsScope postpone(isolate); @@ -1246,14 +1302,8 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { HistogramTimerScope timer(rate); // Compile the code. - if (FLAG_ignition && TopLevelFunctionPassesFilter(FLAG_ignition_filter)) { - if (!GenerateBytecode(info)) { - return Handle<SharedFunctionInfo>::null(); - } - } else { - if (!CompileUnoptimizedCode(info)) { - return Handle<SharedFunctionInfo>::null(); - } + if (!CompileBaselineCode(info)) { + return Handle<SharedFunctionInfo>::null(); } // Allocate function. @@ -1598,9 +1648,8 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( // called. info.EnsureFeedbackVector(); scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate)); - } else if (Renumber(info.parse_info()) && - FullCodeGenerator::MakeCode(&info)) { - // MakeCode will ensure that the feedback vector is present and + } else if (Renumber(info.parse_info()) && GenerateBaselineCode(&info)) { + // Code generation will ensure that the feedback vector is present and // appropriately sized. DCHECK(!info.code().is_null()); scope_info = ScopeInfo::Create(info.isolate(), info.zone(), info.scope()); @@ -1618,6 +1667,10 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( isolate->factory()->NewSharedFunctionInfo( literal->name(), literal->materialized_literal_count(), literal->kind(), info.code(), scope_info, info.feedback_vector()); + if (info.has_bytecode_array()) { + DCHECK(result->function_data()->IsUndefined()); + result->set_function_data(*info.bytecode_array()); + } SharedFunctionInfo::InitFromFunctionLiteral(result, literal); SharedFunctionInfo::SetScript(result, script); |