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