blob: fa043995b40cb7426db690aa6c0379374f661568 [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 Murdoch4a90d5f2016-03-22 12:00:34 +000020class JavaScriptFrame;
Ben Murdochda12d292016-06-02 14:46:10 +010021class OptimizedCompileJob;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022class 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);
47 static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
48 static bool CompileDebugCode(Handle<JSFunction> function);
49 static bool CompileDebugCode(Handle<SharedFunctionInfo> shared);
50 static void CompileForLiveEdit(Handle<Script> script);
51
52 // Generate and install code from previously queued optimization job.
53 static void FinalizeOptimizedCompileJob(OptimizedCompileJob* job);
54
55 // Give the compiler a chance to perform low-latency initialization tasks of
56 // the given {function} on its instantiation. Note that only the runtime will
57 // offer this chance, optimized closure instantiation will not call this.
58 static void PostInstantiation(Handle<JSFunction> function, PretenureFlag);
59
60 // Parser::Parse, then Compiler::Analyze.
61 static bool ParseAndAnalyze(ParseInfo* info);
62 // Rewrite, analyze scopes, and renumber.
63 static bool Analyze(ParseInfo* info);
64 // Adds deoptimization support, requires ParseAndAnalyze.
65 static bool EnsureDeoptimizationSupport(CompilationInfo* info);
66
67 // ===========================================================================
68 // The following family of methods instantiates new functions for scripts or
69 // function literals. The decision whether those functions will be compiled,
70 // is left to the discretion of the compiler.
71 //
72 // Please note this interface returns shared function infos. This means you
73 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
74 // real function with a context.
75
76 // Create a (bound) function for a String source within a context for eval.
77 MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
78 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
79 Handle<Context> context, LanguageMode language_mode,
80 ParseRestriction restriction, int line_offset, int column_offset = 0,
81 Handle<Object> script_name = Handle<Object>(),
82 ScriptOriginOptions options = ScriptOriginOptions());
83
84 // Create a shared function info object for a String source within a context.
85 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
86 Handle<String> source, Handle<Object> script_name, int line_offset,
87 int column_offset, ScriptOriginOptions resource_options,
88 Handle<Object> source_map_url, Handle<Context> context,
89 v8::Extension* extension, ScriptData** cached_data,
90 ScriptCompiler::CompileOptions compile_options,
91 NativesFlag is_natives_code, bool is_module);
92
93 // Create a shared function info object for a Script that has already been
94 // parsed while the script was being loaded from a streamed source.
95 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForStreamedScript(
96 Handle<Script> script, ParseInfo* info, int source_length);
97
98 // Create a shared function info object (the code may be lazily compiled).
99 static Handle<SharedFunctionInfo> GetSharedFunctionInfo(
100 FunctionLiteral* node, Handle<Script> script, CompilationInfo* outer);
101
102 // Create a shared function info object for a native function literal.
103 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
104 v8::Extension* extension, Handle<String> name);
105
106 // ===========================================================================
107 // The following family of methods provides support for OSR. Code generated
108 // for entry via OSR might not be suitable for normal entry, hence will be
109 // returned directly to the caller.
110 //
111 // Please note this interface is the only part dealing with {Code} objects
112 // directly. Other methods are agnostic to {Code} and can use an interpreter
113 // instead of generating JIT code for a function at all.
114
115 // Generate and return optimized code for OSR, or empty handle on failure.
116 MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCodeForOSR(
117 Handle<JSFunction> function, BailoutId osr_ast_id,
118 JavaScriptFrame* osr_frame);
119};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121struct InlinedFunctionInfo {
122 InlinedFunctionInfo(int parent_id, SourcePosition inline_position,
123 int script_id, int start_position)
124 : parent_id(parent_id),
125 inline_position(inline_position),
126 script_id(script_id),
127 start_position(start_position) {}
128 int parent_id;
129 SourcePosition inline_position;
130 int script_id;
131 int start_position;
132 std::vector<size_t> deopt_pc_offsets;
133
134 static const int kNoParentId = -1;
135};
136
137
Andrei Popescu31002712010-02-23 13:46:05 +0000138// CompilationInfo encapsulates some information known at compile time. It
139// is constructed based on the resources available at compile-time.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140class CompilationInfo {
Leon Clarke4515c472010-02-03 11:58:03 +0000141 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000142 // Various configuration flags for a compilation, as well as some properties
143 // of the compiled code produced by a compilation.
144 enum Flag {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 kDeferredCalling = 1 << 0,
146 kNonDeferredCalling = 1 << 1,
147 kSavesCallerDoubles = 1 << 2,
148 kRequiresFrame = 1 << 3,
149 kMustNotHaveEagerFrame = 1 << 4,
150 kDeoptimizationSupport = 1 << 5,
151 kDebug = 1 << 6,
152 kSerializing = 1 << 7,
153 kFunctionContextSpecializing = 1 << 8,
154 kFrameSpecializing = 1 << 9,
155 kNativeContextSpecializing = 1 << 10,
156 kInliningEnabled = 1 << 11,
157 kTypingEnabled = 1 << 12,
158 kDisableFutureOptimization = 1 << 13,
159 kSplittingEnabled = 1 << 14,
160 kDeoptimizationEnabled = 1 << 16,
161 kSourcePositionsEnabled = 1 << 17,
162 kFirstCompile = 1 << 18,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100163 kBailoutOnUninitialized = 1 << 19,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 };
Ben Murdochf87a2032010-10-22 12:50:53 +0100165
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166 explicit CompilationInfo(ParseInfo* parse_info);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100167 CompilationInfo(const char* debug_name, Isolate* isolate, Zone* zone,
168 Code::Flags code_flags = Code::ComputeFlags(Code::STUB));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 virtual ~CompilationInfo();
170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 ParseInfo* parse_info() const { return parse_info_; }
172
173 // -----------------------------------------------------------
174 // TODO(titzer): inline and delete accessors of ParseInfo
175 // -----------------------------------------------------------
176 Handle<Script> script() const;
177 bool is_eval() const;
178 bool is_native() const;
179 bool is_module() const;
180 LanguageMode language_mode() const;
181 Handle<JSFunction> closure() const;
182 FunctionLiteral* literal() const;
183 Scope* scope() const;
184 Handle<Context> context() const;
185 Handle<SharedFunctionInfo> shared_info() const;
186 bool has_shared_info() const;
187 bool has_context() const;
188 bool has_literal() const;
189 bool has_scope() const;
190 // -----------------------------------------------------------
191
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 Isolate* isolate() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100193 return isolate_;
194 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195 Zone* zone() { return zone_; }
196 bool is_osr() const { return !osr_ast_id_.IsNone(); }
Ben Murdochf87a2032010-10-22 12:50:53 +0100197 Handle<Code> code() const { return code_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100198 Code::Flags code_flags() const { return code_flags_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 BailoutId osr_ast_id() const { return osr_ast_id_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 int opt_count() const { return opt_count_; }
201 int num_parameters() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 int num_parameters_including_this() const;
203 bool is_this_defined() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 int num_heap_slots() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205
206 void set_parameter_count(int parameter_count) {
207 DCHECK(IsStub());
208 parameter_count_ = parameter_count;
Steve Block1e0659c2011-05-24 12:43:12 +0100209 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
212 Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213
Ben Murdochda12d292016-06-02 14:46:10 +0100214 Handle<AbstractCode> abstract_code() const {
215 return has_bytecode_array() ? Handle<AbstractCode>::cast(bytecode_array())
216 : Handle<AbstractCode>::cast(code());
217 }
218
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219 bool is_tracking_positions() const { return track_positions_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220
221 bool is_calling() const {
222 return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling);
Steve Block44f0eee2011-05-26 01:26:41 +0100223 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224
225 void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); }
226
227 bool is_deferred_calling() const { return GetFlag(kDeferredCalling); }
228
229 void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); }
230
231 bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); }
232
233 void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); }
234
235 bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); }
236
237 void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); }
238
239 bool requires_frame() const { return GetFlag(kRequiresFrame); }
240
241 void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); }
242
243 bool GetMustNotHaveEagerFrame() const {
244 return GetFlag(kMustNotHaveEagerFrame);
245 }
246
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247 // Compiles marked as debug produce unoptimized code with debug break slots.
248 // Inner functions that cannot be compiled w/o context are compiled eagerly.
249 // Always include deoptimization support to avoid having to recompile again.
250 void MarkAsDebug() {
251 SetFlag(kDebug);
252 SetFlag(kDeoptimizationSupport);
253 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254
255 bool is_debug() const { return GetFlag(kDebug); }
256
257 void PrepareForSerializing() { SetFlag(kSerializing); }
258
259 bool will_serialize() const { return GetFlag(kSerializing); }
260
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000261 void MarkAsFunctionContextSpecializing() {
262 SetFlag(kFunctionContextSpecializing);
263 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 bool is_function_context_specializing() const {
266 return GetFlag(kFunctionContextSpecializing);
267 }
268
269 void MarkAsFrameSpecializing() { SetFlag(kFrameSpecializing); }
270
271 bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
272
273 void MarkAsNativeContextSpecializing() {
274 SetFlag(kNativeContextSpecializing);
275 }
276
277 bool is_native_context_specializing() const {
278 return GetFlag(kNativeContextSpecializing);
279 }
280
281 void MarkAsDeoptimizationEnabled() { SetFlag(kDeoptimizationEnabled); }
282
283 bool is_deoptimization_enabled() const {
284 return GetFlag(kDeoptimizationEnabled);
285 }
286
287 void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); }
288
289 bool is_source_positions_enabled() const {
290 return GetFlag(kSourcePositionsEnabled);
291 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000292
293 void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }
294
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
296
297 void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); }
298
299 bool is_typing_enabled() const { return GetFlag(kTypingEnabled); }
300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400302
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303 bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400304
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305 void MarkAsFirstCompile() { SetFlag(kFirstCompile); }
306
307 void MarkAsCompiled() { SetFlag(kFirstCompile, false); }
308
309 bool is_first_compile() const { return GetFlag(kFirstCompile); }
310
Ben Murdoch097c5b22016-05-18 11:27:45 +0100311 void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); }
312
313 bool is_bailout_on_uninitialized() const {
314 return GetFlag(kBailoutOnUninitialized);
315 }
316
Ben Murdoch4a90d5f2016-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 Murdochda12d292016-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 Murdoch4a90d5f2016-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 Murdoch4a90d5f2016-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 Murdoch4a90d5f2016-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 Murdoch097c5b22016-05-18 11:27:45 +0100353 void SetOptimizing() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354 DCHECK(has_shared_info());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100355 SetMode(OPTIMIZE);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100356 optimization_id_ = isolate()->NextOptimizationId();
357 code_flags_ =
358 Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION);
359 }
Ben Murdochda12d292016-06-02 14:46:10 +0100360 void SetOptimizingForOsr(BailoutId osr_ast_id) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100361 SetOptimizing();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100362 osr_ast_id_ = osr_ast_id;
363 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100364
365 // Deoptimization support.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100366 bool HasDeoptimizationSupport() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000367 return GetFlag(kDeoptimizationSupport);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100368 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100369 void EnableDeoptimizationSupport() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000370 DCHECK_EQ(BASE, mode_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 SetFlag(kDeoptimizationSupport);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100372 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 bool ShouldEnsureSpaceForLazyDeopt() { return !IsStub(); }
374
375 bool ExpectsJSReceiverAsReceiver();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100376
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100377 // Determines whether or not to insert a self-optimization header.
378 bool ShouldSelfOptimize();
Andrei Popescu31002712010-02-23 13:46:05 +0000379
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000380 void set_deferred_handles(DeferredHandles* deferred_handles) {
381 DCHECK(deferred_handles_ == NULL);
382 deferred_handles_ = deferred_handles;
383 }
384
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 void ReopenHandlesInNewHandleScope() {
Ben Murdochda12d292016-06-02 14:46:10 +0100386 // Empty for now but will be needed once fields move from ParseInfo.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387 }
388
389 void AbortOptimization(BailoutReason reason) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000390 DCHECK(reason != kNoReason);
391 if (bailout_reason_ == kNoReason) bailout_reason_ = reason;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000392 SetFlag(kDisableFutureOptimization);
393 }
394
395 void RetryOptimization(BailoutReason reason) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396 DCHECK(reason != kNoReason);
397 if (GetFlag(kDisableFutureOptimization)) return;
398 bailout_reason_ = reason;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399 }
400
401 BailoutReason bailout_reason() const { return bailout_reason_; }
402
403 int prologue_offset() const {
404 DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_);
405 return prologue_offset_;
406 }
407
408 void set_prologue_offset(int prologue_offset) {
409 DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_);
410 prologue_offset_ = prologue_offset;
411 }
412
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000413 int start_position_for(uint32_t inlining_id) {
414 return inlined_function_infos_.at(inlining_id).start_position;
415 }
416 const std::vector<InlinedFunctionInfo>& inlined_function_infos() {
417 return inlined_function_infos_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418 }
419
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420 void LogDeoptCallPosition(int pc_offset, int inlining_id);
421 int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
422 SourcePosition position, int pareint_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000423
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424 CompilationDependencies* dependencies() { return &dependencies_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425
426 bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000427 return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000428 }
429
430 int optimization_id() const { return optimization_id_; }
431
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432 int osr_expr_stack_height() { return osr_expr_stack_height_; }
433 void set_osr_expr_stack_height(int height) {
434 DCHECK(height >= 0);
435 osr_expr_stack_height_ = height;
436 }
437 JavaScriptFrame* osr_frame() const { return osr_frame_; }
438 void set_osr_frame(JavaScriptFrame* osr_frame) { osr_frame_ = osr_frame; }
439
440#if DEBUG
441 void PrintAstForTesting();
442#endif
443
444 bool has_simple_parameters();
445
446 struct InlinedFunctionHolder {
447 Handle<SharedFunctionInfo> shared_info;
448
449 // Root that holds the unoptimized code of the inlined function alive
450 // (and out of reach of code flushing) until we finish compilation.
451 // Do not remove.
452 Handle<Code> inlined_code_object_root;
453
454 explicit InlinedFunctionHolder(
455 Handle<SharedFunctionInfo> inlined_shared_info)
456 : shared_info(inlined_shared_info),
457 inlined_code_object_root(inlined_shared_info->code()) {}
458 };
459
460 typedef std::vector<InlinedFunctionHolder> InlinedFunctionList;
461 InlinedFunctionList const& inlined_functions() const {
462 return inlined_functions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 }
464
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000465 void AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function) {
466 inlined_functions_.push_back(InlinedFunctionHolder(inlined_function));
467 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000468
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 base::SmartArrayPointer<char> GetDebugName() const;
470
Ben Murdoch097c5b22016-05-18 11:27:45 +0100471 Code::Kind output_code_kind() const {
472 return Code::ExtractKindFromFlags(code_flags_);
473 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000474
Ben Murdochda12d292016-06-02 14:46:10 +0100475 StackFrame::Type GetOutputStackFrameType() const;
476
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 protected:
478 ParseInfo* parse_info_;
479
480 void DisableFutureOptimization() {
481 if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100482 // If Crankshaft tried to optimize this function, bailed out, and
483 // doesn't want to try again, then use TurboFan next time.
484 if (!shared_info()->dont_crankshaft() &&
485 bailout_reason() != kOptimizedTooManyTimes) {
486 shared_info()->set_dont_crankshaft(true);
487 if (FLAG_trace_opt) {
488 PrintF("[disabled Crankshaft for ");
489 shared_info()->ShortPrint();
490 PrintF(", reason: %s]\n", GetBailoutReason(bailout_reason()));
491 }
492 } else {
493 shared_info()->DisableOptimization(bailout_reason());
494 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495 }
496 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000497
Leon Clarke4515c472010-02-03 11:58:03 +0000498 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100499 // Compilation mode.
500 // BASE is generated by the full codegen, optionally prepared for bailouts.
501 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100502 enum Mode {
503 BASE,
504 OPTIMIZE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 STUB
Ben Murdochb0fe1622011-05-05 13:52:32 +0100506 };
507
Ben Murdoch097c5b22016-05-18 11:27:45 +0100508 CompilationInfo(ParseInfo* parse_info, const char* debug_name,
509 Code::Flags code_flags, Mode mode, Isolate* isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510 Zone* zone);
511
512 Isolate* isolate_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100513
514 void SetMode(Mode mode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100515 mode_ = mode;
516 }
517
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518 void SetFlag(Flag flag) { flags_ |= flag; }
Andrei Popescu31002712010-02-23 13:46:05 +0000519
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 void SetFlag(Flag flag, bool value) {
521 flags_ = value ? flags_ | flag : flags_ & ~flag;
522 }
523
524 bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000525
Ben Murdochf87a2032010-10-22 12:50:53 +0100526 unsigned flags_;
527
Ben Murdoch097c5b22016-05-18 11:27:45 +0100528 Code::Flags code_flags_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529
Ben Murdochf87a2032010-10-22 12:50:53 +0100530 // The compiled code.
531 Handle<Code> code_;
532
Ben Murdochb0fe1622011-05-05 13:52:32 +0100533 // Compilation mode flag and whether deoptimization is allowed.
534 Mode mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 BailoutId osr_ast_id_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000536
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537 // Holds the bytecode array generated by the interpreter.
538 // TODO(rmcilroy/mstarzinger): Temporary work-around until compiler.cc is
539 // refactored to avoid us needing to carry the BytcodeArray around.
540 Handle<BytecodeArray> bytecode_array_;
541
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000542 // The zone from which the compilation pipeline working on this
543 // CompilationInfo allocates.
544 Zone* zone_;
545
546 DeferredHandles* deferred_handles_;
547
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000548 // Dependencies for this compilation, e.g. stable maps.
549 CompilationDependencies dependencies_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000550
551 BailoutReason bailout_reason_;
552
553 int prologue_offset_;
554
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 std::vector<InlinedFunctionInfo> inlined_function_infos_;
556 bool track_positions_;
557
558 InlinedFunctionList inlined_functions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559
560 // A copy of shared_info()->opt_count() to avoid handle deref
561 // during graph optimization.
562 int opt_count_;
563
564 // Number of parameters used for compilation of stubs that require arguments.
565 int parameter_count_;
566
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567 int optimization_id_;
568
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 int osr_expr_stack_height_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571 // The current OSR frame for specialization or {nullptr}.
572 JavaScriptFrame* osr_frame_ = nullptr;
573
574 const char* debug_name_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100575
Andrei Popescu31002712010-02-23 13:46:05 +0000576 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000577};
578
579
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580class HGraph;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581class LChunk;
582
583// A helper class that calls the three compilation phases in
584// Crankshaft and keeps track of its state. The three phases
585// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
586// fail, bail-out to the full code generator or succeed. Apart from
587// their return value, the status of the phase last run can be checked
588// using last_status().
589class OptimizedCompileJob: public ZoneObject {
590 public:
591 explicit OptimizedCompileJob(CompilationInfo* info)
Ben Murdochda12d292016-06-02 14:46:10 +0100592 : info_(info), graph_(NULL), chunk_(NULL), last_status_(FAILED) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000593
594 enum Status {
595 FAILED, BAILED_OUT, SUCCEEDED
596 };
597
598 MUST_USE_RESULT Status CreateGraph();
599 MUST_USE_RESULT Status OptimizeGraph();
600 MUST_USE_RESULT Status GenerateCode();
601
602 Status last_status() const { return last_status_; }
603 CompilationInfo* info() const { return info_; }
604 Isolate* isolate() const { return info()->isolate(); }
605
606 Status RetryOptimization(BailoutReason reason) {
607 info_->RetryOptimization(reason);
608 return SetLastStatus(BAILED_OUT);
609 }
610
611 Status AbortOptimization(BailoutReason reason) {
612 info_->AbortOptimization(reason);
613 return SetLastStatus(BAILED_OUT);
614 }
615
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616 private:
617 CompilationInfo* info_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000618 HGraph* graph_;
619 LChunk* chunk_;
620 base::TimeDelta time_taken_to_create_graph_;
621 base::TimeDelta time_taken_to_optimize_;
622 base::TimeDelta time_taken_to_codegen_;
623 Status last_status_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624
625 MUST_USE_RESULT Status SetLastStatus(Status status) {
626 last_status_ = status;
627 return last_status_;
628 }
629 void RecordOptimizationStats();
630
631 struct Timer {
632 Timer(OptimizedCompileJob* job, base::TimeDelta* location)
633 : job_(job), location_(location) {
634 DCHECK(location_ != NULL);
635 timer_.Start();
636 }
637
638 ~Timer() {
639 *location_ += timer_.Elapsed();
640 }
641
642 OptimizedCompileJob* job_;
643 base::ElapsedTimer timer_;
644 base::TimeDelta* location_;
645 };
646};
647
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648} // namespace internal
649} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +0000650
651#endif // V8_COMPILER_H_