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
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.
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.
28 #ifndef V8_COMPILER_H_
29 #define V8_COMPILER_H_
31 #include "allocation.h"
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 {
44 explicit CompilationInfo(Handle<Script> script);
45 explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
46 explicit CompilationInfo(Handle<JSFunction> closure);
49 ASSERT(Isolate::Current() == isolate_);
52 bool is_lazy() const { return IsLazy::decode(flags_); }
53 bool is_eval() const { return IsEval::decode(flags_); }
54 bool is_global() const { return IsGlobal::decode(flags_); }
55 bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
56 bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; }
57 LanguageMode language_mode() const {
58 return LanguageModeField::decode(flags_);
60 bool is_in_loop() const { return IsInLoop::decode(flags_); }
61 bool is_qml_mode() const { return IsQmlMode::decode(flags_); }
62 FunctionLiteral* function() const { return function_; }
63 Scope* scope() const { return scope_; }
64 Scope* global_scope() const { return global_scope_; }
65 Handle<Code> code() const { return code_; }
66 Handle<JSFunction> closure() const { return closure_; }
67 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
68 Handle<Script> script() const { return script_; }
69 v8::Extension* extension() const { return extension_; }
70 ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
71 Handle<Context> calling_context() const { return calling_context_; }
72 int osr_ast_id() const { return osr_ast_id_; }
76 flags_ |= IsEval::encode(true);
80 flags_ |= IsGlobal::encode(true);
82 void SetLanguageMode(LanguageMode language_mode) {
83 ASSERT(this->language_mode() == CLASSIC_MODE ||
84 this->language_mode() == language_mode ||
85 language_mode == EXTENDED_MODE);
86 flags_ = LanguageModeField::update(flags_, language_mode);
90 flags_ |= IsInLoop::encode(true);
92 void MarkAsQmlMode() {
93 flags_ |= IsQmlMode::encode(true);
96 flags_ |= IsNative::encode(true);
98 bool is_native() const {
99 return IsNative::decode(flags_);
101 void SetFunction(FunctionLiteral* literal) {
102 ASSERT(function_ == NULL);
105 void SetScope(Scope* scope) {
106 ASSERT(scope_ == NULL);
109 void SetGlobalScope(Scope* global_scope) {
110 ASSERT(global_scope_ == NULL);
111 global_scope_ = global_scope;
113 void SetCode(Handle<Code> code) { code_ = code; }
114 void SetExtension(v8::Extension* extension) {
116 extension_ = extension;
118 void SetPreParseData(ScriptDataImpl* pre_parse_data) {
120 pre_parse_data_ = pre_parse_data;
122 void SetCallingContext(Handle<Context> context) {
124 calling_context_ = context;
126 void SetOsrAstId(int osr_ast_id) {
127 ASSERT(IsOptimizing());
128 osr_ast_id_ = osr_ast_id;
130 void MarkCompilingForDebugging(Handle<Code> current_code) {
131 ASSERT(mode_ != OPTIMIZE);
132 ASSERT(current_code->kind() == Code::FUNCTION);
133 flags_ |= IsCompilingForDebugging::encode(true);
134 if (current_code->is_compiled_optimizable()) {
135 EnableDeoptimizationSupport();
137 mode_ = CompilationInfo::NONOPT;
140 bool IsCompilingForDebugging() {
141 return IsCompilingForDebugging::decode(flags_);
144 bool has_global_object() const {
145 return !closure().is_null() && (closure()->context()->global() != NULL);
148 GlobalObject* global_object() const {
149 return has_global_object() ? closure()->context()->global() : NULL;
152 // Accessors for the different compilation modes.
153 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
154 bool IsOptimizable() const { return mode_ == BASE; }
155 void SetOptimizing(int osr_ast_id) {
157 osr_ast_id_ = osr_ast_id;
159 void DisableOptimization();
161 // Deoptimization support.
162 bool HasDeoptimizationSupport() const {
163 return SupportsDeoptimization::decode(flags_);
165 void EnableDeoptimizationSupport() {
166 ASSERT(IsOptimizable());
167 flags_ |= SupportsDeoptimization::encode(true);
170 // Determines whether or not to insert a self-optimization header.
171 bool ShouldSelfOptimize();
173 // Disable all optimization attempts of this info for the rest of the
174 // current compilation pipeline.
175 void AbortOptimization();
181 // BASE is generated by the full codegen, optionally prepared for bailouts.
182 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
183 // NONOPT is generated by the full codegen and is not prepared for
184 // recompilation/bailouts. These functions are never recompiled.
191 CompilationInfo() : function_(NULL) {}
193 void Initialize(Mode mode) {
194 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
195 ASSERT(!script_.is_null());
196 if (script_->type()->value() == Script::TYPE_NATIVE) {
199 if (!shared_info_.is_null()) {
200 ASSERT(language_mode() == CLASSIC_MODE);
201 SetLanguageMode(shared_info_->language_mode());
203 if (!shared_info_.is_null() && shared_info_->qml_mode()) {
208 void SetMode(Mode mode) {
209 ASSERT(V8::UseCrankshaft());
213 // Flags using template class BitField<type, start, length>. All are
216 // Compilation is either eager or lazy.
217 class IsLazy: public BitField<bool, 0, 1> {};
218 // Flags that can be set for eager compilation.
219 class IsEval: public BitField<bool, 1, 1> {};
220 class IsGlobal: public BitField<bool, 2, 1> {};
221 // Flags that can be set for lazy compilation.
222 class IsInLoop: public BitField<bool, 3, 1> {};
223 // Strict mode - used in eager compilation.
224 class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
225 // Is this a function from our natives.
226 class IsNative: public BitField<bool, 6, 1> {};
227 // Is this code being compiled with support for deoptimization..
228 class SupportsDeoptimization: public BitField<bool, 7, 1> {};
229 // If compiling for debugging produce just full code matching the
230 // initial mode setting.
231 class IsCompilingForDebugging: public BitField<bool, 8, 1> {};
233 class IsQmlMode: public BitField<bool, 9, 1> {};
237 // Fields filled in by the compilation pipeline.
238 // AST filled in by the parser.
239 FunctionLiteral* function_;
240 // The scope of the function literal as a convenience. Set to indicate
241 // that scopes have been analyzed.
243 // The global scope provided as a convenience.
244 Scope* global_scope_;
245 // The compiled code.
248 // Possible initial inputs to the compilation process.
249 Handle<JSFunction> closure_;
250 Handle<SharedFunctionInfo> shared_info_;
251 Handle<Script> script_;
253 // Fields possibly needed for eager compilation, NULL by default.
254 v8::Extension* extension_;
255 ScriptDataImpl* pre_parse_data_;
257 // The context of the caller is needed for eval code, and will be a null
259 Handle<Context> calling_context_;
261 // Compilation mode flag and whether deoptimization is allowed.
265 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
271 // General strategy: Source code is translated into an anonymous function w/o
272 // parameters which then can be executed. If the source code contains other
273 // functions, they will be compiled and allocated as part of the compilation
274 // of the source code.
276 // Please note this interface returns shared function infos. This means you
277 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
278 // real function with a context.
280 class Compiler : public AllStatic {
282 // Default maximum number of function optimization attempts before we
284 static const int kDefaultMaxOptCount = 10;
286 static const int kMaxInliningLevels = 3;
288 // Call count before primitive functions trigger their own optimization.
289 static const int kCallsUntilPrimitiveOpt = 200;
291 // All routines return a SharedFunctionInfo.
292 // If an error occurs an exception is raised and the return handle
295 // Compile a String source within a context.
296 static Handle<SharedFunctionInfo> Compile(Handle<String> source,
297 Handle<Object> script_name,
300 v8::Extension* extension,
301 ScriptDataImpl* pre_data,
302 Handle<Object> script_data,
303 NativesFlag is_natives_code,
304 v8::Script::CompileFlags = v8::Script::Default);
306 // Compile a String source within a context for Eval.
307 static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
308 Handle<Context> context,
310 LanguageMode language_mode,
314 // Compile from function info (used for lazy compilation). Returns true on
315 // success and false if the compilation resulted in a stack overflow.
316 static bool CompileLazy(CompilationInfo* info);
318 // Compile a shared function info object (the function is possibly lazily
320 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
321 Handle<Script> script);
323 // Set the function info for a newly compiled function.
324 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
325 FunctionLiteral* lit,
327 Handle<Script> script);
329 #ifdef ENABLE_DEBUGGER_SUPPORT
330 static bool MakeCodeForLiveEdit(CompilationInfo* info);
333 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
334 CompilationInfo* info,
335 Handle<SharedFunctionInfo> shared);
339 } } // namespace v8::internal
341 #endif // V8_COMPILER_H_