blob: 3db32ce0e328295032a7ab2372cb2fba989775cc [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"
9#include "src/ast.h"
10#include "src/bailout-reason.h"
11#include "src/zone.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000012
13namespace v8 {
14namespace internal {
15
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016class AstValueFactory;
17class HydrogenCodeStub;
18
19// ParseRestriction is used to restrict the set of valid statements in a
20// unit of compilation. Restriction violations cause a syntax error.
21enum ParseRestriction {
22 NO_PARSE_RESTRICTION, // All expressions are allowed.
23 ONLY_SINGLE_FUNCTION_LITERAL // Only a single FunctionLiteral expression.
24};
25
26struct OffsetRange {
27 OffsetRange(int from, int to) : from(from), to(to) {}
28 int from;
29 int to;
30};
31
32
33class ScriptData {
34 public:
35 ScriptData(const byte* data, int length);
36 ~ScriptData() {
37 if (owns_data_) DeleteArray(data_);
38 }
39
40 const byte* data() const { return data_; }
41 int length() const { return length_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040042 bool rejected() const { return rejected_; }
43
44 void Reject() { rejected_ = true; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045
46 void AcquireDataOwnership() {
47 DCHECK(!owns_data_);
48 owns_data_ = true;
49 }
50
51 void ReleaseDataOwnership() {
52 DCHECK(owns_data_);
53 owns_data_ = false;
54 }
55
56 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040057 bool owns_data_ : 1;
58 bool rejected_ : 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059 const byte* data_;
60 int length_;
61
62 DISALLOW_COPY_AND_ASSIGN(ScriptData);
63};
Ben Murdochf87a2032010-10-22 12:50:53 +010064
Andrei Popescu31002712010-02-23 13:46:05 +000065// CompilationInfo encapsulates some information known at compile time. It
66// is constructed based on the resources available at compile-time.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067class CompilationInfo {
Leon Clarke4515c472010-02-03 11:58:03 +000068 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 // Various configuration flags for a compilation, as well as some properties
70 // of the compiled code produced by a compilation.
71 enum Flag {
72 kLazy = 1 << 0,
73 kEval = 1 << 1,
74 kGlobal = 1 << 2,
75 kStrictMode = 1 << 3,
76 kThisHasUses = 1 << 4,
77 kNative = 1 << 5,
78 kDeferredCalling = 1 << 6,
79 kNonDeferredCalling = 1 << 7,
80 kSavesCallerDoubles = 1 << 8,
81 kRequiresFrame = 1 << 9,
82 kMustNotHaveEagerFrame = 1 << 10,
83 kDeoptimizationSupport = 1 << 11,
84 kDebug = 1 << 12,
85 kCompilingForDebugging = 1 << 13,
86 kParseRestriction = 1 << 14,
87 kSerializing = 1 << 15,
88 kContextSpecializing = 1 << 16,
89 kInliningEnabled = 1 << 17,
90 kTypingEnabled = 1 << 18,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040091 kDisableFutureOptimization = 1 << 19,
92 kToplevel = 1 << 20
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093 };
Ben Murdochf87a2032010-10-22 12:50:53 +010094
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 CompilationInfo(Handle<JSFunction> closure, Zone* zone);
96 CompilationInfo(Isolate* isolate, Zone* zone);
97 virtual ~CompilationInfo();
98
99 Isolate* isolate() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100100 return isolate_;
101 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102 Zone* zone() { return zone_; }
103 bool is_osr() const { return !osr_ast_id_.IsNone(); }
104 bool is_lazy() const { return GetFlag(kLazy); }
105 bool is_eval() const { return GetFlag(kEval); }
106 bool is_global() const { return GetFlag(kGlobal); }
107 StrictMode strict_mode() const {
108 return GetFlag(kStrictMode) ? STRICT : SLOPPY;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100109 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100110 FunctionLiteral* function() const { return function_; }
111 Scope* scope() const { return scope_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400112 Scope* script_scope() const { return script_scope_; }
Ben Murdochf87a2032010-10-22 12:50:53 +0100113 Handle<Code> code() const { return code_; }
114 Handle<JSFunction> closure() const { return closure_; }
115 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
116 Handle<Script> script() const { return script_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117 void set_script(Handle<Script> script) { script_ = script; }
118 HydrogenCodeStub* code_stub() const {return code_stub_; }
Ben Murdochf87a2032010-10-22 12:50:53 +0100119 v8::Extension* extension() const { return extension_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120 ScriptData** cached_data() const { return cached_data_; }
121 ScriptCompiler::CompileOptions compile_options() const {
122 return compile_options_;
123 }
124 ScriptCompiler::ExternalSourceStream* source_stream() const {
125 return source_stream_;
126 }
127 ScriptCompiler::StreamedSource::Encoding source_stream_encoding() const {
128 return source_stream_encoding_;
129 }
130 Handle<Context> context() const { return context_; }
131 BailoutId osr_ast_id() const { return osr_ast_id_; }
132 Handle<Code> unoptimized_code() const { return unoptimized_code_; }
133 int opt_count() const { return opt_count_; }
134 int num_parameters() const;
135 int num_heap_slots() const;
136 Code::Flags flags() const;
Ben Murdochf87a2032010-10-22 12:50:53 +0100137
138 void MarkAsEval() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139 DCHECK(!is_lazy());
140 SetFlag(kEval);
Leon Clarke4515c472010-02-03 11:58:03 +0000141 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000142
Ben Murdochf87a2032010-10-22 12:50:53 +0100143 void MarkAsGlobal() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 DCHECK(!is_lazy());
145 SetFlag(kGlobal);
Andrei Popescu31002712010-02-23 13:46:05 +0000146 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147
148 void set_parameter_count(int parameter_count) {
149 DCHECK(IsStub());
150 parameter_count_ = parameter_count;
Steve Block1e0659c2011-05-24 12:43:12 +0100151 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152
153 void set_this_has_uses(bool has_no_uses) {
154 SetFlag(kThisHasUses, has_no_uses);
Andrei Popescu31002712010-02-23 13:46:05 +0000155 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156
157 bool this_has_uses() { return GetFlag(kThisHasUses); }
158
159 void SetStrictMode(StrictMode strict_mode) {
160 SetFlag(kStrictMode, strict_mode == STRICT);
Steve Block44f0eee2011-05-26 01:26:41 +0100161 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162
163 void MarkAsNative() { SetFlag(kNative); }
164
165 bool is_native() const { return GetFlag(kNative); }
166
167 bool is_calling() const {
168 return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling);
Steve Block44f0eee2011-05-26 01:26:41 +0100169 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170
171 void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); }
172
173 bool is_deferred_calling() const { return GetFlag(kDeferredCalling); }
174
175 void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); }
176
177 bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); }
178
179 void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); }
180
181 bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); }
182
183 void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); }
184
185 bool requires_frame() const { return GetFlag(kRequiresFrame); }
186
187 void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); }
188
189 bool GetMustNotHaveEagerFrame() const {
190 return GetFlag(kMustNotHaveEagerFrame);
191 }
192
193 void MarkAsDebug() { SetFlag(kDebug); }
194
195 bool is_debug() const { return GetFlag(kDebug); }
196
197 void PrepareForSerializing() { SetFlag(kSerializing); }
198
199 bool will_serialize() const { return GetFlag(kSerializing); }
200
201 void MarkAsContextSpecializing() { SetFlag(kContextSpecializing); }
202
203 bool is_context_specializing() const { return GetFlag(kContextSpecializing); }
204
205 void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }
206
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
208
209 void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); }
210
211 bool is_typing_enabled() const { return GetFlag(kTypingEnabled); }
212
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213 void MarkAsToplevel() { SetFlag(kToplevel); }
214
215 bool is_toplevel() const { return GetFlag(kToplevel); }
216
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 bool IsCodePreAgingActive() const {
218 return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() &&
219 !is_debug();
220 }
221
222 void SetParseRestriction(ParseRestriction restriction) {
223 SetFlag(kParseRestriction, restriction != NO_PARSE_RESTRICTION);
224 }
225
226 ParseRestriction parse_restriction() const {
227 return GetFlag(kParseRestriction) ? ONLY_SINGLE_FUNCTION_LITERAL
228 : NO_PARSE_RESTRICTION;
229 }
230
Ben Murdochf87a2032010-10-22 12:50:53 +0100231 void SetFunction(FunctionLiteral* literal) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 DCHECK(function_ == NULL);
Ben Murdochf87a2032010-10-22 12:50:53 +0100233 function_ = literal;
Andrei Popescu31002712010-02-23 13:46:05 +0000234 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 void PrepareForCompilation(Scope* scope);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400236 void SetScriptScope(Scope* script_scope) {
237 DCHECK(script_scope_ == NULL);
238 script_scope_ = script_scope;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100239 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400240 void EnsureFeedbackVector();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 Handle<TypeFeedbackVector> feedback_vector() const {
242 return feedback_vector_;
243 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100244 void SetCode(Handle<Code> code) { code_ = code; }
245 void SetExtension(v8::Extension* extension) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246 DCHECK(!is_lazy());
Ben Murdochf87a2032010-10-22 12:50:53 +0100247 extension_ = extension;
Andrei Popescu31002712010-02-23 13:46:05 +0000248 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249 void SetCachedData(ScriptData** cached_data,
250 ScriptCompiler::CompileOptions compile_options) {
251 compile_options_ = compile_options;
252 if (compile_options == ScriptCompiler::kNoCompileOptions) {
253 cached_data_ = NULL;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100254 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 DCHECK(!is_lazy());
256 cached_data_ = cached_data;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100257 }
258 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259 void SetContext(Handle<Context> context) {
260 context_ = context;
261 }
262
263 void MarkCompilingForDebugging() { SetFlag(kCompilingForDebugging); }
264 bool IsCompilingForDebugging() { return GetFlag(kCompilingForDebugging); }
265 void MarkNonOptimizable() {
266 SetMode(CompilationInfo::NONOPT);
267 }
268
269 bool ShouldTrapOnDeopt() const {
270 return (FLAG_trap_on_deopt && IsOptimizing()) ||
271 (FLAG_trap_on_stub_deopt && IsStub());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100272 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100273
274 bool has_global_object() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 return !closure().is_null() &&
276 (closure()->context()->global_object() != NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100277 }
278
279 GlobalObject* global_object() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000280 return has_global_object() ? closure()->context()->global_object() : NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100281 }
282
283 // Accessors for the different compilation modes.
284 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
285 bool IsOptimizable() const { return mode_ == BASE; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 bool IsStub() const { return mode_ == STUB; }
287 void SetOptimizing(BailoutId osr_ast_id, Handle<Code> unoptimized) {
288 DCHECK(!shared_info_.is_null());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100289 SetMode(OPTIMIZE);
290 osr_ast_id_ = osr_ast_id;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 unoptimized_code_ = unoptimized;
292 optimization_id_ = isolate()->NextOptimizationId();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100293 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100294
295 // Deoptimization support.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100296 bool HasDeoptimizationSupport() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 return GetFlag(kDeoptimizationSupport);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100298 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100299 void EnableDeoptimizationSupport() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000300 DCHECK(IsOptimizable());
301 SetFlag(kDeoptimizationSupport);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100302 }
303
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100304 // Determines whether or not to insert a self-optimization header.
305 bool ShouldSelfOptimize();
Andrei Popescu31002712010-02-23 13:46:05 +0000306
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 void set_deferred_handles(DeferredHandles* deferred_handles) {
308 DCHECK(deferred_handles_ == NULL);
309 deferred_handles_ = deferred_handles;
310 }
311
312 ZoneList<Handle<HeapObject> >* dependencies(
313 DependentCode::DependencyGroup group) {
314 if (dependencies_[group] == NULL) {
315 dependencies_[group] = new(zone_) ZoneList<Handle<HeapObject> >(2, zone_);
316 }
317 return dependencies_[group];
318 }
319
320 void CommitDependencies(Handle<Code> code);
321
322 void RollbackDependencies();
323
324 void SaveHandles() {
325 SaveHandle(&closure_);
326 SaveHandle(&shared_info_);
327 SaveHandle(&context_);
328 SaveHandle(&script_);
329 SaveHandle(&unoptimized_code_);
330 }
331
332 void AbortOptimization(BailoutReason reason) {
333 if (bailout_reason_ != kNoReason) bailout_reason_ = reason;
334 SetFlag(kDisableFutureOptimization);
335 }
336
337 void RetryOptimization(BailoutReason reason) {
338 if (bailout_reason_ != kNoReason) bailout_reason_ = reason;
339 }
340
341 BailoutReason bailout_reason() const { return bailout_reason_; }
342
343 int prologue_offset() const {
344 DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_);
345 return prologue_offset_;
346 }
347
348 void set_prologue_offset(int prologue_offset) {
349 DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_);
350 prologue_offset_ = prologue_offset;
351 }
352
353 // Adds offset range [from, to) where fp register does not point
354 // to the current frame base. Used in CPU profiler to detect stack
355 // samples where top frame is not set up.
356 inline void AddNoFrameRange(int from, int to) {
357 if (no_frame_ranges_) no_frame_ranges_->Add(OffsetRange(from, to));
358 }
359
360 List<OffsetRange>* ReleaseNoFrameRanges() {
361 List<OffsetRange>* result = no_frame_ranges_;
362 no_frame_ranges_ = NULL;
363 return result;
364 }
365
366 Handle<Foreign> object_wrapper() {
367 if (object_wrapper_.is_null()) {
368 object_wrapper_ =
369 isolate()->factory()->NewForeign(reinterpret_cast<Address>(this));
370 }
371 return object_wrapper_;
372 }
373
374 void AbortDueToDependencyChange() {
375 DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
376 aborted_due_to_dependency_change_ = true;
377 }
378
379 bool HasAbortedDueToDependencyChange() const {
380 DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
381 return aborted_due_to_dependency_change_;
382 }
383
384 bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) {
385 return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure_);
386 }
387
388 int optimization_id() const { return optimization_id_; }
389
390 AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
391 void SetAstValueFactory(AstValueFactory* ast_value_factory,
392 bool owned = true) {
393 ast_value_factory_ = ast_value_factory;
394 ast_value_factory_owned_ = owned;
395 }
396
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397 protected:
398 CompilationInfo(Handle<Script> script,
399 Zone* zone);
400 CompilationInfo(Handle<SharedFunctionInfo> shared_info,
401 Zone* zone);
402 CompilationInfo(HydrogenCodeStub* stub,
403 Isolate* isolate,
404 Zone* zone);
405 CompilationInfo(ScriptCompiler::ExternalSourceStream* source_stream,
406 ScriptCompiler::StreamedSource::Encoding encoding,
407 Isolate* isolate, Zone* zone);
408
Ben Murdoch257744e2011-11-30 15:57:28 +0000409
Leon Clarke4515c472010-02-03 11:58:03 +0000410 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100411 Isolate* isolate_;
412
Ben Murdochb0fe1622011-05-05 13:52:32 +0100413 // Compilation mode.
414 // BASE is generated by the full codegen, optionally prepared for bailouts.
415 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100416 // NONOPT is generated by the full codegen and is not prepared for
417 // recompilation/bailouts. These functions are never recompiled.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100418 enum Mode {
419 BASE,
420 OPTIMIZE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000421 NONOPT,
422 STUB
Ben Murdochb0fe1622011-05-05 13:52:32 +0100423 };
424
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 void Initialize(Isolate* isolate, Mode mode, Zone* zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100426
427 void SetMode(Mode mode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100428 mode_ = mode;
429 }
430
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431 void SetFlag(Flag flag) { flags_ |= flag; }
Andrei Popescu31002712010-02-23 13:46:05 +0000432
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 void SetFlag(Flag flag, bool value) {
434 flags_ = value ? flags_ | flag : flags_ & ~flag;
435 }
436
437 bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000438
Ben Murdochf87a2032010-10-22 12:50:53 +0100439 unsigned flags_;
440
441 // Fields filled in by the compilation pipeline.
442 // AST filled in by the parser.
443 FunctionLiteral* function_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800444 // The scope of the function literal as a convenience. Set to indicate
Ben Murdochf87a2032010-10-22 12:50:53 +0100445 // that scopes have been analyzed.
446 Scope* scope_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400447 // The script scope provided as a convenience.
448 Scope* script_scope_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000449 // For compiled stubs, the stub object
450 HydrogenCodeStub* code_stub_;
Ben Murdochf87a2032010-10-22 12:50:53 +0100451 // The compiled code.
452 Handle<Code> code_;
453
454 // Possible initial inputs to the compilation process.
Andrei Popescu31002712010-02-23 13:46:05 +0000455 Handle<JSFunction> closure_;
Leon Clarke4515c472010-02-03 11:58:03 +0000456 Handle<SharedFunctionInfo> shared_info_;
Andrei Popescu31002712010-02-23 13:46:05 +0000457 Handle<Script> script_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458 ScriptCompiler::ExternalSourceStream* source_stream_; // Not owned.
459 ScriptCompiler::StreamedSource::Encoding source_stream_encoding_;
Andrei Popescu31002712010-02-23 13:46:05 +0000460
Ben Murdochf87a2032010-10-22 12:50:53 +0100461 // Fields possibly needed for eager compilation, NULL by default.
462 v8::Extension* extension_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 ScriptData** cached_data_;
464 ScriptCompiler::CompileOptions compile_options_;
Andrei Popescu31002712010-02-23 13:46:05 +0000465
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400466 // The context of the caller for eval code, and the script context for a
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000467 // global script. Will be a null handle otherwise.
468 Handle<Context> context_;
469
470 // Used by codegen, ultimately kept rooted by the SharedFunctionInfo.
471 Handle<TypeFeedbackVector> feedback_vector_;
Andrei Popescu31002712010-02-23 13:46:05 +0000472
Ben Murdochb0fe1622011-05-05 13:52:32 +0100473 // Compilation mode flag and whether deoptimization is allowed.
474 Mode mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000475 BailoutId osr_ast_id_;
476 // The unoptimized code we patched for OSR may not be the shared code
477 // afterwards, since we may need to compile it again to include deoptimization
478 // data. Keep track which code we patched.
479 Handle<Code> unoptimized_code_;
480
481 // The zone from which the compilation pipeline working on this
482 // CompilationInfo allocates.
483 Zone* zone_;
484
485 DeferredHandles* deferred_handles_;
486
487 ZoneList<Handle<HeapObject> >* dependencies_[DependentCode::kGroupCount];
488
489 template<typename T>
490 void SaveHandle(Handle<T> *object) {
491 if (!object->is_null()) {
492 Handle<T> handle(*(*object));
493 *object = handle;
494 }
495 }
496
497 BailoutReason bailout_reason_;
498
499 int prologue_offset_;
500
501 List<OffsetRange>* no_frame_ranges_;
502
503 // A copy of shared_info()->opt_count() to avoid handle deref
504 // during graph optimization.
505 int opt_count_;
506
507 // Number of parameters used for compilation of stubs that require arguments.
508 int parameter_count_;
509
510 Handle<Foreign> object_wrapper_;
511
512 int optimization_id_;
513
514 AstValueFactory* ast_value_factory_;
515 bool ast_value_factory_owned_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516
517 // This flag is used by the main thread to track whether this compilation
518 // should be abandoned due to dependency change.
519 bool aborted_due_to_dependency_change_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100520
Andrei Popescu31002712010-02-23 13:46:05 +0000521 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000522};
523
524
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000525// Exactly like a CompilationInfo, except also creates and enters a
526// Zone on construction and deallocates it on exit.
527class CompilationInfoWithZone: public CompilationInfo {
528 public:
529 explicit CompilationInfoWithZone(Handle<Script> script)
530 : CompilationInfo(script, &zone_),
531 zone_(script->GetIsolate()) {}
532 explicit CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info)
533 : CompilationInfo(shared_info, &zone_),
534 zone_(shared_info->GetIsolate()) {}
535 explicit CompilationInfoWithZone(Handle<JSFunction> closure)
536 : CompilationInfo(closure, &zone_),
537 zone_(closure->GetIsolate()) {}
538 CompilationInfoWithZone(HydrogenCodeStub* stub, Isolate* isolate)
539 : CompilationInfo(stub, isolate, &zone_),
540 zone_(isolate) {}
541 CompilationInfoWithZone(ScriptCompiler::ExternalSourceStream* stream,
542 ScriptCompiler::StreamedSource::Encoding encoding,
543 Isolate* isolate)
544 : CompilationInfo(stream, encoding, isolate, &zone_), zone_(isolate) {}
545
546 // Virtual destructor because a CompilationInfoWithZone has to exit the
547 // zone scope and get rid of dependent maps even when the destructor is
548 // called when cast as a CompilationInfo.
549 virtual ~CompilationInfoWithZone() {
550 RollbackDependencies();
551 }
552
553 private:
554 Zone zone_;
555};
556
557
558// A wrapper around a CompilationInfo that detaches the Handles from
559// the underlying DeferredHandleScope and stores them in info_ on
560// destruction.
561class CompilationHandleScope BASE_EMBEDDED {
562 public:
563 explicit CompilationHandleScope(CompilationInfo* info)
564 : deferred_(info->isolate()), info_(info) {}
565 ~CompilationHandleScope() {
566 info_->set_deferred_handles(deferred_.Detach());
567 }
568
569 private:
570 DeferredHandleScope deferred_;
571 CompilationInfo* info_;
572};
573
574
575class HGraph;
576class HOptimizedGraphBuilder;
577class LChunk;
578
579// A helper class that calls the three compilation phases in
580// Crankshaft and keeps track of its state. The three phases
581// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
582// fail, bail-out to the full code generator or succeed. Apart from
583// their return value, the status of the phase last run can be checked
584// using last_status().
585class OptimizedCompileJob: public ZoneObject {
586 public:
587 explicit OptimizedCompileJob(CompilationInfo* info)
588 : info_(info),
589 graph_builder_(NULL),
590 graph_(NULL),
591 chunk_(NULL),
592 last_status_(FAILED),
593 awaiting_install_(false) { }
594
595 enum Status {
596 FAILED, BAILED_OUT, SUCCEEDED
597 };
598
599 MUST_USE_RESULT Status CreateGraph();
600 MUST_USE_RESULT Status OptimizeGraph();
601 MUST_USE_RESULT Status GenerateCode();
602
603 Status last_status() const { return last_status_; }
604 CompilationInfo* info() const { return info_; }
605 Isolate* isolate() const { return info()->isolate(); }
606
607 Status RetryOptimization(BailoutReason reason) {
608 info_->RetryOptimization(reason);
609 return SetLastStatus(BAILED_OUT);
610 }
611
612 Status AbortOptimization(BailoutReason reason) {
613 info_->AbortOptimization(reason);
614 return SetLastStatus(BAILED_OUT);
615 }
616
617 void WaitForInstall() {
618 DCHECK(info_->is_osr());
619 awaiting_install_ = true;
620 }
621
622 bool IsWaitingForInstall() { return awaiting_install_; }
623
624 private:
625 CompilationInfo* info_;
626 HOptimizedGraphBuilder* graph_builder_;
627 HGraph* graph_;
628 LChunk* chunk_;
629 base::TimeDelta time_taken_to_create_graph_;
630 base::TimeDelta time_taken_to_optimize_;
631 base::TimeDelta time_taken_to_codegen_;
632 Status last_status_;
633 bool awaiting_install_;
634
635 MUST_USE_RESULT Status SetLastStatus(Status status) {
636 last_status_ = status;
637 return last_status_;
638 }
639 void RecordOptimizationStats();
640
641 struct Timer {
642 Timer(OptimizedCompileJob* job, base::TimeDelta* location)
643 : job_(job), location_(location) {
644 DCHECK(location_ != NULL);
645 timer_.Start();
646 }
647
648 ~Timer() {
649 *location_ += timer_.Elapsed();
650 }
651
652 OptimizedCompileJob* job_;
653 base::ElapsedTimer timer_;
654 base::TimeDelta* location_;
655 };
656};
657
658
Steve Blocka7e24c12009-10-30 11:49:00 +0000659// The V8 compiler
660//
661// General strategy: Source code is translated into an anonymous function w/o
662// parameters which then can be executed. If the source code contains other
663// functions, they will be compiled and allocated as part of the compilation
664// of the source code.
665
Ben Murdochf87a2032010-10-22 12:50:53 +0100666// Please note this interface returns shared function infos. This means you
667// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
668// real function with a context.
Steve Blocka7e24c12009-10-30 11:49:00 +0000669
670class Compiler : public AllStatic {
671 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000672 MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
673 Handle<JSFunction> function);
674 MUST_USE_RESULT static MaybeHandle<Code> GetLazyCode(
675 Handle<JSFunction> function);
676 MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
677 Handle<SharedFunctionInfo> shared);
678 MUST_USE_RESULT static MaybeHandle<Code> GetDebugCode(
679 Handle<JSFunction> function);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100680
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400681 // Parser::Parse, then Compiler::Analyze.
682 static bool ParseAndAnalyze(CompilationInfo* info);
683 // Rewrite, analyze scopes, and renumber.
684 static bool Analyze(CompilationInfo* info);
685 // Adds deoptimization support, requires ParseAndAnalyze.
686 static bool EnsureDeoptimizationSupport(CompilationInfo* info);
687
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000688 static bool EnsureCompiled(Handle<JSFunction> function,
689 ClearExceptionFlag flag);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100690
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000691 static void CompileForLiveEdit(Handle<Script> script);
692
693 // Compile a String source within a context for eval.
694 MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
695 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
696 Handle<Context> context, StrictMode strict_mode,
697 ParseRestriction restriction, int scope_position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000698
699 // Compile a String source within a context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000700 static Handle<SharedFunctionInfo> CompileScript(
701 Handle<String> source, Handle<Object> script_name, int line_offset,
702 int column_offset, bool is_shared_cross_origin, Handle<Context> context,
703 v8::Extension* extension, ScriptData** cached_data,
704 ScriptCompiler::CompileOptions compile_options,
705 NativesFlag is_natives_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000706
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 static Handle<SharedFunctionInfo> CompileStreamedScript(CompilationInfo* info,
708 int source_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000709
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000710 // Create a shared function info object (the code may be lazily compiled).
Steve Block6ded16b2010-05-10 14:33:55 +0100711 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712 Handle<Script> script,
713 CompilationInfo* outer);
Steve Blockd0582a62009-12-15 09:54:21 +0000714
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000715 enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
Andrei Popescu31002712010-02-23 13:46:05 +0000716
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717 // Generate and return optimized code or start a concurrent optimization job.
718 // In the latter case, return the InOptimizationQueue builtin. On failure,
719 // return the empty handle.
720 MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
721 Handle<JSFunction> function,
722 Handle<Code> current_code,
723 ConcurrencyMode mode,
724 BailoutId osr_ast_id = BailoutId::None());
Ben Murdochf87a2032010-10-22 12:50:53 +0100725
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000726 // Generate and return code from previously queued optimization job.
727 // On failure, return the empty handle.
728 static Handle<Code> GetConcurrentlyOptimizedCode(OptimizedCompileJob* job);
729
730 static bool DebuggerWantsEagerCompilation(
731 CompilationInfo* info, bool allow_lazy_without_ctx = false);
Steve Blocka7e24c12009-10-30 11:49:00 +0000732};
733
734
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000735class CompilationPhase BASE_EMBEDDED {
736 public:
737 CompilationPhase(const char* name, CompilationInfo* info);
738 ~CompilationPhase();
739
740 protected:
741 bool ShouldProduceTraceOutput() const;
742
743 const char* name() const { return name_; }
744 CompilationInfo* info() const { return info_; }
745 Isolate* isolate() const { return info()->isolate(); }
746 Zone* zone() { return &zone_; }
747
748 private:
749 const char* name_;
750 CompilationInfo* info_;
751 Zone zone_;
752 unsigned info_zone_start_allocation_size_;
753 base::ElapsedTimer timer_;
754
755 DISALLOW_COPY_AND_ASSIGN(CompilationPhase);
756};
757
Steve Blocka7e24c12009-10-30 11:49:00 +0000758} } // namespace v8::internal
759
760#endif // V8_COMPILER_H_