Line data Source code
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 :
30 9177226 : PARSE_INFO_GETTER(Handle<Script>, script)
31 28790475 : PARSE_INFO_GETTER(FunctionLiteral*, literal)
32 33789211 : PARSE_INFO_GETTER_WITH_DEFAULT(DeclarationScope*, scope, nullptr)
33 34477865 : PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info)
34 :
35 : #undef PARSE_INFO_GETTER
36 : #undef PARSE_INFO_GETTER_WITH_DEFAULT
37 :
38 21444783 : bool CompilationInfo::is_debug() const {
39 42889566 : return parse_info() ? parse_info()->is_debug() : false;
40 : }
41 :
42 10197 : void CompilationInfo::set_is_debug() {
43 10197 : CHECK(parse_info());
44 : parse_info()->set_is_debug();
45 10197 : }
46 :
47 35638 : void CompilationInfo::PrepareForSerializing() {
48 35638 : if (parse_info()) parse_info()->set_will_serialize();
49 : SetFlag(kSerializing);
50 35638 : }
51 :
52 469578 : bool CompilationInfo::has_shared_info() const {
53 518386 : return parse_info_ && !parse_info_->shared_info().is_null();
54 : }
55 :
56 4290909 : CompilationInfo::CompilationInfo(Zone* zone, ParseInfo* parse_info,
57 : Isolate* isolate, Handle<JSFunction> closure)
58 : : CompilationInfo(parse_info, {}, Code::ComputeFlags(Code::FUNCTION), BASE,
59 : isolate, zone) {
60 4290909 : 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 4290909 : if (isolate_->serializer_enabled()) EnableDeoptimizationSupport();
69 :
70 4290909 : if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing();
71 4290909 : 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 4290909 : if (isolate_->NeedsSourcePositionsForProfiling()) {
77 : MarkAsSourcePositionsEnabled();
78 : }
79 4290912 : }
80 :
81 544509 : CompilationInfo::CompilationInfo(Vector<const char> debug_name,
82 : Isolate* isolate, Zone* zone,
83 : Code::Flags code_flags)
84 544509 : : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {}
85 :
86 0 : 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 24177090 : debug_name_(debug_name) {}
105 :
106 4884205 : CompilationInfo::~CompilationInfo() {
107 4884205 : if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
108 97616 : shared_info()->DisableOptimization(bailout_reason());
109 : }
110 4835397 : dependencies()->Rollback();
111 4835394 : }
112 :
113 2840138 : int CompilationInfo::num_parameters() const {
114 2840138 : return !IsStub() ? scope()->num_parameters() : parameter_count_;
115 : }
116 :
117 2082464 : int CompilationInfo::num_parameters_including_this() const {
118 4164936 : return num_parameters() + (is_this_defined() ? 1 : 0);
119 : }
120 :
121 2084979 : 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.
126 1080961 : bool CompilationInfo::ShouldSelfOptimize() {
127 2160606 : return FLAG_opt && FLAG_crankshaft &&
128 2079704 : !(literal()->flags() & AstProperties::kDontSelfOptimize) &&
129 999999 : !literal()->dont_optimize() &&
130 3080956 : literal()->scope()->AllowsLazyCompilation() &&
131 2080955 : !shared_info()->optimization_disabled();
132 : }
133 :
134 5 : 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 5 : }
139 :
140 148195 : void CompilationInfo::set_deferred_handles(DeferredHandles* deferred_handles) {
141 : DCHECK(deferred_handles_.get() == nullptr);
142 148195 : deferred_handles_.reset(deferred_handles);
143 148195 : }
144 :
145 752949 : void CompilationInfo::ReopenHandlesInNewHandleScope() {
146 752949 : if (!closure_.is_null()) {
147 752951 : closure_ = Handle<JSFunction>(*closure_);
148 : }
149 752951 : }
150 :
151 68237 : bool CompilationInfo::has_simple_parameters() {
152 68237 : return scope()->has_simple_parameters();
153 : }
154 :
155 943816 : std::unique_ptr<char[]> CompilationInfo::GetDebugName() const {
156 943816 : if (parse_info() && parse_info()->literal()) {
157 : AllowHandleDereference allow_deref;
158 882 : return parse_info()->literal()->debug_name()->ToCString();
159 : }
160 943375 : if (parse_info() && !parse_info()->shared_info().is_null()) {
161 422787 : return parse_info()->shared_info()->DebugName()->ToCString();
162 : }
163 520588 : Vector<const char> name_vec = debug_name_;
164 520588 : if (name_vec.is_empty()) name_vec = ArrayVector("unknown");
165 520588 : std::unique_ptr<char[]> name(new char[name_vec.length() + 1]);
166 520581 : memcpy(name.get(), name_vec.start(), name_vec.length());
167 520581 : name[name_vec.length()] = '\0';
168 : return name;
169 : }
170 :
171 193389 : StackFrame::Type CompilationInfo::GetOutputStackFrameType() const {
172 193389 : 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 52539 : return StackFrame::WASM_COMPILED;
183 : case Code::JS_TO_WASM_FUNCTION:
184 0 : return StackFrame::JS_TO_WASM;
185 : case Code::WASM_TO_JS_FUNCTION:
186 37883 : return StackFrame::WASM_TO_JS;
187 : case Code::WASM_INTERPRETER_ENTRY:
188 1369 : return StackFrame::WASM_INTERPRETER_ENTRY;
189 : default:
190 0 : UNIMPLEMENTED();
191 : return StackFrame::NONE;
192 : }
193 : }
194 :
195 129059 : int CompilationInfo::GetDeclareGlobalsFlags() const {
196 : DCHECK(DeclareGlobalsLanguageMode::is_valid(parse_info()->language_mode()));
197 129059 : return DeclareGlobalsEvalFlag::encode(parse_info()->is_eval()) |
198 129059 : DeclareGlobalsNativeFlag::encode(parse_info()->is_native()) |
199 129059 : DeclareGlobalsLanguageMode::encode(parse_info()->language_mode());
200 : }
201 :
202 : SourcePositionTableBuilder::RecordingMode
203 4349548 : CompilationInfo::SourcePositionRecordingMode() const {
204 : return parse_info() && parse_info()->is_native()
205 : ? SourcePositionTableBuilder::OMIT_SOURCE_POSITIONS
206 8154989 : : SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS;
207 : }
208 :
209 123 : bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
210 246 : return is_sloppy(parse_info()->language_mode()) && !parse_info()->is_native();
211 : }
212 :
213 0 : bool CompilationInfo::has_context() const { return !closure().is_null(); }
214 :
215 1253330 : Context* CompilationInfo::context() const {
216 2506660 : return has_context() ? closure()->context() : nullptr;
217 : }
218 :
219 2694725 : bool CompilationInfo::has_native_context() const {
220 5389451 : return !closure().is_null() && (closure()->native_context() != nullptr);
221 : }
222 :
223 1957169 : Context* CompilationInfo::native_context() const {
224 3914339 : return has_native_context() ? closure()->native_context() : nullptr;
225 : }
226 :
227 737556 : bool CompilationInfo::has_global_object() const { return has_native_context(); }
228 :
229 371554 : JSGlobalObject* CompilationInfo::global_object() const {
230 371554 : return has_global_object() ? native_context()->global_object() : nullptr;
231 : }
232 :
233 1604504 : void CompilationInfo::SetOptimizing() {
234 : DCHECK(has_shared_info());
235 : SetMode(OPTIMIZE);
236 802252 : optimization_id_ = isolate()->NextOptimizationId();
237 1604504 : code_flags_ = Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION);
238 802252 : }
239 :
240 145428 : int CompilationInfo::AddInlinedFunction(
241 : Handle<SharedFunctionInfo> inlined_function, SourcePosition pos) {
242 290856 : int id = static_cast<int>(inlined_functions_.size());
243 : inlined_functions_.push_back(InlinedFunctionHolder(
244 290856 : inlined_function, handle(inlined_function->code()), pos));
245 145428 : return id;
246 : }
247 :
248 26 : Code::Kind CompilationInfo::output_code_kind() const {
249 193441 : return Code::ExtractKindFromFlags(code_flags_);
250 : }
251 :
252 : } // namespace internal
253 : } // namespace v8
|