blob: 1176c6941a2c12fb029b0e082a4b6b293bc336c5 [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; }
Ben Murdochf87a2032010-10-22 12:50:53 +010052 bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
53 FunctionLiteral* function() const { return function_; }
54 Scope* scope() const { return scope_; }
55 Handle<Code> code() const { return code_; }
56 Handle<JSFunction> closure() const { return closure_; }
57 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
58 Handle<Script> script() const { return script_; }
59 v8::Extension* extension() const { return extension_; }
60 ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
61 Handle<Context> calling_context() const { return calling_context_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +010062 int osr_ast_id() const { return osr_ast_id_; }
Ben Murdochf87a2032010-10-22 12:50:53 +010063
64 void MarkAsEval() {
65 ASSERT(!is_lazy());
66 flags_ |= IsEval::encode(true);
Leon Clarke4515c472010-02-03 11:58:03 +000067 }
Ben Murdochf87a2032010-10-22 12:50:53 +010068 void MarkAsGlobal() {
69 ASSERT(!is_lazy());
70 flags_ |= IsGlobal::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000071 }
Ben Murdochf87a2032010-10-22 12:50:53 +010072 void MarkAsInLoop() {
73 ASSERT(is_lazy());
74 flags_ |= IsInLoop::encode(true);
Andrei Popescu31002712010-02-23 13:46:05 +000075 }
Ben Murdochf87a2032010-10-22 12:50:53 +010076 void SetFunction(FunctionLiteral* literal) {
77 ASSERT(function_ == NULL);
78 function_ = literal;
Andrei Popescu31002712010-02-23 13:46:05 +000079 }
Ben Murdochf87a2032010-10-22 12:50:53 +010080 void SetScope(Scope* scope) {
81 ASSERT(scope_ == NULL);
82 scope_ = scope;
Andrei Popescu31002712010-02-23 13:46:05 +000083 }
Ben Murdochf87a2032010-10-22 12:50:53 +010084 void SetCode(Handle<Code> code) { code_ = code; }
85 void SetExtension(v8::Extension* extension) {
86 ASSERT(!is_lazy());
87 extension_ = extension;
Andrei Popescu31002712010-02-23 13:46:05 +000088 }
Ben Murdochf87a2032010-10-22 12:50:53 +010089 void SetPreParseData(ScriptDataImpl* pre_parse_data) {
90 ASSERT(!is_lazy());
91 pre_parse_data_ = pre_parse_data;
92 }
93 void SetCallingContext(Handle<Context> context) {
94 ASSERT(is_eval());
95 calling_context_ = context;
96 }
Ben Murdochb0fe1622011-05-05 13:52:32 +010097 void SetOsrAstId(int osr_ast_id) {
98 ASSERT(IsOptimizing());
99 osr_ast_id_ = osr_ast_id;
100 }
101
102 bool has_global_object() const {
103 return !closure().is_null() && (closure()->context()->global() != NULL);
104 }
105
106 GlobalObject* global_object() const {
107 return has_global_object() ? closure()->context()->global() : NULL;
108 }
109
110 // Accessors for the different compilation modes.
111 bool IsOptimizing() const { return mode_ == OPTIMIZE; }
112 bool IsOptimizable() const { return mode_ == BASE; }
113 void SetOptimizing(int osr_ast_id) {
114 SetMode(OPTIMIZE);
115 osr_ast_id_ = osr_ast_id;
116 }
117 void DisableOptimization() { SetMode(NONOPT); }
118
119 // Deoptimization support.
120 bool HasDeoptimizationSupport() const { return supports_deoptimization_; }
121 void EnableDeoptimizationSupport() {
122 ASSERT(IsOptimizable());
123 supports_deoptimization_ = true;
124 }
125
126 // Determine whether or not we can adaptively optimize.
127 bool AllowOptimize() {
128 return V8::UseCrankshaft() &&
129 !closure_.is_null() &&
130 function_->AllowOptimize();
131 }
Andrei Popescu31002712010-02-23 13:46:05 +0000132
Leon Clarke4515c472010-02-03 11:58:03 +0000133 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100134 // Compilation mode.
135 // BASE is generated by the full codegen, optionally prepared for bailouts.
136 // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
137 // NONOPT is generated by the full codegen or the classic backend
138 // and is not prepared for recompilation/bailouts. These functions
139 // are never recompiled.
140 enum Mode {
141 BASE,
142 OPTIMIZE,
143 NONOPT
144 };
145
146 CompilationInfo() : function_(NULL) {}
147
148 void Initialize(Mode mode) {
149 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
150 }
151
152 void SetMode(Mode mode) {
153 ASSERT(V8::UseCrankshaft());
154 mode_ = mode;
155 }
156
Ben Murdochf87a2032010-10-22 12:50:53 +0100157 // Flags using template class BitField<type, start, length>. All are
158 // false by default.
159 //
160 // Compilation is either eager or lazy.
161 class IsLazy: public BitField<bool, 0, 1> {};
162 // Flags that can be set for eager compilation.
163 class IsEval: public BitField<bool, 1, 1> {};
164 class IsGlobal: public BitField<bool, 2, 1> {};
Ben Murdochf87a2032010-10-22 12:50:53 +0100165 // Flags that can be set for lazy compilation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800166 class IsInLoop: public BitField<bool, 3, 1> {};
Andrei Popescu31002712010-02-23 13:46:05 +0000167
Ben Murdochf87a2032010-10-22 12:50:53 +0100168 unsigned flags_;
169
170 // Fields filled in by the compilation pipeline.
171 // AST filled in by the parser.
172 FunctionLiteral* function_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800173 // The scope of the function literal as a convenience. Set to indicate
Ben Murdochf87a2032010-10-22 12:50:53 +0100174 // that scopes have been analyzed.
175 Scope* scope_;
176 // The compiled code.
177 Handle<Code> code_;
178
179 // Possible initial inputs to the compilation process.
Andrei Popescu31002712010-02-23 13:46:05 +0000180 Handle<JSFunction> closure_;
Leon Clarke4515c472010-02-03 11:58:03 +0000181 Handle<SharedFunctionInfo> shared_info_;
Andrei Popescu31002712010-02-23 13:46:05 +0000182 Handle<Script> script_;
183
Ben Murdochf87a2032010-10-22 12:50:53 +0100184 // Fields possibly needed for eager compilation, NULL by default.
185 v8::Extension* extension_;
186 ScriptDataImpl* pre_parse_data_;
Andrei Popescu31002712010-02-23 13:46:05 +0000187
Ben Murdochf87a2032010-10-22 12:50:53 +0100188 // The context of the caller is needed for eval code, and will be a null
189 // handle otherwise.
190 Handle<Context> calling_context_;
Andrei Popescu31002712010-02-23 13:46:05 +0000191
Ben Murdochb0fe1622011-05-05 13:52:32 +0100192 // Compilation mode flag and whether deoptimization is allowed.
193 Mode mode_;
194 bool supports_deoptimization_;
195 int osr_ast_id_;
196
Andrei Popescu31002712010-02-23 13:46:05 +0000197 DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
Leon Clarke4515c472010-02-03 11:58:03 +0000198};
199
200
Steve Blocka7e24c12009-10-30 11:49:00 +0000201// The V8 compiler
202//
203// General strategy: Source code is translated into an anonymous function w/o
204// parameters which then can be executed. If the source code contains other
205// functions, they will be compiled and allocated as part of the compilation
206// of the source code.
207
Ben Murdochf87a2032010-10-22 12:50:53 +0100208// Please note this interface returns shared function infos. This means you
209// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
210// real function with a context.
Steve Blocka7e24c12009-10-30 11:49:00 +0000211
212class Compiler : public AllStatic {
213 public:
Steve Blocka7e24c12009-10-30 11:49:00 +0000214 // All routines return a JSFunction.
215 // If an error occurs an exception is raised and
216 // the return handle contains NULL.
217
218 // Compile a String source within a context.
Steve Block6ded16b2010-05-10 14:33:55 +0100219 static Handle<SharedFunctionInfo> Compile(Handle<String> source,
220 Handle<Object> script_name,
221 int line_offset,
222 int column_offset,
223 v8::Extension* extension,
224 ScriptDataImpl* pre_data,
225 Handle<Object> script_data,
226 NativesFlag is_natives_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000227
228 // Compile a String source within a context for Eval.
Steve Block6ded16b2010-05-10 14:33:55 +0100229 static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
230 Handle<Context> context,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800231 bool is_global);
Steve Blocka7e24c12009-10-30 11:49:00 +0000232
Ben Murdochf87a2032010-10-22 12:50:53 +0100233 // Compile from function info (used for lazy compilation). Returns true on
234 // success and false if the compilation resulted in a stack overflow.
Leon Clarke4515c472010-02-03 11:58:03 +0000235 static bool CompileLazy(CompilationInfo* info);
Steve Blockd0582a62009-12-15 09:54:21 +0000236
Ben Murdochf87a2032010-10-22 12:50:53 +0100237 // Compile a shared function info object (the function is possibly lazily
238 // compiled).
Steve Block6ded16b2010-05-10 14:33:55 +0100239 static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
Ben Murdochf87a2032010-10-22 12:50:53 +0100240 Handle<Script> script);
Steve Blockd0582a62009-12-15 09:54:21 +0000241
242 // Set the function info for a newly compiled function.
Steve Block6ded16b2010-05-10 14:33:55 +0100243 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000244 FunctionLiteral* lit,
245 bool is_toplevel,
246 Handle<Script> script);
Andrei Popescu31002712010-02-23 13:46:05 +0000247
Ben Murdochf87a2032010-10-22 12:50:53 +0100248#ifdef ENABLE_DEBUGGER_SUPPORT
249 static bool MakeCodeForLiveEdit(CompilationInfo* info);
250#endif
251
Steve Block6ded16b2010-05-10 14:33:55 +0100252 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
253 Handle<String> name,
Steve Block6ded16b2010-05-10 14:33:55 +0100254 int start_position,
Ben Murdochf87a2032010-10-22 12:50:53 +0100255 CompilationInfo* info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000256};
257
258
Steve Blocka7e24c12009-10-30 11:49:00 +0000259// During compilation we need a global list of handles to constants
260// for frame elements. When the zone gets deleted, we make sure to
261// clear this list of handles as well.
262class CompilationZoneScope : public ZoneScope {
263 public:
264 explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
265 virtual ~CompilationZoneScope() {
266 if (ShouldDeleteOnExit()) {
267 FrameElement::ClearConstantList();
268 Result::ClearConstantList();
269 }
270 }
271};
272
273
274} } // namespace v8::internal
275
276#endif // V8_COMPILER_H_