OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_COMPILER_H_ | 5 #ifndef V8_COMPILER_H_ |
6 #define V8_COMPILER_H_ | 6 #define V8_COMPILER_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/ast.h" | 9 #include "src/ast.h" |
10 #include "src/zone.h" | 10 #include "src/zone.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 } | 50 } |
51 | 51 |
52 private: | 52 private: |
53 bool owns_data_; | 53 bool owns_data_; |
54 const byte* data_; | 54 const byte* data_; |
55 int length_; | 55 int length_; |
56 | 56 |
57 DISALLOW_COPY_AND_ASSIGN(ScriptData); | 57 DISALLOW_COPY_AND_ASSIGN(ScriptData); |
58 }; | 58 }; |
59 | 59 |
60 | |
61 // CompilationInfo encapsulates some information known at compile time. It | 60 // CompilationInfo encapsulates some information known at compile time. It |
62 // is constructed based on the resources available at compile-time. | 61 // is constructed based on the resources available at compile-time. |
63 class CompilationInfo { | 62 class CompilationInfo { |
64 public: | 63 public: |
| 64 // Various configuration flags for a compilation, as well as some properties |
| 65 // of the compiled code produced by a compilation. |
| 66 enum Flag { |
| 67 kLazy = 1 << 0, |
| 68 kEval = 1 << 1, |
| 69 kGlobal = 1 << 2, |
| 70 kStrictMode = 1 << 3, |
| 71 kThisHasUses = 1 << 4, |
| 72 kNative = 1 << 5, |
| 73 kDeferredCalling = 1 << 6, |
| 74 kNonDeferredCalling = 1 << 7, |
| 75 kSavesCallerDoubles = 1 << 8, |
| 76 kRequiresFrame = 1 << 9, |
| 77 kMustNotHaveEagerFrame = 1 << 10, |
| 78 kDeoptimizationSupport = 1 << 11, |
| 79 kDebug = 1 << 12, |
| 80 kCompilingForDebugging = 1 << 13, |
| 81 kParseRestriction = 1 << 14, |
| 82 kSerializing = 1 << 15 |
| 83 }; |
| 84 |
65 CompilationInfo(Handle<JSFunction> closure, Zone* zone); | 85 CompilationInfo(Handle<JSFunction> closure, Zone* zone); |
66 CompilationInfo(Isolate* isolate, Zone* zone); | 86 CompilationInfo(Isolate* isolate, Zone* zone); |
67 virtual ~CompilationInfo(); | 87 virtual ~CompilationInfo(); |
68 | 88 |
69 Isolate* isolate() const { | 89 Isolate* isolate() const { |
70 return isolate_; | 90 return isolate_; |
71 } | 91 } |
72 Zone* zone() { return zone_; } | 92 Zone* zone() { return zone_; } |
73 bool is_osr() const { return !osr_ast_id_.IsNone(); } | 93 bool is_osr() const { return !osr_ast_id_.IsNone(); } |
74 bool is_lazy() const { return IsLazy::decode(flags_); } | 94 bool is_lazy() const { return GetFlag(kLazy); } |
75 bool is_eval() const { return IsEval::decode(flags_); } | 95 bool is_eval() const { return GetFlag(kEval); } |
76 bool is_global() const { return IsGlobal::decode(flags_); } | 96 bool is_global() const { return GetFlag(kGlobal); } |
77 StrictMode strict_mode() const { return StrictModeField::decode(flags_); } | 97 StrictMode strict_mode() const { |
| 98 return GetFlag(kStrictMode) ? STRICT : SLOPPY; |
| 99 } |
78 FunctionLiteral* function() const { return function_; } | 100 FunctionLiteral* function() const { return function_; } |
79 Scope* scope() const { return scope_; } | 101 Scope* scope() const { return scope_; } |
80 Scope* global_scope() const { return global_scope_; } | 102 Scope* global_scope() const { return global_scope_; } |
81 Handle<Code> code() const { return code_; } | 103 Handle<Code> code() const { return code_; } |
82 Handle<JSFunction> closure() const { return closure_; } | 104 Handle<JSFunction> closure() const { return closure_; } |
83 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } | 105 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } |
84 Handle<Script> script() const { return script_; } | 106 Handle<Script> script() const { return script_; } |
85 HydrogenCodeStub* code_stub() const {return code_stub_; } | 107 HydrogenCodeStub* code_stub() const {return code_stub_; } |
86 v8::Extension* extension() const { return extension_; } | 108 v8::Extension* extension() const { return extension_; } |
87 ScriptData** cached_data() const { return cached_data_; } | 109 ScriptData** cached_data() const { return cached_data_; } |
88 ScriptCompiler::CompileOptions compile_options() const { | 110 ScriptCompiler::CompileOptions compile_options() const { |
89 return compile_options_; | 111 return compile_options_; |
90 } | 112 } |
91 Handle<Context> context() const { return context_; } | 113 Handle<Context> context() const { return context_; } |
92 BailoutId osr_ast_id() const { return osr_ast_id_; } | 114 BailoutId osr_ast_id() const { return osr_ast_id_; } |
93 Handle<Code> unoptimized_code() const { return unoptimized_code_; } | 115 Handle<Code> unoptimized_code() const { return unoptimized_code_; } |
94 int opt_count() const { return opt_count_; } | 116 int opt_count() const { return opt_count_; } |
95 int num_parameters() const; | 117 int num_parameters() const; |
96 int num_heap_slots() const; | 118 int num_heap_slots() const; |
97 Code::Flags flags() const; | 119 Code::Flags flags() const; |
98 | 120 |
99 void MarkAsEval() { | 121 void MarkAsEval() { |
100 DCHECK(!is_lazy()); | 122 DCHECK(!is_lazy()); |
101 flags_ |= IsEval::encode(true); | 123 SetFlag(kEval); |
102 } | 124 } |
103 | 125 |
104 void MarkAsGlobal() { | 126 void MarkAsGlobal() { |
105 DCHECK(!is_lazy()); | 127 DCHECK(!is_lazy()); |
106 flags_ |= IsGlobal::encode(true); | 128 SetFlag(kGlobal); |
107 } | 129 } |
108 | 130 |
109 void set_parameter_count(int parameter_count) { | 131 void set_parameter_count(int parameter_count) { |
110 DCHECK(IsStub()); | 132 DCHECK(IsStub()); |
111 parameter_count_ = parameter_count; | 133 parameter_count_ = parameter_count; |
112 } | 134 } |
113 | 135 |
114 void set_this_has_uses(bool has_no_uses) { | 136 void set_this_has_uses(bool has_no_uses) { |
115 this_has_uses_ = has_no_uses; | 137 SetFlag(kThisHasUses, has_no_uses); |
116 } | 138 } |
117 | 139 |
118 bool this_has_uses() { | 140 bool this_has_uses() { return GetFlag(kThisHasUses); } |
119 return this_has_uses_; | 141 |
| 142 void SetStrictMode(StrictMode strict_mode) { |
| 143 SetFlag(kStrictMode, strict_mode == STRICT); |
120 } | 144 } |
121 | 145 |
122 void SetStrictMode(StrictMode strict_mode) { | 146 void MarkAsNative() { SetFlag(kNative); } |
123 DCHECK(this->strict_mode() == SLOPPY || this->strict_mode() == strict_mode); | 147 |
124 flags_ = StrictModeField::update(flags_, strict_mode); | 148 bool is_native() const { return GetFlag(kNative); } |
| 149 |
| 150 bool is_calling() const { |
| 151 return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling); |
125 } | 152 } |
126 | 153 |
127 void MarkAsNative() { | 154 void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); } |
128 flags_ |= IsNative::encode(true); | 155 |
| 156 bool is_deferred_calling() const { return GetFlag(kDeferredCalling); } |
| 157 |
| 158 void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); } |
| 159 |
| 160 bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); } |
| 161 |
| 162 void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); } |
| 163 |
| 164 bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); } |
| 165 |
| 166 void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); } |
| 167 |
| 168 bool requires_frame() const { return GetFlag(kRequiresFrame); } |
| 169 |
| 170 void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); } |
| 171 |
| 172 bool GetMustNotHaveEagerFrame() const { |
| 173 return GetFlag(kMustNotHaveEagerFrame); |
129 } | 174 } |
130 | 175 |
131 bool is_native() const { | 176 void MarkAsDebug() { SetFlag(kDebug); } |
132 return IsNative::decode(flags_); | |
133 } | |
134 | 177 |
135 bool is_calling() const { | 178 bool is_debug() const { return GetFlag(kDebug); } |
136 return is_deferred_calling() || is_non_deferred_calling(); | |
137 } | |
138 | 179 |
139 void MarkAsDeferredCalling() { | 180 void PrepareForSerializing() { SetFlag(kSerializing); } |
140 flags_ |= IsDeferredCalling::encode(true); | |
141 } | |
142 | 181 |
143 bool is_deferred_calling() const { | 182 bool will_serialize() const { return GetFlag(kSerializing); } |
144 return IsDeferredCalling::decode(flags_); | |
145 } | |
146 | |
147 void MarkAsNonDeferredCalling() { | |
148 flags_ |= IsNonDeferredCalling::encode(true); | |
149 } | |
150 | |
151 bool is_non_deferred_calling() const { | |
152 return IsNonDeferredCalling::decode(flags_); | |
153 } | |
154 | |
155 void MarkAsSavesCallerDoubles() { | |
156 flags_ |= SavesCallerDoubles::encode(true); | |
157 } | |
158 | |
159 bool saves_caller_doubles() const { | |
160 return SavesCallerDoubles::decode(flags_); | |
161 } | |
162 | |
163 void MarkAsRequiresFrame() { | |
164 flags_ |= RequiresFrame::encode(true); | |
165 } | |
166 | |
167 bool requires_frame() const { | |
168 return RequiresFrame::decode(flags_); | |
169 } | |
170 | |
171 void MarkMustNotHaveEagerFrame() { | |
172 flags_ |= MustNotHaveEagerFrame::encode(true); | |
173 } | |
174 | |
175 bool GetMustNotHaveEagerFrame() const { | |
176 return MustNotHaveEagerFrame::decode(flags_); | |
177 } | |
178 | |
179 void MarkAsDebug() { | |
180 flags_ |= IsDebug::encode(true); | |
181 } | |
182 | |
183 bool is_debug() const { | |
184 return IsDebug::decode(flags_); | |
185 } | |
186 | |
187 void PrepareForSerializing() { | |
188 flags_ |= PrepareForSerializing::encode(true); | |
189 } | |
190 | |
191 bool will_serialize() const { return PrepareForSerializing::decode(flags_); } | |
192 | 183 |
193 bool IsCodePreAgingActive() const { | 184 bool IsCodePreAgingActive() const { |
194 return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() && | 185 return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() && |
195 !is_debug(); | 186 !is_debug(); |
196 } | 187 } |
197 | 188 |
198 void SetParseRestriction(ParseRestriction restriction) { | 189 void SetParseRestriction(ParseRestriction restriction) { |
199 flags_ = ParseRestricitonField::update(flags_, restriction); | 190 SetFlag(kParseRestriction, restriction != NO_PARSE_RESTRICTION); |
200 } | 191 } |
201 | 192 |
202 ParseRestriction parse_restriction() const { | 193 ParseRestriction parse_restriction() const { |
203 return ParseRestricitonField::decode(flags_); | 194 return GetFlag(kParseRestriction) ? ONLY_SINGLE_FUNCTION_LITERAL |
| 195 : NO_PARSE_RESTRICTION; |
204 } | 196 } |
205 | 197 |
206 void SetFunction(FunctionLiteral* literal) { | 198 void SetFunction(FunctionLiteral* literal) { |
207 DCHECK(function_ == NULL); | 199 DCHECK(function_ == NULL); |
208 function_ = literal; | 200 function_ = literal; |
209 } | 201 } |
210 void PrepareForCompilation(Scope* scope); | 202 void PrepareForCompilation(Scope* scope); |
211 void SetGlobalScope(Scope* global_scope) { | 203 void SetGlobalScope(Scope* global_scope) { |
212 DCHECK(global_scope_ == NULL); | 204 DCHECK(global_scope_ == NULL); |
213 global_scope_ = global_scope; | 205 global_scope_ = global_scope; |
(...skipping 13 matching lines...) Expand all Loading... |
227 cached_data_ = NULL; | 219 cached_data_ = NULL; |
228 } else { | 220 } else { |
229 DCHECK(!is_lazy()); | 221 DCHECK(!is_lazy()); |
230 cached_data_ = cached_data; | 222 cached_data_ = cached_data; |
231 } | 223 } |
232 } | 224 } |
233 void SetContext(Handle<Context> context) { | 225 void SetContext(Handle<Context> context) { |
234 context_ = context; | 226 context_ = context; |
235 } | 227 } |
236 | 228 |
237 void MarkCompilingForDebugging() { | 229 void MarkCompilingForDebugging() { SetFlag(kCompilingForDebugging); } |
238 flags_ |= IsCompilingForDebugging::encode(true); | 230 bool IsCompilingForDebugging() { return GetFlag(kCompilingForDebugging); } |
239 } | |
240 bool IsCompilingForDebugging() { | |
241 return IsCompilingForDebugging::decode(flags_); | |
242 } | |
243 void MarkNonOptimizable() { | 231 void MarkNonOptimizable() { |
244 SetMode(CompilationInfo::NONOPT); | 232 SetMode(CompilationInfo::NONOPT); |
245 } | 233 } |
246 | 234 |
247 bool ShouldTrapOnDeopt() const { | 235 bool ShouldTrapOnDeopt() const { |
248 return (FLAG_trap_on_deopt && IsOptimizing()) || | 236 return (FLAG_trap_on_deopt && IsOptimizing()) || |
249 (FLAG_trap_on_stub_deopt && IsStub()); | 237 (FLAG_trap_on_stub_deopt && IsStub()); |
250 } | 238 } |
251 | 239 |
252 bool has_global_object() const { | 240 bool has_global_object() const { |
(...skipping 13 matching lines...) Expand all Loading... |
266 DCHECK(!shared_info_.is_null()); | 254 DCHECK(!shared_info_.is_null()); |
267 SetMode(OPTIMIZE); | 255 SetMode(OPTIMIZE); |
268 osr_ast_id_ = osr_ast_id; | 256 osr_ast_id_ = osr_ast_id; |
269 unoptimized_code_ = unoptimized; | 257 unoptimized_code_ = unoptimized; |
270 optimization_id_ = isolate()->NextOptimizationId(); | 258 optimization_id_ = isolate()->NextOptimizationId(); |
271 } | 259 } |
272 void DisableOptimization(); | 260 void DisableOptimization(); |
273 | 261 |
274 // Deoptimization support. | 262 // Deoptimization support. |
275 bool HasDeoptimizationSupport() const { | 263 bool HasDeoptimizationSupport() const { |
276 return SupportsDeoptimization::decode(flags_); | 264 return GetFlag(kDeoptimizationSupport); |
277 } | 265 } |
278 void EnableDeoptimizationSupport() { | 266 void EnableDeoptimizationSupport() { |
279 DCHECK(IsOptimizable()); | 267 DCHECK(IsOptimizable()); |
280 flags_ |= SupportsDeoptimization::encode(true); | 268 SetFlag(kDeoptimizationSupport); |
281 } | 269 } |
282 | 270 |
283 // Determines whether or not to insert a self-optimization header. | 271 // Determines whether or not to insert a self-optimization header. |
284 bool ShouldSelfOptimize(); | 272 bool ShouldSelfOptimize(); |
285 | 273 |
286 void set_deferred_handles(DeferredHandles* deferred_handles) { | 274 void set_deferred_handles(DeferredHandles* deferred_handles) { |
287 DCHECK(deferred_handles_ == NULL); | 275 DCHECK(deferred_handles_ == NULL); |
288 deferred_handles_ = deferred_handles; | 276 deferred_handles_ = deferred_handles; |
289 } | 277 } |
290 | 278 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 NONOPT, | 378 NONOPT, |
391 STUB | 379 STUB |
392 }; | 380 }; |
393 | 381 |
394 void Initialize(Isolate* isolate, Mode mode, Zone* zone); | 382 void Initialize(Isolate* isolate, Mode mode, Zone* zone); |
395 | 383 |
396 void SetMode(Mode mode) { | 384 void SetMode(Mode mode) { |
397 mode_ = mode; | 385 mode_ = mode; |
398 } | 386 } |
399 | 387 |
400 // Flags using template class BitField<type, start, length>. All are | 388 void SetFlag(Flag flag) { flags_ |= flag; } |
401 // false by default. | 389 |
402 // | 390 void SetFlag(Flag flag, bool value) { |
403 // Compilation is either eager or lazy. | 391 flags_ = value ? flags_ | flag : flags_ & ~flag; |
404 class IsLazy: public BitField<bool, 0, 1> {}; | 392 } |
405 // Flags that can be set for eager compilation. | 393 |
406 class IsEval: public BitField<bool, 1, 1> {}; | 394 bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; } |
407 class IsGlobal: public BitField<bool, 2, 1> {}; | |
408 // If the function is being compiled for the debugger. | |
409 class IsDebug: public BitField<bool, 3, 1> {}; | |
410 // Strict mode - used in eager compilation. | |
411 class StrictModeField: public BitField<StrictMode, 4, 1> {}; | |
412 // Is this a function from our natives. | |
413 class IsNative: public BitField<bool, 5, 1> {}; | |
414 // Is this code being compiled with support for deoptimization.. | |
415 class SupportsDeoptimization: public BitField<bool, 6, 1> {}; | |
416 // If compiling for debugging produce just full code matching the | |
417 // initial mode setting. | |
418 class IsCompilingForDebugging: public BitField<bool, 7, 1> {}; | |
419 // If the compiled code contains calls that require building a frame | |
420 class IsCalling: public BitField<bool, 8, 1> {}; | |
421 // If the compiled code contains calls that require building a frame | |
422 class IsDeferredCalling: public BitField<bool, 9, 1> {}; | |
423 // If the compiled code contains calls that require building a frame | |
424 class IsNonDeferredCalling: public BitField<bool, 10, 1> {}; | |
425 // If the compiled code saves double caller registers that it clobbers. | |
426 class SavesCallerDoubles: public BitField<bool, 11, 1> {}; | |
427 // If the set of valid statements is restricted. | |
428 class ParseRestricitonField: public BitField<ParseRestriction, 12, 1> {}; | |
429 // If the function requires a frame (for unspecified reasons) | |
430 class RequiresFrame: public BitField<bool, 13, 1> {}; | |
431 // If the function cannot build a frame (for unspecified reasons) | |
432 class MustNotHaveEagerFrame: public BitField<bool, 14, 1> {}; | |
433 // If we plan to serialize the compiled code. | |
434 class PrepareForSerializing : public BitField<bool, 15, 1> {}; | |
435 | 395 |
436 unsigned flags_; | 396 unsigned flags_; |
437 | 397 |
438 // Fields filled in by the compilation pipeline. | 398 // Fields filled in by the compilation pipeline. |
439 // AST filled in by the parser. | 399 // AST filled in by the parser. |
440 FunctionLiteral* function_; | 400 FunctionLiteral* function_; |
441 // The scope of the function literal as a convenience. Set to indicate | 401 // The scope of the function literal as a convenience. Set to indicate |
442 // that scopes have been analyzed. | 402 // that scopes have been analyzed. |
443 Scope* scope_; | 403 Scope* scope_; |
444 // The global scope provided as a convenience. | 404 // The global scope provided as a convenience. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 | 458 |
499 List<OffsetRange>* no_frame_ranges_; | 459 List<OffsetRange>* no_frame_ranges_; |
500 | 460 |
501 // A copy of shared_info()->opt_count() to avoid handle deref | 461 // A copy of shared_info()->opt_count() to avoid handle deref |
502 // during graph optimization. | 462 // during graph optimization. |
503 int opt_count_; | 463 int opt_count_; |
504 | 464 |
505 // Number of parameters used for compilation of stubs that require arguments. | 465 // Number of parameters used for compilation of stubs that require arguments. |
506 int parameter_count_; | 466 int parameter_count_; |
507 | 467 |
508 bool this_has_uses_; | |
509 | |
510 Handle<Foreign> object_wrapper_; | 468 Handle<Foreign> object_wrapper_; |
511 | 469 |
512 int optimization_id_; | 470 int optimization_id_; |
513 | 471 |
514 AstValueFactory* ast_value_factory_; | 472 AstValueFactory* ast_value_factory_; |
515 bool ast_value_factory_owned_; | 473 bool ast_value_factory_owned_; |
516 AstNode::IdGen ast_node_id_gen_; | 474 AstNode::IdGen ast_node_id_gen_; |
517 | 475 |
518 DISALLOW_COPY_AND_ASSIGN(CompilationInfo); | 476 DISALLOW_COPY_AND_ASSIGN(CompilationInfo); |
519 }; | 477 }; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 Zone zone_; | 697 Zone zone_; |
740 unsigned info_zone_start_allocation_size_; | 698 unsigned info_zone_start_allocation_size_; |
741 base::ElapsedTimer timer_; | 699 base::ElapsedTimer timer_; |
742 | 700 |
743 DISALLOW_COPY_AND_ASSIGN(CompilationPhase); | 701 DISALLOW_COPY_AND_ASSIGN(CompilationPhase); |
744 }; | 702 }; |
745 | 703 |
746 } } // namespace v8::internal | 704 } } // namespace v8::internal |
747 | 705 |
748 #endif // V8_COMPILER_H_ | 706 #endif // V8_COMPILER_H_ |
OLD | NEW |