blob: 26c0ac43c1b33d5ea25c942544cd3cbb882a0b86 [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
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000038class ScriptDataImpl;
39
ager@chromium.org5c838252010-02-19 08:53:10 +000040// CompilationInfo encapsulates some information known at compile time. It
41// is constructed based on the resources available at compile-time.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000042class CompilationInfo BASE_EMBEDDED {
43 public:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000044 CompilationInfo(Handle<Script> script, Zone* zone);
45 CompilationInfo(Handle<SharedFunctionInfo> shared_info, Zone* zone);
46 CompilationInfo(Handle<JSFunction> closure, Zone* zone);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +000047
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000048 Isolate* isolate() {
49 ASSERT(Isolate::Current() == isolate_);
50 return isolate_;
51 }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000052 Zone* zone() {
53 return zone_;
54 }
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000055 bool is_lazy() const { return IsLazy::decode(flags_); }
56 bool is_eval() const { return IsEval::decode(flags_); }
57 bool is_global() const { return IsGlobal::decode(flags_); }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000058 bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
59 bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; }
60 LanguageMode language_mode() const {
61 return LanguageModeField::decode(flags_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000062 }
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000063 bool is_in_loop() const { return IsInLoop::decode(flags_); }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000064 FunctionLiteral* function() const { return function_; }
65 Scope* scope() const { return scope_; }
ricow@chromium.org27bf2882011-11-17 08:34:43 +000066 Scope* global_scope() const { return global_scope_; }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000067 Handle<Code> code() const { return code_; }
68 Handle<JSFunction> closure() const { return closure_; }
69 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
70 Handle<Script> script() const { return script_; }
71 v8::Extension* extension() const { return extension_; }
72 ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
73 Handle<Context> calling_context() const { return calling_context_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000074 int osr_ast_id() const { return osr_ast_id_; }
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +000075
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000076 void MarkAsEval() {
77 ASSERT(!is_lazy());
78 flags_ |= IsEval::encode(true);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000079 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000080 void MarkAsGlobal() {
81 ASSERT(!is_lazy());
82 flags_ |= IsGlobal::encode(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000083 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000084 void SetLanguageMode(LanguageMode language_mode) {
85 ASSERT(this->language_mode() == CLASSIC_MODE ||
86 this->language_mode() == language_mode ||
87 language_mode == EXTENDED_MODE);
88 flags_ = LanguageModeField::update(flags_, language_mode);
ricow@chromium.org83aa5492011-02-07 12:42:56 +000089 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000090 void MarkAsInLoop() {
91 ASSERT(is_lazy());
92 flags_ |= IsInLoop::encode(true);
93 }
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000094 void MarkAsNative() {
95 flags_ |= IsNative::encode(true);
96 }
97 bool is_native() const {
98 return IsNative::decode(flags_);
99 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000100 void SetFunction(FunctionLiteral* literal) {
101 ASSERT(function_ == NULL);
102 function_ = literal;
103 }
104 void SetScope(Scope* scope) {
105 ASSERT(scope_ == NULL);
106 scope_ = scope;
107 }
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000108 void SetGlobalScope(Scope* global_scope) {
109 ASSERT(global_scope_ == NULL);
110 global_scope_ = global_scope;
111 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000112 void SetCode(Handle<Code> code) { code_ = code; }
113 void SetExtension(v8::Extension* extension) {
114 ASSERT(!is_lazy());
115 extension_ = extension;
116 }
117 void SetPreParseData(ScriptDataImpl* pre_parse_data) {
118 ASSERT(!is_lazy());
119 pre_parse_data_ = pre_parse_data;
120 }
121 void SetCallingContext(Handle<Context> context) {
122 ASSERT(is_eval());
123 calling_context_ = context;
124 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000125 void SetOsrAstId(int osr_ast_id) {
126 ASSERT(IsOptimizing());
127 osr_ast_id_ = osr_ast_id;
128 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000129 void MarkCompilingForDebugging(Handle<Code> current_code) {
130 ASSERT(mode_ != OPTIMIZE);
131 ASSERT(current_code->kind() == Code::FUNCTION);
132 flags_ |= IsCompilingForDebugging::encode(true);
133 if (current_code->is_compiled_optimizable()) {
134 EnableDeoptimizationSupport();
135 } else {
136 mode_ = CompilationInfo::NONOPT;
137 }
138 }
139 bool IsCompilingForDebugging() {
140 return IsCompilingForDebugging::decode(flags_);
141 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000142
143 bool has_global_object() const {
144 return !closure().is_null() && (closure()->context()->global() != NULL);
145 }
146
147 GlobalObject* global_object() const {
148 return has_global_object() ? closure()->context()->global() : NULL;
149 }
150
151 // Accessors for the different compilation modes.
152 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
153 bool IsOptimizable() const { return mode_ == BASE; }
154 void SetOptimizing(int osr_ast_id) {
155 SetMode(OPTIMIZE);
156 osr_ast_id_ = osr_ast_id;
157 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000158 void DisableOptimization();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000159
160 // Deoptimization support.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000161 bool HasDeoptimizationSupport() const {
162 return SupportsDeoptimization::decode(flags_);
163 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000164 void EnableDeoptimizationSupport() {
165 ASSERT(IsOptimizable());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000166 flags_ |= SupportsDeoptimization::encode(true);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000167 }
168
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000169 // Determines whether or not to insert a self-optimization header.
170 bool ShouldSelfOptimize();
171
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000172 // Disable all optimization attempts of this info for the rest of the
173 // current compilation pipeline.
174 void AbortOptimization();
175
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000176 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000177 Isolate* isolate_;
178
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000179 // Compilation mode.
180 // BASE is generated by the full codegen, optionally prepared for bailouts.
181 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
yangguo@chromium.org56454712012-02-16 15:33:53 +0000182 // NONOPT is generated by the full codegen and is not prepared for
183 // recompilation/bailouts. These functions are never recompiled.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000184 enum Mode {
185 BASE,
186 OPTIMIZE,
187 NONOPT
188 };
189
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000190 void Initialize(Mode mode) {
191 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000192 ASSERT(!script_.is_null());
193 if (script_->type()->value() == Script::TYPE_NATIVE) {
194 MarkAsNative();
195 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000196 if (!shared_info_.is_null()) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000197 ASSERT(language_mode() == CLASSIC_MODE);
198 SetLanguageMode(shared_info_->language_mode());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000199 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000200 }
201
202 void SetMode(Mode mode) {
203 ASSERT(V8::UseCrankshaft());
204 mode_ = mode;
205 }
206
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000207 // Flags using template class BitField<type, start, length>. All are
208 // false by default.
209 //
210 // Compilation is either eager or lazy.
211 class IsLazy: public BitField<bool, 0, 1> {};
212 // Flags that can be set for eager compilation.
213 class IsEval: public BitField<bool, 1, 1> {};
214 class IsGlobal: public BitField<bool, 2, 1> {};
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000215 // Flags that can be set for lazy compilation.
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000216 class IsInLoop: public BitField<bool, 3, 1> {};
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000217 // Strict mode - used in eager compilation.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000218 class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000219 // Is this a function from our natives.
220 class IsNative: public BitField<bool, 6, 1> {};
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000221 // Is this code being compiled with support for deoptimization..
222 class SupportsDeoptimization: public BitField<bool, 7, 1> {};
223 // If compiling for debugging produce just full code matching the
224 // initial mode setting.
225 class IsCompilingForDebugging: public BitField<bool, 8, 1> {};
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000226
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000227
228 unsigned flags_;
229
230 // Fields filled in by the compilation pipeline.
231 // AST filled in by the parser.
ager@chromium.org5c838252010-02-19 08:53:10 +0000232 FunctionLiteral* function_;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000233 // The scope of the function literal as a convenience. Set to indicate
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000234 // that scopes have been analyzed.
235 Scope* scope_;
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000236 // The global scope provided as a convenience.
237 Scope* global_scope_;
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000238 // The compiled code.
239 Handle<Code> code_;
240
241 // Possible initial inputs to the compilation process.
242 Handle<JSFunction> closure_;
243 Handle<SharedFunctionInfo> shared_info_;
244 Handle<Script> script_;
245
246 // Fields possibly needed for eager compilation, NULL by default.
247 v8::Extension* extension_;
248 ScriptDataImpl* pre_parse_data_;
249
250 // The context of the caller is needed for eval code, and will be a null
251 // handle otherwise.
252 Handle<Context> calling_context_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000253
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000254 // Compilation mode flag and whether deoptimization is allowed.
255 Mode mode_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000256 int osr_ast_id_;
257
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000258 // The zone from which the compilation pipeline working on this
259 // CompilationInfo allocates.
260 Zone* zone_;
261
ager@chromium.org5c838252010-02-19 08:53:10 +0000262 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000263};
264
265
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000266// Exactly like a CompilationInfo, except also creates and enters a
267// Zone on construction and deallocates it on exit.
268class CompilationInfoWithZone: public CompilationInfo {
269 public:
270 explicit CompilationInfoWithZone(Handle<Script> script)
271 : CompilationInfo(script, &zone_),
272 zone_(script->GetIsolate()),
273 zone_scope_(&zone_, DELETE_ON_EXIT) {}
274 explicit CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info)
275 : CompilationInfo(shared_info, &zone_),
276 zone_(shared_info->GetIsolate()),
277 zone_scope_(&zone_, DELETE_ON_EXIT) {}
278 explicit CompilationInfoWithZone(Handle<JSFunction> closure)
279 : CompilationInfo(closure, &zone_),
280 zone_(closure->GetIsolate()),
281 zone_scope_(&zone_, DELETE_ON_EXIT) {}
282
283 private:
284 Zone zone_;
285 ZoneScope zone_scope_;
286};
287
288
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000289// The V8 compiler
290//
291// General strategy: Source code is translated into an anonymous function w/o
292// parameters which then can be executed. If the source code contains other
293// functions, they will be compiled and allocated as part of the compilation
294// of the source code.
295
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000296// Please note this interface returns shared function infos. This means you
297// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
298// real function with a context.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000299
300class Compiler : public AllStatic {
301 public:
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000302 // Default maximum number of function optimization attempts before we
303 // give up.
304 static const int kDefaultMaxOptCount = 10;
305
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000306 static const int kMaxInliningLevels = 3;
307
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000308 // Call count before primitive functions trigger their own optimization.
309 static const int kCallsUntilPrimitiveOpt = 200;
310
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000311 // All routines return a SharedFunctionInfo.
312 // If an error occurs an exception is raised and the return handle
313 // contains NULL.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000314
315 // Compile a String source within a context.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000316 static Handle<SharedFunctionInfo> Compile(Handle<String> source,
317 Handle<Object> script_name,
318 int line_offset,
319 int column_offset,
320 v8::Extension* extension,
321 ScriptDataImpl* pre_data,
322 Handle<Object> script_data,
323 NativesFlag is_natives_code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000324
325 // Compile a String source within a context for Eval.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000326 static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
327 Handle<Context> context,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000328 bool is_global,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000329 LanguageMode language_mode,
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000330 int scope_position);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000331
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000332 // Compile from function info (used for lazy compilation). Returns true on
333 // success and false if the compilation resulted in a stack overflow.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000334 static bool CompileLazy(CompilationInfo* info);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000335
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000336 // Compile a shared function info object (the function is possibly lazily
337 // compiled).
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000338 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000339 Handle<Script> script);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000340
341 // Set the function info for a newly compiled function.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000342 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000343 FunctionLiteral* lit,
344 bool is_toplevel,
345 Handle<Script> script);
ager@chromium.org5c838252010-02-19 08:53:10 +0000346
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000347#ifdef ENABLE_DEBUGGER_SUPPORT
348 static bool MakeCodeForLiveEdit(CompilationInfo* info);
349#endif
350
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000351 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000352 CompilationInfo* info,
353 Handle<SharedFunctionInfo> shared);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000354};
355
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000356
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000357} } // namespace v8::internal
358
359#endif // V8_COMPILER_H_