| // 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/compilation-info.h" |
| |
| #include "src/api.h" |
| #include "src/ast/ast.h" |
| #include "src/ast/scopes.h" |
| #include "src/debug/debug.h" |
| #include "src/isolate.h" |
| #include "src/objects-inl.h" |
| #include "src/parsing/parse-info.h" |
| #include "src/source-position.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| // TODO(mvstanton): the Code::OPTIMIZED_FUNCTION constant below is |
| // bogus, it's just that I've eliminated Code::FUNCTION and there isn't |
| // a "better" value to put in this place. |
| CompilationInfo::CompilationInfo(Zone* zone, ParseInfo* parse_info, |
| FunctionLiteral* literal) |
| : CompilationInfo({}, Code::OPTIMIZED_FUNCTION, BASE, zone) { |
| // NOTE: The parse_info passed here represents the global information gathered |
| // during parsing, but does not represent specific details of the actual |
| // function literal being compiled for this CompilationInfo. As such, |
| // parse_info->literal() might be different from literal, and only global |
| // details of the script being parsed are relevant to this CompilationInfo. |
| DCHECK_NOT_NULL(literal); |
| literal_ = literal; |
| source_range_map_ = parse_info->source_range_map(); |
| |
| if (parse_info->is_eval()) MarkAsEval(); |
| if (parse_info->is_native()) MarkAsNative(); |
| if (parse_info->collect_type_profile()) MarkAsCollectTypeProfile(); |
| } |
| |
| CompilationInfo::CompilationInfo(Zone* zone, Isolate* isolate, |
| Handle<SharedFunctionInfo> shared, |
| Handle<JSFunction> closure) |
| : CompilationInfo({}, Code::OPTIMIZED_FUNCTION, OPTIMIZE, zone) { |
| shared_info_ = shared; |
| closure_ = closure; |
| optimization_id_ = isolate->NextOptimizationId(); |
| dependencies_.reset(new CompilationDependencies(isolate, zone)); |
| |
| if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing(); |
| if (FLAG_turbo_splitting) MarkAsSplittingEnabled(); |
| |
| // 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->NeedsSourcePositionsForProfiling()) { |
| MarkAsSourcePositionsEnabled(); |
| } |
| } |
| |
| CompilationInfo::CompilationInfo(Vector<const char> debug_name, Zone* zone, |
| Code::Kind code_kind) |
| : CompilationInfo(debug_name, code_kind, STUB, zone) {} |
| |
| CompilationInfo::CompilationInfo(Vector<const char> debug_name, |
| Code::Kind code_kind, Mode mode, Zone* zone) |
| : literal_(nullptr), |
| source_range_map_(nullptr), |
| flags_(FLAG_untrusted_code_mitigations ? kUntrustedCodeMitigations : 0), |
| code_kind_(code_kind), |
| stub_key_(0), |
| builtin_index_(Builtins::kNoBuiltinId), |
| mode_(mode), |
| osr_offset_(BailoutId::None()), |
| feedback_vector_spec_(zone), |
| zone_(zone), |
| deferred_handles_(nullptr), |
| dependencies_(nullptr), |
| bailout_reason_(BailoutReason::kNoReason), |
| parameter_count_(0), |
| optimization_id_(-1), |
| debug_name_(debug_name) {} |
| |
| CompilationInfo::~CompilationInfo() { |
| if (GetFlag(kDisableFutureOptimization) && has_shared_info()) { |
| shared_info()->DisableOptimization(bailout_reason()); |
| } |
| if (dependencies()) { |
| dependencies()->Rollback(); |
| } |
| } |
| |
| DeclarationScope* CompilationInfo::scope() const { |
| DCHECK_NOT_NULL(literal_); |
| return literal_->scope(); |
| } |
| |
| int CompilationInfo::num_parameters() const { |
| return !IsStub() ? scope()->num_parameters() : parameter_count_; |
| } |
| |
| int CompilationInfo::num_parameters_including_this() const { |
| return num_parameters() + (is_this_defined() ? 1 : 0); |
| } |
| |
| bool CompilationInfo::is_this_defined() const { return !IsStub(); } |
| |
| void CompilationInfo::set_deferred_handles( |
| std::shared_ptr<DeferredHandles> deferred_handles) { |
| DCHECK_NULL(deferred_handles_); |
| deferred_handles_.swap(deferred_handles); |
| } |
| |
| void CompilationInfo::set_deferred_handles(DeferredHandles* deferred_handles) { |
| DCHECK_NULL(deferred_handles_); |
| deferred_handles_.reset(deferred_handles); |
| } |
| |
| void CompilationInfo::ReopenHandlesInNewHandleScope() { |
| if (!shared_info_.is_null()) { |
| shared_info_ = Handle<SharedFunctionInfo>(*shared_info_); |
| } |
| if (!closure_.is_null()) { |
| closure_ = Handle<JSFunction>(*closure_); |
| } |
| } |
| |
| bool CompilationInfo::has_simple_parameters() { |
| return scope()->has_simple_parameters(); |
| } |
| |
| std::unique_ptr<char[]> CompilationInfo::GetDebugName() const { |
| if (literal()) { |
| return literal()->GetDebugName(); |
| } |
| 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 CompilationInfo::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_WASM_FUNCTION: |
| return StackFrame::WASM_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; |
| } |
| } |
| |
| int CompilationInfo::GetDeclareGlobalsFlags() const { |
| return DeclareGlobalsEvalFlag::encode(is_eval()) | |
| DeclareGlobalsNativeFlag::encode(is_native()); |
| } |
| |
| SourcePositionTableBuilder::RecordingMode |
| CompilationInfo::SourcePositionRecordingMode() const { |
| return is_native() ? SourcePositionTableBuilder::OMIT_SOURCE_POSITIONS |
| : SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS; |
| } |
| |
| bool CompilationInfo::has_context() const { return !closure().is_null(); } |
| |
| Context* CompilationInfo::context() const { |
| return has_context() ? closure()->context() : nullptr; |
| } |
| |
| bool CompilationInfo::has_native_context() const { |
| return !closure().is_null() && (closure()->native_context() != nullptr); |
| } |
| |
| Context* CompilationInfo::native_context() const { |
| return has_native_context() ? closure()->native_context() : nullptr; |
| } |
| |
| bool CompilationInfo::has_global_object() const { return has_native_context(); } |
| |
| JSGlobalObject* CompilationInfo::global_object() const { |
| return has_global_object() ? native_context()->global_object() : nullptr; |
| } |
| |
| int CompilationInfo::AddInlinedFunction( |
| Handle<SharedFunctionInfo> inlined_function, SourcePosition pos) { |
| int id = static_cast<int>(inlined_functions_.size()); |
| inlined_functions_.push_back(InlinedFunctionHolder(inlined_function, pos)); |
| return id; |
| } |
| |
| } // namespace internal |
| } // namespace v8 |