blob: 58906b77ac5c754255e6fdc5acaf8f292fec65a8 [file] [log] [blame]
// 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"
namespace v8 {
namespace internal {
OptimizedCompilationInfo::OptimizedCompilationInfo(
Zone* zone, Isolate* isolate, Handle<SharedFunctionInfo> shared,
Handle<JSFunction> 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<const char> 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;
}
}
OptimizedCompilationInfo::~OptimizedCompilationInfo() {
if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
shared_info()->DisableOptimization(bailout_reason());
}
}
void OptimizedCompilationInfo::set_deferred_handles(
std::shared_ptr<DeferredHandles> 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<SharedFunctionInfo>(*shared_info_, isolate);
}
if (!bytecode_array_.is_null()) {
bytecode_array_ = Handle<BytecodeArray>(*bytecode_array_, isolate);
}
if (!closure_.is_null()) {
closure_ = Handle<JSFunction>(*closure_, isolate);
}
}
std::unique_ptr<char[]> OptimizedCompilationInfo::GetDebugName() const {
if (!shared_info().is_null()) {
return shared_info()->DebugName()->ToCString();
}
Vector<const char> name_vec = debug_name_;
if (name_vec.is_empty()) name_vec = ArrayVector("unknown");
std::unique_ptr<char[]> 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;
}
}
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<SharedFunctionInfo> inlined_function,
Handle<BytecodeArray> inlined_bytecode, SourcePosition pos) {
int id = static_cast<int>(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);
}
} // namespace internal
} // namespace v8