blob: 44df9e090f1e17b4ac7ef59eb1356c8b2e0cde32 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +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
Ben Murdoch257744e2011-11-30 15:57:28 +000031#include "allocation.h"
Andrei Popescu402d9372010-02-26 13:31:12 +000032#include "ast.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033#include "zone.h"
34
35namespace v8 {
36namespace internal {
37
Ben Murdochf87a2032010-10-22 12:50:53 +010038class ScriptDataImpl;
39
Andrei Popescu31002712010-02-23 13:46:05 +000040// CompilationInfo encapsulates some information known at compile time. It
41// is constructed based on the resources available at compile-time.
Leon Clarke4515c472010-02-03 11:58:03 +000042class CompilationInfo BASE_EMBEDDED {
43 public:
Ben Murdochf87a2032010-10-22 12:50:53 +010044 explicit CompilationInfo(Handle<Script> script);
45 explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
46 explicit CompilationInfo(Handle<JSFunction> closure);
47
Steve Block44f0eee2011-05-26 01:26:41 +010048 Isolate* isolate() {
49 ASSERT(Isolate::Current() == isolate_);
50 return isolate_;
51 }
Ben Murdoch589d6972011-11-30 16:04:58 +000052 bool is_lazy() const { return IsLazy::decode(flags_); }
53 bool is_eval() const { return IsEval::decode(flags_); }
54 bool is_global() const { return IsGlobal::decode(flags_); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010055 bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
56 bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; }
57 LanguageMode language_mode() const {
58 return LanguageModeField::decode(flags_);
59 }
Ben Murdoch589d6972011-11-30 16:04:58 +000060 bool is_in_loop() const { return IsInLoop::decode(flags_); }
Ben Murdochf87a2032010-10-22 12:50:53 +010061 FunctionLiteral* function() const { return function_; }
62 Scope* scope() const { return scope_; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010063 Scope* global_scope() const { return global_scope_; }
Ben Murdochf87a2032010-10-22 12:50:53 +010064 Handle<Code> code() const { return code_; }
65 Handle<JSFunction> closure() const { return closure_; }
66 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
67 Handle<Script> script() const { return script_; }
68 v8::Extension* extension() const { return extension_; }
69 ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
70 Handle<Context> calling_context() const { return calling_context_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +010071 int osr_ast_id() const { return osr_ast_id_; }
Ben Murdochf87a2032010-10-22 12:50:53 +010072
73 void MarkAsEval() {
74 ASSERT(!is_lazy());
75 flags_ |= IsEval::encode(true);
Leon Clarke4515c472010-02-03 11:58:03 +000076 }
Ben Murdochf87a2032010-10-22 12:50:53 +010077 void MarkAsGlobal() {
78 ASSERT(!is_lazy());
79 flags_ |= IsGlobal::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000080 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010081 void SetLanguageMode(LanguageMode language_mode) {
82 ASSERT(this->language_mode() == CLASSIC_MODE ||
83 this->language_mode() == language_mode ||
84 language_mode == EXTENDED_MODE);
85 flags_ = LanguageModeField::update(flags_, language_mode);
Steve Block1e0659c2011-05-24 12:43:12 +010086 }
Ben Murdochf87a2032010-10-22 12:50:53 +010087 void MarkAsInLoop() {
88 ASSERT(is_lazy());
89 flags_ |= IsInLoop::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000090 }
Ben Murdoch203a29f2011-10-20 14:36:23 +010091 void MarkAsNative() {
92 flags_ |= IsNative::encode(true);
Steve Block44f0eee2011-05-26 01:26:41 +010093 }
Ben Murdoch203a29f2011-10-20 14:36:23 +010094 bool is_native() const {
95 return IsNative::decode(flags_);
Steve Block44f0eee2011-05-26 01:26:41 +010096 }
Ben Murdochf87a2032010-10-22 12:50:53 +010097 void SetFunction(FunctionLiteral* literal) {
98 ASSERT(function_ == NULL);
99 function_ = literal;
Andrei Popescu31002712010-02-23 13:46:05 +0000100 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100101 void SetScope(Scope* scope) {
102 ASSERT(scope_ == NULL);
103 scope_ = scope;
Andrei Popescu31002712010-02-23 13:46:05 +0000104 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100105 void SetGlobalScope(Scope* global_scope) {
106 ASSERT(global_scope_ == NULL);
107 global_scope_ = global_scope;
108 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100109 void SetCode(Handle<Code> code) { code_ = code; }
110 void SetExtension(v8::Extension* extension) {
111 ASSERT(!is_lazy());
112 extension_ = extension;
Andrei Popescu31002712010-02-23 13:46:05 +0000113 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100114 void SetPreParseData(ScriptDataImpl* pre_parse_data) {
115 ASSERT(!is_lazy());
116 pre_parse_data_ = pre_parse_data;
117 }
118 void SetCallingContext(Handle<Context> context) {
119 ASSERT(is_eval());
120 calling_context_ = context;
121 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100122 void SetOsrAstId(int osr_ast_id) {
123 ASSERT(IsOptimizing());
124 osr_ast_id_ = osr_ast_id;
125 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100126 void MarkCompilingForDebugging(Handle<Code> current_code) {
127 ASSERT(mode_ != OPTIMIZE);
128 ASSERT(current_code->kind() == Code::FUNCTION);
129 flags_ |= IsCompilingForDebugging::encode(true);
130 if (current_code->is_compiled_optimizable()) {
131 EnableDeoptimizationSupport();
132 } else {
133 mode_ = CompilationInfo::NONOPT;
134 }
135 }
136 bool IsCompilingForDebugging() {
137 return IsCompilingForDebugging::decode(flags_);
138 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100139
140 bool has_global_object() const {
141 return !closure().is_null() && (closure()->context()->global() != NULL);
142 }
143
144 GlobalObject* global_object() const {
145 return has_global_object() ? closure()->context()->global() : NULL;
146 }
147
148 // Accessors for the different compilation modes.
149 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
150 bool IsOptimizable() const { return mode_ == BASE; }
151 void SetOptimizing(int osr_ast_id) {
152 SetMode(OPTIMIZE);
153 osr_ast_id_ = osr_ast_id;
154 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100155 void DisableOptimization();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100156
157 // Deoptimization support.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100158 bool HasDeoptimizationSupport() const {
159 return SupportsDeoptimization::decode(flags_);
160 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100161 void EnableDeoptimizationSupport() {
162 ASSERT(IsOptimizable());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100163 flags_ |= SupportsDeoptimization::encode(true);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100164 }
165
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100166 // Determines whether or not to insert a self-optimization header.
167 bool ShouldSelfOptimize();
Andrei Popescu31002712010-02-23 13:46:05 +0000168
Ben Murdoch257744e2011-11-30 15:57:28 +0000169 // Disable all optimization attempts of this info for the rest of the
170 // current compilation pipeline.
171 void AbortOptimization();
172
Leon Clarke4515c472010-02-03 11:58:03 +0000173 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100174 Isolate* isolate_;
175
Ben Murdochb0fe1622011-05-05 13:52:32 +0100176 // Compilation mode.
177 // BASE is generated by the full codegen, optionally prepared for bailouts.
178 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100179 // NONOPT is generated by the full codegen and is not prepared for
180 // recompilation/bailouts. These functions are never recompiled.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100181 enum Mode {
182 BASE,
183 OPTIMIZE,
184 NONOPT
185 };
186
187 CompilationInfo() : function_(NULL) {}
188
189 void Initialize(Mode mode) {
190 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000191 ASSERT(!script_.is_null());
Ben Murdoch203a29f2011-10-20 14:36:23 +0100192 if (script_->type()->value() == Script::TYPE_NATIVE) {
193 MarkAsNative();
194 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100195 if (!shared_info_.is_null()) {
196 ASSERT(language_mode() == CLASSIC_MODE);
197 SetLanguageMode(shared_info_->language_mode());
Steve Block1e0659c2011-05-24 12:43:12 +0100198 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100199 }
200
201 void SetMode(Mode mode) {
202 ASSERT(V8::UseCrankshaft());
203 mode_ = mode;
204 }
205
Ben Murdochf87a2032010-10-22 12:50:53 +0100206 // Flags using template class BitField<type, start, length>. All are
207 // false by default.
208 //
209 // Compilation is either eager or lazy.
210 class IsLazy: public BitField<bool, 0, 1> {};
211 // Flags that can be set for eager compilation.
212 class IsEval: public BitField<bool, 1, 1> {};
213 class IsGlobal: public BitField<bool, 2, 1> {};
Ben Murdochf87a2032010-10-22 12:50:53 +0100214 // Flags that can be set for lazy compilation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800215 class IsInLoop: public BitField<bool, 3, 1> {};
Steve Block1e0659c2011-05-24 12:43:12 +0100216 // Strict mode - used in eager compilation.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100217 class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
Ben Murdoch203a29f2011-10-20 14:36:23 +0100218 // Is this a function from our natives.
219 class IsNative: public BitField<bool, 6, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100220 // Is this code being compiled with support for deoptimization..
221 class SupportsDeoptimization: public BitField<bool, 7, 1> {};
222 // If compiling for debugging produce just full code matching the
223 // initial mode setting.
224 class IsCompilingForDebugging: public BitField<bool, 8, 1> {};
Andrei Popescu31002712010-02-23 13:46:05 +0000225
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000226
Ben Murdochf87a2032010-10-22 12:50:53 +0100227 unsigned flags_;
228
229 // Fields filled in by the compilation pipeline.
230 // AST filled in by the parser.
231 FunctionLiteral* function_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800232 // The scope of the function literal as a convenience. Set to indicate
Ben Murdochf87a2032010-10-22 12:50:53 +0100233 // that scopes have been analyzed.
234 Scope* scope_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100235 // The global scope provided as a convenience.
236 Scope* global_scope_;
Ben Murdochf87a2032010-10-22 12:50:53 +0100237 // The compiled code.
238 Handle<Code> code_;
239
240 // Possible initial inputs to the compilation process.
Andrei Popescu31002712010-02-23 13:46:05 +0000241 Handle<JSFunction> closure_;
Leon Clarke4515c472010-02-03 11:58:03 +0000242 Handle<SharedFunctionInfo> shared_info_;
Andrei Popescu31002712010-02-23 13:46:05 +0000243 Handle<Script> script_;
244
Ben Murdochf87a2032010-10-22 12:50:53 +0100245 // Fields possibly needed for eager compilation, NULL by default.
246 v8::Extension* extension_;
247 ScriptDataImpl* pre_parse_data_;
Andrei Popescu31002712010-02-23 13:46:05 +0000248
Ben Murdochf87a2032010-10-22 12:50:53 +0100249 // The context of the caller is needed for eval code, and will be a null
250 // handle otherwise.
251 Handle<Context> calling_context_;
Andrei Popescu31002712010-02-23 13:46:05 +0000252
Ben Murdochb0fe1622011-05-05 13:52:32 +0100253 // Compilation mode flag and whether deoptimization is allowed.
254 Mode mode_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100255 int osr_ast_id_;
256
Andrei Popescu31002712010-02-23 13:46:05 +0000257 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000258};
259
260
Steve Blocka7e24c12009-10-30 11:49:00 +0000261// The V8 compiler
262//
263// General strategy: Source code is translated into an anonymous function w/o
264// parameters which then can be executed. If the source code contains other
265// functions, they will be compiled and allocated as part of the compilation
266// of the source code.
267
Ben Murdochf87a2032010-10-22 12:50:53 +0100268// Please note this interface returns shared function infos. This means you
269// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
270// real function with a context.
Steve Blocka7e24c12009-10-30 11:49:00 +0000271
272class Compiler : public AllStatic {
273 public:
Ben Murdochb8e0da22011-05-16 14:20:40 +0100274 // Default maximum number of function optimization attempts before we
275 // give up.
276 static const int kDefaultMaxOptCount = 10;
277
Ben Murdoch8b112d22011-06-08 16:22:53 +0100278 static const int kMaxInliningLevels = 3;
279
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100280 // Call count before primitive functions trigger their own optimization.
281 static const int kCallsUntilPrimitiveOpt = 200;
282
Ben Murdochb8e0da22011-05-16 14:20:40 +0100283 // All routines return a SharedFunctionInfo.
284 // If an error occurs an exception is raised and the return handle
285 // contains NULL.
Steve Blocka7e24c12009-10-30 11:49:00 +0000286
287 // Compile a String source within a context.
Steve Block6ded16b2010-05-10 14:33:55 +0100288 static Handle<SharedFunctionInfo> Compile(Handle<String> source,
289 Handle<Object> script_name,
290 int line_offset,
291 int column_offset,
292 v8::Extension* extension,
293 ScriptDataImpl* pre_data,
294 Handle<Object> script_data,
295 NativesFlag is_natives_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000296
297 // Compile a String source within a context for Eval.
Steve Block6ded16b2010-05-10 14:33:55 +0100298 static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
299 Handle<Context> context,
Steve Block1e0659c2011-05-24 12:43:12 +0100300 bool is_global,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100301 LanguageMode language_mode,
302 int scope_position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000303
Ben Murdochf87a2032010-10-22 12:50:53 +0100304 // Compile from function info (used for lazy compilation). Returns true on
305 // success and false if the compilation resulted in a stack overflow.
Leon Clarke4515c472010-02-03 11:58:03 +0000306 static bool CompileLazy(CompilationInfo* info);
Steve Blockd0582a62009-12-15 09:54:21 +0000307
Ben Murdochf87a2032010-10-22 12:50:53 +0100308 // Compile a shared function info object (the function is possibly lazily
309 // compiled).
Steve Block6ded16b2010-05-10 14:33:55 +0100310 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
Ben Murdochf87a2032010-10-22 12:50:53 +0100311 Handle<Script> script);
Steve Blockd0582a62009-12-15 09:54:21 +0000312
313 // Set the function info for a newly compiled function.
Steve Block6ded16b2010-05-10 14:33:55 +0100314 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000315 FunctionLiteral* lit,
316 bool is_toplevel,
317 Handle<Script> script);
Andrei Popescu31002712010-02-23 13:46:05 +0000318
Ben Murdochf87a2032010-10-22 12:50:53 +0100319#ifdef ENABLE_DEBUGGER_SUPPORT
320 static bool MakeCodeForLiveEdit(CompilationInfo* info);
321#endif
322
Steve Block6ded16b2010-05-10 14:33:55 +0100323 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100324 CompilationInfo* info,
325 Handle<SharedFunctionInfo> shared);
Steve Blocka7e24c12009-10-30 11:49:00 +0000326};
327
328
Steve Blocka7e24c12009-10-30 11:49:00 +0000329} } // namespace v8::internal
330
331#endif // V8_COMPILER_H_