blob: ea74d60db6f4034595b7ecbfebaab4571264b560 [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 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 Murdochf87a2032010-10-22 12:50:53 +010052 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; }
Ben Murdoch8b112d22011-06-08 16:22:53 +010055 bool is_strict_mode() const { return (flags_ & IsStrictMode::mask()) != 0; }
Ben Murdochf87a2032010-10-22 12:50:53 +010056 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_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +010066 int osr_ast_id() const { return osr_ast_id_; }
Ben Murdochf87a2032010-10-22 12:50:53 +010067
68 void MarkAsEval() {
69 ASSERT(!is_lazy());
70 flags_ |= IsEval::encode(true);
Leon Clarke4515c472010-02-03 11:58:03 +000071 }
Ben Murdochf87a2032010-10-22 12:50:53 +010072 void MarkAsGlobal() {
73 ASSERT(!is_lazy());
74 flags_ |= IsGlobal::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000075 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010076 void MarkAsStrictMode() {
77 flags_ |= IsStrictMode::encode(true);
Steve Block1e0659c2011-05-24 12:43:12 +010078 }
79 StrictModeFlag StrictMode() {
Ben Murdoch8b112d22011-06-08 16:22:53 +010080 return is_strict_mode() ? kStrictMode : kNonStrictMode;
Steve Block1e0659c2011-05-24 12:43:12 +010081 }
Ben Murdochf87a2032010-10-22 12:50:53 +010082 void MarkAsInLoop() {
83 ASSERT(is_lazy());
84 flags_ |= IsInLoop::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000085 }
Ben Murdoch203a29f2011-10-20 14:36:23 +010086 void MarkAsNative() {
87 flags_ |= IsNative::encode(true);
Steve Block44f0eee2011-05-26 01:26:41 +010088 }
Ben Murdoch203a29f2011-10-20 14:36:23 +010089 bool is_native() const {
90 return IsNative::decode(flags_);
Steve Block44f0eee2011-05-26 01:26:41 +010091 }
Ben Murdochf87a2032010-10-22 12:50:53 +010092 void SetFunction(FunctionLiteral* literal) {
93 ASSERT(function_ == NULL);
94 function_ = literal;
Andrei Popescu31002712010-02-23 13:46:05 +000095 }
Ben Murdochf87a2032010-10-22 12:50:53 +010096 void SetScope(Scope* scope) {
97 ASSERT(scope_ == NULL);
98 scope_ = scope;
Andrei Popescu31002712010-02-23 13:46:05 +000099 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100100 void SetCode(Handle<Code> code) { code_ = code; }
101 void SetExtension(v8::Extension* extension) {
102 ASSERT(!is_lazy());
103 extension_ = extension;
Andrei Popescu31002712010-02-23 13:46:05 +0000104 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100105 void SetPreParseData(ScriptDataImpl* pre_parse_data) {
106 ASSERT(!is_lazy());
107 pre_parse_data_ = pre_parse_data;
108 }
109 void SetCallingContext(Handle<Context> context) {
110 ASSERT(is_eval());
111 calling_context_ = context;
112 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100113 void SetOsrAstId(int osr_ast_id) {
114 ASSERT(IsOptimizing());
115 osr_ast_id_ = osr_ast_id;
116 }
117
118 bool has_global_object() const {
119 return !closure().is_null() && (closure()->context()->global() != NULL);
120 }
121
122 GlobalObject* global_object() const {
123 return has_global_object() ? closure()->context()->global() : NULL;
124 }
125
126 // Accessors for the different compilation modes.
127 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
128 bool IsOptimizable() const { return mode_ == BASE; }
129 void SetOptimizing(int osr_ast_id) {
130 SetMode(OPTIMIZE);
131 osr_ast_id_ = osr_ast_id;
132 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100133 void DisableOptimization();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100134
135 // Deoptimization support.
136 bool HasDeoptimizationSupport() const { return supports_deoptimization_; }
137 void EnableDeoptimizationSupport() {
138 ASSERT(IsOptimizable());
139 supports_deoptimization_ = true;
140 }
141
142 // Determine whether or not we can adaptively optimize.
143 bool AllowOptimize() {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100144 return V8::UseCrankshaft() && !closure_.is_null();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100145 }
Andrei Popescu31002712010-02-23 13:46:05 +0000146
Ben Murdoch257744e2011-11-30 15:57:28 +0000147 // Disable all optimization attempts of this info for the rest of the
148 // current compilation pipeline.
149 void AbortOptimization();
150
Leon Clarke4515c472010-02-03 11:58:03 +0000151 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100152 Isolate* isolate_;
153
Ben Murdochb0fe1622011-05-05 13:52:32 +0100154 // Compilation mode.
155 // BASE is generated by the full codegen, optionally prepared for bailouts.
156 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
157 // NONOPT is generated by the full codegen or the classic backend
158 // and is not prepared for recompilation/bailouts. These functions
159 // are never recompiled.
160 enum Mode {
161 BASE,
162 OPTIMIZE,
163 NONOPT
164 };
165
166 CompilationInfo() : function_(NULL) {}
167
168 void Initialize(Mode mode) {
169 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
Ben Murdoch203a29f2011-10-20 14:36:23 +0100170 if (script_->type()->value() == Script::TYPE_NATIVE) {
171 MarkAsNative();
172 }
Steve Block1e0659c2011-05-24 12:43:12 +0100173 if (!shared_info_.is_null() && shared_info_->strict_mode()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100174 MarkAsStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100175 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100176 }
177
178 void SetMode(Mode mode) {
179 ASSERT(V8::UseCrankshaft());
180 mode_ = mode;
181 }
182
Ben Murdochf87a2032010-10-22 12:50:53 +0100183 // Flags using template class BitField<type, start, length>. All are
184 // false by default.
185 //
186 // Compilation is either eager or lazy.
187 class IsLazy: public BitField<bool, 0, 1> {};
188 // Flags that can be set for eager compilation.
189 class IsEval: public BitField<bool, 1, 1> {};
190 class IsGlobal: public BitField<bool, 2, 1> {};
Ben Murdochf87a2032010-10-22 12:50:53 +0100191 // Flags that can be set for lazy compilation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800192 class IsInLoop: public BitField<bool, 3, 1> {};
Steve Block1e0659c2011-05-24 12:43:12 +0100193 // Strict mode - used in eager compilation.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100194 class IsStrictMode: public BitField<bool, 4, 1> {};
Ben Murdoch203a29f2011-10-20 14:36:23 +0100195 // Is this a function from our natives.
196 class IsNative: public BitField<bool, 6, 1> {};
Andrei Popescu31002712010-02-23 13:46:05 +0000197
Ben Murdochf87a2032010-10-22 12:50:53 +0100198 unsigned flags_;
199
200 // Fields filled in by the compilation pipeline.
201 // AST filled in by the parser.
202 FunctionLiteral* function_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800203 // The scope of the function literal as a convenience. Set to indicate
Ben Murdochf87a2032010-10-22 12:50:53 +0100204 // that scopes have been analyzed.
205 Scope* scope_;
206 // The compiled code.
207 Handle<Code> code_;
208
209 // Possible initial inputs to the compilation process.
Andrei Popescu31002712010-02-23 13:46:05 +0000210 Handle<JSFunction> closure_;
Leon Clarke4515c472010-02-03 11:58:03 +0000211 Handle<SharedFunctionInfo> shared_info_;
Andrei Popescu31002712010-02-23 13:46:05 +0000212 Handle<Script> script_;
213
Ben Murdochf87a2032010-10-22 12:50:53 +0100214 // Fields possibly needed for eager compilation, NULL by default.
215 v8::Extension* extension_;
216 ScriptDataImpl* pre_parse_data_;
Andrei Popescu31002712010-02-23 13:46:05 +0000217
Ben Murdochf87a2032010-10-22 12:50:53 +0100218 // The context of the caller is needed for eval code, and will be a null
219 // handle otherwise.
220 Handle<Context> calling_context_;
Andrei Popescu31002712010-02-23 13:46:05 +0000221
Ben Murdochb0fe1622011-05-05 13:52:32 +0100222 // Compilation mode flag and whether deoptimization is allowed.
223 Mode mode_;
224 bool supports_deoptimization_;
225 int osr_ast_id_;
226
Andrei Popescu31002712010-02-23 13:46:05 +0000227 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000228};
229
230
Steve Blocka7e24c12009-10-30 11:49:00 +0000231// The V8 compiler
232//
233// General strategy: Source code is translated into an anonymous function w/o
234// parameters which then can be executed. If the source code contains other
235// functions, they will be compiled and allocated as part of the compilation
236// of the source code.
237
Ben Murdochf87a2032010-10-22 12:50:53 +0100238// Please note this interface returns shared function infos. This means you
239// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
240// real function with a context.
Steve Blocka7e24c12009-10-30 11:49:00 +0000241
242class Compiler : public AllStatic {
243 public:
Ben Murdochb8e0da22011-05-16 14:20:40 +0100244 // Default maximum number of function optimization attempts before we
245 // give up.
246 static const int kDefaultMaxOptCount = 10;
247
Ben Murdoch8b112d22011-06-08 16:22:53 +0100248 static const int kMaxInliningLevels = 3;
249
Ben Murdochb8e0da22011-05-16 14:20:40 +0100250 // All routines return a SharedFunctionInfo.
251 // If an error occurs an exception is raised and the return handle
252 // contains NULL.
Steve Blocka7e24c12009-10-30 11:49:00 +0000253
254 // Compile a String source within a context.
Steve Block6ded16b2010-05-10 14:33:55 +0100255 static Handle<SharedFunctionInfo> Compile(Handle<String> source,
256 Handle<Object> script_name,
257 int line_offset,
258 int column_offset,
259 v8::Extension* extension,
260 ScriptDataImpl* pre_data,
261 Handle<Object> script_data,
262 NativesFlag is_natives_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000263
264 // Compile a String source within a context for Eval.
Steve Block6ded16b2010-05-10 14:33:55 +0100265 static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
266 Handle<Context> context,
Steve Block1e0659c2011-05-24 12:43:12 +0100267 bool is_global,
268 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000269
Ben Murdochf87a2032010-10-22 12:50:53 +0100270 // Compile from function info (used for lazy compilation). Returns true on
271 // success and false if the compilation resulted in a stack overflow.
Leon Clarke4515c472010-02-03 11:58:03 +0000272 static bool CompileLazy(CompilationInfo* info);
Steve Blockd0582a62009-12-15 09:54:21 +0000273
Ben Murdochf87a2032010-10-22 12:50:53 +0100274 // Compile a shared function info object (the function is possibly lazily
275 // compiled).
Steve Block6ded16b2010-05-10 14:33:55 +0100276 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
Ben Murdochf87a2032010-10-22 12:50:53 +0100277 Handle<Script> script);
Steve Blockd0582a62009-12-15 09:54:21 +0000278
279 // Set the function info for a newly compiled function.
Steve Block6ded16b2010-05-10 14:33:55 +0100280 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000281 FunctionLiteral* lit,
282 bool is_toplevel,
283 Handle<Script> script);
Andrei Popescu31002712010-02-23 13:46:05 +0000284
Ben Murdochf87a2032010-10-22 12:50:53 +0100285#ifdef ENABLE_DEBUGGER_SUPPORT
286 static bool MakeCodeForLiveEdit(CompilationInfo* info);
287#endif
288
Steve Block6ded16b2010-05-10 14:33:55 +0100289 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100290 CompilationInfo* info,
291 Handle<SharedFunctionInfo> shared);
Steve Blocka7e24c12009-10-30 11:49:00 +0000292};
293
294
Steve Blocka7e24c12009-10-30 11:49:00 +0000295// During compilation we need a global list of handles to constants
296// for frame elements. When the zone gets deleted, we make sure to
297// clear this list of handles as well.
298class CompilationZoneScope : public ZoneScope {
299 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000300 CompilationZoneScope(Isolate* isolate, ZoneScopeMode mode)
301 : ZoneScope(isolate, mode) {}
302
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 virtual ~CompilationZoneScope() {
304 if (ShouldDeleteOnExit()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100305 Isolate* isolate = Isolate::Current();
306 isolate->frame_element_constant_list()->Clear();
307 isolate->result_constant_list()->Clear();
Steve Blocka7e24c12009-10-30 11:49:00 +0000308 }
309 }
310};
311
312
313} } // namespace v8::internal
314
315#endif // V8_COMPILER_H_