// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/optimized-compilation-info.h" #include "src/api.h" #include "src/debug/debug.h" #include "src/isolate.h" #include "src/objects-inl.h" #include "src/objects/shared-function-info.h" #include "src/source-position.h" #include "src/tracing/trace-event.h" #include "src/tracing/traced-value.h" #include "src/wasm/function-compiler.h" namespace v8 { namespace internal { OptimizedCompilationInfo::OptimizedCompilationInfo( Zone* zone, Isolate* isolate, Handle shared, Handle closure) : OptimizedCompilationInfo(Code::OPTIMIZED_FUNCTION, zone) { DCHECK(shared->is_compiled()); bytecode_array_ = handle(shared->GetBytecodeArray(), isolate); shared_info_ = shared; closure_ = closure; optimization_id_ = isolate->NextOptimizationId(); // Collect source positions for optimized code when profiling or if debugger // is active, to be able to get more precise source positions at the price of // more memory consumption. if (isolate->NeedsDetailedOptimizedCodeLineInfo()) { MarkAsSourcePositionsEnabled(); } SetTracingFlags(shared->PassesFilter(FLAG_trace_turbo_filter)); } OptimizedCompilationInfo::OptimizedCompilationInfo( Vector debug_name, Zone* zone, Code::Kind code_kind) : OptimizedCompilationInfo(code_kind, zone) { debug_name_ = debug_name; SetTracingFlags( PassesFilter(debug_name, CStrVector(FLAG_trace_turbo_filter))); } OptimizedCompilationInfo::OptimizedCompilationInfo(Code::Kind code_kind, Zone* zone) : code_kind_(code_kind), zone_(zone) { ConfigureFlags(); } void OptimizedCompilationInfo::ConfigureFlags() { if (FLAG_untrusted_code_mitigations) SetFlag(kUntrustedCodeMitigations); switch (code_kind_) { case Code::OPTIMIZED_FUNCTION: SetFlag(kCalledWithCodeStartRegister); SetFlag(kSwitchJumpTableEnabled); if (FLAG_function_context_specialization) { MarkAsFunctionContextSpecializing(); } if (FLAG_turbo_splitting) { MarkAsSplittingEnabled(); } if (FLAG_untrusted_code_mitigations) { MarkAsPoisoningRegisterArguments(); } if (FLAG_analyze_environment_liveness) { // TODO(yangguo): Disable this in case of debugging for crbug.com/826613 MarkAsAnalyzeEnvironmentLiveness(); } break; case Code::BYTECODE_HANDLER: SetFlag(kCalledWithCodeStartRegister); break; case Code::BUILTIN: case Code::STUB: #if ENABLE_GDB_JIT_INTERFACE && DEBUG MarkAsSourcePositionsEnabled(); #endif // ENABLE_GDB_JIT_INTERFACE && DEBUG break; case Code::WASM_FUNCTION: SetFlag(kSwitchJumpTableEnabled); break; default: break; } if (FLAG_turbo_control_flow_aware_allocation) { MarkAsTurboControlFlowAwareAllocation(); } if (FLAG_turbo_preprocess_ranges) { MarkAsTurboPreprocessRanges(); } } OptimizedCompilationInfo::~OptimizedCompilationInfo() { if (GetFlag(kDisableFutureOptimization) && has_shared_info()) { shared_info()->DisableOptimization(bailout_reason()); } } void OptimizedCompilationInfo::set_deferred_handles( std::shared_ptr deferred_handles) { DCHECK_NULL(deferred_handles_); deferred_handles_.swap(deferred_handles); } void OptimizedCompilationInfo::set_deferred_handles( DeferredHandles* deferred_handles) { DCHECK_NULL(deferred_handles_); deferred_handles_.reset(deferred_handles); } void OptimizedCompilationInfo::ReopenHandlesInNewHandleScope(Isolate* isolate) { if (!shared_info_.is_null()) { shared_info_ = Handle(*shared_info_, isolate); } if (!bytecode_array_.is_null()) { bytecode_array_ = Handle(*bytecode_array_, isolate); } if (!closure_.is_null()) { closure_ = Handle(*closure_, isolate); } } void OptimizedCompilationInfo::AbortOptimization(BailoutReason reason) { DCHECK_NE(reason, BailoutReason::kNoReason); if (bailout_reason_ == BailoutReason::kNoReason) { TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.AbortOptimization", TRACE_EVENT_SCOPE_THREAD, "reason", GetBailoutReason(reason), "function", shared_info()->TraceIDRef()); bailout_reason_ = reason; } SetFlag(kDisableFutureOptimization); } void OptimizedCompilationInfo::RetryOptimization(BailoutReason reason) { DCHECK_NE(reason, BailoutReason::kNoReason); if (GetFlag(kDisableFutureOptimization)) return; TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.RetryOptimization", TRACE_EVENT_SCOPE_THREAD, "reason", GetBailoutReason(reason), "function", shared_info()->TraceIDRef()); bailout_reason_ = reason; } std::unique_ptr OptimizedCompilationInfo::GetDebugName() const { if (!shared_info().is_null()) { return shared_info()->DebugName()->ToCString(); } Vector name_vec = debug_name_; if (name_vec.empty()) name_vec = ArrayVector("unknown"); std::unique_ptr name(new char[name_vec.length() + 1]); memcpy(name.get(), name_vec.start(), name_vec.length()); name[name_vec.length()] = '\0'; return name; } StackFrame::Type OptimizedCompilationInfo::GetOutputStackFrameType() const { switch (code_kind()) { case Code::STUB: case Code::BYTECODE_HANDLER: case Code::BUILTIN: return StackFrame::STUB; case Code::WASM_FUNCTION: return StackFrame::WASM_COMPILED; case Code::JS_TO_WASM_FUNCTION: return StackFrame::JS_TO_WASM; case Code::WASM_TO_JS_FUNCTION: return StackFrame::WASM_TO_JS; case Code::WASM_INTERPRETER_ENTRY: return StackFrame::WASM_INTERPRETER_ENTRY; default: UNIMPLEMENTED(); return StackFrame::NONE; } } void OptimizedCompilationInfo::SetWasmCompilationResult( std::unique_ptr wasm_compilation_result) { wasm_compilation_result_ = std::move(wasm_compilation_result); } std::unique_ptr OptimizedCompilationInfo::ReleaseWasmCompilationResult() { return std::move(wasm_compilation_result_); } bool OptimizedCompilationInfo::has_context() const { return !closure().is_null(); } Context OptimizedCompilationInfo::context() const { DCHECK(has_context()); return closure()->context(); } bool OptimizedCompilationInfo::has_native_context() const { return !closure().is_null() && !closure()->native_context().is_null(); } Context OptimizedCompilationInfo::native_context() const { DCHECK(has_native_context()); return closure()->native_context(); } bool OptimizedCompilationInfo::has_global_object() const { return has_native_context(); } JSGlobalObject OptimizedCompilationInfo::global_object() const { DCHECK(has_global_object()); return native_context()->global_object(); } int OptimizedCompilationInfo::AddInlinedFunction( Handle inlined_function, Handle inlined_bytecode, SourcePosition pos) { int id = static_cast(inlined_functions_.size()); inlined_functions_.push_back( InlinedFunctionHolder(inlined_function, inlined_bytecode, pos)); return id; } void OptimizedCompilationInfo::SetTracingFlags(bool passes_filter) { if (!passes_filter) return; if (FLAG_trace_turbo) SetFlag(kTraceTurboJson); if (FLAG_trace_turbo_graph) SetFlag(kTraceTurboGraph); if (FLAG_trace_turbo_scheduled) SetFlag(kTraceTurboScheduled); } OptimizedCompilationInfo::InlinedFunctionHolder::InlinedFunctionHolder( Handle inlined_shared_info, Handle inlined_bytecode, SourcePosition pos) : shared_info(inlined_shared_info), bytecode_array(inlined_bytecode) { DCHECK_EQ(shared_info->GetBytecodeArray(), *bytecode_array); position.position = pos; // initialized when generating the deoptimization literals position.inlined_function_id = DeoptimizationData::kNotInlinedIndex; } std::unique_ptr OptimizedCompilationInfo::ToTracedValue() { auto value = v8::tracing::TracedValue::Create(); value->SetBoolean("osr", is_osr()); value->SetBoolean("functionContextSpecialized", is_function_context_specializing()); if (has_shared_info()) { value->SetValue("function", shared_info()->TraceIDRef()); } if (bailout_reason() != BailoutReason::kNoReason) { value->SetString("bailoutReason", GetBailoutReason(bailout_reason())); value->SetBoolean("disableFutureOptimization", is_disable_future_optimization()); } else { value->SetInteger("optimizationId", optimization_id()); value->BeginArray("inlinedFunctions"); for (auto const& inlined_function : inlined_functions()) { value->BeginDictionary(); value->SetValue("function", inlined_function.shared_info->TraceIDRef()); // TODO(bmeurer): Also include the source position from the // {inlined_function} here as dedicated "sourcePosition" field. value->EndDictionary(); } value->EndArray(); } return value; } } // namespace internal } // namespace v8