aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler.cc')
-rw-r--r--deps/v8/src/compiler.cc219
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);