blob: 8e92cf5a1772057169342ee4be9223174d4c20d7 [file] [log] [blame]
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001// Copyright 2011 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:
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000044 explicit CompilationInfo(Handle<Script> script);
45 explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
46 explicit CompilationInfo(Handle<JSFunction> closure);
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 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000052 bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
53 bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
54 bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000055 bool is_strict_mode() const { return (flags_ & IsStrictMode::mask()) != 0; }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000056 bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
57 FunctionLiteral* function() const { return function_; }
58 Scope* scope() const { return scope_; }
59 Handle<Code> code() const { return code_; }
60 Handle<JSFunction> closure() const { return closure_; }
61 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
62 Handle<Script> script() const { return script_; }
63 v8::Extension* extension() const { return extension_; }
64 ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
65 Handle<Context> calling_context() const { return calling_context_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000066 int osr_ast_id() const { return osr_ast_id_; }
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +000067
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000068 void MarkAsEval() {
69 ASSERT(!is_lazy());
70 flags_ |= IsEval::encode(true);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000071 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000072 void MarkAsGlobal() {
73 ASSERT(!is_lazy());
74 flags_ |= IsGlobal::encode(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000075 }
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000076 void MarkAsStrictMode() {
77 flags_ |= IsStrictMode::encode(true);
ricow@chromium.org83aa5492011-02-07 12:42:56 +000078 }
79 StrictModeFlag StrictMode() {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000080 return is_strict_mode() ? kStrictMode : kNonStrictMode;
ricow@chromium.org83aa5492011-02-07 12:42:56 +000081 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000082 void MarkAsInLoop() {
83 ASSERT(is_lazy());
84 flags_ |= IsInLoop::encode(true);
85 }
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000086 void MarkAsAllowingNativesSyntax() {
87 flags_ |= IsNativesSyntaxAllowed::encode(true);
88 }
89 bool allows_natives_syntax() const {
90 return IsNativesSyntaxAllowed::decode(flags_);
91 }
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000092 void MarkAsNative() {
93 flags_ |= IsNative::encode(true);
94 }
95 bool is_native() const {
96 return IsNative::decode(flags_);
97 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000098 void SetFunction(FunctionLiteral* literal) {
99 ASSERT(function_ == NULL);
100 function_ = literal;
101 }
102 void SetScope(Scope* scope) {
103 ASSERT(scope_ == NULL);
104 scope_ = scope;
105 }
106 void SetCode(Handle<Code> code) { code_ = code; }
107 void SetExtension(v8::Extension* extension) {
108 ASSERT(!is_lazy());
109 extension_ = extension;
110 }
111 void SetPreParseData(ScriptDataImpl* pre_parse_data) {
112 ASSERT(!is_lazy());
113 pre_parse_data_ = pre_parse_data;
114 }
115 void SetCallingContext(Handle<Context> context) {
116 ASSERT(is_eval());
117 calling_context_ = context;
118 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000119 void SetOsrAstId(int osr_ast_id) {
120 ASSERT(IsOptimizing());
121 osr_ast_id_ = osr_ast_id;
122 }
123
124 bool has_global_object() const {
125 return !closure().is_null() && (closure()->context()->global() != NULL);
126 }
127
128 GlobalObject* global_object() const {
129 return has_global_object() ? closure()->context()->global() : NULL;
130 }
131
132 // Accessors for the different compilation modes.
133 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
134 bool IsOptimizable() const { return mode_ == BASE; }
135 void SetOptimizing(int osr_ast_id) {
136 SetMode(OPTIMIZE);
137 osr_ast_id_ = osr_ast_id;
138 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000139 void DisableOptimization();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000140
141 // Deoptimization support.
142 bool HasDeoptimizationSupport() const { return supports_deoptimization_; }
143 void EnableDeoptimizationSupport() {
144 ASSERT(IsOptimizable());
145 supports_deoptimization_ = true;
146 }
147
148 // Determine whether or not we can adaptively optimize.
149 bool AllowOptimize() {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000150 return V8::UseCrankshaft() && !closure_.is_null();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000151 }
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000152
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000153 // Disable all optimization attempts of this info for the rest of the
154 // current compilation pipeline.
155 void AbortOptimization();
156
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000157 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000158 Isolate* isolate_;
159
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000160 // Compilation mode.
161 // BASE is generated by the full codegen, optionally prepared for bailouts.
162 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
163 // NONOPT is generated by the full codegen or the classic backend
164 // and is not prepared for recompilation/bailouts. These functions
165 // are never recompiled.
166 enum Mode {
167 BASE,
168 OPTIMIZE,
169 NONOPT
170 };
171
172 CompilationInfo() : function_(NULL) {}
173
174 void Initialize(Mode mode) {
175 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000176 ASSERT(!script_.is_null());
177 if (script_->type()->value() == Script::TYPE_NATIVE) {
178 MarkAsNative();
179 }
180 if (!shared_info_.is_null() && shared_info_->strict_mode()) {
181 MarkAsStrictMode();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000182 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000183 }
184
185 void SetMode(Mode mode) {
186 ASSERT(V8::UseCrankshaft());
187 mode_ = mode;
188 }
189
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000190 // Flags using template class BitField<type, start, length>. All are
191 // false by default.
192 //
193 // Compilation is either eager or lazy.
194 class IsLazy: public BitField<bool, 0, 1> {};
195 // Flags that can be set for eager compilation.
196 class IsEval: public BitField<bool, 1, 1> {};
197 class IsGlobal: public BitField<bool, 2, 1> {};
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000198 // Flags that can be set for lazy compilation.
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000199 class IsInLoop: public BitField<bool, 3, 1> {};
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000200 // Strict mode - used in eager compilation.
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000201 class IsStrictMode: public BitField<bool, 4, 1> {};
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000202 // Native syntax (%-stuff) allowed?
203 class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {};
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000204 // Is this a function from our natives.
205 class IsNative: public BitField<bool, 6, 1> {};
206
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000207
208 unsigned flags_;
209
210 // Fields filled in by the compilation pipeline.
211 // AST filled in by the parser.
ager@chromium.org5c838252010-02-19 08:53:10 +0000212 FunctionLiteral* function_;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000213 // The scope of the function literal as a convenience. Set to indicate
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000214 // that scopes have been analyzed.
215 Scope* scope_;
216 // The compiled code.
217 Handle<Code> code_;
218
219 // Possible initial inputs to the compilation process.
220 Handle<JSFunction> closure_;
221 Handle<SharedFunctionInfo> shared_info_;
222 Handle<Script> script_;
223
224 // Fields possibly needed for eager compilation, NULL by default.
225 v8::Extension* extension_;
226 ScriptDataImpl* pre_parse_data_;
227
228 // The context of the caller is needed for eval code, and will be a null
229 // handle otherwise.
230 Handle<Context> calling_context_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000231
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000232 // Compilation mode flag and whether deoptimization is allowed.
233 Mode mode_;
234 bool supports_deoptimization_;
235 int osr_ast_id_;
236
ager@chromium.org5c838252010-02-19 08:53:10 +0000237 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000238};
239
240
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000241// The V8 compiler
242//
243// General strategy: Source code is translated into an anonymous function w/o
244// parameters which then can be executed. If the source code contains other
245// functions, they will be compiled and allocated as part of the compilation
246// of the source code.
247
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000248// Please note this interface returns shared function infos. This means you
249// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
250// real function with a context.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251
252class Compiler : public AllStatic {
253 public:
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000254 // Default maximum number of function optimization attempts before we
255 // give up.
256 static const int kDefaultMaxOptCount = 10;
257
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000258 static const int kMaxInliningLevels = 3;
259
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000260 // All routines return a SharedFunctionInfo.
261 // If an error occurs an exception is raised and the return handle
262 // contains NULL.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000263
264 // Compile a String source within a context.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000265 static Handle<SharedFunctionInfo> Compile(Handle<String> source,
266 Handle<Object> script_name,
267 int line_offset,
268 int column_offset,
269 v8::Extension* extension,
270 ScriptDataImpl* pre_data,
271 Handle<Object> script_data,
272 NativesFlag is_natives_code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273
274 // Compile a String source within a context for Eval.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000275 static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
276 Handle<Context> context,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000277 bool is_global,
278 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000280 // Compile from function info (used for lazy compilation). Returns true on
281 // success and false if the compilation resulted in a stack overflow.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000282 static bool CompileLazy(CompilationInfo* info);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000283
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000284 // Compile a shared function info object (the function is possibly lazily
285 // compiled).
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000286 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000287 Handle<Script> script);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000288
289 // Set the function info for a newly compiled function.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000290 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000291 FunctionLiteral* lit,
292 bool is_toplevel,
293 Handle<Script> script);
ager@chromium.org5c838252010-02-19 08:53:10 +0000294
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000295#ifdef ENABLE_DEBUGGER_SUPPORT
296 static bool MakeCodeForLiveEdit(CompilationInfo* info);
297#endif
298
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000299 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000300 CompilationInfo* info,
301 Handle<SharedFunctionInfo> shared);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000302};
303
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000304
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305} } // namespace v8::internal
306
307#endif // V8_COMPILER_H_