blob: 55215733c11c66a8b9160a0adebc927e1c564ad0 [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 Murdochf91f0612016-11-29 16:50:11 +00008#include <memory>
9
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/allocation.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/bailout-reason.h"
Ben Murdoch014dc512016-03-22 12:00:34 +000012#include "src/compilation-dependencies.h"
Ben Murdochf91f0612016-11-29 16:50:11 +000013#include "src/contexts.h"
14#include "src/frames.h"
15#include "src/isolate.h"
16#include "src/objects-inl.h"
17#include "src/source-position-table.h"
Ben Murdoch109988c2016-05-18 11:27:45 +010018#include "src/source-position.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019#include "src/zone.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000020
21namespace v8 {
22namespace internal {
23
Ben Murdoch109988c2016-05-18 11:27:45 +010024// Forward declarations.
Ben Murdoch3b9bc312016-06-02 14:46:10 +010025class CompilationInfo;
Ben Murdochbcf72ee2016-08-08 18:44:38 +010026class CompilationJob;
Ben Murdoch014dc512016-03-22 12:00:34 +000027class JavaScriptFrame;
28class ParseInfo;
29class ScriptData;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030
Ben Murdoch3b9bc312016-06-02 14:46:10 +010031// The V8 compiler API.
32//
33// This is the central hub for dispatching to the various compilers within V8.
34// Logic for which compiler to choose and how to wire compilation results into
35// the object heap should be kept inside this class.
36//
37// General strategy: Scripts are translated into anonymous functions w/o
38// parameters which then can be executed. If the source code contains other
39// functions, they might be compiled and allocated as part of the compilation
40// of the source code or deferred for lazy compilation at a later point.
41class Compiler : public AllStatic {
42 public:
43 enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
44 enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
Ben Murdochf91f0612016-11-29 16:50:11 +000045 enum CompilationTier { INTERPRETED, BASELINE, OPTIMIZED };
Ben Murdoch3b9bc312016-06-02 14:46:10 +010046
47 // ===========================================================================
48 // The following family of methods ensures a given function is compiled. The
49 // general contract is that failures will be reported by returning {false},
50 // whereas successful compilation ensures the {is_compiled} predicate on the
51 // given function holds (except for live-edit, which compiles the world).
52
53 static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
Ben Murdochbcf72ee2016-08-08 18:44:38 +010054 static bool CompileBaseline(Handle<JSFunction> function);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010055 static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
56 static bool CompileDebugCode(Handle<JSFunction> function);
57 static bool CompileDebugCode(Handle<SharedFunctionInfo> shared);
Ben Murdochbcf72ee2016-08-08 18:44:38 +010058 static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010059
Ben Murdochbcf72ee2016-08-08 18:44:38 +010060 // Generate and install code from previously queued compilation job.
61 static void FinalizeCompilationJob(CompilationJob* job);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010062
63 // Give the compiler a chance to perform low-latency initialization tasks of
64 // the given {function} on its instantiation. Note that only the runtime will
65 // offer this chance, optimized closure instantiation will not call this.
66 static void PostInstantiation(Handle<JSFunction> function, PretenureFlag);
67
68 // Parser::Parse, then Compiler::Analyze.
69 static bool ParseAndAnalyze(ParseInfo* info);
70 // Rewrite, analyze scopes, and renumber.
71 static bool Analyze(ParseInfo* info);
72 // Adds deoptimization support, requires ParseAndAnalyze.
73 static bool EnsureDeoptimizationSupport(CompilationInfo* info);
Ben Murdochf91f0612016-11-29 16:50:11 +000074 // Ensures that bytecode is generated, calls ParseAndAnalyze internally.
75 static bool EnsureBytecode(CompilationInfo* info);
76
77 // The next compilation tier which the function should be compiled to for
78 // optimization. This is used as a hint by the runtime profiler.
79 static CompilationTier NextCompilationTier(JSFunction* function);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010080
81 // ===========================================================================
82 // The following family of methods instantiates new functions for scripts or
83 // function literals. The decision whether those functions will be compiled,
84 // is left to the discretion of the compiler.
85 //
86 // Please note this interface returns shared function infos. This means you
87 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
88 // real function with a context.
89
90 // Create a (bound) function for a String source within a context for eval.
91 MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
92 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
93 Handle<Context> context, LanguageMode language_mode,
Ben Murdochbcf72ee2016-08-08 18:44:38 +010094 ParseRestriction restriction, int eval_scope_position, int eval_position,
95 int line_offset = 0, int column_offset = 0,
Ben Murdoch3b9bc312016-06-02 14:46:10 +010096 Handle<Object> script_name = Handle<Object>(),
97 ScriptOriginOptions options = ScriptOriginOptions());
98
Ben Murdochf91f0612016-11-29 16:50:11 +000099 // Create a (bound) function for a String source within a context for eval.
100 MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromString(
101 Handle<Context> context, Handle<String> source,
102 ParseRestriction restriction);
103
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100104 // Create a shared function info object for a String source within a context.
105 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
106 Handle<String> source, Handle<Object> script_name, int line_offset,
107 int column_offset, ScriptOriginOptions resource_options,
108 Handle<Object> source_map_url, Handle<Context> context,
109 v8::Extension* extension, ScriptData** cached_data,
110 ScriptCompiler::CompileOptions compile_options,
111 NativesFlag is_natives_code, bool is_module);
112
113 // Create a shared function info object for a Script that has already been
114 // parsed while the script was being loaded from a streamed source.
115 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForStreamedScript(
116 Handle<Script> script, ParseInfo* info, int source_length);
117
118 // Create a shared function info object (the code may be lazily compiled).
119 static Handle<SharedFunctionInfo> GetSharedFunctionInfo(
120 FunctionLiteral* node, Handle<Script> script, CompilationInfo* outer);
121
122 // Create a shared function info object for a native function literal.
123 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
124 v8::Extension* extension, Handle<String> name);
125
126 // ===========================================================================
127 // The following family of methods provides support for OSR. Code generated
128 // for entry via OSR might not be suitable for normal entry, hence will be
129 // returned directly to the caller.
130 //
131 // Please note this interface is the only part dealing with {Code} objects
132 // directly. Other methods are agnostic to {Code} and can use an interpreter
133 // instead of generating JIT code for a function at all.
134
135 // Generate and return optimized code for OSR, or empty handle on failure.
136 MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCodeForOSR(
137 Handle<JSFunction> function, BailoutId osr_ast_id,
138 JavaScriptFrame* osr_frame);
139};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140
Ben Murdoch014dc512016-03-22 12:00:34 +0000141
Andrei Popescu31002712010-02-23 13:46:05 +0000142// CompilationInfo encapsulates some information known at compile time. It
143// is constructed based on the resources available at compile-time.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100144class CompilationInfo final {
Leon Clarke4515c472010-02-03 11:58:03 +0000145 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 // Various configuration flags for a compilation, as well as some properties
147 // of the compiled code produced by a compilation.
148 enum Flag {
Ben Murdoch014dc512016-03-22 12:00:34 +0000149 kDeferredCalling = 1 << 0,
150 kNonDeferredCalling = 1 << 1,
151 kSavesCallerDoubles = 1 << 2,
152 kRequiresFrame = 1 << 3,
153 kMustNotHaveEagerFrame = 1 << 4,
154 kDeoptimizationSupport = 1 << 5,
155 kDebug = 1 << 6,
156 kSerializing = 1 << 7,
157 kFunctionContextSpecializing = 1 << 8,
158 kFrameSpecializing = 1 << 9,
159 kNativeContextSpecializing = 1 << 10,
160 kInliningEnabled = 1 << 11,
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100161 kDisableFutureOptimization = 1 << 12,
162 kSplittingEnabled = 1 << 13,
163 kDeoptimizationEnabled = 1 << 14,
164 kSourcePositionsEnabled = 1 << 15,
165 kBailoutOnUninitialized = 1 << 16,
166 kOptimizeFromBytecode = 1 << 17,
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100167 kTypeFeedbackEnabled = 1 << 18,
Ben Murdochf91f0612016-11-29 16:50:11 +0000168 kAccessorInliningEnabled = 1 << 19,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 };
Ben Murdochf87a2032010-10-22 12:50:53 +0100170
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100171 CompilationInfo(ParseInfo* parse_info, Handle<JSFunction> closure);
172 CompilationInfo(Vector<const char> debug_name, Isolate* isolate, Zone* zone,
Ben Murdoch109988c2016-05-18 11:27:45 +0100173 Code::Flags code_flags = Code::ComputeFlags(Code::STUB));
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100174 ~CompilationInfo();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175
Ben Murdoch014dc512016-03-22 12:00:34 +0000176 ParseInfo* parse_info() const { return parse_info_; }
177
178 // -----------------------------------------------------------
179 // TODO(titzer): inline and delete accessors of ParseInfo
180 // -----------------------------------------------------------
181 Handle<Script> script() const;
Ben Murdoch014dc512016-03-22 12:00:34 +0000182 FunctionLiteral* literal() const;
Ben Murdochf91f0612016-11-29 16:50:11 +0000183 DeclarationScope* scope() const;
Ben Murdoch014dc512016-03-22 12:00:34 +0000184 Handle<Context> context() const;
185 Handle<SharedFunctionInfo> shared_info() const;
186 bool has_shared_info() const;
Ben Murdoch014dc512016-03-22 12:00:34 +0000187 // -----------------------------------------------------------
188
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 Isolate* isolate() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100190 return isolate_;
191 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 Zone* zone() { return zone_; }
193 bool is_osr() const { return !osr_ast_id_.IsNone(); }
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100194 Handle<JSFunction> closure() const { return closure_; }
Ben Murdochf87a2032010-10-22 12:50:53 +0100195 Handle<Code> code() const { return code_; }
Ben Murdoch109988c2016-05-18 11:27:45 +0100196 Code::Flags code_flags() const { return code_flags_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197 BailoutId osr_ast_id() const { return osr_ast_id_; }
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100198 JavaScriptFrame* osr_frame() const { return osr_frame_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 int num_parameters() const;
Ben Murdoch014dc512016-03-22 12:00:34 +0000200 int num_parameters_including_this() const;
201 bool is_this_defined() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202
203 void set_parameter_count(int parameter_count) {
204 DCHECK(IsStub());
205 parameter_count_ = parameter_count;
Steve Block1e0659c2011-05-24 12:43:12 +0100206 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207
Ben Murdoch014dc512016-03-22 12:00:34 +0000208 bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
209 Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210
Ben Murdoch014dc512016-03-22 12:00:34 +0000211 bool is_tracking_positions() const { return track_positions_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212
213 bool is_calling() const {
214 return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling);
Steve Block44f0eee2011-05-26 01:26:41 +0100215 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216
217 void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); }
218
219 bool is_deferred_calling() const { return GetFlag(kDeferredCalling); }
220
221 void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); }
222
223 bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); }
224
225 void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); }
226
227 bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); }
228
229 void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); }
230
231 bool requires_frame() const { return GetFlag(kRequiresFrame); }
232
233 void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); }
234
235 bool GetMustNotHaveEagerFrame() const {
236 return GetFlag(kMustNotHaveEagerFrame);
237 }
238
Ben Murdoch014dc512016-03-22 12:00:34 +0000239 // Compiles marked as debug produce unoptimized code with debug break slots.
240 // Inner functions that cannot be compiled w/o context are compiled eagerly.
241 // Always include deoptimization support to avoid having to recompile again.
242 void MarkAsDebug() {
243 SetFlag(kDebug);
244 SetFlag(kDeoptimizationSupport);
245 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246
247 bool is_debug() const { return GetFlag(kDebug); }
248
249 void PrepareForSerializing() { SetFlag(kSerializing); }
250
251 bool will_serialize() const { return GetFlag(kSerializing); }
252
Ben Murdoch014dc512016-03-22 12:00:34 +0000253 void MarkAsFunctionContextSpecializing() {
254 SetFlag(kFunctionContextSpecializing);
255 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256
Ben Murdoch014dc512016-03-22 12:00:34 +0000257 bool is_function_context_specializing() const {
258 return GetFlag(kFunctionContextSpecializing);
259 }
260
261 void MarkAsFrameSpecializing() { SetFlag(kFrameSpecializing); }
262
263 bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
264
265 void MarkAsNativeContextSpecializing() {
266 SetFlag(kNativeContextSpecializing);
267 }
268
269 bool is_native_context_specializing() const {
270 return GetFlag(kNativeContextSpecializing);
271 }
272
273 void MarkAsDeoptimizationEnabled() { SetFlag(kDeoptimizationEnabled); }
274
275 bool is_deoptimization_enabled() const {
276 return GetFlag(kDeoptimizationEnabled);
277 }
278
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100279 void MarkAsTypeFeedbackEnabled() { SetFlag(kTypeFeedbackEnabled); }
280
281 bool is_type_feedback_enabled() const {
282 return GetFlag(kTypeFeedbackEnabled);
283 }
284
Ben Murdochf91f0612016-11-29 16:50:11 +0000285 void MarkAsAccessorInliningEnabled() { SetFlag(kAccessorInliningEnabled); }
286
287 bool is_accessor_inlining_enabled() const {
288 return GetFlag(kAccessorInliningEnabled);
289 }
290
Ben Murdoch014dc512016-03-22 12:00:34 +0000291 void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); }
292
293 bool is_source_positions_enabled() const {
294 return GetFlag(kSourcePositionsEnabled);
295 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296
297 void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }
298
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299 bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
300
Ben Murdoch014dc512016-03-22 12:00:34 +0000301 void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); }
Emily Bernier958fae72015-03-24 16:35:39 -0400302
Ben Murdoch014dc512016-03-22 12:00:34 +0000303 bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); }
Emily Bernier958fae72015-03-24 16:35:39 -0400304
Ben Murdoch109988c2016-05-18 11:27:45 +0100305 void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); }
306
307 bool is_bailout_on_uninitialized() const {
308 return GetFlag(kBailoutOnUninitialized);
309 }
310
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100311 void MarkAsOptimizeFromBytecode() { SetFlag(kOptimizeFromBytecode); }
312
313 bool is_optimizing_from_bytecode() const {
314 return GetFlag(kOptimizeFromBytecode);
315 }
316
Ben Murdoch014dc512016-03-22 12:00:34 +0000317 bool GeneratePreagedPrologue() const {
318 // Generate a pre-aged prologue if we are optimizing for size, which
319 // will make code flushing more aggressive. Only apply to Code::FUNCTION,
320 // since StaticMarkingVisitor::IsFlushable only flushes proper functions.
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100321 return FLAG_optimize_for_size && FLAG_age_code && !is_debug() &&
322 output_code_kind() == Code::FUNCTION;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 }
324
Ben Murdochf87a2032010-10-22 12:50:53 +0100325 void SetCode(Handle<Code> code) { code_ = code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326
Ben Murdoch014dc512016-03-22 12:00:34 +0000327 void SetBytecodeArray(Handle<BytecodeArray> bytecode_array) {
328 bytecode_array_ = bytecode_array;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 }
330
331 bool ShouldTrapOnDeopt() const {
332 return (FLAG_trap_on_deopt && IsOptimizing()) ||
333 (FLAG_trap_on_stub_deopt && IsStub());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100334 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100335
Ben Murdoch014dc512016-03-22 12:00:34 +0000336 bool has_native_context() const {
337 return !closure().is_null() && (closure()->native_context() != nullptr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100338 }
339
Ben Murdoch014dc512016-03-22 12:00:34 +0000340 Context* native_context() const {
341 return has_native_context() ? closure()->native_context() : nullptr;
342 }
343
344 bool has_global_object() const { return has_native_context(); }
345
346 JSGlobalObject* global_object() const {
347 return has_global_object() ? native_context()->global_object() : nullptr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100348 }
349
350 // Accessors for the different compilation modes.
351 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352 bool IsStub() const { return mode_ == STUB; }
Ben Murdoch109988c2016-05-18 11:27:45 +0100353 void SetOptimizing() {
Ben Murdoch014dc512016-03-22 12:00:34 +0000354 DCHECK(has_shared_info());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100355 SetMode(OPTIMIZE);
Ben Murdoch109988c2016-05-18 11:27:45 +0100356 optimization_id_ = isolate()->NextOptimizationId();
357 code_flags_ =
358 Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION);
359 }
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100360 void SetOptimizingForOsr(BailoutId osr_ast_id, JavaScriptFrame* osr_frame) {
Ben Murdoch109988c2016-05-18 11:27:45 +0100361 SetOptimizing();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100362 osr_ast_id_ = osr_ast_id;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100363 osr_frame_ = osr_frame;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100364 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100365
366 // Deoptimization support.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100367 bool HasDeoptimizationSupport() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368 return GetFlag(kDeoptimizationSupport);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100369 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100370 void EnableDeoptimizationSupport() {
Ben Murdoch014dc512016-03-22 12:00:34 +0000371 DCHECK_EQ(BASE, mode_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000372 SetFlag(kDeoptimizationSupport);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100373 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000374 bool ShouldEnsureSpaceForLazyDeopt() { return !IsStub(); }
375
376 bool ExpectsJSReceiverAsReceiver();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100377
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100378 // Determines whether or not to insert a self-optimization header.
379 bool ShouldSelfOptimize();
Andrei Popescu31002712010-02-23 13:46:05 +0000380
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381 void set_deferred_handles(DeferredHandles* deferred_handles) {
382 DCHECK(deferred_handles_ == NULL);
383 deferred_handles_ = deferred_handles;
384 }
385
Ben Murdoch014dc512016-03-22 12:00:34 +0000386 void ReopenHandlesInNewHandleScope() {
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100387 closure_ = Handle<JSFunction>(*closure_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388 }
389
390 void AbortOptimization(BailoutReason reason) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000391 DCHECK(reason != kNoReason);
392 if (bailout_reason_ == kNoReason) bailout_reason_ = reason;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000393 SetFlag(kDisableFutureOptimization);
394 }
395
396 void RetryOptimization(BailoutReason reason) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000397 DCHECK(reason != kNoReason);
398 if (GetFlag(kDisableFutureOptimization)) return;
399 bailout_reason_ = reason;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000400 }
401
402 BailoutReason bailout_reason() const { return bailout_reason_; }
403
404 int prologue_offset() const {
405 DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_);
406 return prologue_offset_;
407 }
408
409 void set_prologue_offset(int prologue_offset) {
410 DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_);
411 prologue_offset_ = prologue_offset;
412 }
413
Ben Murdoch014dc512016-03-22 12:00:34 +0000414 CompilationDependencies* dependencies() { return &dependencies_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000415
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000416 int optimization_id() const { return optimization_id_; }
417
Ben Murdoch014dc512016-03-22 12:00:34 +0000418 int osr_expr_stack_height() { return osr_expr_stack_height_; }
419 void set_osr_expr_stack_height(int height) {
420 DCHECK(height >= 0);
421 osr_expr_stack_height_ = height;
422 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000423
Ben Murdoch014dc512016-03-22 12:00:34 +0000424 bool has_simple_parameters();
425
426 struct InlinedFunctionHolder {
427 Handle<SharedFunctionInfo> shared_info;
428
429 // Root that holds the unoptimized code of the inlined function alive
430 // (and out of reach of code flushing) until we finish compilation.
431 // Do not remove.
432 Handle<Code> inlined_code_object_root;
433
434 explicit InlinedFunctionHolder(
435 Handle<SharedFunctionInfo> inlined_shared_info)
436 : shared_info(inlined_shared_info),
437 inlined_code_object_root(inlined_shared_info->code()) {}
438 };
439
440 typedef std::vector<InlinedFunctionHolder> InlinedFunctionList;
441 InlinedFunctionList const& inlined_functions() const {
442 return inlined_functions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 }
444
Ben Murdoch014dc512016-03-22 12:00:34 +0000445 void AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function) {
446 inlined_functions_.push_back(InlinedFunctionHolder(inlined_function));
447 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448
Ben Murdochf91f0612016-11-29 16:50:11 +0000449 std::unique_ptr<char[]> GetDebugName() const;
Ben Murdoch014dc512016-03-22 12:00:34 +0000450
Ben Murdoch109988c2016-05-18 11:27:45 +0100451 Code::Kind output_code_kind() const {
452 return Code::ExtractKindFromFlags(code_flags_);
453 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000454
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100455 StackFrame::Type GetOutputStackFrameType() const;
456
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100457 int GetDeclareGlobalsFlags() const;
458
Ben Murdochf91f0612016-11-29 16:50:11 +0000459 SourcePositionTableBuilder::RecordingMode SourcePositionRecordingMode() const;
Ben Murdoch257744e2011-11-30 15:57:28 +0000460
Leon Clarke4515c472010-02-03 11:58:03 +0000461 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100462 // Compilation mode.
463 // BASE is generated by the full codegen, optionally prepared for bailouts.
464 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100465 enum Mode {
466 BASE,
467 OPTIMIZE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000468 STUB
Ben Murdochb0fe1622011-05-05 13:52:32 +0100469 };
470
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100471 CompilationInfo(ParseInfo* parse_info, Vector<const char> debug_name,
Ben Murdoch109988c2016-05-18 11:27:45 +0100472 Code::Flags code_flags, Mode mode, Isolate* isolate,
Ben Murdoch014dc512016-03-22 12:00:34 +0000473 Zone* zone);
474
Ben Murdochf91f0612016-11-29 16:50:11 +0000475 ParseInfo* parse_info_;
Ben Murdoch014dc512016-03-22 12:00:34 +0000476 Isolate* isolate_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100477
478 void SetMode(Mode mode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100479 mode_ = mode;
480 }
481
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000482 void SetFlag(Flag flag) { flags_ |= flag; }
Andrei Popescu31002712010-02-23 13:46:05 +0000483
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000484 void SetFlag(Flag flag, bool value) {
485 flags_ = value ? flags_ | flag : flags_ & ~flag;
486 }
487
488 bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000489
Ben Murdochf87a2032010-10-22 12:50:53 +0100490 unsigned flags_;
491
Ben Murdoch109988c2016-05-18 11:27:45 +0100492 Code::Flags code_flags_;
Ben Murdoch014dc512016-03-22 12:00:34 +0000493
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100494 Handle<JSFunction> closure_;
495
Ben Murdochf87a2032010-10-22 12:50:53 +0100496 // The compiled code.
497 Handle<Code> code_;
498
Ben Murdochb0fe1622011-05-05 13:52:32 +0100499 // Compilation mode flag and whether deoptimization is allowed.
500 Mode mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 BailoutId osr_ast_id_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000502
Ben Murdoch014dc512016-03-22 12:00:34 +0000503 // Holds the bytecode array generated by the interpreter.
504 // TODO(rmcilroy/mstarzinger): Temporary work-around until compiler.cc is
505 // refactored to avoid us needing to carry the BytcodeArray around.
506 Handle<BytecodeArray> bytecode_array_;
507
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508 // The zone from which the compilation pipeline working on this
509 // CompilationInfo allocates.
510 Zone* zone_;
511
512 DeferredHandles* deferred_handles_;
513
Ben Murdoch014dc512016-03-22 12:00:34 +0000514 // Dependencies for this compilation, e.g. stable maps.
515 CompilationDependencies dependencies_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516
517 BailoutReason bailout_reason_;
518
519 int prologue_offset_;
520
Ben Murdoch014dc512016-03-22 12:00:34 +0000521 bool track_positions_;
522
523 InlinedFunctionList inlined_functions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000524
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000525 // Number of parameters used for compilation of stubs that require arguments.
526 int parameter_count_;
527
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000528 int optimization_id_;
529
Ben Murdoch014dc512016-03-22 12:00:34 +0000530 int osr_expr_stack_height_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000531
Ben Murdoch014dc512016-03-22 12:00:34 +0000532 // The current OSR frame for specialization or {nullptr}.
533 JavaScriptFrame* osr_frame_ = nullptr;
534
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100535 Vector<const char> debug_name_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100536
Andrei Popescu31002712010-02-23 13:46:05 +0000537 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000538};
539
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100540// A base class for compilation jobs intended to run concurrent to the main
541// thread. The job is split into three phases which are called in sequence on
542// different threads and with different limitations:
Ben Murdochf91f0612016-11-29 16:50:11 +0000543// 1) PrepareJob: Runs on main thread. No major limitations.
544// 2) ExecuteJob: Runs concurrently. No heap allocation or handle derefs.
545// 3) FinalizeJob: Runs on main thread. No dependency changes.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100546//
Ben Murdochf91f0612016-11-29 16:50:11 +0000547// Each of the three phases can either fail or succeed. The current state of
548// the job can be checked using {state()}.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100549class CompilationJob {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000550 public:
Ben Murdochf91f0612016-11-29 16:50:11 +0000551 enum Status { SUCCEEDED, FAILED };
552 enum class State {
553 kReadyToPrepare,
554 kReadyToExecute,
555 kReadyToFinalize,
556 kSucceeded,
557 kFailed,
558 };
559
560 explicit CompilationJob(CompilationInfo* info, const char* compiler_name,
561 State initial_state = State::kReadyToPrepare)
562 : info_(info), compiler_name_(compiler_name), state_(initial_state) {}
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100563 virtual ~CompilationJob() {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564
Ben Murdochf91f0612016-11-29 16:50:11 +0000565 // Prepare the compile job. Must be called on the main thread.
566 MUST_USE_RESULT Status PrepareJob();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567
Ben Murdochf91f0612016-11-29 16:50:11 +0000568 // Executes the compile job. Can be called off the main thread.
569 MUST_USE_RESULT Status ExecuteJob();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570
Ben Murdochf91f0612016-11-29 16:50:11 +0000571 // Finalizes the compile job. Must be called on the main thread.
572 MUST_USE_RESULT Status FinalizeJob();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573
Ben Murdochf91f0612016-11-29 16:50:11 +0000574 // Report a transient failure, try again next time. Should only be called on
575 // optimization compilation jobs.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576 Status RetryOptimization(BailoutReason reason) {
Ben Murdochf91f0612016-11-29 16:50:11 +0000577 DCHECK(info_->IsOptimizing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578 info_->RetryOptimization(reason);
Ben Murdochf91f0612016-11-29 16:50:11 +0000579 state_ = State::kFailed;
580 return FAILED;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581 }
582
Ben Murdochf91f0612016-11-29 16:50:11 +0000583 // Report a persistent failure, disable future optimization on the function.
584 // Should only be called on optimization compilation jobs.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000585 Status AbortOptimization(BailoutReason reason) {
Ben Murdochf91f0612016-11-29 16:50:11 +0000586 DCHECK(info_->IsOptimizing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587 info_->AbortOptimization(reason);
Ben Murdochf91f0612016-11-29 16:50:11 +0000588 state_ = State::kFailed;
589 return FAILED;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000590 }
591
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100592 void RecordOptimizationStats();
593
Ben Murdochf91f0612016-11-29 16:50:11 +0000594 State state() const { return state_; }
595 CompilationInfo* info() const { return info_; }
596 Isolate* isolate() const { return info()->isolate(); }
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100597
Ben Murdochf91f0612016-11-29 16:50:11 +0000598 protected:
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100599 // Overridden by the actual implementation.
Ben Murdochf91f0612016-11-29 16:50:11 +0000600 virtual Status PrepareJobImpl() = 0;
601 virtual Status ExecuteJobImpl() = 0;
602 virtual Status FinalizeJobImpl() = 0;
603
604 // Registers weak object to optimized code dependencies.
605 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
606 void RegisterWeakObjectsInOptimizedCode(Handle<Code> code);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100607
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000608 private:
609 CompilationInfo* info_;
Ben Murdochf91f0612016-11-29 16:50:11 +0000610 base::TimeDelta time_taken_to_prepare_;
611 base::TimeDelta time_taken_to_execute_;
612 base::TimeDelta time_taken_to_finalize_;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100613 const char* compiler_name_;
Ben Murdochf91f0612016-11-29 16:50:11 +0000614 State state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000615
Ben Murdochf91f0612016-11-29 16:50:11 +0000616 MUST_USE_RESULT Status UpdateState(Status status, State next_state) {
617 if (status == SUCCEEDED) {
618 state_ = next_state;
619 } else {
620 state_ = State::kFailed;
621 }
622 return status;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624};
625
Ben Murdoch014dc512016-03-22 12:00:34 +0000626} // namespace internal
627} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +0000628
629#endif // V8_COMPILER_H_