• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/compilation-info.h"
6 
7 #include "src/api.h"
8 #include "src/ast/ast.h"
9 #include "src/ast/scopes.h"
10 #include "src/debug/debug.h"
11 #include "src/isolate.h"
12 #include "src/objects-inl.h"
13 #include "src/parsing/parse-info.h"
14 #include "src/source-position.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 #define PARSE_INFO_GETTER(type, name)  \
20   type CompilationInfo::name() const { \
21     CHECK(parse_info());               \
22     return parse_info()->name();       \
23   }
24 
25 #define PARSE_INFO_GETTER_WITH_DEFAULT(type, name, def) \
26   type CompilationInfo::name() const {                  \
27     return parse_info() ? parse_info()->name() : def;   \
28   }
29 
PARSE_INFO_GETTER(Handle<Script>,script)30 PARSE_INFO_GETTER(Handle<Script>, script)
31 PARSE_INFO_GETTER(FunctionLiteral*, literal)
32 PARSE_INFO_GETTER_WITH_DEFAULT(DeclarationScope*, scope, nullptr)
33 PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info)
34 
35 #undef PARSE_INFO_GETTER
36 #undef PARSE_INFO_GETTER_WITH_DEFAULT
37 
38 bool CompilationInfo::is_debug() const {
39   return parse_info() ? parse_info()->is_debug() : false;
40 }
41 
set_is_debug()42 void CompilationInfo::set_is_debug() {
43   CHECK(parse_info());
44   parse_info()->set_is_debug();
45 }
46 
PrepareForSerializing()47 void CompilationInfo::PrepareForSerializing() {
48   if (parse_info()) parse_info()->set_will_serialize();
49   SetFlag(kSerializing);
50 }
51 
has_shared_info() const52 bool CompilationInfo::has_shared_info() const {
53   return parse_info_ && !parse_info_->shared_info().is_null();
54 }
55 
CompilationInfo(Zone * zone,ParseInfo * parse_info,Handle<JSFunction> closure)56 CompilationInfo::CompilationInfo(Zone* zone, ParseInfo* parse_info,
57                                  Handle<JSFunction> closure)
58     : CompilationInfo(parse_info, {}, Code::ComputeFlags(Code::FUNCTION), BASE,
59                       parse_info->isolate(), zone) {
60   closure_ = closure;
61 
62   // Compiling for the snapshot typically results in different code than
63   // compiling later on. This means that code recompiled with deoptimization
64   // support won't be "equivalent" (as defined by SharedFunctionInfo::
65   // EnableDeoptimizationSupport), so it will replace the old code and all
66   // its type feedback. To avoid this, always compile functions in the snapshot
67   // with deoptimization support.
68   if (isolate_->serializer_enabled()) EnableDeoptimizationSupport();
69 
70   if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing();
71   if (FLAG_turbo_splitting) MarkAsSplittingEnabled();
72 
73   // Collect source positions for optimized code when profiling or if debugger
74   // is active, to be able to get more precise source positions at the price of
75   // more memory consumption.
76   if (isolate_->NeedsSourcePositionsForProfiling()) {
77     MarkAsSourcePositionsEnabled();
78   }
79 }
80 
CompilationInfo(Vector<const char> debug_name,Isolate * isolate,Zone * zone,Code::Flags code_flags)81 CompilationInfo::CompilationInfo(Vector<const char> debug_name,
82                                  Isolate* isolate, Zone* zone,
83                                  Code::Flags code_flags)
84     : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {}
85 
CompilationInfo(ParseInfo * parse_info,Vector<const char> debug_name,Code::Flags code_flags,Mode mode,Isolate * isolate,Zone * zone)86 CompilationInfo::CompilationInfo(ParseInfo* parse_info,
87                                  Vector<const char> debug_name,
88                                  Code::Flags code_flags, Mode mode,
89                                  Isolate* isolate, Zone* zone)
90     : parse_info_(parse_info),
91       isolate_(isolate),
92       flags_(0),
93       code_flags_(code_flags),
94       mode_(mode),
95       osr_ast_id_(BailoutId::None()),
96       zone_(zone),
97       deferred_handles_(nullptr),
98       dependencies_(isolate, zone),
99       bailout_reason_(kNoReason),
100       prologue_offset_(Code::kPrologueOffsetNotSet),
101       parameter_count_(0),
102       optimization_id_(-1),
103       osr_expr_stack_height_(-1),
104       debug_name_(debug_name) {}
105 
~CompilationInfo()106 CompilationInfo::~CompilationInfo() {
107   if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
108     shared_info()->DisableOptimization(bailout_reason());
109   }
110   dependencies()->Rollback();
111 }
112 
num_parameters() const113 int CompilationInfo::num_parameters() const {
114   return !IsStub() ? scope()->num_parameters() : parameter_count_;
115 }
116 
num_parameters_including_this() const117 int CompilationInfo::num_parameters_including_this() const {
118   return num_parameters() + (is_this_defined() ? 1 : 0);
119 }
120 
is_this_defined() const121 bool CompilationInfo::is_this_defined() const { return !IsStub(); }
122 
123 // Primitive functions are unlikely to be picked up by the stack-walking
124 // profiler, so they trigger their own optimization when they're called
125 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
ShouldSelfOptimize()126 bool CompilationInfo::ShouldSelfOptimize() {
127   return FLAG_opt && FLAG_crankshaft &&
128          !(literal()->flags() & AstProperties::kDontSelfOptimize) &&
129          !literal()->dont_optimize() &&
130          literal()->scope()->AllowsLazyCompilation() &&
131          !shared_info()->optimization_disabled();
132 }
133 
set_deferred_handles(std::shared_ptr<DeferredHandles> deferred_handles)134 void CompilationInfo::set_deferred_handles(
135     std::shared_ptr<DeferredHandles> deferred_handles) {
136   DCHECK(deferred_handles_.get() == nullptr);
137   deferred_handles_.swap(deferred_handles);
138 }
139 
set_deferred_handles(DeferredHandles * deferred_handles)140 void CompilationInfo::set_deferred_handles(DeferredHandles* deferred_handles) {
141   DCHECK(deferred_handles_.get() == nullptr);
142   deferred_handles_.reset(deferred_handles);
143 }
144 
ReopenHandlesInNewHandleScope()145 void CompilationInfo::ReopenHandlesInNewHandleScope() {
146   if (!closure_.is_null()) {
147     closure_ = Handle<JSFunction>(*closure_);
148   }
149 }
150 
has_simple_parameters()151 bool CompilationInfo::has_simple_parameters() {
152   return scope()->has_simple_parameters();
153 }
154 
GetDebugName() const155 std::unique_ptr<char[]> CompilationInfo::GetDebugName() const {
156   if (parse_info() && parse_info()->literal()) {
157     AllowHandleDereference allow_deref;
158     return parse_info()->literal()->debug_name()->ToCString();
159   }
160   if (parse_info() && !parse_info()->shared_info().is_null()) {
161     return parse_info()->shared_info()->DebugName()->ToCString();
162   }
163   Vector<const char> name_vec = debug_name_;
164   if (name_vec.is_empty()) name_vec = ArrayVector("unknown");
165   std::unique_ptr<char[]> name(new char[name_vec.length() + 1]);
166   memcpy(name.get(), name_vec.start(), name_vec.length());
167   name[name_vec.length()] = '\0';
168   return name;
169 }
170 
GetOutputStackFrameType() const171 StackFrame::Type CompilationInfo::GetOutputStackFrameType() const {
172   switch (output_code_kind()) {
173     case Code::STUB:
174     case Code::BYTECODE_HANDLER:
175     case Code::HANDLER:
176     case Code::BUILTIN:
177 #define CASE_KIND(kind) case Code::kind:
178       IC_KIND_LIST(CASE_KIND)
179 #undef CASE_KIND
180       return StackFrame::STUB;
181     case Code::WASM_FUNCTION:
182       return StackFrame::WASM_COMPILED;
183     case Code::JS_TO_WASM_FUNCTION:
184       return StackFrame::JS_TO_WASM;
185     case Code::WASM_TO_JS_FUNCTION:
186       return StackFrame::WASM_TO_JS;
187     case Code::WASM_INTERPRETER_ENTRY:
188       return StackFrame::WASM_INTERPRETER_ENTRY;
189     default:
190       UNIMPLEMENTED();
191       return StackFrame::NONE;
192   }
193 }
194 
GetDeclareGlobalsFlags() const195 int CompilationInfo::GetDeclareGlobalsFlags() const {
196   DCHECK(DeclareGlobalsLanguageMode::is_valid(parse_info()->language_mode()));
197   return DeclareGlobalsEvalFlag::encode(parse_info()->is_eval()) |
198          DeclareGlobalsNativeFlag::encode(parse_info()->is_native()) |
199          DeclareGlobalsLanguageMode::encode(parse_info()->language_mode());
200 }
201 
202 SourcePositionTableBuilder::RecordingMode
SourcePositionRecordingMode() const203 CompilationInfo::SourcePositionRecordingMode() const {
204   return parse_info() && parse_info()->is_native()
205              ? SourcePositionTableBuilder::OMIT_SOURCE_POSITIONS
206              : SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS;
207 }
208 
ExpectsJSReceiverAsReceiver()209 bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
210   return is_sloppy(parse_info()->language_mode()) && !parse_info()->is_native();
211 }
212 
has_context() const213 bool CompilationInfo::has_context() const { return !closure().is_null(); }
214 
context() const215 Context* CompilationInfo::context() const {
216   return has_context() ? closure()->context() : nullptr;
217 }
218 
has_native_context() const219 bool CompilationInfo::has_native_context() const {
220   return !closure().is_null() && (closure()->native_context() != nullptr);
221 }
222 
native_context() const223 Context* CompilationInfo::native_context() const {
224   return has_native_context() ? closure()->native_context() : nullptr;
225 }
226 
has_global_object() const227 bool CompilationInfo::has_global_object() const { return has_native_context(); }
228 
global_object() const229 JSGlobalObject* CompilationInfo::global_object() const {
230   return has_global_object() ? native_context()->global_object() : nullptr;
231 }
232 
SetOptimizing()233 void CompilationInfo::SetOptimizing() {
234   DCHECK(has_shared_info());
235   SetMode(OPTIMIZE);
236   optimization_id_ = isolate()->NextOptimizationId();
237   code_flags_ = Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION);
238 }
239 
AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function,SourcePosition pos)240 int CompilationInfo::AddInlinedFunction(
241     Handle<SharedFunctionInfo> inlined_function, SourcePosition pos) {
242   int id = static_cast<int>(inlined_functions_.size());
243   inlined_functions_.push_back(InlinedFunctionHolder(
244       inlined_function, handle(inlined_function->code()), pos));
245   return id;
246 }
247 
output_code_kind() const248 Code::Kind CompilationInfo::output_code_kind() const {
249   return Code::ExtractKindFromFlags(code_flags_);
250 }
251 
252 }  // namespace internal
253 }  // namespace v8
254