blob: d166c2a14baef9cf3d3426a622c2f344cb83a30b [file] [log] [blame]
yangguo@chromium.org56454712012-02-16 15:33:53 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_COMPILER_H_
29#define V8_COMPILER_H_
30
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
ager@chromium.org5c838252010-02-19 08:53:10 +000032#include "ast.h"
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +000033#include "zone.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034
kasperl@chromium.org71affb52009-05-26 05:44:31 +000035namespace v8 {
36namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000038static const int kPrologueOffsetNotSet = -1;
39
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000040class ScriptDataImpl;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000041class HydrogenCodeStub;
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000042
svenpanne@chromium.org9faefa42013-03-08 13:13:16 +000043// ParseRestriction is used to restrict the set of valid statements in a
44// unit of compilation. Restriction violations cause a syntax error.
45enum ParseRestriction {
46 NO_PARSE_RESTRICTION, // All expressions are allowed.
47 ONLY_SINGLE_FUNCTION_LITERAL // Only a single FunctionLiteral expression.
48};
49
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000050struct OffsetRange {
51 OffsetRange(int from, int to) : from(from), to(to) {}
52 int from;
53 int to;
54};
55
ager@chromium.org5c838252010-02-19 08:53:10 +000056// CompilationInfo encapsulates some information known at compile time. It
57// is constructed based on the resources available at compile-time.
yangguo@chromium.org304cc332012-07-24 07:59:48 +000058class CompilationInfo {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000059 public:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000060 CompilationInfo(Handle<JSFunction> closure, Zone* zone);
danno@chromium.org41728482013-06-12 22:31:22 +000061 virtual ~CompilationInfo();
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000062
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +000063 Isolate* isolate() const {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000064 return isolate_;
65 }
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000066 Zone* zone() { return zone_; }
67 bool is_osr() const { return !osr_ast_id_.IsNone(); }
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000068 bool is_lazy() const { return IsLazy::decode(flags_); }
69 bool is_eval() const { return IsEval::decode(flags_); }
70 bool is_global() const { return IsGlobal::decode(flags_); }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000071 bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
72 bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; }
73 LanguageMode language_mode() const {
74 return LanguageModeField::decode(flags_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000075 }
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000076 bool is_in_loop() const { return IsInLoop::decode(flags_); }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000077 FunctionLiteral* function() const { return function_; }
78 Scope* scope() const { return scope_; }
ricow@chromium.org27bf2882011-11-17 08:34:43 +000079 Scope* global_scope() const { return global_scope_; }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000080 Handle<Code> code() const { return code_; }
81 Handle<JSFunction> closure() const { return closure_; }
82 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
83 Handle<Script> script() const { return script_; }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +000084 HydrogenCodeStub* code_stub() const {return code_stub_; }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000085 v8::Extension* extension() const { return extension_; }
86 ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000087 Handle<Context> context() const { return context_; }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +000088 BailoutId osr_ast_id() const { return osr_ast_id_; }
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +000089 uint32_t osr_pc_offset() const { return osr_pc_offset_; }
yangguo@chromium.org003650e2013-01-24 16:31:08 +000090 int opt_count() const { return opt_count_; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000091 int num_parameters() const;
92 int num_heap_slots() const;
93 Code::Flags flags() const;
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +000094
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000095 void MarkAsEval() {
96 ASSERT(!is_lazy());
97 flags_ |= IsEval::encode(true);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000098 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000099 void MarkAsGlobal() {
100 ASSERT(!is_lazy());
101 flags_ |= IsGlobal::encode(true);
ager@chromium.org5c838252010-02-19 08:53:10 +0000102 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000103 void SetLanguageMode(LanguageMode language_mode) {
104 ASSERT(this->language_mode() == CLASSIC_MODE ||
105 this->language_mode() == language_mode ||
106 language_mode == EXTENDED_MODE);
107 flags_ = LanguageModeField::update(flags_, language_mode);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000108 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000109 void MarkAsInLoop() {
110 ASSERT(is_lazy());
111 flags_ |= IsInLoop::encode(true);
112 }
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000113 void MarkAsNative() {
114 flags_ |= IsNative::encode(true);
115 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000116
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000117 bool is_native() const {
118 return IsNative::decode(flags_);
119 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000120
121 bool is_calling() const {
122 return is_deferred_calling() || is_non_deferred_calling();
123 }
124
125 void MarkAsDeferredCalling() {
126 flags_ |= IsDeferredCalling::encode(true);
127 }
128
129 bool is_deferred_calling() const {
130 return IsDeferredCalling::decode(flags_);
131 }
132
133 void MarkAsNonDeferredCalling() {
134 flags_ |= IsNonDeferredCalling::encode(true);
135 }
136
137 bool is_non_deferred_calling() const {
138 return IsNonDeferredCalling::decode(flags_);
139 }
140
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000141 void MarkAsSavesCallerDoubles() {
142 flags_ |= SavesCallerDoubles::encode(true);
143 }
144
145 bool saves_caller_doubles() const {
146 return SavesCallerDoubles::decode(flags_);
147 }
148
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000149 void MarkAsRequiresFrame() {
150 flags_ |= RequiresFrame::encode(true);
151 }
152
153 bool requires_frame() const {
154 return RequiresFrame::decode(flags_);
155 }
156
svenpanne@chromium.org9faefa42013-03-08 13:13:16 +0000157 void SetParseRestriction(ParseRestriction restriction) {
158 flags_ = ParseRestricitonField::update(flags_, restriction);
159 }
160
161 ParseRestriction parse_restriction() const {
162 return ParseRestricitonField::decode(flags_);
163 }
164
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000165 void SetFunction(FunctionLiteral* literal) {
166 ASSERT(function_ == NULL);
167 function_ = literal;
168 }
169 void SetScope(Scope* scope) {
170 ASSERT(scope_ == NULL);
171 scope_ = scope;
172 }
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000173 void SetGlobalScope(Scope* global_scope) {
174 ASSERT(global_scope_ == NULL);
175 global_scope_ = global_scope;
176 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000177 void SetCode(Handle<Code> code) { code_ = code; }
178 void SetExtension(v8::Extension* extension) {
179 ASSERT(!is_lazy());
180 extension_ = extension;
181 }
182 void SetPreParseData(ScriptDataImpl* pre_parse_data) {
183 ASSERT(!is_lazy());
184 pre_parse_data_ = pre_parse_data;
185 }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000186 void SetContext(Handle<Context> context) {
187 context_ = context;
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000188 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000189 void MarkCompilingForDebugging(Handle<Code> current_code) {
190 ASSERT(mode_ != OPTIMIZE);
191 ASSERT(current_code->kind() == Code::FUNCTION);
192 flags_ |= IsCompilingForDebugging::encode(true);
193 if (current_code->is_compiled_optimizable()) {
194 EnableDeoptimizationSupport();
195 } else {
196 mode_ = CompilationInfo::NONOPT;
197 }
198 }
199 bool IsCompilingForDebugging() {
200 return IsCompilingForDebugging::decode(flags_);
201 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000202
danno@chromium.org59400602013-08-13 17:09:37 +0000203 bool ShouldTrapOnDeopt() const {
204 return (FLAG_trap_on_deopt && IsOptimizing()) ||
205 (FLAG_trap_on_stub_deopt && IsStub());
206 }
207
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000208 bool has_global_object() const {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000209 return !closure().is_null() &&
210 (closure()->context()->global_object() != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000211 }
212
213 GlobalObject* global_object() const {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000214 return has_global_object() ? closure()->context()->global_object() : NULL;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000215 }
216
217 // Accessors for the different compilation modes.
218 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
219 bool IsOptimizable() const { return mode_ == BASE; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000220 bool IsStub() const { return mode_ == STUB; }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000221 void SetOptimizing(BailoutId osr_ast_id) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000222 SetMode(OPTIMIZE);
223 osr_ast_id_ = osr_ast_id;
224 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000225 void DisableOptimization();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000226
227 // Deoptimization support.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000228 bool HasDeoptimizationSupport() const {
229 return SupportsDeoptimization::decode(flags_);
230 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000231 void EnableDeoptimizationSupport() {
232 ASSERT(IsOptimizable());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000233 flags_ |= SupportsDeoptimization::encode(true);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000234 }
235
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000236 // Determines whether or not to insert a self-optimization header.
237 bool ShouldSelfOptimize();
238
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000239 // Reset code to the unoptimized version when optimization is aborted.
240 void AbortOptimization() {
241 SetCode(handle(shared_info()->code()));
242 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000243
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000244 void set_deferred_handles(DeferredHandles* deferred_handles) {
245 ASSERT(deferred_handles_ == NULL);
246 deferred_handles_ = deferred_handles;
247 }
248
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000249 ZoneList<Handle<HeapObject> >* dependencies(
250 DependentCode::DependencyGroup group) {
251 if (dependencies_[group] == NULL) {
252 dependencies_[group] = new(zone_) ZoneList<Handle<HeapObject> >(2, zone_);
danno@chromium.org41728482013-06-12 22:31:22 +0000253 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000254 return dependencies_[group];
danno@chromium.org41728482013-06-12 22:31:22 +0000255 }
256
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000257 void CommitDependencies(Handle<Code> code);
danno@chromium.org41728482013-06-12 22:31:22 +0000258
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000259 void RollbackDependencies();
danno@chromium.org41728482013-06-12 22:31:22 +0000260
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000261 void SaveHandles() {
262 SaveHandle(&closure_);
263 SaveHandle(&shared_info_);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000264 SaveHandle(&context_);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000265 SaveHandle(&script_);
266 }
267
danno@chromium.org59400602013-08-13 17:09:37 +0000268 BailoutReason bailout_reason() const { return bailout_reason_; }
269 void set_bailout_reason(BailoutReason reason) { bailout_reason_ = reason; }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000270
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000271 int prologue_offset() const {
272 ASSERT_NE(kPrologueOffsetNotSet, prologue_offset_);
273 return prologue_offset_;
274 }
275
276 void set_prologue_offset(int prologue_offset) {
277 ASSERT_EQ(kPrologueOffsetNotSet, prologue_offset_);
278 prologue_offset_ = prologue_offset;
279 }
280
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000281 // Adds offset range [from, to) where fp register does not point
282 // to the current frame base. Used in CPU profiler to detect stack
283 // samples where top frame is not set up.
284 inline void AddNoFrameRange(int from, int to) {
285 if (no_frame_ranges_) no_frame_ranges_->Add(OffsetRange(from, to));
286 }
287
288 List<OffsetRange>* ReleaseNoFrameRanges() {
289 List<OffsetRange>* result = no_frame_ranges_;
290 no_frame_ranges_ = NULL;
291 return result;
292 }
293
danno@chromium.org41728482013-06-12 22:31:22 +0000294 Handle<Foreign> object_wrapper() {
295 if (object_wrapper_.is_null()) {
296 object_wrapper_ =
297 isolate()->factory()->NewForeign(reinterpret_cast<Address>(this));
298 }
299 return object_wrapper_;
300 }
301
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000302 void AbortDueToDependencyChange() {
danno@chromium.org59400602013-08-13 17:09:37 +0000303 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
304 abort_due_to_dependency_ = true;
danno@chromium.org41728482013-06-12 22:31:22 +0000305 }
306
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000307 bool HasAbortedDueToDependencyChange() {
danno@chromium.org59400602013-08-13 17:09:37 +0000308 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
309 return abort_due_to_dependency_;
danno@chromium.org41728482013-06-12 22:31:22 +0000310 }
311
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000312 void set_osr_pc_offset(uint32_t pc_offset) {
313 osr_pc_offset_ = pc_offset;
314 }
315
316 bool HasSameOsrEntry(Handle<JSFunction> function, uint32_t pc_offset) {
317 return osr_pc_offset_ == pc_offset && function.is_identical_to(closure_);
318 }
319
danno@chromium.org41728482013-06-12 22:31:22 +0000320 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000321 CompilationInfo(Handle<Script> script,
322 Zone* zone);
323 CompilationInfo(Handle<SharedFunctionInfo> shared_info,
324 Zone* zone);
325 CompilationInfo(HydrogenCodeStub* stub,
326 Isolate* isolate,
327 Zone* zone);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000328
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000329 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000330 Isolate* isolate_;
331
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000332 // Compilation mode.
333 // BASE is generated by the full codegen, optionally prepared for bailouts.
334 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
yangguo@chromium.org56454712012-02-16 15:33:53 +0000335 // NONOPT is generated by the full codegen and is not prepared for
336 // recompilation/bailouts. These functions are never recompiled.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000337 enum Mode {
338 BASE,
339 OPTIMIZE,
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000340 NONOPT,
danno@chromium.org59400602013-08-13 17:09:37 +0000341 STUB
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000342 };
343
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000344 void Initialize(Isolate* isolate, Mode mode, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000345
346 void SetMode(Mode mode) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000347 ASSERT(isolate()->use_crankshaft());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000348 mode_ = mode;
349 }
350
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000351 // Flags using template class BitField<type, start, length>. All are
352 // false by default.
353 //
354 // Compilation is either eager or lazy.
355 class IsLazy: public BitField<bool, 0, 1> {};
356 // Flags that can be set for eager compilation.
357 class IsEval: public BitField<bool, 1, 1> {};
358 class IsGlobal: public BitField<bool, 2, 1> {};
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000359 // Flags that can be set for lazy compilation.
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000360 class IsInLoop: public BitField<bool, 3, 1> {};
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000361 // Strict mode - used in eager compilation.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000362 class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000363 // Is this a function from our natives.
364 class IsNative: public BitField<bool, 6, 1> {};
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000365 // Is this code being compiled with support for deoptimization..
366 class SupportsDeoptimization: public BitField<bool, 7, 1> {};
367 // If compiling for debugging produce just full code matching the
368 // initial mode setting.
369 class IsCompilingForDebugging: public BitField<bool, 8, 1> {};
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000370 // If the compiled code contains calls that require building a frame
371 class IsCalling: public BitField<bool, 9, 1> {};
372 // If the compiled code contains calls that require building a frame
373 class IsDeferredCalling: public BitField<bool, 10, 1> {};
374 // If the compiled code contains calls that require building a frame
375 class IsNonDeferredCalling: public BitField<bool, 11, 1> {};
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000376 // If the compiled code saves double caller registers that it clobbers.
377 class SavesCallerDoubles: public BitField<bool, 12, 1> {};
svenpanne@chromium.org9faefa42013-03-08 13:13:16 +0000378 // If the set of valid statements is restricted.
379 class ParseRestricitonField: public BitField<ParseRestriction, 13, 1> {};
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000380 // If the function requires a frame (for unspecified reasons)
381 class RequiresFrame: public BitField<bool, 14, 1> {};
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000382
383 unsigned flags_;
384
385 // Fields filled in by the compilation pipeline.
386 // AST filled in by the parser.
ager@chromium.org5c838252010-02-19 08:53:10 +0000387 FunctionLiteral* function_;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000388 // The scope of the function literal as a convenience. Set to indicate
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000389 // that scopes have been analyzed.
390 Scope* scope_;
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000391 // The global scope provided as a convenience.
392 Scope* global_scope_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000393 // For compiled stubs, the stub object
394 HydrogenCodeStub* code_stub_;
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000395 // The compiled code.
396 Handle<Code> code_;
397
398 // Possible initial inputs to the compilation process.
399 Handle<JSFunction> closure_;
400 Handle<SharedFunctionInfo> shared_info_;
401 Handle<Script> script_;
402
403 // Fields possibly needed for eager compilation, NULL by default.
404 v8::Extension* extension_;
405 ScriptDataImpl* pre_parse_data_;
406
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000407 // The context of the caller for eval code, and the global context for a
408 // global script. Will be a null handle otherwise.
409 Handle<Context> context_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000410
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000411 // Compilation mode flag and whether deoptimization is allowed.
412 Mode mode_;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000413 BailoutId osr_ast_id_;
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000414 // The pc_offset corresponding to osr_ast_id_ in unoptimized code.
415 // We can look this up in the back edge table, but cache it for quick access.
416 uint32_t osr_pc_offset_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000417
danno@chromium.org59400602013-08-13 17:09:37 +0000418 // Flag whether compilation needs to be aborted due to dependency change.
419 bool abort_due_to_dependency_;
420
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000421 // The zone from which the compilation pipeline working on this
422 // CompilationInfo allocates.
423 Zone* zone_;
424
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000425 DeferredHandles* deferred_handles_;
426
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000427 ZoneList<Handle<HeapObject> >* dependencies_[DependentCode::kGroupCount];
danno@chromium.org41728482013-06-12 22:31:22 +0000428
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000429 template<typename T>
430 void SaveHandle(Handle<T> *object) {
431 if (!object->is_null()) {
432 Handle<T> handle(*(*object));
433 *object = handle;
434 }
435 }
436
danno@chromium.org59400602013-08-13 17:09:37 +0000437 BailoutReason bailout_reason_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000438
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000439 int prologue_offset_;
440
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000441 List<OffsetRange>* no_frame_ranges_;
442
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000443 // A copy of shared_info()->opt_count() to avoid handle deref
444 // during graph optimization.
445 int opt_count_;
446
danno@chromium.org41728482013-06-12 22:31:22 +0000447 Handle<Foreign> object_wrapper_;
448
ager@chromium.org5c838252010-02-19 08:53:10 +0000449 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000450};
451
452
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000453// Exactly like a CompilationInfo, except also creates and enters a
454// Zone on construction and deallocates it on exit.
455class CompilationInfoWithZone: public CompilationInfo {
456 public:
457 explicit CompilationInfoWithZone(Handle<Script> script)
458 : CompilationInfo(script, &zone_),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000459 zone_(script->GetIsolate()) {}
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000460 explicit CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info)
461 : CompilationInfo(shared_info, &zone_),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000462 zone_(shared_info->GetIsolate()) {}
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000463 explicit CompilationInfoWithZone(Handle<JSFunction> closure)
464 : CompilationInfo(closure, &zone_),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000465 zone_(closure->GetIsolate()) {}
danno@chromium.org41728482013-06-12 22:31:22 +0000466 CompilationInfoWithZone(HydrogenCodeStub* stub, Isolate* isolate)
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000467 : CompilationInfo(stub, isolate, &zone_),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000468 zone_(isolate) {}
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000469
danno@chromium.org41728482013-06-12 22:31:22 +0000470 // Virtual destructor because a CompilationInfoWithZone has to exit the
471 // zone scope and get rid of dependent maps even when the destructor is
472 // called when cast as a CompilationInfo.
473 virtual ~CompilationInfoWithZone() {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000474 RollbackDependencies();
danno@chromium.org41728482013-06-12 22:31:22 +0000475 }
476
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000477 private:
478 Zone zone_;
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000479};
480
481
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000482// A wrapper around a CompilationInfo that detaches the Handles from
483// the underlying DeferredHandleScope and stores them in info_ on
484// destruction.
485class CompilationHandleScope BASE_EMBEDDED {
486 public:
487 explicit CompilationHandleScope(CompilationInfo* info)
488 : deferred_(info->isolate()), info_(info) {}
489 ~CompilationHandleScope() {
490 info_->set_deferred_handles(deferred_.Detach());
491 }
492
493 private:
494 DeferredHandleScope deferred_;
495 CompilationInfo* info_;
496};
497
498
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000499class HGraph;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000500class HOptimizedGraphBuilder;
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000501class LChunk;
502
503// A helper class that calls the three compilation phases in
504// Crankshaft and keeps track of its state. The three phases
505// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
506// fail, bail-out to the full code generator or succeed. Apart from
507// their return value, the status of the phase last run can be checked
508// using last_status().
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +0000509class RecompileJob: public ZoneObject {
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000510 public:
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +0000511 explicit RecompileJob(CompilationInfo* info)
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000512 : info_(info),
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000513 graph_builder_(NULL),
514 graph_(NULL),
515 chunk_(NULL),
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000516 last_status_(FAILED),
517 awaiting_install_(false) { }
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000518
519 enum Status {
520 FAILED, BAILED_OUT, SUCCEEDED
521 };
522
523 MUST_USE_RESULT Status CreateGraph();
524 MUST_USE_RESULT Status OptimizeGraph();
525 MUST_USE_RESULT Status GenerateAndInstallCode();
526
527 Status last_status() const { return last_status_; }
528 CompilationInfo* info() const { return info_; }
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000529 Isolate* isolate() const { return info()->isolate(); }
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000530
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000531 MUST_USE_RESULT Status AbortOptimization() {
532 info_->AbortOptimization();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000533 info_->shared_info()->DisableOptimization(info_->bailout_reason());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000534 return SetLastStatus(BAILED_OUT);
535 }
536
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +0000537 void WaitForInstall() {
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000538 ASSERT(info_->is_osr());
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +0000539 awaiting_install_ = true;
540 }
541
542 bool IsWaitingForInstall() { return awaiting_install_; }
543
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000544 private:
545 CompilationInfo* info_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000546 HOptimizedGraphBuilder* graph_builder_;
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000547 HGraph* graph_;
548 LChunk* chunk_;
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000549 TimeDelta time_taken_to_create_graph_;
550 TimeDelta time_taken_to_optimize_;
551 TimeDelta time_taken_to_codegen_;
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000552 Status last_status_;
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +0000553 bool awaiting_install_;
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000554
555 MUST_USE_RESULT Status SetLastStatus(Status status) {
556 last_status_ = status;
557 return last_status_;
558 }
559 void RecordOptimizationStats();
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000560
561 struct Timer {
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +0000562 Timer(RecompileJob* job, TimeDelta* location)
563 : job_(job), location_(location) {
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000564 ASSERT(location_ != NULL);
565 timer_.Start();
566 }
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000567
568 ~Timer() {
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000569 *location_ += timer_.Elapsed();
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000570 }
571
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +0000572 RecompileJob* job_;
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000573 ElapsedTimer timer_;
574 TimeDelta* location_;
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000575 };
576};
577
578
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000579// The V8 compiler
580//
581// General strategy: Source code is translated into an anonymous function w/o
582// parameters which then can be executed. If the source code contains other
583// functions, they will be compiled and allocated as part of the compilation
584// of the source code.
585
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000586// Please note this interface returns shared function infos. This means you
587// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
588// real function with a context.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000589
590class Compiler : public AllStatic {
591 public:
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000592 // Call count before primitive functions trigger their own optimization.
593 static const int kCallsUntilPrimitiveOpt = 200;
594
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000595 // All routines return a SharedFunctionInfo.
596 // If an error occurs an exception is raised and the return handle
597 // contains NULL.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000598
599 // Compile a String source within a context.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000600 static Handle<SharedFunctionInfo> Compile(Handle<String> source,
601 Handle<Object> script_name,
602 int line_offset,
603 int column_offset,
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000604 bool is_shared_cross_origin,
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000605 Handle<Context> context,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000606 v8::Extension* extension,
607 ScriptDataImpl* pre_data,
608 Handle<Object> script_data,
609 NativesFlag is_natives_code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000610
611 // Compile a String source within a context for Eval.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000612 static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
613 Handle<Context> context,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000614 bool is_global,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000615 LanguageMode language_mode,
svenpanne@chromium.org9faefa42013-03-08 13:13:16 +0000616 ParseRestriction restriction,
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000617 int scope_position);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000619 // Compile from function info (used for lazy compilation). Returns true on
620 // success and false if the compilation resulted in a stack overflow.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000621 static bool CompileLazy(CompilationInfo* info);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000622
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000623 static bool RecompileConcurrent(Handle<JSFunction> function,
624 uint32_t osr_pc_offset = 0);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000625
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000626 // Compile a shared function info object (the function is possibly lazily
627 // compiled).
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000628 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000629 Handle<Script> script);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000630
631 // Set the function info for a newly compiled function.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000632 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000633 FunctionLiteral* lit,
634 bool is_toplevel,
635 Handle<Script> script);
ager@chromium.org5c838252010-02-19 08:53:10 +0000636
machenbach@chromium.org8e36b5b2013-09-26 07:36:30 +0000637 static Handle<Code> InstallOptimizedCode(RecompileJob* job);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000638
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000639#ifdef ENABLE_DEBUGGER_SUPPORT
640 static bool MakeCodeForLiveEdit(CompilationInfo* info);
641#endif
642
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000643 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000644 CompilationInfo* info,
645 Handle<SharedFunctionInfo> shared);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000646};
647
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000648
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000649class CompilationPhase BASE_EMBEDDED {
650 public:
651 CompilationPhase(const char* name, CompilationInfo* info);
652 ~CompilationPhase();
653
654 protected:
655 bool ShouldProduceTraceOutput() const;
656
657 const char* name() const { return name_; }
658 CompilationInfo* info() const { return info_; }
659 Isolate* isolate() const { return info()->isolate(); }
660 Zone* zone() { return &zone_; }
661
662 private:
663 const char* name_;
664 CompilationInfo* info_;
665 Zone zone_;
666 unsigned info_zone_start_allocation_size_;
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000667 ElapsedTimer timer_;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000668
669 DISALLOW_COPY_AND_ASSIGN(CompilationPhase);
670};
671
672
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000673} } // namespace v8::internal
674
675#endif // V8_COMPILER_H_