blob: e0ebd453781f4a7102c007aec79edde0ac7efa6b [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"
Ben Murdoch097c5b22016-05-18 11:27:45 +010012#include "src/source-position.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/zone.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000014
15namespace v8 {
16namespace internal {
17
Ben Murdoch097c5b22016-05-18 11:27:45 +010018// Forward declarations.
Ben Murdochda12d292016-06-02 14:46:10 +010019class CompilationInfo;
Ben Murdochc5610432016-08-08 18:44:38 +010020class CompilationJob;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021class JavaScriptFrame;
22class ParseInfo;
23class ScriptData;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024
Ben Murdochda12d292016-06-02 14:46:10 +010025// The V8 compiler API.
26//
27// This is the central hub for dispatching to the various compilers within V8.
28// Logic for which compiler to choose and how to wire compilation results into
29// the object heap should be kept inside this class.
30//
31// General strategy: Scripts are translated into anonymous functions w/o
32// parameters which then can be executed. If the source code contains other
33// functions, they might be compiled and allocated as part of the compilation
34// of the source code or deferred for lazy compilation at a later point.
35class Compiler : public AllStatic {
36 public:
37 enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
38 enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
39
40 // ===========================================================================
41 // The following family of methods ensures a given function is compiled. The
42 // general contract is that failures will be reported by returning {false},
43 // whereas successful compilation ensures the {is_compiled} predicate on the
44 // given function holds (except for live-edit, which compiles the world).
45
46 static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
Ben Murdochc5610432016-08-08 18:44:38 +010047 static bool CompileBaseline(Handle<JSFunction> function);
Ben Murdochda12d292016-06-02 14:46:10 +010048 static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
49 static bool CompileDebugCode(Handle<JSFunction> function);
50 static bool CompileDebugCode(Handle<SharedFunctionInfo> shared);
Ben Murdochc5610432016-08-08 18:44:38 +010051 static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script);
Ben Murdochda12d292016-06-02 14:46:10 +010052
Ben Murdochc5610432016-08-08 18:44:38 +010053 // Generate and install code from previously queued compilation job.
54 static void FinalizeCompilationJob(CompilationJob* job);
Ben Murdochda12d292016-06-02 14:46:10 +010055
56 // Give the compiler a chance to perform low-latency initialization tasks of
57 // the given {function} on its instantiation. Note that only the runtime will
58 // offer this chance, optimized closure instantiation will not call this.
59 static void PostInstantiation(Handle<JSFunction> function, PretenureFlag);
60
61 // Parser::Parse, then Compiler::Analyze.
62 static bool ParseAndAnalyze(ParseInfo* info);
63 // Rewrite, analyze scopes, and renumber.
64 static bool Analyze(ParseInfo* info);
65 // Adds deoptimization support, requires ParseAndAnalyze.
66 static bool EnsureDeoptimizationSupport(CompilationInfo* info);
67
68 // ===========================================================================
69 // The following family of methods instantiates new functions for scripts or
70 // function literals. The decision whether those functions will be compiled,
71 // is left to the discretion of the compiler.
72 //
73 // Please note this interface returns shared function infos. This means you
74 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
75 // real function with a context.
76
77 // Create a (bound) function for a String source within a context for eval.
78 MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
79 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
80 Handle<Context> context, LanguageMode language_mode,
Ben Murdochc5610432016-08-08 18:44:38 +010081 ParseRestriction restriction, int eval_scope_position, int eval_position,
82 int line_offset = 0, int column_offset = 0,
Ben Murdochda12d292016-06-02 14:46:10 +010083 Handle<Object> script_name = Handle<Object>(),
84 ScriptOriginOptions options = ScriptOriginOptions());
85
86 // Create a shared function info object for a String source within a context.
87 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
88 Handle<String> source, Handle<Object> script_name, int line_offset,
89 int column_offset, ScriptOriginOptions resource_options,
90 Handle<Object> source_map_url, Handle<Context> context,
91 v8::Extension* extension, ScriptData** cached_data,
92 ScriptCompiler::CompileOptions compile_options,
93 NativesFlag is_natives_code, bool is_module);
94
95 // Create a shared function info object for a Script that has already been
96 // parsed while the script was being loaded from a streamed source.
97 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForStreamedScript(
98 Handle<Script> script, ParseInfo* info, int source_length);
99
100 // Create a shared function info object (the code may be lazily compiled).
101 static Handle<SharedFunctionInfo> GetSharedFunctionInfo(
102 FunctionLiteral* node, Handle<Script> script, CompilationInfo* outer);
103
104 // Create a shared function info object for a native function literal.
105 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
106 v8::Extension* extension, Handle<String> name);
107
108 // ===========================================================================
109 // The following family of methods provides support for OSR. Code generated
110 // for entry via OSR might not be suitable for normal entry, hence will be
111 // returned directly to the caller.
112 //
113 // Please note this interface is the only part dealing with {Code} objects
114 // directly. Other methods are agnostic to {Code} and can use an interpreter
115 // instead of generating JIT code for a function at all.
116
117 // Generate and return optimized code for OSR, or empty handle on failure.
118 MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCodeForOSR(
119 Handle<JSFunction> function, BailoutId osr_ast_id,
120 JavaScriptFrame* osr_frame);
121};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123
Andrei Popescu31002712010-02-23 13:46:05 +0000124// CompilationInfo encapsulates some information known at compile time. It
125// is constructed based on the resources available at compile-time.
Ben Murdochc5610432016-08-08 18:44:38 +0100126class CompilationInfo final {
Leon Clarke4515c472010-02-03 11:58:03 +0000127 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 // Various configuration flags for a compilation, as well as some properties
129 // of the compiled code produced by a compilation.
130 enum Flag {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 kDeferredCalling = 1 << 0,
132 kNonDeferredCalling = 1 << 1,
133 kSavesCallerDoubles = 1 << 2,
134 kRequiresFrame = 1 << 3,
135 kMustNotHaveEagerFrame = 1 << 4,
136 kDeoptimizationSupport = 1 << 5,
137 kDebug = 1 << 6,
138 kSerializing = 1 << 7,
139 kFunctionContextSpecializing = 1 << 8,
140 kFrameSpecializing = 1 << 9,
141 kNativeContextSpecializing = 1 << 10,
142 kInliningEnabled = 1 << 11,
Ben Murdochc5610432016-08-08 18:44:38 +0100143 kDisableFutureOptimization = 1 << 12,
144 kSplittingEnabled = 1 << 13,
145 kDeoptimizationEnabled = 1 << 14,
146 kSourcePositionsEnabled = 1 << 15,
147 kBailoutOnUninitialized = 1 << 16,
148 kOptimizeFromBytecode = 1 << 17,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100149 kTypeFeedbackEnabled = 1 << 18,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 };
Ben Murdochf87a2032010-10-22 12:50:53 +0100151
Ben Murdochc5610432016-08-08 18:44:38 +0100152 CompilationInfo(ParseInfo* parse_info, Handle<JSFunction> closure);
153 CompilationInfo(Vector<const char> debug_name, Isolate* isolate, Zone* zone,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100154 Code::Flags code_flags = Code::ComputeFlags(Code::STUB));
Ben Murdochc5610432016-08-08 18:44:38 +0100155 ~CompilationInfo();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 ParseInfo* parse_info() const { return parse_info_; }
158
159 // -----------------------------------------------------------
160 // TODO(titzer): inline and delete accessors of ParseInfo
161 // -----------------------------------------------------------
162 Handle<Script> script() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000163 FunctionLiteral* literal() const;
164 Scope* scope() const;
165 Handle<Context> context() const;
166 Handle<SharedFunctionInfo> shared_info() const;
167 bool has_shared_info() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 // -----------------------------------------------------------
169
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170 Isolate* isolate() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100171 return isolate_;
172 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 Zone* zone() { return zone_; }
174 bool is_osr() const { return !osr_ast_id_.IsNone(); }
Ben Murdochc5610432016-08-08 18:44:38 +0100175 Handle<JSFunction> closure() const { return closure_; }
Ben Murdochf87a2032010-10-22 12:50:53 +0100176 Handle<Code> code() const { return code_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100177 Code::Flags code_flags() const { return code_flags_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000178 BailoutId osr_ast_id() const { return osr_ast_id_; }
Ben Murdochc5610432016-08-08 18:44:38 +0100179 JavaScriptFrame* osr_frame() const { return osr_frame_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 int num_parameters() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 int num_parameters_including_this() const;
182 bool is_this_defined() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183
184 void set_parameter_count(int parameter_count) {
185 DCHECK(IsStub());
186 parameter_count_ = parameter_count;
Steve Block1e0659c2011-05-24 12:43:12 +0100187 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
190 Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 bool is_tracking_positions() const { return track_positions_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193
194 bool is_calling() const {
195 return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling);
Steve Block44f0eee2011-05-26 01:26:41 +0100196 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197
198 void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); }
199
200 bool is_deferred_calling() const { return GetFlag(kDeferredCalling); }
201
202 void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); }
203
204 bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); }
205
206 void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); }
207
208 bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); }
209
210 void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); }
211
212 bool requires_frame() const { return GetFlag(kRequiresFrame); }
213
214 void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); }
215
216 bool GetMustNotHaveEagerFrame() const {
217 return GetFlag(kMustNotHaveEagerFrame);
218 }
219
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 // Compiles marked as debug produce unoptimized code with debug break slots.
221 // Inner functions that cannot be compiled w/o context are compiled eagerly.
222 // Always include deoptimization support to avoid having to recompile again.
223 void MarkAsDebug() {
224 SetFlag(kDebug);
225 SetFlag(kDeoptimizationSupport);
226 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227
228 bool is_debug() const { return GetFlag(kDebug); }
229
230 void PrepareForSerializing() { SetFlag(kSerializing); }
231
232 bool will_serialize() const { return GetFlag(kSerializing); }
233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 void MarkAsFunctionContextSpecializing() {
235 SetFlag(kFunctionContextSpecializing);
236 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 bool is_function_context_specializing() const {
239 return GetFlag(kFunctionContextSpecializing);
240 }
241
242 void MarkAsFrameSpecializing() { SetFlag(kFrameSpecializing); }
243
244 bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
245
246 void MarkAsNativeContextSpecializing() {
247 SetFlag(kNativeContextSpecializing);
248 }
249
250 bool is_native_context_specializing() const {
251 return GetFlag(kNativeContextSpecializing);
252 }
253
254 void MarkAsDeoptimizationEnabled() { SetFlag(kDeoptimizationEnabled); }
255
256 bool is_deoptimization_enabled() const {
257 return GetFlag(kDeoptimizationEnabled);
258 }
259
Ben Murdoch61f157c2016-09-16 13:49:30 +0100260 void MarkAsTypeFeedbackEnabled() { SetFlag(kTypeFeedbackEnabled); }
261
262 bool is_type_feedback_enabled() const {
263 return GetFlag(kTypeFeedbackEnabled);
264 }
265
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); }
267
268 bool is_source_positions_enabled() const {
269 return GetFlag(kSourcePositionsEnabled);
270 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271
272 void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }
273
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
275
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400277
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400279
Ben Murdoch097c5b22016-05-18 11:27:45 +0100280 void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); }
281
282 bool is_bailout_on_uninitialized() const {
283 return GetFlag(kBailoutOnUninitialized);
284 }
285
Ben Murdochc5610432016-08-08 18:44:38 +0100286 void MarkAsOptimizeFromBytecode() { SetFlag(kOptimizeFromBytecode); }
287
288 bool is_optimizing_from_bytecode() const {
289 return GetFlag(kOptimizeFromBytecode);
290 }
291
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292 bool GeneratePreagedPrologue() const {
293 // Generate a pre-aged prologue if we are optimizing for size, which
294 // will make code flushing more aggressive. Only apply to Code::FUNCTION,
295 // since StaticMarkingVisitor::IsFlushable only flushes proper functions.
Ben Murdochda12d292016-06-02 14:46:10 +0100296 return FLAG_optimize_for_size && FLAG_age_code && !is_debug() &&
297 output_code_kind() == Code::FUNCTION;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 }
299
Ben Murdochf87a2032010-10-22 12:50:53 +0100300 void SetCode(Handle<Code> code) { code_ = code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302 void SetBytecodeArray(Handle<BytecodeArray> bytecode_array) {
303 bytecode_array_ = bytecode_array;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304 }
305
306 bool ShouldTrapOnDeopt() const {
307 return (FLAG_trap_on_deopt && IsOptimizing()) ||
308 (FLAG_trap_on_stub_deopt && IsStub());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100309 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 bool has_native_context() const {
312 return !closure().is_null() && (closure()->native_context() != nullptr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100313 }
314
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315 Context* native_context() const {
316 return has_native_context() ? closure()->native_context() : nullptr;
317 }
318
319 bool has_global_object() const { return has_native_context(); }
320
321 JSGlobalObject* global_object() const {
322 return has_global_object() ? native_context()->global_object() : nullptr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100323 }
324
325 // Accessors for the different compilation modes.
326 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327 bool IsStub() const { return mode_ == STUB; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100328 void SetOptimizing() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 DCHECK(has_shared_info());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100330 SetMode(OPTIMIZE);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100331 optimization_id_ = isolate()->NextOptimizationId();
332 code_flags_ =
333 Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION);
334 }
Ben Murdochc5610432016-08-08 18:44:38 +0100335 void SetOptimizingForOsr(BailoutId osr_ast_id, JavaScriptFrame* osr_frame) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100336 SetOptimizing();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100337 osr_ast_id_ = osr_ast_id;
Ben Murdochc5610432016-08-08 18:44:38 +0100338 osr_frame_ = osr_frame;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100339 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100340
341 // Deoptimization support.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100342 bool HasDeoptimizationSupport() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000343 return GetFlag(kDeoptimizationSupport);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100344 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100345 void EnableDeoptimizationSupport() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346 DCHECK_EQ(BASE, mode_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347 SetFlag(kDeoptimizationSupport);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100348 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349 bool ShouldEnsureSpaceForLazyDeopt() { return !IsStub(); }
350
351 bool ExpectsJSReceiverAsReceiver();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100352
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100353 // Determines whether or not to insert a self-optimization header.
354 bool ShouldSelfOptimize();
Andrei Popescu31002712010-02-23 13:46:05 +0000355
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356 void set_deferred_handles(DeferredHandles* deferred_handles) {
357 DCHECK(deferred_handles_ == NULL);
358 deferred_handles_ = deferred_handles;
359 }
360
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361 void ReopenHandlesInNewHandleScope() {
Ben Murdochc5610432016-08-08 18:44:38 +0100362 closure_ = Handle<JSFunction>(*closure_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 }
364
365 void AbortOptimization(BailoutReason reason) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 DCHECK(reason != kNoReason);
367 if (bailout_reason_ == kNoReason) bailout_reason_ = reason;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368 SetFlag(kDisableFutureOptimization);
369 }
370
371 void RetryOptimization(BailoutReason reason) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372 DCHECK(reason != kNoReason);
373 if (GetFlag(kDisableFutureOptimization)) return;
374 bailout_reason_ = reason;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000375 }
376
377 BailoutReason bailout_reason() const { return bailout_reason_; }
378
379 int prologue_offset() const {
380 DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_);
381 return prologue_offset_;
382 }
383
384 void set_prologue_offset(int prologue_offset) {
385 DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_);
386 prologue_offset_ = prologue_offset;
387 }
388
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389 CompilationDependencies* dependencies() { return &dependencies_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000390
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000391 int optimization_id() const { return optimization_id_; }
392
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000393 int osr_expr_stack_height() { return osr_expr_stack_height_; }
394 void set_osr_expr_stack_height(int height) {
395 DCHECK(height >= 0);
396 osr_expr_stack_height_ = height;
397 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000398
399#if DEBUG
400 void PrintAstForTesting();
401#endif
402
403 bool has_simple_parameters();
404
405 struct InlinedFunctionHolder {
406 Handle<SharedFunctionInfo> shared_info;
407
408 // Root that holds the unoptimized code of the inlined function alive
409 // (and out of reach of code flushing) until we finish compilation.
410 // Do not remove.
411 Handle<Code> inlined_code_object_root;
412
413 explicit InlinedFunctionHolder(
414 Handle<SharedFunctionInfo> inlined_shared_info)
415 : shared_info(inlined_shared_info),
416 inlined_code_object_root(inlined_shared_info->code()) {}
417 };
418
419 typedef std::vector<InlinedFunctionHolder> InlinedFunctionList;
420 InlinedFunctionList const& inlined_functions() const {
421 return inlined_functions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 }
423
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424 void AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function) {
425 inlined_functions_.push_back(InlinedFunctionHolder(inlined_function));
426 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000428 base::SmartArrayPointer<char> GetDebugName() const;
429
Ben Murdoch097c5b22016-05-18 11:27:45 +0100430 Code::Kind output_code_kind() const {
431 return Code::ExtractKindFromFlags(code_flags_);
432 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000433
Ben Murdochda12d292016-06-02 14:46:10 +0100434 StackFrame::Type GetOutputStackFrameType() const;
435
Ben Murdochc5610432016-08-08 18:44:38 +0100436 int GetDeclareGlobalsFlags() const;
437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438 protected:
439 ParseInfo* parse_info_;
440
441 void DisableFutureOptimization() {
442 if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100443 // If Crankshaft tried to optimize this function, bailed out, and
444 // doesn't want to try again, then use TurboFan next time.
445 if (!shared_info()->dont_crankshaft() &&
446 bailout_reason() != kOptimizedTooManyTimes) {
447 shared_info()->set_dont_crankshaft(true);
448 if (FLAG_trace_opt) {
449 PrintF("[disabled Crankshaft for ");
450 shared_info()->ShortPrint();
451 PrintF(", reason: %s]\n", GetBailoutReason(bailout_reason()));
452 }
453 } else {
454 shared_info()->DisableOptimization(bailout_reason());
455 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000456 }
457 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000458
Leon Clarke4515c472010-02-03 11:58:03 +0000459 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100460 // Compilation mode.
461 // BASE is generated by the full codegen, optionally prepared for bailouts.
462 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100463 enum Mode {
464 BASE,
465 OPTIMIZE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000466 STUB
Ben Murdochb0fe1622011-05-05 13:52:32 +0100467 };
468
Ben Murdochc5610432016-08-08 18:44:38 +0100469 CompilationInfo(ParseInfo* parse_info, Vector<const char> debug_name,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100470 Code::Flags code_flags, Mode mode, Isolate* isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471 Zone* zone);
472
473 Isolate* isolate_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100474
475 void SetMode(Mode mode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100476 mode_ = mode;
477 }
478
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000479 void SetFlag(Flag flag) { flags_ |= flag; }
Andrei Popescu31002712010-02-23 13:46:05 +0000480
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481 void SetFlag(Flag flag, bool value) {
482 flags_ = value ? flags_ | flag : flags_ & ~flag;
483 }
484
485 bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000486
Ben Murdochf87a2032010-10-22 12:50:53 +0100487 unsigned flags_;
488
Ben Murdoch097c5b22016-05-18 11:27:45 +0100489 Code::Flags code_flags_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490
Ben Murdochc5610432016-08-08 18:44:38 +0100491 Handle<JSFunction> closure_;
492
Ben Murdochf87a2032010-10-22 12:50:53 +0100493 // The compiled code.
494 Handle<Code> code_;
495
Ben Murdochb0fe1622011-05-05 13:52:32 +0100496 // Compilation mode flag and whether deoptimization is allowed.
497 Mode mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498 BailoutId osr_ast_id_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 // Holds the bytecode array generated by the interpreter.
501 // TODO(rmcilroy/mstarzinger): Temporary work-around until compiler.cc is
502 // refactored to avoid us needing to carry the BytcodeArray around.
503 Handle<BytecodeArray> bytecode_array_;
504
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 // The zone from which the compilation pipeline working on this
506 // CompilationInfo allocates.
507 Zone* zone_;
508
509 DeferredHandles* deferred_handles_;
510
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511 // Dependencies for this compilation, e.g. stable maps.
512 CompilationDependencies dependencies_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000513
514 BailoutReason bailout_reason_;
515
516 int prologue_offset_;
517
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518 bool track_positions_;
519
520 InlinedFunctionList inlined_functions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000521
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522 // Number of parameters used for compilation of stubs that require arguments.
523 int parameter_count_;
524
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000525 int optimization_id_;
526
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 int osr_expr_stack_height_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000528
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 // The current OSR frame for specialization or {nullptr}.
530 JavaScriptFrame* osr_frame_ = nullptr;
531
Ben Murdochc5610432016-08-08 18:44:38 +0100532 Vector<const char> debug_name_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100533
Andrei Popescu31002712010-02-23 13:46:05 +0000534 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000535};
536
Ben Murdochc5610432016-08-08 18:44:38 +0100537// A base class for compilation jobs intended to run concurrent to the main
538// thread. The job is split into three phases which are called in sequence on
539// different threads and with different limitations:
540// 1) CreateGraph: Runs on main thread. No major limitations.
541// 2) OptimizeGraph: Runs concurrently. No heap allocation or handle derefs.
542// 3) GenerateCode: Runs on main thread. No dependency changes.
543//
544// Each of the three phases can either fail or succeed. Apart from their return
545// value, the status of the phase last run can be checked using {last_status()}
546// as well. When failing we distinguish between the following levels:
547// a) AbortOptimization: Persistent failure, disable future optimization.
548// b) RetryOptimzation: Transient failure, try again next time.
549class CompilationJob {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000550 public:
Ben Murdochc5610432016-08-08 18:44:38 +0100551 explicit CompilationJob(CompilationInfo* info, const char* compiler_name)
552 : info_(info), compiler_name_(compiler_name), last_status_(SUCCEEDED) {}
553 virtual ~CompilationJob() {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000554
Ben Murdochc5610432016-08-08 18:44:38 +0100555 enum Status { FAILED, SUCCEEDED };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556
557 MUST_USE_RESULT Status CreateGraph();
558 MUST_USE_RESULT Status OptimizeGraph();
559 MUST_USE_RESULT Status GenerateCode();
560
561 Status last_status() const { return last_status_; }
562 CompilationInfo* info() const { return info_; }
563 Isolate* isolate() const { return info()->isolate(); }
564
565 Status RetryOptimization(BailoutReason reason) {
566 info_->RetryOptimization(reason);
Ben Murdochc5610432016-08-08 18:44:38 +0100567 return SetLastStatus(FAILED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568 }
569
570 Status AbortOptimization(BailoutReason reason) {
571 info_->AbortOptimization(reason);
Ben Murdochc5610432016-08-08 18:44:38 +0100572 return SetLastStatus(FAILED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 }
574
Ben Murdochc5610432016-08-08 18:44:38 +0100575 void RecordOptimizationStats();
576
577 protected:
578 void RegisterWeakObjectsInOptimizedCode(Handle<Code> code);
579
580 // Overridden by the actual implementation.
581 virtual Status CreateGraphImpl() = 0;
582 virtual Status OptimizeGraphImpl() = 0;
583 virtual Status GenerateCodeImpl() = 0;
584
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000585 private:
586 CompilationInfo* info_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587 base::TimeDelta time_taken_to_create_graph_;
588 base::TimeDelta time_taken_to_optimize_;
589 base::TimeDelta time_taken_to_codegen_;
Ben Murdochc5610432016-08-08 18:44:38 +0100590 const char* compiler_name_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000591 Status last_status_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592
593 MUST_USE_RESULT Status SetLastStatus(Status status) {
594 last_status_ = status;
595 return last_status_;
596 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000597};
598
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000599} // namespace internal
600} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +0000601
602#endif // V8_COMPILER_H_