blob: e0a437ac6de8419a777a631772a828796080f763 [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
49 bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
50 bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
51 bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
Steve Block1e0659c2011-05-24 12:43:12 +010052 bool is_strict() const { return (flags_ & IsStrict::mask()) != 0; }
Ben Murdochf87a2032010-10-22 12:50:53 +010053 bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
54 FunctionLiteral* function() const { return function_; }
55 Scope* scope() const { return scope_; }
56 Handle<Code> code() const { return code_; }
57 Handle<JSFunction> closure() const { return closure_; }
58 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
59 Handle<Script> script() const { return script_; }
60 v8::Extension* extension() const { return extension_; }
61 ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
62 Handle<Context> calling_context() const { return calling_context_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +010063 int osr_ast_id() const { return osr_ast_id_; }
Ben Murdochf87a2032010-10-22 12:50:53 +010064
65 void MarkAsEval() {
66 ASSERT(!is_lazy());
67 flags_ |= IsEval::encode(true);
Leon Clarke4515c472010-02-03 11:58:03 +000068 }
Ben Murdochf87a2032010-10-22 12:50:53 +010069 void MarkAsGlobal() {
70 ASSERT(!is_lazy());
71 flags_ |= IsGlobal::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000072 }
Steve Block1e0659c2011-05-24 12:43:12 +010073 void MarkAsStrict() {
74 flags_ |= IsStrict::encode(true);
75 }
76 StrictModeFlag StrictMode() {
77 return is_strict() ? kStrictMode : kNonStrictMode;
78 }
Ben Murdochf87a2032010-10-22 12:50:53 +010079 void MarkAsInLoop() {
80 ASSERT(is_lazy());
81 flags_ |= IsInLoop::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000082 }
Ben Murdochf87a2032010-10-22 12:50:53 +010083 void SetFunction(FunctionLiteral* literal) {
84 ASSERT(function_ == NULL);
85 function_ = literal;
Andrei Popescu31002712010-02-23 13:46:05 +000086 }
Ben Murdochf87a2032010-10-22 12:50:53 +010087 void SetScope(Scope* scope) {
88 ASSERT(scope_ == NULL);
89 scope_ = scope;
Andrei Popescu31002712010-02-23 13:46:05 +000090 }
Ben Murdochf87a2032010-10-22 12:50:53 +010091 void SetCode(Handle<Code> code) { code_ = code; }
92 void SetExtension(v8::Extension* extension) {
93 ASSERT(!is_lazy());
94 extension_ = extension;
Andrei Popescu31002712010-02-23 13:46:05 +000095 }
Ben Murdochf87a2032010-10-22 12:50:53 +010096 void SetPreParseData(ScriptDataImpl* pre_parse_data) {
97 ASSERT(!is_lazy());
98 pre_parse_data_ = pre_parse_data;
99 }
100 void SetCallingContext(Handle<Context> context) {
101 ASSERT(is_eval());
102 calling_context_ = context;
103 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100104 void SetOsrAstId(int osr_ast_id) {
105 ASSERT(IsOptimizing());
106 osr_ast_id_ = osr_ast_id;
107 }
108
109 bool has_global_object() const {
110 return !closure().is_null() && (closure()->context()->global() != NULL);
111 }
112
113 GlobalObject* global_object() const {
114 return has_global_object() ? closure()->context()->global() : NULL;
115 }
116
117 // Accessors for the different compilation modes.
118 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
119 bool IsOptimizable() const { return mode_ == BASE; }
120 void SetOptimizing(int osr_ast_id) {
121 SetMode(OPTIMIZE);
122 osr_ast_id_ = osr_ast_id;
123 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100124 void DisableOptimization();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100125
126 // Deoptimization support.
127 bool HasDeoptimizationSupport() const { return supports_deoptimization_; }
128 void EnableDeoptimizationSupport() {
129 ASSERT(IsOptimizable());
130 supports_deoptimization_ = true;
131 }
132
133 // Determine whether or not we can adaptively optimize.
134 bool AllowOptimize() {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100135 return V8::UseCrankshaft() && !closure_.is_null();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100136 }
Andrei Popescu31002712010-02-23 13:46:05 +0000137
Leon Clarke4515c472010-02-03 11:58:03 +0000138 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100139 // Compilation mode.
140 // BASE is generated by the full codegen, optionally prepared for bailouts.
141 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
142 // NONOPT is generated by the full codegen or the classic backend
143 // and is not prepared for recompilation/bailouts. These functions
144 // are never recompiled.
145 enum Mode {
146 BASE,
147 OPTIMIZE,
148 NONOPT
149 };
150
151 CompilationInfo() : function_(NULL) {}
152
153 void Initialize(Mode mode) {
154 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
Steve Block1e0659c2011-05-24 12:43:12 +0100155 if (!shared_info_.is_null() && shared_info_->strict_mode()) {
156 MarkAsStrict();
157 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100158 }
159
160 void SetMode(Mode mode) {
161 ASSERT(V8::UseCrankshaft());
162 mode_ = mode;
163 }
164
Ben Murdochf87a2032010-10-22 12:50:53 +0100165 // Flags using template class BitField<type, start, length>. All are
166 // false by default.
167 //
168 // Compilation is either eager or lazy.
169 class IsLazy: public BitField<bool, 0, 1> {};
170 // Flags that can be set for eager compilation.
171 class IsEval: public BitField<bool, 1, 1> {};
172 class IsGlobal: public BitField<bool, 2, 1> {};
Ben Murdochf87a2032010-10-22 12:50:53 +0100173 // Flags that can be set for lazy compilation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800174 class IsInLoop: public BitField<bool, 3, 1> {};
Steve Block1e0659c2011-05-24 12:43:12 +0100175 // Strict mode - used in eager compilation.
176 class IsStrict: public BitField<bool, 4, 1> {};
Andrei Popescu31002712010-02-23 13:46:05 +0000177
Ben Murdochf87a2032010-10-22 12:50:53 +0100178 unsigned flags_;
179
180 // Fields filled in by the compilation pipeline.
181 // AST filled in by the parser.
182 FunctionLiteral* function_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800183 // The scope of the function literal as a convenience. Set to indicate
Ben Murdochf87a2032010-10-22 12:50:53 +0100184 // that scopes have been analyzed.
185 Scope* scope_;
186 // The compiled code.
187 Handle<Code> code_;
188
189 // Possible initial inputs to the compilation process.
Andrei Popescu31002712010-02-23 13:46:05 +0000190 Handle<JSFunction> closure_;
Leon Clarke4515c472010-02-03 11:58:03 +0000191 Handle<SharedFunctionInfo> shared_info_;
Andrei Popescu31002712010-02-23 13:46:05 +0000192 Handle<Script> script_;
193
Ben Murdochf87a2032010-10-22 12:50:53 +0100194 // Fields possibly needed for eager compilation, NULL by default.
195 v8::Extension* extension_;
196 ScriptDataImpl* pre_parse_data_;
Andrei Popescu31002712010-02-23 13:46:05 +0000197
Ben Murdochf87a2032010-10-22 12:50:53 +0100198 // The context of the caller is needed for eval code, and will be a null
199 // handle otherwise.
200 Handle<Context> calling_context_;
Andrei Popescu31002712010-02-23 13:46:05 +0000201
Ben Murdochb0fe1622011-05-05 13:52:32 +0100202 // Compilation mode flag and whether deoptimization is allowed.
203 Mode mode_;
204 bool supports_deoptimization_;
205 int osr_ast_id_;
206
Andrei Popescu31002712010-02-23 13:46:05 +0000207 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000208};
209
210
Steve Blocka7e24c12009-10-30 11:49:00 +0000211// The V8 compiler
212//
213// General strategy: Source code is translated into an anonymous function w/o
214// parameters which then can be executed. If the source code contains other
215// functions, they will be compiled and allocated as part of the compilation
216// of the source code.
217
Ben Murdochf87a2032010-10-22 12:50:53 +0100218// Please note this interface returns shared function infos. This means you
219// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
220// real function with a context.
Steve Blocka7e24c12009-10-30 11:49:00 +0000221
222class Compiler : public AllStatic {
223 public:
Ben Murdochb8e0da22011-05-16 14:20:40 +0100224 // Default maximum number of function optimization attempts before we
225 // give up.
226 static const int kDefaultMaxOptCount = 10;
227
228 // All routines return a SharedFunctionInfo.
229 // If an error occurs an exception is raised and the return handle
230 // contains NULL.
Steve Blocka7e24c12009-10-30 11:49:00 +0000231
232 // Compile a String source within a context.
Steve Block6ded16b2010-05-10 14:33:55 +0100233 static Handle<SharedFunctionInfo> Compile(Handle<String> source,
234 Handle<Object> script_name,
235 int line_offset,
236 int column_offset,
237 v8::Extension* extension,
238 ScriptDataImpl* pre_data,
239 Handle<Object> script_data,
240 NativesFlag is_natives_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000241
242 // Compile a String source within a context for Eval.
Steve Block6ded16b2010-05-10 14:33:55 +0100243 static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
244 Handle<Context> context,
Steve Block1e0659c2011-05-24 12:43:12 +0100245 bool is_global,
246 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000247
Ben Murdochf87a2032010-10-22 12:50:53 +0100248 // Compile from function info (used for lazy compilation). Returns true on
249 // success and false if the compilation resulted in a stack overflow.
Leon Clarke4515c472010-02-03 11:58:03 +0000250 static bool CompileLazy(CompilationInfo* info);
Steve Blockd0582a62009-12-15 09:54:21 +0000251
Ben Murdochf87a2032010-10-22 12:50:53 +0100252 // Compile a shared function info object (the function is possibly lazily
253 // compiled).
Steve Block6ded16b2010-05-10 14:33:55 +0100254 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
Ben Murdochf87a2032010-10-22 12:50:53 +0100255 Handle<Script> script);
Steve Blockd0582a62009-12-15 09:54:21 +0000256
257 // Set the function info for a newly compiled function.
Steve Block6ded16b2010-05-10 14:33:55 +0100258 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000259 FunctionLiteral* lit,
260 bool is_toplevel,
261 Handle<Script> script);
Andrei Popescu31002712010-02-23 13:46:05 +0000262
Ben Murdochf87a2032010-10-22 12:50:53 +0100263#ifdef ENABLE_DEBUGGER_SUPPORT
264 static bool MakeCodeForLiveEdit(CompilationInfo* info);
265#endif
266
Steve Block6ded16b2010-05-10 14:33:55 +0100267 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100268 CompilationInfo* info,
269 Handle<SharedFunctionInfo> shared);
Steve Blocka7e24c12009-10-30 11:49:00 +0000270};
271
272
Steve Blocka7e24c12009-10-30 11:49:00 +0000273// During compilation we need a global list of handles to constants
274// for frame elements. When the zone gets deleted, we make sure to
275// clear this list of handles as well.
276class CompilationZoneScope : public ZoneScope {
277 public:
278 explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
279 virtual ~CompilationZoneScope() {
280 if (ShouldDeleteOnExit()) {
281 FrameElement::ClearConstantList();
282 Result::ClearConstantList();
283 }
284 }
285};
286
287
288} } // namespace v8::internal
289
290#endif // V8_COMPILER_H_