• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 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 "ast.h"
32 #include "frame-element.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 (flags_ & IsLazy::mask()) != 0; }
is_eval()53   bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
is_global()54   bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
is_strict_mode()55   bool is_strict_mode() const { return (flags_ & IsStrictMode::mask()) != 0; }
is_in_loop()56   bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
function()57   FunctionLiteral* function() const { return function_; }
scope()58   Scope* scope() const { return scope_; }
code()59   Handle<Code> code() const { return code_; }
closure()60   Handle<JSFunction> closure() const { return closure_; }
shared_info()61   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
script()62   Handle<Script> script() const { return script_; }
extension()63   v8::Extension* extension() const { return extension_; }
pre_parse_data()64   ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
calling_context()65   Handle<Context> calling_context() const { return calling_context_; }
osr_ast_id()66   int osr_ast_id() const { return osr_ast_id_; }
67 
MarkAsEval()68   void MarkAsEval() {
69     ASSERT(!is_lazy());
70     flags_ |= IsEval::encode(true);
71   }
MarkAsGlobal()72   void MarkAsGlobal() {
73     ASSERT(!is_lazy());
74     flags_ |= IsGlobal::encode(true);
75   }
MarkAsStrictMode()76   void MarkAsStrictMode() {
77     flags_ |= IsStrictMode::encode(true);
78   }
StrictMode()79   StrictModeFlag StrictMode() {
80     return is_strict_mode() ? kStrictMode : kNonStrictMode;
81   }
MarkAsInLoop()82   void MarkAsInLoop() {
83     ASSERT(is_lazy());
84     flags_ |= IsInLoop::encode(true);
85   }
MarkAsNative()86   void MarkAsNative() {
87     flags_ |= IsNative::encode(true);
88   }
is_native()89   bool is_native() const {
90     return IsNative::decode(flags_);
91   }
SetFunction(FunctionLiteral * literal)92   void SetFunction(FunctionLiteral* literal) {
93     ASSERT(function_ == NULL);
94     function_ = literal;
95   }
SetScope(Scope * scope)96   void SetScope(Scope* scope) {
97     ASSERT(scope_ == NULL);
98     scope_ = scope;
99   }
SetCode(Handle<Code> code)100   void SetCode(Handle<Code> code) { code_ = code; }
SetExtension(v8::Extension * extension)101   void SetExtension(v8::Extension* extension) {
102     ASSERT(!is_lazy());
103     extension_ = extension;
104   }
SetPreParseData(ScriptDataImpl * pre_parse_data)105   void SetPreParseData(ScriptDataImpl* pre_parse_data) {
106     ASSERT(!is_lazy());
107     pre_parse_data_ = pre_parse_data;
108   }
SetCallingContext(Handle<Context> context)109   void SetCallingContext(Handle<Context> context) {
110     ASSERT(is_eval());
111     calling_context_ = context;
112   }
SetOsrAstId(int osr_ast_id)113   void SetOsrAstId(int osr_ast_id) {
114     ASSERT(IsOptimizing());
115     osr_ast_id_ = osr_ast_id;
116   }
117 
has_global_object()118   bool has_global_object() const {
119     return !closure().is_null() && (closure()->context()->global() != NULL);
120   }
121 
global_object()122   GlobalObject* global_object() const {
123     return has_global_object() ? closure()->context()->global() : NULL;
124   }
125 
126   // Accessors for the different compilation modes.
IsOptimizing()127   bool IsOptimizing() const { return mode_ == OPTIMIZE; }
IsOptimizable()128   bool IsOptimizable() const { return mode_ == BASE; }
SetOptimizing(int osr_ast_id)129   void SetOptimizing(int osr_ast_id) {
130     SetMode(OPTIMIZE);
131     osr_ast_id_ = osr_ast_id;
132   }
133   void DisableOptimization();
134 
135   // Deoptimization support.
HasDeoptimizationSupport()136   bool HasDeoptimizationSupport() const { return supports_deoptimization_; }
EnableDeoptimizationSupport()137   void EnableDeoptimizationSupport() {
138     ASSERT(IsOptimizable());
139     supports_deoptimization_ = true;
140   }
141 
142   // Determine whether or not we can adaptively optimize.
AllowOptimize()143   bool AllowOptimize() {
144     return V8::UseCrankshaft() && !closure_.is_null();
145   }
146 
147  private:
148   Isolate* isolate_;
149 
150   // Compilation mode.
151   // BASE is generated by the full codegen, optionally prepared for bailouts.
152   // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
153   // NONOPT is generated by the full codegen or the classic backend
154   //   and is not prepared for recompilation/bailouts. These functions
155   //   are never recompiled.
156   enum Mode {
157     BASE,
158     OPTIMIZE,
159     NONOPT
160   };
161 
CompilationInfo()162   CompilationInfo() : function_(NULL) {}
163 
Initialize(Mode mode)164   void Initialize(Mode mode) {
165     mode_ = V8::UseCrankshaft() ? mode : NONOPT;
166     if (script_->type()->value() == Script::TYPE_NATIVE) {
167       MarkAsNative();
168     }
169     if (!shared_info_.is_null() && shared_info_->strict_mode()) {
170       MarkAsStrictMode();
171     }
172   }
173 
SetMode(Mode mode)174   void SetMode(Mode mode) {
175     ASSERT(V8::UseCrankshaft());
176     mode_ = mode;
177   }
178 
179   // Flags using template class BitField<type, start, length>.  All are
180   // false by default.
181   //
182   // Compilation is either eager or lazy.
183   class IsLazy:   public BitField<bool, 0, 1> {};
184   // Flags that can be set for eager compilation.
185   class IsEval:   public BitField<bool, 1, 1> {};
186   class IsGlobal: public BitField<bool, 2, 1> {};
187   // Flags that can be set for lazy compilation.
188   class IsInLoop: public BitField<bool, 3, 1> {};
189   // Strict mode - used in eager compilation.
190   class IsStrictMode: public BitField<bool, 4, 1> {};
191   // Is this a function from our natives.
192   class IsNative: public BitField<bool, 6, 1> {};
193 
194   unsigned flags_;
195 
196   // Fields filled in by the compilation pipeline.
197   // AST filled in by the parser.
198   FunctionLiteral* function_;
199   // The scope of the function literal as a convenience.  Set to indicate
200   // that scopes have been analyzed.
201   Scope* scope_;
202   // The compiled code.
203   Handle<Code> code_;
204 
205   // Possible initial inputs to the compilation process.
206   Handle<JSFunction> closure_;
207   Handle<SharedFunctionInfo> shared_info_;
208   Handle<Script> script_;
209 
210   // Fields possibly needed for eager compilation, NULL by default.
211   v8::Extension* extension_;
212   ScriptDataImpl* pre_parse_data_;
213 
214   // The context of the caller is needed for eval code, and will be a null
215   // handle otherwise.
216   Handle<Context> calling_context_;
217 
218   // Compilation mode flag and whether deoptimization is allowed.
219   Mode mode_;
220   bool supports_deoptimization_;
221   int osr_ast_id_;
222 
223   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
224 };
225 
226 
227 // The V8 compiler
228 //
229 // General strategy: Source code is translated into an anonymous function w/o
230 // parameters which then can be executed. If the source code contains other
231 // functions, they will be compiled and allocated as part of the compilation
232 // of the source code.
233 
234 // Please note this interface returns shared function infos.  This means you
235 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
236 // real function with a context.
237 
238 class Compiler : public AllStatic {
239  public:
240   // Default maximum number of function optimization attempts before we
241   // give up.
242   static const int kDefaultMaxOptCount = 10;
243 
244   static const int kMaxInliningLevels = 3;
245 
246   // All routines return a SharedFunctionInfo.
247   // If an error occurs an exception is raised and the return handle
248   // contains NULL.
249 
250   // Compile a String source within a context.
251   static Handle<SharedFunctionInfo> Compile(Handle<String> source,
252                                             Handle<Object> script_name,
253                                             int line_offset,
254                                             int column_offset,
255                                             v8::Extension* extension,
256                                             ScriptDataImpl* pre_data,
257                                             Handle<Object> script_data,
258                                             NativesFlag is_natives_code);
259 
260   // Compile a String source within a context for Eval.
261   static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
262                                                 Handle<Context> context,
263                                                 bool is_global,
264                                                 StrictModeFlag strict_mode);
265 
266   // Compile from function info (used for lazy compilation). Returns true on
267   // success and false if the compilation resulted in a stack overflow.
268   static bool CompileLazy(CompilationInfo* info);
269 
270   // Compile a shared function info object (the function is possibly lazily
271   // compiled).
272   static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
273                                                       Handle<Script> script);
274 
275   // Set the function info for a newly compiled function.
276   static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
277                               FunctionLiteral* lit,
278                               bool is_toplevel,
279                               Handle<Script> script);
280 
281 #ifdef ENABLE_DEBUGGER_SUPPORT
282   static bool MakeCodeForLiveEdit(CompilationInfo* info);
283 #endif
284 
285   static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
286                                         CompilationInfo* info,
287                                         Handle<SharedFunctionInfo> shared);
288 };
289 
290 
291 // During compilation we need a global list of handles to constants
292 // for frame elements.  When the zone gets deleted, we make sure to
293 // clear this list of handles as well.
294 class CompilationZoneScope : public ZoneScope {
295  public:
CompilationZoneScope(ZoneScopeMode mode)296   explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
~CompilationZoneScope()297   virtual ~CompilationZoneScope() {
298     if (ShouldDeleteOnExit()) {
299       Isolate* isolate = Isolate::Current();
300       isolate->frame_element_constant_list()->Clear();
301       isolate->result_constant_list()->Clear();
302     }
303   }
304 };
305 
306 
307 } }  // namespace v8::internal
308 
309 #endif  // V8_COMPILER_H_
310