| 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 |