blob: a66c54010e5e74b6d9680c06366dd31a3857693a [file] [log] [blame]
Ben Murdochf87a2032010-10-22 12:50:53 +01001// Copyright 2010 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
Andrei Popescu402d9372010-02-26 13:31:12 +000031#include "ast.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "frame-element.h"
Andrei Popescu402d9372010-02-26 13:31:12 +000033#include "register-allocator.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "zone.h"
35
36namespace v8 {
37namespace internal {
38
Ben Murdochf87a2032010-10-22 12:50:53 +010039class ScriptDataImpl;
40
Andrei Popescu31002712010-02-23 13:46:05 +000041// CompilationInfo encapsulates some information known at compile time. It
42// is constructed based on the resources available at compile-time.
Leon Clarke4515c472010-02-03 11:58:03 +000043class CompilationInfo BASE_EMBEDDED {
44 public:
Ben Murdochf87a2032010-10-22 12:50:53 +010045 explicit CompilationInfo(Handle<Script> script);
46 explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
47 explicit CompilationInfo(Handle<JSFunction> closure);
48
Steve Block44f0eee2011-05-26 01:26:41 +010049 Isolate* isolate() {
50 ASSERT(Isolate::Current() == isolate_);
51 return isolate_;
52 }
Ben Murdochf87a2032010-10-22 12:50:53 +010053 bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
54 bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
55 bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
Steve Block1e0659c2011-05-24 12:43:12 +010056 bool is_strict() const { return (flags_ & IsStrict::mask()) != 0; }
Ben Murdochf87a2032010-10-22 12:50:53 +010057 bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
58 FunctionLiteral* function() const { return function_; }
59 Scope* scope() const { return scope_; }
60 Handle<Code> code() const { return code_; }
61 Handle<JSFunction> closure() const { return closure_; }
62 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
63 Handle<Script> script() const { return script_; }
64 v8::Extension* extension() const { return extension_; }
65 ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
66 Handle<Context> calling_context() const { return calling_context_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +010067 int osr_ast_id() const { return osr_ast_id_; }
Ben Murdochf87a2032010-10-22 12:50:53 +010068
69 void MarkAsEval() {
70 ASSERT(!is_lazy());
71 flags_ |= IsEval::encode(true);
Leon Clarke4515c472010-02-03 11:58:03 +000072 }
Ben Murdochf87a2032010-10-22 12:50:53 +010073 void MarkAsGlobal() {
74 ASSERT(!is_lazy());
75 flags_ |= IsGlobal::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000076 }
Steve Block1e0659c2011-05-24 12:43:12 +010077 void MarkAsStrict() {
78 flags_ |= IsStrict::encode(true);
79 }
80 StrictModeFlag StrictMode() {
81 return is_strict() ? kStrictMode : kNonStrictMode;
82 }
Ben Murdochf87a2032010-10-22 12:50:53 +010083 void MarkAsInLoop() {
84 ASSERT(is_lazy());
85 flags_ |= IsInLoop::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000086 }
Steve Block44f0eee2011-05-26 01:26:41 +010087 void MarkAsAllowingNativesSyntax() {
88 flags_ |= IsNativesSyntaxAllowed::encode(true);
89 }
90 bool allows_natives_syntax() const {
91 return IsNativesSyntaxAllowed::decode(flags_);
92 }
Ben Murdochf87a2032010-10-22 12:50:53 +010093 void SetFunction(FunctionLiteral* literal) {
94 ASSERT(function_ == NULL);
95 function_ = literal;
Andrei Popescu31002712010-02-23 13:46:05 +000096 }
Ben Murdochf87a2032010-10-22 12:50:53 +010097 void SetScope(Scope* scope) {
98 ASSERT(scope_ == NULL);
99 scope_ = scope;
Andrei Popescu31002712010-02-23 13:46:05 +0000100 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100101 void SetCode(Handle<Code> code) { code_ = code; }
102 void SetExtension(v8::Extension* extension) {
103 ASSERT(!is_lazy());
104 extension_ = extension;
Andrei Popescu31002712010-02-23 13:46:05 +0000105 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100106 void SetPreParseData(ScriptDataImpl* pre_parse_data) {
107 ASSERT(!is_lazy());
108 pre_parse_data_ = pre_parse_data;
109 }
110 void SetCallingContext(Handle<Context> context) {
111 ASSERT(is_eval());
112 calling_context_ = context;
113 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100114 void SetOsrAstId(int osr_ast_id) {
115 ASSERT(IsOptimizing());
116 osr_ast_id_ = osr_ast_id;
117 }
118
119 bool has_global_object() const {
120 return !closure().is_null() && (closure()->context()->global() != NULL);
121 }
122
123 GlobalObject* global_object() const {
124 return has_global_object() ? closure()->context()->global() : NULL;
125 }
126
127 // Accessors for the different compilation modes.
128 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
129 bool IsOptimizable() const { return mode_ == BASE; }
130 void SetOptimizing(int osr_ast_id) {
131 SetMode(OPTIMIZE);
132 osr_ast_id_ = osr_ast_id;
133 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100134 void DisableOptimization();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100135
136 // Deoptimization support.
137 bool HasDeoptimizationSupport() const { return supports_deoptimization_; }
138 void EnableDeoptimizationSupport() {
139 ASSERT(IsOptimizable());
140 supports_deoptimization_ = true;
141 }
142
143 // Determine whether or not we can adaptively optimize.
144 bool AllowOptimize() {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100145 return V8::UseCrankshaft() && !closure_.is_null();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100146 }
Andrei Popescu31002712010-02-23 13:46:05 +0000147
Leon Clarke4515c472010-02-03 11:58:03 +0000148 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100149 Isolate* isolate_;
150
Ben Murdochb0fe1622011-05-05 13:52:32 +0100151 // Compilation mode.
152 // BASE is generated by the full codegen, optionally prepared for bailouts.
153 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
154 // NONOPT is generated by the full codegen or the classic backend
155 // and is not prepared for recompilation/bailouts. These functions
156 // are never recompiled.
157 enum Mode {
158 BASE,
159 OPTIMIZE,
160 NONOPT
161 };
162
163 CompilationInfo() : function_(NULL) {}
164
165 void Initialize(Mode mode) {
166 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
Steve Block1e0659c2011-05-24 12:43:12 +0100167 if (!shared_info_.is_null() && shared_info_->strict_mode()) {
168 MarkAsStrict();
169 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100170 }
171
172 void SetMode(Mode mode) {
173 ASSERT(V8::UseCrankshaft());
174 mode_ = mode;
175 }
176
Ben Murdochf87a2032010-10-22 12:50:53 +0100177 // Flags using template class BitField<type, start, length>. All are
178 // false by default.
179 //
180 // Compilation is either eager or lazy.
181 class IsLazy: public BitField<bool, 0, 1> {};
182 // Flags that can be set for eager compilation.
183 class IsEval: public BitField<bool, 1, 1> {};
184 class IsGlobal: public BitField<bool, 2, 1> {};
Ben Murdochf87a2032010-10-22 12:50:53 +0100185 // Flags that can be set for lazy compilation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800186 class IsInLoop: public BitField<bool, 3, 1> {};
Steve Block1e0659c2011-05-24 12:43:12 +0100187 // Strict mode - used in eager compilation.
188 class IsStrict: public BitField<bool, 4, 1> {};
Steve Block44f0eee2011-05-26 01:26:41 +0100189 // Native syntax (%-stuff) allowed?
190 class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {};
Andrei Popescu31002712010-02-23 13:46:05 +0000191
Ben Murdochf87a2032010-10-22 12:50:53 +0100192 unsigned flags_;
193
194 // Fields filled in by the compilation pipeline.
195 // AST filled in by the parser.
196 FunctionLiteral* function_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800197 // The scope of the function literal as a convenience. Set to indicate
Ben Murdochf87a2032010-10-22 12:50:53 +0100198 // that scopes have been analyzed.
199 Scope* scope_;
200 // The compiled code.
201 Handle<Code> code_;
202
203 // Possible initial inputs to the compilation process.
Andrei Popescu31002712010-02-23 13:46:05 +0000204 Handle<JSFunction> closure_;
Leon Clarke4515c472010-02-03 11:58:03 +0000205 Handle<SharedFunctionInfo> shared_info_;
Andrei Popescu31002712010-02-23 13:46:05 +0000206 Handle<Script> script_;
207
Ben Murdochf87a2032010-10-22 12:50:53 +0100208 // Fields possibly needed for eager compilation, NULL by default.
209 v8::Extension* extension_;
210 ScriptDataImpl* pre_parse_data_;
Andrei Popescu31002712010-02-23 13:46:05 +0000211
Ben Murdochf87a2032010-10-22 12:50:53 +0100212 // The context of the caller is needed for eval code, and will be a null
213 // handle otherwise.
214 Handle<Context> calling_context_;
Andrei Popescu31002712010-02-23 13:46:05 +0000215
Ben Murdochb0fe1622011-05-05 13:52:32 +0100216 // Compilation mode flag and whether deoptimization is allowed.
217 Mode mode_;
218 bool supports_deoptimization_;
219 int osr_ast_id_;
220
Andrei Popescu31002712010-02-23 13:46:05 +0000221 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000222};
223
224
Steve Blocka7e24c12009-10-30 11:49:00 +0000225// The V8 compiler
226//
227// General strategy: Source code is translated into an anonymous function w/o
228// parameters which then can be executed. If the source code contains other
229// functions, they will be compiled and allocated as part of the compilation
230// of the source code.
231
Ben Murdochf87a2032010-10-22 12:50:53 +0100232// Please note this interface returns shared function infos. This means you
233// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
234// real function with a context.
Steve Blocka7e24c12009-10-30 11:49:00 +0000235
236class Compiler : public AllStatic {
237 public:
Ben Murdochb8e0da22011-05-16 14:20:40 +0100238 // Default maximum number of function optimization attempts before we
239 // give up.
240 static const int kDefaultMaxOptCount = 10;
241
242 // All routines return a SharedFunctionInfo.
243 // If an error occurs an exception is raised and the return handle
244 // contains NULL.
Steve Blocka7e24c12009-10-30 11:49:00 +0000245
246 // Compile a String source within a context.
Steve Block6ded16b2010-05-10 14:33:55 +0100247 static Handle<SharedFunctionInfo> Compile(Handle<String> source,
248 Handle<Object> script_name,
249 int line_offset,
250 int column_offset,
251 v8::Extension* extension,
252 ScriptDataImpl* pre_data,
253 Handle<Object> script_data,
254 NativesFlag is_natives_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000255
256 // Compile a String source within a context for Eval.
Steve Block6ded16b2010-05-10 14:33:55 +0100257 static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
258 Handle<Context> context,
Steve Block1e0659c2011-05-24 12:43:12 +0100259 bool is_global,
260 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000261
Ben Murdochf87a2032010-10-22 12:50:53 +0100262 // Compile from function info (used for lazy compilation). Returns true on
263 // success and false if the compilation resulted in a stack overflow.
Leon Clarke4515c472010-02-03 11:58:03 +0000264 static bool CompileLazy(CompilationInfo* info);
Steve Blockd0582a62009-12-15 09:54:21 +0000265
Ben Murdochf87a2032010-10-22 12:50:53 +0100266 // Compile a shared function info object (the function is possibly lazily
267 // compiled).
Steve Block6ded16b2010-05-10 14:33:55 +0100268 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
Ben Murdochf87a2032010-10-22 12:50:53 +0100269 Handle<Script> script);
Steve Blockd0582a62009-12-15 09:54:21 +0000270
271 // Set the function info for a newly compiled function.
Steve Block6ded16b2010-05-10 14:33:55 +0100272 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000273 FunctionLiteral* lit,
274 bool is_toplevel,
275 Handle<Script> script);
Andrei Popescu31002712010-02-23 13:46:05 +0000276
Ben Murdochf87a2032010-10-22 12:50:53 +0100277#ifdef ENABLE_DEBUGGER_SUPPORT
278 static bool MakeCodeForLiveEdit(CompilationInfo* info);
279#endif
280
Steve Block6ded16b2010-05-10 14:33:55 +0100281 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100282 CompilationInfo* info,
283 Handle<SharedFunctionInfo> shared);
Steve Blocka7e24c12009-10-30 11:49:00 +0000284};
285
286
Steve Blocka7e24c12009-10-30 11:49:00 +0000287// During compilation we need a global list of handles to constants
288// for frame elements. When the zone gets deleted, we make sure to
289// clear this list of handles as well.
290class CompilationZoneScope : public ZoneScope {
291 public:
292 explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
293 virtual ~CompilationZoneScope() {
294 if (ShouldDeleteOnExit()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100295 Isolate* isolate = Isolate::Current();
296 isolate->frame_element_constant_list()->Clear();
297 isolate->result_constant_list()->Clear();
Steve Blocka7e24c12009-10-30 11:49:00 +0000298 }
299 }
300};
301
302
303} } // namespace v8::internal
304
305#endif // V8_COMPILER_H_