• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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 
31 #include "allocation.h"
32 #include "ast.h"
33 #include "zone.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 class ScriptDataImpl;
39 
40 // CompilationInfo encapsulates some information known at compile time.  It
41 // is constructed based on the resources available at compile-time.
42 class CompilationInfo BASE_EMBEDDED {
43  public:
44   explicit CompilationInfo(Handle<Script> script);
45   explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
46   explicit CompilationInfo(Handle<JSFunction> closure);
47 
isolate()48   Isolate* isolate() {
49     ASSERT(Isolate::Current() == isolate_);
50     return isolate_;
51   }
is_lazy()52   bool is_lazy() const { return IsLazy::decode(flags_); }
is_eval()53   bool is_eval() const { return IsEval::decode(flags_); }
is_global()54   bool is_global() const { return IsGlobal::decode(flags_); }
is_classic_mode()55   bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
is_extended_mode()56   bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; }
language_mode()57   LanguageMode language_mode() const {
58     return LanguageModeField::decode(flags_);
59   }
is_in_loop()60   bool is_in_loop() const { return IsInLoop::decode(flags_); }
function()61   FunctionLiteral* function() const { return function_; }
scope()62   Scope* scope() const { return scope_; }
global_scope()63   Scope* global_scope() const { return global_scope_; }
code()64   Handle<Code> code() const { return code_; }
closure()65   Handle<JSFunction> closure() const { return closure_; }
shared_info()66   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
script()67   Handle<Script> script() const { return script_; }
extension()68   v8::Extension* extension() const { return extension_; }
pre_parse_data()69   ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
calling_context()70   Handle<Context> calling_context() const { return calling_context_; }
osr_ast_id()71   int osr_ast_id() const { return osr_ast_id_; }
72 
MarkAsEval()73   void MarkAsEval() {
74     ASSERT(!is_lazy());
75     flags_ |= IsEval::encode(true);
76   }
MarkAsGlobal()77   void MarkAsGlobal() {
78     ASSERT(!is_lazy());
79     flags_ |= IsGlobal::encode(true);
80   }
SetLanguageMode(LanguageMode language_mode)81   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);
86   }
MarkAsInLoop()87   void MarkAsInLoop() {
88     ASSERT(is_lazy());
89     flags_ |= IsInLoop::encode(true);
90   }
MarkAsNative()91   void MarkAsNative() {
92     flags_ |= IsNative::encode(true);
93   }
is_native()94   bool is_native() const {
95     return IsNative::decode(flags_);
96   }
SetFunction(FunctionLiteral * literal)97   void SetFunction(FunctionLiteral* literal) {
98     ASSERT(function_ == NULL);
99     function_ = literal;
100   }
SetScope(Scope * scope)101   void SetScope(Scope* scope) {
102     ASSERT(scope_ == NULL);
103     scope_ = scope;
104   }
SetGlobalScope(Scope * global_scope)105   void SetGlobalScope(Scope* global_scope) {
106     ASSERT(global_scope_ == NULL);
107     global_scope_ = global_scope;
108   }
SetCode(Handle<Code> code)109   void SetCode(Handle<Code> code) { code_ = code; }
SetExtension(v8::Extension * extension)110   void SetExtension(v8::Extension* extension) {
111     ASSERT(!is_lazy());
112     extension_ = extension;
113   }
SetPreParseData(ScriptDataImpl * pre_parse_data)114   void SetPreParseData(ScriptDataImpl* pre_parse_data) {
115     ASSERT(!is_lazy());
116     pre_parse_data_ = pre_parse_data;
117   }
SetCallingContext(Handle<Context> context)118   void SetCallingContext(Handle<Context> context) {
119     ASSERT(is_eval());
120     calling_context_ = context;
121   }
SetOsrAstId(int osr_ast_id)122   void SetOsrAstId(int osr_ast_id) {
123     ASSERT(IsOptimizing());
124     osr_ast_id_ = osr_ast_id;
125   }
MarkCompilingForDebugging(Handle<Code> current_code)126   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   }
IsCompilingForDebugging()136   bool IsCompilingForDebugging() {
137     return IsCompilingForDebugging::decode(flags_);
138   }
139 
has_global_object()140   bool has_global_object() const {
141     return !closure().is_null() && (closure()->context()->global() != NULL);
142   }
143 
global_object()144   GlobalObject* global_object() const {
145     return has_global_object() ? closure()->context()->global() : NULL;
146   }
147 
148   // Accessors for the different compilation modes.
IsOptimizing()149   bool IsOptimizing() const { return mode_ == OPTIMIZE; }
IsOptimizable()150   bool IsOptimizable() const { return mode_ == BASE; }
SetOptimizing(int osr_ast_id)151   void SetOptimizing(int osr_ast_id) {
152     SetMode(OPTIMIZE);
153     osr_ast_id_ = osr_ast_id;
154   }
155   void DisableOptimization();
156 
157   // Deoptimization support.
HasDeoptimizationSupport()158   bool HasDeoptimizationSupport() const {
159     return SupportsDeoptimization::decode(flags_);
160   }
EnableDeoptimizationSupport()161   void EnableDeoptimizationSupport() {
162     ASSERT(IsOptimizable());
163     flags_ |= SupportsDeoptimization::encode(true);
164   }
165 
166   // Determines whether or not to insert a self-optimization header.
167   bool ShouldSelfOptimize();
168 
169   // Disable all optimization attempts of this info for the rest of the
170   // current compilation pipeline.
171   void AbortOptimization();
172 
173  private:
174   Isolate* isolate_;
175 
176   // 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.
179   // NONOPT is generated by the full codegen and is not prepared for
180   //   recompilation/bailouts.  These functions are never recompiled.
181   enum Mode {
182     BASE,
183     OPTIMIZE,
184     NONOPT
185   };
186 
CompilationInfo()187   CompilationInfo() : function_(NULL) {}
188 
Initialize(Mode mode)189   void Initialize(Mode mode) {
190     mode_ = V8::UseCrankshaft() ? mode : NONOPT;
191     ASSERT(!script_.is_null());
192     if (script_->type()->value() == Script::TYPE_NATIVE) {
193       MarkAsNative();
194     }
195     if (!shared_info_.is_null()) {
196       ASSERT(language_mode() == CLASSIC_MODE);
197       SetLanguageMode(shared_info_->language_mode());
198     }
199   }
200 
SetMode(Mode mode)201   void SetMode(Mode mode) {
202     ASSERT(V8::UseCrankshaft());
203     mode_ = mode;
204   }
205 
206   // 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> {};
214   // Flags that can be set for lazy compilation.
215   class IsInLoop: public BitField<bool, 3, 1> {};
216   // Strict mode - used in eager compilation.
217   class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
218   // Is this a function from our natives.
219   class IsNative: public BitField<bool, 6, 1> {};
220   // 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> {};
225 
226 
227   unsigned flags_;
228 
229   // Fields filled in by the compilation pipeline.
230   // AST filled in by the parser.
231   FunctionLiteral* function_;
232   // The scope of the function literal as a convenience.  Set to indicate
233   // that scopes have been analyzed.
234   Scope* scope_;
235   // The global scope provided as a convenience.
236   Scope* global_scope_;
237   // The compiled code.
238   Handle<Code> code_;
239 
240   // Possible initial inputs to the compilation process.
241   Handle<JSFunction> closure_;
242   Handle<SharedFunctionInfo> shared_info_;
243   Handle<Script> script_;
244 
245   // Fields possibly needed for eager compilation, NULL by default.
246   v8::Extension* extension_;
247   ScriptDataImpl* pre_parse_data_;
248 
249   // The context of the caller is needed for eval code, and will be a null
250   // handle otherwise.
251   Handle<Context> calling_context_;
252 
253   // Compilation mode flag and whether deoptimization is allowed.
254   Mode mode_;
255   int osr_ast_id_;
256 
257   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
258 };
259 
260 
261 // 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 
268 // 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.
271 
272 class Compiler : public AllStatic {
273  public:
274   // Default maximum number of function optimization attempts before we
275   // give up.
276   static const int kDefaultMaxOptCount = 10;
277 
278   static const int kMaxInliningLevels = 3;
279 
280   // Call count before primitive functions trigger their own optimization.
281   static const int kCallsUntilPrimitiveOpt = 200;
282 
283   // All routines return a SharedFunctionInfo.
284   // If an error occurs an exception is raised and the return handle
285   // contains NULL.
286 
287   // Compile a String source within a context.
288   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);
296 
297   // Compile a String source within a context for Eval.
298   static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
299                                                 Handle<Context> context,
300                                                 bool is_global,
301                                                 LanguageMode language_mode,
302                                                 int scope_position);
303 
304   // Compile from function info (used for lazy compilation). Returns true on
305   // success and false if the compilation resulted in a stack overflow.
306   static bool CompileLazy(CompilationInfo* info);
307 
308   // Compile a shared function info object (the function is possibly lazily
309   // compiled).
310   static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
311                                                       Handle<Script> script);
312 
313   // Set the function info for a newly compiled function.
314   static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
315                               FunctionLiteral* lit,
316                               bool is_toplevel,
317                               Handle<Script> script);
318 
319 #ifdef ENABLE_DEBUGGER_SUPPORT
320   static bool MakeCodeForLiveEdit(CompilationInfo* info);
321 #endif
322 
323   static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
324                                         CompilationInfo* info,
325                                         Handle<SharedFunctionInfo> shared);
326 };
327 
328 
329 } }  // namespace v8::internal
330 
331 #endif  // V8_COMPILER_H_
332