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 #include "src/v8.h" | 5 #include "src/compiler.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include <algorithm> |
8 | 8 |
9 #include "src/ast-numbering.h" | 9 #include "src/ast-numbering.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
11 #include "src/codegen.h" | 11 #include "src/codegen.h" |
12 #include "src/compilation-cache.h" | 12 #include "src/compilation-cache.h" |
13 #include "src/compiler/pipeline.h" | 13 #include "src/compiler/pipeline.h" |
14 #include "src/cpu-profiler.h" | 14 #include "src/cpu-profiler.h" |
15 #include "src/debug.h" | 15 #include "src/debug.h" |
16 #include "src/deoptimizer.h" | 16 #include "src/deoptimizer.h" |
17 #include "src/full-codegen.h" | 17 #include "src/full-codegen.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 #undef PARSE_INFO_GETTER | 74 #undef PARSE_INFO_GETTER |
75 #undef PARSE_INFO_GETTER_WITH_DEFAULT | 75 #undef PARSE_INFO_GETTER_WITH_DEFAULT |
76 | 76 |
77 | 77 |
78 bool CompilationInfo::has_shared_info() const { | 78 bool CompilationInfo::has_shared_info() const { |
79 return parse_info_ && !parse_info_->shared_info().is_null(); | 79 return parse_info_ && !parse_info_->shared_info().is_null(); |
80 } | 80 } |
81 | 81 |
82 | 82 |
83 CompilationInfo::CompilationInfo(ParseInfo* parse_info) | 83 CompilationInfo::CompilationInfo(ParseInfo* parse_info) |
84 : parse_info_(parse_info), | 84 : CompilationInfo(parse_info, nullptr, BASE, parse_info->isolate(), |
85 flags_(0), | 85 parse_info->zone()) { |
86 osr_ast_id_(BailoutId::None()), | |
87 parameter_count_(0), | |
88 optimization_id_(-1), | |
89 aborted_due_to_dependency_change_(false), | |
90 osr_expr_stack_height_(0) { | |
91 Initialize(parse_info->isolate(), BASE, parse_info->zone()); | |
92 } | |
93 | |
94 | |
95 CompilationInfo::CompilationInfo(CodeStub* stub, Isolate* isolate, Zone* zone) | |
96 : parse_info_(nullptr), | |
97 flags_(0), | |
98 osr_ast_id_(BailoutId::None()), | |
99 parameter_count_(0), | |
100 optimization_id_(-1), | |
101 aborted_due_to_dependency_change_(false), | |
102 osr_expr_stack_height_(0) { | |
103 Initialize(isolate, STUB, zone); | |
104 code_stub_ = stub; | |
105 } | |
106 | |
107 | |
108 void CompilationInfo::Initialize(Isolate* isolate, | |
109 Mode mode, | |
110 Zone* zone) { | |
111 isolate_ = isolate; | |
112 zone_ = zone; | |
113 deferred_handles_ = NULL; | |
114 code_stub_ = NULL; | |
115 prologue_offset_ = Code::kPrologueOffsetNotSet; | |
116 opt_count_ = has_shared_info() ? shared_info()->opt_count() : 0; | |
117 no_frame_ranges_ = isolate->cpu_profiler()->is_profiling() | |
118 ? new List<OffsetRange>(2) : NULL; | |
119 if (FLAG_hydrogen_track_positions) { | |
120 inlined_function_infos_ = new std::vector<InlinedFunctionInfo>(); | |
121 track_positions_ = true; | |
122 } else { | |
123 inlined_function_infos_ = NULL; | |
124 track_positions_ = false; | |
125 } | |
126 | |
127 for (int i = 0; i < DependentCode::kGroupCount; i++) { | |
128 dependencies_[i] = NULL; | |
129 } | |
130 if (mode == STUB) { | |
131 mode_ = STUB; | |
132 return; | |
133 } | |
134 mode_ = mode; | |
135 // Compiling for the snapshot typically results in different code than | 86 // Compiling for the snapshot typically results in different code than |
136 // compiling later on. This means that code recompiled with deoptimization | 87 // compiling later on. This means that code recompiled with deoptimization |
137 // support won't be "equivalent" (as defined by SharedFunctionInfo:: | 88 // support won't be "equivalent" (as defined by SharedFunctionInfo:: |
138 // EnableDeoptimizationSupport), so it will replace the old code and all | 89 // EnableDeoptimizationSupport), so it will replace the old code and all |
139 // its type feedback. To avoid this, always compile functions in the snapshot | 90 // its type feedback. To avoid this, always compile functions in the snapshot |
140 // with deoptimization support. | 91 // with deoptimization support. |
141 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport(); | 92 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport(); |
142 | 93 |
143 if (isolate_->debug()->is_active()) MarkAsDebug(); | 94 if (isolate_->debug()->is_active()) MarkAsDebug(); |
144 if (FLAG_context_specialization) MarkAsContextSpecializing(); | 95 if (FLAG_context_specialization) MarkAsContextSpecializing(); |
145 if (FLAG_turbo_builtin_inlining) MarkAsBuiltinInliningEnabled(); | 96 if (FLAG_turbo_builtin_inlining) MarkAsBuiltinInliningEnabled(); |
146 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); | 97 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); |
147 if (FLAG_turbo_splitting) MarkAsSplittingEnabled(); | 98 if (FLAG_turbo_splitting) MarkAsSplittingEnabled(); |
148 if (FLAG_turbo_types) MarkAsTypingEnabled(); | 99 if (FLAG_turbo_types) MarkAsTypingEnabled(); |
149 | 100 |
150 bailout_reason_ = kNoReason; | |
151 | |
152 if (has_shared_info() && shared_info()->is_compiled()) { | 101 if (has_shared_info() && shared_info()->is_compiled()) { |
153 // We should initialize the CompilationInfo feedback vector from the | 102 // We should initialize the CompilationInfo feedback vector from the |
154 // passed in shared info, rather than creating a new one. | 103 // passed in shared info, rather than creating a new one. |
155 feedback_vector_ = | 104 feedback_vector_ = Handle<TypeFeedbackVector>( |
156 Handle<TypeFeedbackVector>(shared_info()->feedback_vector(), isolate); | 105 shared_info()->feedback_vector(), parse_info->isolate()); |
157 } | 106 } |
158 } | 107 } |
159 | 108 |
160 | 109 |
| 110 CompilationInfo::CompilationInfo(CodeStub* stub, Isolate* isolate, Zone* zone) |
| 111 : CompilationInfo(nullptr, stub, STUB, isolate, zone) {} |
| 112 |
| 113 |
| 114 CompilationInfo::CompilationInfo(ParseInfo* parse_info, CodeStub* code_stub, |
| 115 Mode mode, Isolate* isolate, Zone* zone) |
| 116 : parse_info_(parse_info), |
| 117 isolate_(isolate), |
| 118 flags_(0), |
| 119 code_stub_(code_stub), |
| 120 mode_(mode), |
| 121 osr_ast_id_(BailoutId::None()), |
| 122 zone_(zone), |
| 123 deferred_handles_(nullptr), |
| 124 bailout_reason_(kNoReason), |
| 125 prologue_offset_(Code::kPrologueOffsetNotSet), |
| 126 no_frame_ranges_(isolate->cpu_profiler()->is_profiling() |
| 127 ? new List<OffsetRange>(2) |
| 128 : nullptr), |
| 129 track_positions_(FLAG_hydrogen_track_positions), |
| 130 opt_count_(has_shared_info() ? shared_info()->opt_count() : 0), |
| 131 parameter_count_(0), |
| 132 optimization_id_(-1), |
| 133 aborted_due_to_dependency_change_(false), |
| 134 osr_expr_stack_height_(0) { |
| 135 std::fill_n(dependencies_, DependentCode::kGroupCount, nullptr); |
| 136 } |
| 137 |
| 138 |
161 CompilationInfo::~CompilationInfo() { | 139 CompilationInfo::~CompilationInfo() { |
162 DisableFutureOptimization(); | 140 DisableFutureOptimization(); |
163 delete deferred_handles_; | 141 delete deferred_handles_; |
164 delete no_frame_ranges_; | 142 delete no_frame_ranges_; |
165 delete inlined_function_infos_; | |
166 #ifdef DEBUG | 143 #ifdef DEBUG |
167 // Check that no dependent maps have been added or added dependent maps have | 144 // Check that no dependent maps have been added or added dependent maps have |
168 // been rolled back or committed. | 145 // been rolled back or committed. |
169 for (int i = 0; i < DependentCode::kGroupCount; i++) { | 146 for (int i = 0; i < DependentCode::kGroupCount; i++) { |
170 DCHECK(!dependencies_[i]); | 147 DCHECK(!dependencies_[i]); |
171 } | 148 } |
172 #endif // DEBUG | 149 #endif // DEBUG |
173 } | 150 } |
174 | 151 |
175 | 152 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 | 237 |
261 bool CompilationInfo::is_simple_parameter_list() { | 238 bool CompilationInfo::is_simple_parameter_list() { |
262 return scope()->is_simple_parameter_list(); | 239 return scope()->is_simple_parameter_list(); |
263 } | 240 } |
264 | 241 |
265 | 242 |
266 int CompilationInfo::TraceInlinedFunction(Handle<SharedFunctionInfo> shared, | 243 int CompilationInfo::TraceInlinedFunction(Handle<SharedFunctionInfo> shared, |
267 SourcePosition position, | 244 SourcePosition position, |
268 int parent_id) { | 245 int parent_id) { |
269 DCHECK(track_positions_); | 246 DCHECK(track_positions_); |
270 DCHECK(inlined_function_infos_); | |
271 | 247 |
272 int inline_id = static_cast<int>(inlined_function_infos_->size()); | 248 int inline_id = static_cast<int>(inlined_function_infos_.size()); |
273 InlinedFunctionInfo info(parent_id, position, UnboundScript::kNoScriptId, | 249 InlinedFunctionInfo info(parent_id, position, UnboundScript::kNoScriptId, |
274 shared->start_position()); | 250 shared->start_position()); |
275 if (!shared->script()->IsUndefined()) { | 251 if (!shared->script()->IsUndefined()) { |
276 Handle<Script> script(Script::cast(shared->script())); | 252 Handle<Script> script(Script::cast(shared->script())); |
277 info.script_id = script->id()->value(); | 253 info.script_id = script->id()->value(); |
278 | 254 |
279 if (FLAG_hydrogen_track_positions && !script->source()->IsUndefined()) { | 255 if (FLAG_hydrogen_track_positions && !script->source()->IsUndefined()) { |
280 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); | 256 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); |
281 OFStream os(tracing_scope.file()); | 257 OFStream os(tracing_scope.file()); |
282 os << "--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get() | 258 os << "--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get() |
283 << ") id{" << optimization_id() << "," << inline_id << "} ---\n"; | 259 << ") id{" << optimization_id() << "," << inline_id << "} ---\n"; |
284 { | 260 { |
285 DisallowHeapAllocation no_allocation; | 261 DisallowHeapAllocation no_allocation; |
286 int start = shared->start_position(); | 262 int start = shared->start_position(); |
287 int len = shared->end_position() - start; | 263 int len = shared->end_position() - start; |
288 String::SubStringRange source(String::cast(script->source()), start, | 264 String::SubStringRange source(String::cast(script->source()), start, |
289 len); | 265 len); |
290 for (const auto& c : source) { | 266 for (const auto& c : source) { |
291 os << AsReversiblyEscapedUC16(c); | 267 os << AsReversiblyEscapedUC16(c); |
292 } | 268 } |
293 } | 269 } |
294 | 270 |
295 os << "\n--- END ---\n"; | 271 os << "\n--- END ---\n"; |
296 } | 272 } |
297 } | 273 } |
298 | 274 |
299 inlined_function_infos_->push_back(info); | 275 inlined_function_infos_.push_back(info); |
300 | 276 |
301 if (FLAG_hydrogen_track_positions && inline_id != 0) { | 277 if (FLAG_hydrogen_track_positions && inline_id != 0) { |
302 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); | 278 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); |
303 OFStream os(tracing_scope.file()); | 279 OFStream os(tracing_scope.file()); |
304 os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{" | 280 os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{" |
305 << optimization_id() << "," << inline_id << "} AS " << inline_id | 281 << optimization_id() << "," << inline_id << "} AS " << inline_id |
306 << " AT " << position << std::endl; | 282 << " AT " << position << std::endl; |
307 } | 283 } |
308 | 284 |
309 return inline_id; | 285 return inline_id; |
310 } | 286 } |
311 | 287 |
312 | 288 |
313 void CompilationInfo::LogDeoptCallPosition(int pc_offset, int inlining_id) { | 289 void CompilationInfo::LogDeoptCallPosition(int pc_offset, int inlining_id) { |
314 if (!track_positions_ || IsStub()) return; | 290 if (!track_positions_ || IsStub()) return; |
315 DCHECK_LT(static_cast<size_t>(inlining_id), inlined_function_infos_->size()); | 291 DCHECK_LT(static_cast<size_t>(inlining_id), inlined_function_infos_.size()); |
316 inlined_function_infos_->at(inlining_id) | 292 inlined_function_infos_.at(inlining_id).deopt_pc_offsets.push_back(pc_offset); |
317 .deopt_pc_offsets.push_back(pc_offset); | |
318 } | 293 } |
319 | 294 |
320 | 295 |
321 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { | 296 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { |
322 public: | 297 public: |
323 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) | 298 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) |
324 : HOptimizedGraphBuilder(info) { | 299 : HOptimizedGraphBuilder(info) { |
325 } | 300 } |
326 | 301 |
327 #define DEF_VISIT(type) \ | 302 #define DEF_VISIT(type) \ |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
919 | 894 |
920 return result; | 895 return result; |
921 } | 896 } |
922 | 897 |
923 | 898 |
924 MaybeHandle<Code> Compiler::GetUnoptimizedCode( | 899 MaybeHandle<Code> Compiler::GetUnoptimizedCode( |
925 Handle<SharedFunctionInfo> shared) { | 900 Handle<SharedFunctionInfo> shared) { |
926 DCHECK(!shared->GetIsolate()->has_pending_exception()); | 901 DCHECK(!shared->GetIsolate()->has_pending_exception()); |
927 DCHECK(!shared->is_compiled()); | 902 DCHECK(!shared->is_compiled()); |
928 | 903 |
929 CompilationInfoWithZone info(shared); | 904 Zone zone; |
| 905 ParseInfo parse_info(&zone, shared); |
| 906 CompilationInfo info(&parse_info); |
930 return GetUnoptimizedCodeCommon(&info); | 907 return GetUnoptimizedCodeCommon(&info); |
931 } | 908 } |
932 | 909 |
933 | 910 |
934 bool Compiler::EnsureCompiled(Handle<JSFunction> function, | 911 bool Compiler::EnsureCompiled(Handle<JSFunction> function, |
935 ClearExceptionFlag flag) { | 912 ClearExceptionFlag flag) { |
936 if (function->is_compiled()) return true; | 913 if (function->is_compiled()) return true; |
937 MaybeHandle<Code> maybe_code = Compiler::GetLazyCode(function); | 914 MaybeHandle<Code> maybe_code = Compiler::GetLazyCode(function); |
938 Handle<Code> code; | 915 Handle<Code> code; |
939 if (!maybe_code.ToHandle(&code)) { | 916 if (!maybe_code.ToHandle(&code)) { |
940 if (flag == CLEAR_EXCEPTION) { | 917 if (flag == CLEAR_EXCEPTION) { |
941 function->GetIsolate()->clear_pending_exception(); | 918 function->GetIsolate()->clear_pending_exception(); |
942 } | 919 } |
943 return false; | 920 return false; |
944 } | 921 } |
945 function->ReplaceCode(*code); | 922 function->ReplaceCode(*code); |
946 DCHECK(function->is_compiled()); | 923 DCHECK(function->is_compiled()); |
947 return true; | 924 return true; |
948 } | 925 } |
949 | 926 |
950 | 927 |
951 // TODO(turbofan): In the future, unoptimized code with deopt support could | 928 // TODO(turbofan): In the future, unoptimized code with deopt support could |
952 // be generated lazily once deopt is triggered. | 929 // be generated lazily once deopt is triggered. |
953 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { | 930 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { |
954 DCHECK(info->function() != NULL); | 931 DCHECK(info->function() != NULL); |
955 DCHECK(info->scope() != NULL); | 932 DCHECK(info->scope() != NULL); |
956 if (!info->shared_info()->has_deoptimization_support()) { | 933 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 934 if (!shared->has_deoptimization_support()) { |
957 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile. | 935 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile. |
958 Handle<SharedFunctionInfo> shared = info->shared_info(); | 936 CompilationInfoWithZone unoptimized(info->closure()); |
959 CompilationInfoWithZone unoptimized(shared); | |
960 // Note that we use the same AST that we will use for generating the | 937 // Note that we use the same AST that we will use for generating the |
961 // optimized code. | 938 // optimized code. |
962 ParseInfo* parse_info = unoptimized.parse_info(); | 939 ParseInfo* parse_info = unoptimized.parse_info(); |
963 parse_info->set_literal(info->function()); | 940 parse_info->set_literal(info->function()); |
964 parse_info->set_scope(info->scope()); | 941 parse_info->set_scope(info->scope()); |
965 parse_info->set_context(info->context()); | 942 parse_info->set_context(info->context()); |
966 unoptimized.EnableDeoptimizationSupport(); | 943 unoptimized.EnableDeoptimizationSupport(); |
967 // If the current code has reloc info for serialization, also include | 944 // If the current code has reloc info for serialization, also include |
968 // reloc info for serialization for the new code, so that deopt support | 945 // reloc info for serialization for the new code, so that deopt support |
969 // can be added without losing IC state. | 946 // can be added without losing IC state. |
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1574 | 1551 |
1575 | 1552 |
1576 CompilationInfoWithZone::CompilationInfoWithZone(Handle<Script> script) | 1553 CompilationInfoWithZone::CompilationInfoWithZone(Handle<Script> script) |
1577 : CompilationInfo(new ParseInfo(&zone_, script)) {} | 1554 : CompilationInfo(new ParseInfo(&zone_, script)) {} |
1578 | 1555 |
1579 | 1556 |
1580 CompilationInfoWithZone::CompilationInfoWithZone(Handle<JSFunction> function) | 1557 CompilationInfoWithZone::CompilationInfoWithZone(Handle<JSFunction> function) |
1581 : CompilationInfo(new ParseInfo(&zone_, function)) {} | 1558 : CompilationInfo(new ParseInfo(&zone_, function)) {} |
1582 | 1559 |
1583 | 1560 |
1584 CompilationInfoWithZone::CompilationInfoWithZone( | |
1585 Handle<SharedFunctionInfo> shared_info) | |
1586 : CompilationInfo(new ParseInfo(&zone_, shared_info)) {} | |
1587 | |
1588 | |
1589 CompilationInfoWithZone::~CompilationInfoWithZone() { | 1561 CompilationInfoWithZone::~CompilationInfoWithZone() { |
1590 DisableFutureOptimization(); | 1562 DisableFutureOptimization(); |
1591 RollbackDependencies(); | 1563 RollbackDependencies(); |
1592 delete parse_info_; | 1564 delete parse_info_; |
1593 parse_info_ = nullptr; | 1565 parse_info_ = nullptr; |
1594 } | 1566 } |
1595 | 1567 |
1596 #if DEBUG | 1568 #if DEBUG |
1597 void CompilationInfo::PrintAstForTesting() { | 1569 void CompilationInfo::PrintAstForTesting() { |
1598 PrintF("--- Source from AST ---\n%s\n", | 1570 PrintF("--- Source from AST ---\n%s\n", |
1599 PrettyPrinter(isolate(), zone()).PrintProgram(function())); | 1571 PrettyPrinter(isolate(), zone()).PrintProgram(function())); |
1600 } | 1572 } |
1601 #endif | 1573 #endif |
1602 } } // namespace v8::internal | 1574 } } // namespace v8::internal |
OLD | NEW |