blob: a56fa13c488eb6f511aef99f4e525e99721e7732 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_COMPILER_H_
6#define V8_COMPILER_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/allocation.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/ast/ast.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/bailout-reason.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/compilation-dependencies.h"
12#include "src/signature.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010013#include "src/source-position.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014#include "src/zone.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000015
16namespace v8 {
17namespace internal {
18
Ben Murdoch097c5b22016-05-18 11:27:45 +010019// Forward declarations.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020class JavaScriptFrame;
21class ParseInfo;
22class ScriptData;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023
24
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025struct InlinedFunctionInfo {
26 InlinedFunctionInfo(int parent_id, SourcePosition inline_position,
27 int script_id, int start_position)
28 : parent_id(parent_id),
29 inline_position(inline_position),
30 script_id(script_id),
31 start_position(start_position) {}
32 int parent_id;
33 SourcePosition inline_position;
34 int script_id;
35 int start_position;
36 std::vector<size_t> deopt_pc_offsets;
37
38 static const int kNoParentId = -1;
39};
40
41
Andrei Popescu31002712010-02-23 13:46:05 +000042// CompilationInfo encapsulates some information known at compile time. It
43// is constructed based on the resources available at compile-time.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044class CompilationInfo {
Leon Clarke4515c472010-02-03 11:58:03 +000045 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046 // Various configuration flags for a compilation, as well as some properties
47 // of the compiled code produced by a compilation.
48 enum Flag {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 kDeferredCalling = 1 << 0,
50 kNonDeferredCalling = 1 << 1,
51 kSavesCallerDoubles = 1 << 2,
52 kRequiresFrame = 1 << 3,
53 kMustNotHaveEagerFrame = 1 << 4,
54 kDeoptimizationSupport = 1 << 5,
55 kDebug = 1 << 6,
56 kSerializing = 1 << 7,
57 kFunctionContextSpecializing = 1 << 8,
58 kFrameSpecializing = 1 << 9,
59 kNativeContextSpecializing = 1 << 10,
60 kInliningEnabled = 1 << 11,
61 kTypingEnabled = 1 << 12,
62 kDisableFutureOptimization = 1 << 13,
63 kSplittingEnabled = 1 << 14,
64 kDeoptimizationEnabled = 1 << 16,
65 kSourcePositionsEnabled = 1 << 17,
66 kFirstCompile = 1 << 18,
Ben Murdoch097c5b22016-05-18 11:27:45 +010067 kBailoutOnUninitialized = 1 << 19,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068 };
Ben Murdochf87a2032010-10-22 12:50:53 +010069
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 explicit CompilationInfo(ParseInfo* parse_info);
Ben Murdoch097c5b22016-05-18 11:27:45 +010071 CompilationInfo(const char* debug_name, Isolate* isolate, Zone* zone,
72 Code::Flags code_flags = Code::ComputeFlags(Code::STUB));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 virtual ~CompilationInfo();
74
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 ParseInfo* parse_info() const { return parse_info_; }
76
77 // -----------------------------------------------------------
78 // TODO(titzer): inline and delete accessors of ParseInfo
79 // -----------------------------------------------------------
80 Handle<Script> script() const;
81 bool is_eval() const;
82 bool is_native() const;
83 bool is_module() const;
84 LanguageMode language_mode() const;
85 Handle<JSFunction> closure() const;
86 FunctionLiteral* literal() const;
87 Scope* scope() const;
88 Handle<Context> context() const;
89 Handle<SharedFunctionInfo> shared_info() const;
90 bool has_shared_info() const;
91 bool has_context() const;
92 bool has_literal() const;
93 bool has_scope() const;
94 // -----------------------------------------------------------
95
Ben Murdochb8a8cc12014-11-26 15:28:44 +000096 Isolate* isolate() const {
Steve Block44f0eee2011-05-26 01:26:41 +010097 return isolate_;
98 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 Zone* zone() { return zone_; }
100 bool is_osr() const { return !osr_ast_id_.IsNone(); }
Ben Murdochf87a2032010-10-22 12:50:53 +0100101 Handle<Code> code() const { return code_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100102 Code::Flags code_flags() const { return code_flags_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 BailoutId osr_ast_id() const { return osr_ast_id_; }
104 Handle<Code> unoptimized_code() const { return unoptimized_code_; }
105 int opt_count() const { return opt_count_; }
106 int num_parameters() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 int num_parameters_including_this() const;
108 bool is_this_defined() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109 int num_heap_slots() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000110
111 void set_parameter_count(int parameter_count) {
112 DCHECK(IsStub());
113 parameter_count_ = parameter_count;
Steve Block1e0659c2011-05-24 12:43:12 +0100114 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
117 Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000119 bool is_tracking_positions() const { return track_positions_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120
121 bool is_calling() const {
122 return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling);
Steve Block44f0eee2011-05-26 01:26:41 +0100123 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000124
125 void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); }
126
127 bool is_deferred_calling() const { return GetFlag(kDeferredCalling); }
128
129 void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); }
130
131 bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); }
132
133 void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); }
134
135 bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); }
136
137 void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); }
138
139 bool requires_frame() const { return GetFlag(kRequiresFrame); }
140
141 void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); }
142
143 bool GetMustNotHaveEagerFrame() const {
144 return GetFlag(kMustNotHaveEagerFrame);
145 }
146
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 // Compiles marked as debug produce unoptimized code with debug break slots.
148 // Inner functions that cannot be compiled w/o context are compiled eagerly.
149 // Always include deoptimization support to avoid having to recompile again.
150 void MarkAsDebug() {
151 SetFlag(kDebug);
152 SetFlag(kDeoptimizationSupport);
153 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154
155 bool is_debug() const { return GetFlag(kDebug); }
156
157 void PrepareForSerializing() { SetFlag(kSerializing); }
158
159 bool will_serialize() const { return GetFlag(kSerializing); }
160
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 void MarkAsFunctionContextSpecializing() {
162 SetFlag(kFunctionContextSpecializing);
163 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 bool is_function_context_specializing() const {
166 return GetFlag(kFunctionContextSpecializing);
167 }
168
169 void MarkAsFrameSpecializing() { SetFlag(kFrameSpecializing); }
170
171 bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
172
173 void MarkAsNativeContextSpecializing() {
174 SetFlag(kNativeContextSpecializing);
175 }
176
177 bool is_native_context_specializing() const {
178 return GetFlag(kNativeContextSpecializing);
179 }
180
181 void MarkAsDeoptimizationEnabled() { SetFlag(kDeoptimizationEnabled); }
182
183 bool is_deoptimization_enabled() const {
184 return GetFlag(kDeoptimizationEnabled);
185 }
186
187 void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); }
188
189 bool is_source_positions_enabled() const {
190 return GetFlag(kSourcePositionsEnabled);
191 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192
193 void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }
194
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195 bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
196
197 void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); }
198
199 bool is_typing_enabled() const { return GetFlag(kTypingEnabled); }
200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400204
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 void MarkAsFirstCompile() { SetFlag(kFirstCompile); }
206
207 void MarkAsCompiled() { SetFlag(kFirstCompile, false); }
208
209 bool is_first_compile() const { return GetFlag(kFirstCompile); }
210
Ben Murdoch097c5b22016-05-18 11:27:45 +0100211 void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); }
212
213 bool is_bailout_on_uninitialized() const {
214 return GetFlag(kBailoutOnUninitialized);
215 }
216
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217 bool GeneratePreagedPrologue() const {
218 // Generate a pre-aged prologue if we are optimizing for size, which
219 // will make code flushing more aggressive. Only apply to Code::FUNCTION,
220 // since StaticMarkingVisitor::IsFlushable only flushes proper functions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() &&
Ben Murdoch097c5b22016-05-18 11:27:45 +0100222 !is_debug() && output_code_kind() == Code::FUNCTION;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000223 }
224
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400225 void EnsureFeedbackVector();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 Handle<TypeFeedbackVector> feedback_vector() const {
227 return feedback_vector_;
228 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100229 void SetCode(Handle<Code> code) { code_ = code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 void SetBytecodeArray(Handle<BytecodeArray> bytecode_array) {
232 bytecode_array_ = bytecode_array;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 }
234
235 bool ShouldTrapOnDeopt() const {
236 return (FLAG_trap_on_deopt && IsOptimizing()) ||
237 (FLAG_trap_on_stub_deopt && IsStub());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100238 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100239
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 bool has_native_context() const {
241 return !closure().is_null() && (closure()->native_context() != nullptr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100242 }
243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 Context* native_context() const {
245 return has_native_context() ? closure()->native_context() : nullptr;
246 }
247
248 bool has_global_object() const { return has_native_context(); }
249
250 JSGlobalObject* global_object() const {
251 return has_global_object() ? native_context()->global_object() : nullptr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100252 }
253
254 // Accessors for the different compilation modes.
255 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256 bool IsStub() const { return mode_ == STUB; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100257 void SetOptimizing() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 DCHECK(has_shared_info());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100259 SetMode(OPTIMIZE);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100260 optimization_id_ = isolate()->NextOptimizationId();
261 code_flags_ =
262 Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION);
263 }
264 void SetOptimizingForOsr(BailoutId osr_ast_id, Handle<Code> unoptimized) {
265 SetOptimizing();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100266 osr_ast_id_ = osr_ast_id;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 unoptimized_code_ = unoptimized;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100268 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100269
270 // Deoptimization support.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100271 bool HasDeoptimizationSupport() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 return GetFlag(kDeoptimizationSupport);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100273 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100274 void EnableDeoptimizationSupport() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 DCHECK_EQ(BASE, mode_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 SetFlag(kDeoptimizationSupport);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100277 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 bool ShouldEnsureSpaceForLazyDeopt() { return !IsStub(); }
279
280 bool ExpectsJSReceiverAsReceiver();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100281
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100282 // Determines whether or not to insert a self-optimization header.
283 bool ShouldSelfOptimize();
Andrei Popescu31002712010-02-23 13:46:05 +0000284
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 void set_deferred_handles(DeferredHandles* deferred_handles) {
286 DCHECK(deferred_handles_ == NULL);
287 deferred_handles_ = deferred_handles;
288 }
289
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 void ReopenHandlesInNewHandleScope() {
291 unoptimized_code_ = Handle<Code>(*unoptimized_code_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000292 }
293
294 void AbortOptimization(BailoutReason reason) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 DCHECK(reason != kNoReason);
296 if (bailout_reason_ == kNoReason) bailout_reason_ = reason;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 SetFlag(kDisableFutureOptimization);
298 }
299
300 void RetryOptimization(BailoutReason reason) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 DCHECK(reason != kNoReason);
302 if (GetFlag(kDisableFutureOptimization)) return;
303 bailout_reason_ = reason;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304 }
305
306 BailoutReason bailout_reason() const { return bailout_reason_; }
307
308 int prologue_offset() const {
309 DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_);
310 return prologue_offset_;
311 }
312
313 void set_prologue_offset(int prologue_offset) {
314 DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_);
315 prologue_offset_ = prologue_offset;
316 }
317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318 int start_position_for(uint32_t inlining_id) {
319 return inlined_function_infos_.at(inlining_id).start_position;
320 }
321 const std::vector<InlinedFunctionInfo>& inlined_function_infos() {
322 return inlined_function_infos_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 }
324
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325 void LogDeoptCallPosition(int pc_offset, int inlining_id);
326 int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
327 SourcePosition position, int pareint_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 CompilationDependencies* dependencies() { return &dependencies_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000330
331 bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332 return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333 }
334
335 int optimization_id() const { return optimization_id_; }
336
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 int osr_expr_stack_height() { return osr_expr_stack_height_; }
338 void set_osr_expr_stack_height(int height) {
339 DCHECK(height >= 0);
340 osr_expr_stack_height_ = height;
341 }
342 JavaScriptFrame* osr_frame() const { return osr_frame_; }
343 void set_osr_frame(JavaScriptFrame* osr_frame) { osr_frame_ = osr_frame; }
344
345#if DEBUG
346 void PrintAstForTesting();
347#endif
348
349 bool has_simple_parameters();
350
351 struct InlinedFunctionHolder {
352 Handle<SharedFunctionInfo> shared_info;
353
354 // Root that holds the unoptimized code of the inlined function alive
355 // (and out of reach of code flushing) until we finish compilation.
356 // Do not remove.
357 Handle<Code> inlined_code_object_root;
358
359 explicit InlinedFunctionHolder(
360 Handle<SharedFunctionInfo> inlined_shared_info)
361 : shared_info(inlined_shared_info),
362 inlined_code_object_root(inlined_shared_info->code()) {}
363 };
364
365 typedef std::vector<InlinedFunctionHolder> InlinedFunctionList;
366 InlinedFunctionList const& inlined_functions() const {
367 return inlined_functions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368 }
369
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000370 void AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function) {
371 inlined_functions_.push_back(InlinedFunctionHolder(inlined_function));
372 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374 base::SmartArrayPointer<char> GetDebugName() const;
375
Ben Murdoch097c5b22016-05-18 11:27:45 +0100376 Code::Kind output_code_kind() const {
377 return Code::ExtractKindFromFlags(code_flags_);
378 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379
380 protected:
381 ParseInfo* parse_info_;
382
383 void DisableFutureOptimization() {
384 if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
385 shared_info()->DisableOptimization(bailout_reason());
386 }
387 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000388
Leon Clarke4515c472010-02-03 11:58:03 +0000389 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100390 // Compilation mode.
391 // BASE is generated by the full codegen, optionally prepared for bailouts.
392 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100393 enum Mode {
394 BASE,
395 OPTIMIZE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000396 STUB
Ben Murdochb0fe1622011-05-05 13:52:32 +0100397 };
398
Ben Murdoch097c5b22016-05-18 11:27:45 +0100399 CompilationInfo(ParseInfo* parse_info, const char* debug_name,
400 Code::Flags code_flags, Mode mode, Isolate* isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401 Zone* zone);
402
403 Isolate* isolate_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100404
405 void SetMode(Mode mode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100406 mode_ = mode;
407 }
408
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409 void SetFlag(Flag flag) { flags_ |= flag; }
Andrei Popescu31002712010-02-23 13:46:05 +0000410
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411 void SetFlag(Flag flag, bool value) {
412 flags_ = value ? flags_ | flag : flags_ & ~flag;
413 }
414
415 bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000416
Ben Murdochf87a2032010-10-22 12:50:53 +0100417 unsigned flags_;
418
Ben Murdoch097c5b22016-05-18 11:27:45 +0100419 Code::Flags code_flags_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420
Ben Murdochf87a2032010-10-22 12:50:53 +0100421 // The compiled code.
422 Handle<Code> code_;
423
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 // Used by codegen, ultimately kept rooted by the SharedFunctionInfo.
425 Handle<TypeFeedbackVector> feedback_vector_;
Andrei Popescu31002712010-02-23 13:46:05 +0000426
Ben Murdochb0fe1622011-05-05 13:52:32 +0100427 // Compilation mode flag and whether deoptimization is allowed.
428 Mode mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429 BailoutId osr_ast_id_;
430 // The unoptimized code we patched for OSR may not be the shared code
431 // afterwards, since we may need to compile it again to include deoptimization
432 // data. Keep track which code we patched.
433 Handle<Code> unoptimized_code_;
434
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 // Holds the bytecode array generated by the interpreter.
436 // TODO(rmcilroy/mstarzinger): Temporary work-around until compiler.cc is
437 // refactored to avoid us needing to carry the BytcodeArray around.
438 Handle<BytecodeArray> bytecode_array_;
439
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440 // The zone from which the compilation pipeline working on this
441 // CompilationInfo allocates.
442 Zone* zone_;
443
444 DeferredHandles* deferred_handles_;
445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 // Dependencies for this compilation, e.g. stable maps.
447 CompilationDependencies dependencies_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448
449 BailoutReason bailout_reason_;
450
451 int prologue_offset_;
452
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 std::vector<InlinedFunctionInfo> inlined_function_infos_;
454 bool track_positions_;
455
456 InlinedFunctionList inlined_functions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457
458 // A copy of shared_info()->opt_count() to avoid handle deref
459 // during graph optimization.
460 int opt_count_;
461
462 // Number of parameters used for compilation of stubs that require arguments.
463 int parameter_count_;
464
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000465 int optimization_id_;
466
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000467 int osr_expr_stack_height_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000468
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 // The current OSR frame for specialization or {nullptr}.
470 JavaScriptFrame* osr_frame_ = nullptr;
471
472 const char* debug_name_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100473
Andrei Popescu31002712010-02-23 13:46:05 +0000474 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000475};
476
477
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478// A wrapper around a CompilationInfo that detaches the Handles from
479// the underlying DeferredHandleScope and stores them in info_ on
480// destruction.
481class CompilationHandleScope BASE_EMBEDDED {
482 public:
483 explicit CompilationHandleScope(CompilationInfo* info)
484 : deferred_(info->isolate()), info_(info) {}
485 ~CompilationHandleScope() {
486 info_->set_deferred_handles(deferred_.Detach());
487 }
488
489 private:
490 DeferredHandleScope deferred_;
491 CompilationInfo* info_;
492};
493
494
495class HGraph;
496class HOptimizedGraphBuilder;
497class LChunk;
498
499// A helper class that calls the three compilation phases in
500// Crankshaft and keeps track of its state. The three phases
501// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
502// fail, bail-out to the full code generator or succeed. Apart from
503// their return value, the status of the phase last run can be checked
504// using last_status().
505class OptimizedCompileJob: public ZoneObject {
506 public:
507 explicit OptimizedCompileJob(CompilationInfo* info)
508 : info_(info),
509 graph_builder_(NULL),
510 graph_(NULL),
511 chunk_(NULL),
512 last_status_(FAILED),
513 awaiting_install_(false) { }
514
515 enum Status {
516 FAILED, BAILED_OUT, SUCCEEDED
517 };
518
519 MUST_USE_RESULT Status CreateGraph();
520 MUST_USE_RESULT Status OptimizeGraph();
521 MUST_USE_RESULT Status GenerateCode();
522
523 Status last_status() const { return last_status_; }
524 CompilationInfo* info() const { return info_; }
525 Isolate* isolate() const { return info()->isolate(); }
526
527 Status RetryOptimization(BailoutReason reason) {
528 info_->RetryOptimization(reason);
529 return SetLastStatus(BAILED_OUT);
530 }
531
532 Status AbortOptimization(BailoutReason reason) {
533 info_->AbortOptimization(reason);
534 return SetLastStatus(BAILED_OUT);
535 }
536
537 void WaitForInstall() {
538 DCHECK(info_->is_osr());
539 awaiting_install_ = true;
540 }
541
542 bool IsWaitingForInstall() { return awaiting_install_; }
543
544 private:
545 CompilationInfo* info_;
546 HOptimizedGraphBuilder* graph_builder_;
547 HGraph* graph_;
548 LChunk* chunk_;
549 base::TimeDelta time_taken_to_create_graph_;
550 base::TimeDelta time_taken_to_optimize_;
551 base::TimeDelta time_taken_to_codegen_;
552 Status last_status_;
553 bool awaiting_install_;
554
555 MUST_USE_RESULT Status SetLastStatus(Status status) {
556 last_status_ = status;
557 return last_status_;
558 }
559 void RecordOptimizationStats();
560
561 struct Timer {
562 Timer(OptimizedCompileJob* job, base::TimeDelta* location)
563 : job_(job), location_(location) {
564 DCHECK(location_ != NULL);
565 timer_.Start();
566 }
567
568 ~Timer() {
569 *location_ += timer_.Elapsed();
570 }
571
572 OptimizedCompileJob* job_;
573 base::ElapsedTimer timer_;
574 base::TimeDelta* location_;
575 };
576};
577
578
Steve Blocka7e24c12009-10-30 11:49:00 +0000579// The V8 compiler
580//
581// General strategy: Source code is translated into an anonymous function w/o
582// parameters which then can be executed. If the source code contains other
583// functions, they will be compiled and allocated as part of the compilation
584// of the source code.
585
Ben Murdochf87a2032010-10-22 12:50:53 +0100586// Please note this interface returns shared function infos. This means you
587// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
588// real function with a context.
Steve Blocka7e24c12009-10-30 11:49:00 +0000589
590class Compiler : public AllStatic {
591 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592 MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
593 Handle<JSFunction> function);
594 MUST_USE_RESULT static MaybeHandle<Code> GetLazyCode(
595 Handle<JSFunction> function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596
597 static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
598 static bool CompileDebugCode(Handle<JSFunction> function);
599 static bool CompileDebugCode(Handle<SharedFunctionInfo> shared);
600 static void CompileForLiveEdit(Handle<Script> script);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100601
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400602 // Parser::Parse, then Compiler::Analyze.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 static bool ParseAndAnalyze(ParseInfo* info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400604 // Rewrite, analyze scopes, and renumber.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605 static bool Analyze(ParseInfo* info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400606 // Adds deoptimization support, requires ParseAndAnalyze.
607 static bool EnsureDeoptimizationSupport(CompilationInfo* info);
608
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 // Compile a String source within a context for eval.
610 MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
611 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 Handle<Context> context, LanguageMode language_mode,
613 ParseRestriction restriction, int line_offset, int column_offset = 0,
614 Handle<Object> script_name = Handle<Object>(),
615 ScriptOriginOptions options = ScriptOriginOptions());
Steve Blocka7e24c12009-10-30 11:49:00 +0000616
617 // Compile a String source within a context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000618 static Handle<SharedFunctionInfo> CompileScript(
619 Handle<String> source, Handle<Object> script_name, int line_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 int column_offset, ScriptOriginOptions resource_options,
621 Handle<Object> source_map_url, Handle<Context> context,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622 v8::Extension* extension, ScriptData** cached_data,
623 ScriptCompiler::CompileOptions compile_options,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624 NativesFlag is_natives_code, bool is_module);
Steve Blocka7e24c12009-10-30 11:49:00 +0000625
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000626 static Handle<SharedFunctionInfo> CompileStreamedScript(Handle<Script> script,
627 ParseInfo* info,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628 int source_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000629
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000630 // Create a shared function info object (the code may be lazily compiled).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631 static Handle<SharedFunctionInfo> GetSharedFunctionInfo(
632 FunctionLiteral* node, Handle<Script> script, CompilationInfo* outer);
Steve Blockd0582a62009-12-15 09:54:21 +0000633
Ben Murdoch097c5b22016-05-18 11:27:45 +0100634 // Create a shared function info object for a native function literal.
635 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
636 v8::Extension* extension, Handle<String> name);
637
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
Andrei Popescu31002712010-02-23 13:46:05 +0000639
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000640 // Generate and return optimized code or start a concurrent optimization job.
641 // In the latter case, return the InOptimizationQueue builtin. On failure,
642 // return the empty handle.
643 MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100644 Handle<JSFunction> function, ConcurrencyMode mode,
645 BailoutId osr_ast_id = BailoutId::None(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000646 JavaScriptFrame* osr_frame = nullptr);
Ben Murdochf87a2032010-10-22 12:50:53 +0100647
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648 // Generate and return code from previously queued optimization job.
649 // On failure, return the empty handle.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100650 MUST_USE_RESULT static MaybeHandle<Code> GetConcurrentlyOptimizedCode(
651 OptimizedCompileJob* job);
Steve Blocka7e24c12009-10-30 11:49:00 +0000652};
653
654
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655class CompilationPhase BASE_EMBEDDED {
656 public:
657 CompilationPhase(const char* name, CompilationInfo* info);
658 ~CompilationPhase();
659
660 protected:
661 bool ShouldProduceTraceOutput() const;
662
663 const char* name() const { return name_; }
664 CompilationInfo* info() const { return info_; }
665 Isolate* isolate() const { return info()->isolate(); }
666 Zone* zone() { return &zone_; }
667
668 private:
669 const char* name_;
670 CompilationInfo* info_;
671 Zone zone_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000672 size_t info_zone_start_allocation_size_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000673 base::ElapsedTimer timer_;
674
675 DISALLOW_COPY_AND_ASSIGN(CompilationPhase);
676};
677
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000678} // namespace internal
679} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +0000680
681#endif // V8_COMPILER_H_