// Copyright 2012 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/codegen/compiler.h" #include #include #include "src/api/api-inl.h" #include "src/asmjs/asm-js.h" #include "src/ast/prettyprinter.h" #include "src/ast/scopes.h" #include "src/base/logging.h" #include "src/base/optional.h" #include "src/base/platform/time.h" #include "src/baseline/baseline.h" #include "src/codegen/assembler-inl.h" #include "src/codegen/compilation-cache.h" #include "src/codegen/optimized-compilation-info.h" #include "src/codegen/pending-optimization-table.h" #include "src/codegen/unoptimized-compilation-info.h" #include "src/common/assert-scope.h" #include "src/common/globals.h" #include "src/common/message-template.h" #include "src/compiler-dispatcher/compiler-dispatcher.h" #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" #include "src/compiler/pipeline.h" #include "src/debug/debug.h" #include "src/debug/liveedit.h" #include "src/diagnostics/code-tracer.h" #include "src/execution/frames-inl.h" #include "src/execution/isolate-inl.h" #include "src/execution/isolate.h" #include "src/execution/local-isolate.h" #include "src/execution/runtime-profiler.h" #include "src/execution/vm-state-inl.h" #include "src/handles/maybe-handles.h" #include "src/heap/heap-inl.h" #include "src/heap/local-factory-inl.h" #include "src/heap/local-heap-inl.h" #include "src/heap/local-heap.h" #include "src/heap/parked-scope.h" #include "src/init/bootstrapper.h" #include "src/interpreter/interpreter.h" #include "src/logging/log-inl.h" #include "src/objects/feedback-cell-inl.h" #include "src/objects/js-function-inl.h" #include "src/objects/map.h" #include "src/objects/object-list-macros.h" #include "src/objects/shared-function-info.h" #include "src/objects/string.h" #include "src/parsing/parse-info.h" #include "src/parsing/parser.h" #include "src/parsing/parsing.h" #include "src/parsing/pending-compilation-error-handler.h" #include "src/parsing/scanner-character-streams.h" #include "src/snapshot/code-serializer.h" #include "src/utils/ostreams.h" #include "src/zone/zone-list-inl.h" // crbug.com/v8/8816 namespace v8 { namespace internal { namespace { class CompilerTracer : public AllStatic { public: static void TracePrepareJob(Isolate* isolate, OptimizedCompilationInfo* info, const char* compiler_name) { if (!FLAG_trace_opt || !info->IsOptimizing()) return; CodeTracer::Scope scope(isolate->GetCodeTracer()); PrintTracePrefix(scope, "compiling method", info); PrintF(scope.file(), " using %s%s", compiler_name, info->is_osr() ? " OSR" : ""); PrintTraceSuffix(scope); } static void TraceStartBaselineCompile(Isolate* isolate, Handle shared) { if (!FLAG_trace_baseline) return; CodeTracer::Scope scope(isolate->GetCodeTracer()); PrintTracePrefix(scope, "compiling method", shared, CodeKind::BASELINE); PrintF(scope.file(), " using Sparkplug"); PrintTraceSuffix(scope); } static void TraceCompilationStats(Isolate* isolate, OptimizedCompilationInfo* info, double ms_creategraph, double ms_optimize, double ms_codegen) { if (!FLAG_trace_opt || !info->IsOptimizing()) return; CodeTracer::Scope scope(isolate->GetCodeTracer()); PrintTracePrefix(scope, "optimizing", info); PrintF(scope.file(), " - took %0.3f, %0.3f, %0.3f ms", ms_creategraph, ms_optimize, ms_codegen); PrintTraceSuffix(scope); } static void TraceFinishBaselineCompile(Isolate* isolate, Handle shared, double ms_timetaken) { if (!FLAG_trace_baseline) return; CodeTracer::Scope scope(isolate->GetCodeTracer()); PrintTracePrefix(scope, "compiling", shared, CodeKind::BASELINE); PrintF(scope.file(), " - took %0.3f ms", ms_timetaken); PrintTraceSuffix(scope); } static void TraceCompletedJob(Isolate* isolate, OptimizedCompilationInfo* info) { if (!FLAG_trace_opt) return; CodeTracer::Scope scope(isolate->GetCodeTracer()); PrintTracePrefix(scope, "completed optimizing", info); PrintTraceSuffix(scope); } static void TraceAbortedJob(Isolate* isolate, OptimizedCompilationInfo* info) { if (!FLAG_trace_opt) return; CodeTracer::Scope scope(isolate->GetCodeTracer()); PrintTracePrefix(scope, "aborted optimizing", info); PrintF(scope.file(), " because: %s", GetBailoutReason(info->bailout_reason())); PrintTraceSuffix(scope); } static void TraceOptimizedCodeCacheHit(Isolate* isolate, Handle function, BytecodeOffset osr_offset, CodeKind code_kind) { if (!FLAG_trace_opt) return; CodeTracer::Scope scope(isolate->GetCodeTracer()); PrintTracePrefix(scope, "found optimized code for", function, code_kind); if (!osr_offset.IsNone()) { PrintF(scope.file(), " at OSR bytecode offset %d", osr_offset.ToInt()); } PrintTraceSuffix(scope); } static void TraceOptimizeForAlwaysOpt(Isolate* isolate, Handle function, CodeKind code_kind) { if (!FLAG_trace_opt) return; CodeTracer::Scope scope(isolate->GetCodeTracer()); PrintTracePrefix(scope, "optimizing", function, code_kind); PrintF(scope.file(), " because --always-opt"); PrintTraceSuffix(scope); } static void TraceMarkForAlwaysOpt(Isolate* isolate, Handle function) { if (!FLAG_trace_opt) return; CodeTracer::Scope scope(isolate->GetCodeTracer()); PrintF(scope.file(), "[marking "); function->ShortPrint(scope.file()); PrintF(scope.file(), " for optimized recompilation because --always-opt"); PrintF(scope.file(), "]\n"); } private: static void PrintTracePrefix(const CodeTracer::Scope& scope, const char* header, OptimizedCompilationInfo* info) { PrintTracePrefix(scope, header, info->closure(), info->code_kind()); } static void PrintTracePrefix(const CodeTracer::Scope& scope, const char* header, Handle function, CodeKind code_kind) { PrintF(scope.file(), "[%s ", header); function->ShortPrint(scope.file()); PrintF(scope.file(), " (target %s)", CodeKindToString(code_kind)); } static void PrintTracePrefix(const CodeTracer::Scope& scope, const char* header, Handle shared, CodeKind code_kind) { PrintF(scope.file(), "[%s ", header); shared->ShortPrint(scope.file()); PrintF(scope.file(), " (target %s)", CodeKindToString(code_kind)); } static void PrintTraceSuffix(const CodeTracer::Scope& scope) { PrintF(scope.file(), "]\n"); } }; } // namespace // Helper that times a scoped region and records the elapsed time. struct ScopedTimer { explicit ScopedTimer(base::TimeDelta* location) : location_(location) { DCHECK_NOT_NULL(location_); timer_.Start(); } ~ScopedTimer() { *location_ += timer_.Elapsed(); } base::ElapsedTimer timer_; base::TimeDelta* location_; }; // static void Compiler::LogFunctionCompilation(Isolate* isolate, CodeEventListener::LogEventsAndTags tag, Handle shared, Handle