LCOV - code coverage report
Current view: top level - src - log.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 578 1075 53.8 %
Date: 2019-01-20 Functions: 88 161 54.7 %

          Line data    Source code
       1             : // Copyright 2011 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/log.h"
       6             : 
       7             : #include <cstdarg>
       8             : #include <memory>
       9             : #include <sstream>
      10             : 
      11             : #include "src/api-inl.h"
      12             : #include "src/bailout-reason.h"
      13             : #include "src/base/platform/platform.h"
      14             : #include "src/bootstrapper.h"
      15             : #include "src/counters.h"
      16             : #include "src/deoptimizer.h"
      17             : #include "src/global-handles.h"
      18             : #include "src/interpreter/bytecodes.h"
      19             : #include "src/interpreter/interpreter.h"
      20             : #include "src/libsampler/sampler.h"
      21             : #include "src/log-inl.h"
      22             : #include "src/macro-assembler.h"
      23             : #include "src/memcopy.h"
      24             : #include "src/objects/api-callbacks.h"
      25             : #include "src/perf-jit.h"
      26             : #include "src/profiler/tick-sample.h"
      27             : #include "src/runtime-profiler.h"
      28             : #include "src/snapshot/embedded-data.h"
      29             : #include "src/source-position-table.h"
      30             : #include "src/string-stream.h"
      31             : #include "src/tracing/tracing-category-observer.h"
      32             : #include "src/unicode-inl.h"
      33             : #include "src/vm-state-inl.h"
      34             : #include "src/wasm/wasm-code-manager.h"
      35             : #include "src/wasm/wasm-objects-inl.h"
      36             : 
      37             : #include "src/version.h"
      38             : 
      39             : namespace v8 {
      40             : namespace internal {
      41             : 
      42             : #define DECLARE_EVENT(ignore1, name) #name,
      43             : static const char* kLogEventsNames[CodeEventListener::NUMBER_OF_LOG_EVENTS] = {
      44             :     LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)};
      45             : #undef DECLARE_EVENT
      46             : 
      47       20826 : static v8::CodeEventType GetCodeEventTypeForTag(
      48             :     CodeEventListener::LogEventsAndTags tag) {
      49       20826 :   switch (tag) {
      50             :     case CodeEventListener::NUMBER_OF_LOG_EVENTS:
      51             : #define V(Event, _) case CodeEventListener::Event:
      52             :       LOG_EVENTS_LIST(V)
      53             : #undef V
      54             :       return v8::CodeEventType::kUnknownType;
      55             : #define V(From, To)             \
      56             :   case CodeEventListener::From: \
      57             :     return v8::CodeEventType::k##To##Type;
      58       20700 :       TAGS_LIST(V)
      59             : #undef V
      60             :   }
      61             :   // The execution should never pass here
      62           0 :   UNREACHABLE();
      63             :   // NOTE(mmarchini): Workaround to fix a compiler failure on GCC 4.9
      64             :   return v8::CodeEventType::kUnknownType;
      65             : }
      66             : #define CALL_CODE_EVENT_HANDLER(Call) \
      67             :   if (listener_) {                    \
      68             :     listener_->Call;                  \
      69             :   } else {                            \
      70             :     PROFILE(isolate_, Call);          \
      71             :   }
      72             : 
      73         502 : static const char* ComputeMarker(SharedFunctionInfo shared, AbstractCode code) {
      74         502 :   switch (code->kind()) {
      75             :     case AbstractCode::INTERPRETED_FUNCTION:
      76         386 :       return shared->optimization_disabled() ? "" : "~";
      77             :     case AbstractCode::OPTIMIZED_FUNCTION:
      78             :       return "*";
      79             :     default:
      80          35 :       return "";
      81             :   }
      82             : }
      83             : 
      84           0 : static const char* ComputeMarker(const wasm::WasmCode* code) {
      85           0 :   switch (code->kind()) {
      86             :     case wasm::WasmCode::kFunction:
      87           0 :       return code->is_liftoff() ? "" : "*";
      88             :     case wasm::WasmCode::kInterpreterEntry:
      89             :       return "~";
      90             :     default:
      91             :       return "";
      92             :   }
      93             : }
      94             : 
      95             : class CodeEventLogger::NameBuffer {
      96             :  public:
      97             :   NameBuffer() { Reset(); }
      98             : 
      99             :   void Reset() {
     100        6002 :     utf8_pos_ = 0;
     101             :   }
     102             : 
     103        5480 :   void Init(CodeEventListener::LogEventsAndTags tag) {
     104             :     Reset();
     105        5480 :     AppendBytes(kLogEventsNames[tag]);
     106             :     AppendByte(':');
     107        5480 :   }
     108             : 
     109           0 :   void AppendName(Name name) {
     110           0 :     if (name->IsString()) {
     111           0 :       AppendString(String::cast(name));
     112             :     } else {
     113           0 :       Symbol symbol = Symbol::cast(name);
     114           0 :       AppendBytes("symbol(");
     115           0 :       if (!symbol->name()->IsUndefined()) {
     116           0 :         AppendBytes("\"");
     117           0 :         AppendString(String::cast(symbol->name()));
     118           0 :         AppendBytes("\" ");
     119             :       }
     120           0 :       AppendBytes("hash ");
     121           0 :       AppendHex(symbol->Hash());
     122             :       AppendByte(')');
     123             :     }
     124           0 :   }
     125             : 
     126         604 :   void AppendString(String str) {
     127         604 :     if (str.is_null()) return;
     128         604 :     int length = 0;
     129             :     std::unique_ptr<char[]> c_str =
     130         604 :         str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, &length);
     131        1208 :     AppendBytes(c_str.get(), length);
     132             :   }
     133             : 
     134       11564 :   void AppendBytes(const char* bytes, int size) {
     135       11564 :     size = Min(size, kUtf8BufferSize - utf8_pos_);
     136       11564 :     MemCopy(utf8_buffer_ + utf8_pos_, bytes, size);
     137       11564 :     utf8_pos_ += size;
     138       11564 :   }
     139             : 
     140       10960 :   void AppendBytes(const char* bytes) {
     141       10960 :     AppendBytes(bytes, StrLength(bytes));
     142       10960 :   }
     143             : 
     144             :   void AppendByte(char c) {
     145        6084 :     if (utf8_pos_ >= kUtf8BufferSize) return;
     146        6060 :     utf8_buffer_[utf8_pos_++] = c;
     147             :   }
     148             : 
     149         302 :   void AppendInt(int n) {
     150         302 :     int space = kUtf8BufferSize - utf8_pos_;
     151         314 :     if (space <= 0) return;
     152         290 :     Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
     153         290 :     int size = SNPrintF(buffer, "%d", n);
     154         290 :     if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
     155         290 :       utf8_pos_ += size;
     156             :     }
     157             :   }
     158             : 
     159           0 :   void AppendHex(uint32_t n) {
     160           0 :     int space = kUtf8BufferSize - utf8_pos_;
     161           0 :     if (space <= 0) return;
     162           0 :     Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
     163           0 :     int size = SNPrintF(buffer, "%x", n);
     164           0 :     if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
     165           0 :       utf8_pos_ += size;
     166             :     }
     167             :   }
     168             : 
     169             :   const char* get() { return utf8_buffer_; }
     170             :   int size() const { return utf8_pos_; }
     171             : 
     172             :  private:
     173             :   static const int kUtf8BufferSize = 512;
     174             :   static const int kUtf16BufferSize = kUtf8BufferSize;
     175             : 
     176             :   int utf8_pos_;
     177             :   char utf8_buffer_[kUtf8BufferSize];
     178             : };
     179             : 
     180         487 : CodeEventLogger::CodeEventLogger(Isolate* isolate)
     181        1044 :     : isolate_(isolate), name_buffer_(new NameBuffer) {}
     182             : 
     183        1009 : CodeEventLogger::~CodeEventLogger() { delete name_buffer_; }
     184             : 
     185        5178 : void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
     186             :                                       AbstractCode code, const char* comment) {
     187       10356 :   name_buffer_->Init(tag);
     188        5178 :   name_buffer_->AppendBytes(comment);
     189             :   LogRecordedBuffer(code, SharedFunctionInfo(), name_buffer_->get(),
     190       15534 :                     name_buffer_->size());
     191        5178 : }
     192             : 
     193           0 : void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
     194             :                                       AbstractCode code, Name name) {
     195           0 :   name_buffer_->Init(tag);
     196           0 :   name_buffer_->AppendName(name);
     197             :   LogRecordedBuffer(code, SharedFunctionInfo(), name_buffer_->get(),
     198           0 :                     name_buffer_->size());
     199           0 : }
     200             : 
     201           0 : void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
     202             :                                       AbstractCode code,
     203             :                                       SharedFunctionInfo shared, Name name) {
     204           0 :   name_buffer_->Init(tag);
     205           0 :   name_buffer_->AppendBytes(ComputeMarker(shared, code));
     206           0 :   name_buffer_->AppendByte(' ');
     207           0 :   name_buffer_->AppendName(name);
     208           0 :   LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
     209           0 : }
     210             : 
     211         302 : void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
     212             :                                       AbstractCode code,
     213             :                                       SharedFunctionInfo shared, Name source,
     214             :                                       int line, int column) {
     215         604 :   name_buffer_->Init(tag);
     216         302 :   name_buffer_->AppendBytes(ComputeMarker(shared, code));
     217         302 :   name_buffer_->AppendString(shared->DebugName());
     218         302 :   name_buffer_->AppendByte(' ');
     219         302 :   if (source->IsString()) {
     220         302 :     name_buffer_->AppendString(String::cast(source));
     221             :   } else {
     222           0 :     name_buffer_->AppendBytes("symbol(hash ");
     223           0 :     name_buffer_->AppendHex(Name::cast(source)->Hash());
     224           0 :     name_buffer_->AppendByte(')');
     225             :   }
     226         302 :   name_buffer_->AppendByte(':');
     227         302 :   name_buffer_->AppendInt(line);
     228         604 :   LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
     229         302 : }
     230             : 
     231           0 : void CodeEventLogger::CodeCreateEvent(LogEventsAndTags tag,
     232           0 :                                       const wasm::WasmCode* code,
     233             :                                       wasm::WasmName name) {
     234           0 :   name_buffer_->Init(tag);
     235           0 :   if (name.is_empty()) {
     236           0 :     name_buffer_->AppendBytes("<wasm-unknown>");
     237             :   } else {
     238           0 :     name_buffer_->AppendBytes(name.start(), name.length());
     239             :   }
     240           0 :   name_buffer_->AppendByte('-');
     241           0 :   if (code->IsAnonymous()) {
     242           0 :     name_buffer_->AppendBytes("<anonymous>");
     243             :   } else {
     244           0 :     name_buffer_->AppendInt(code->index());
     245             :   }
     246           0 :   LogRecordedBuffer(code, name_buffer_->get(), name_buffer_->size());
     247           0 : }
     248             : 
     249           0 : void CodeEventLogger::RegExpCodeCreateEvent(AbstractCode code, String source) {
     250           0 :   name_buffer_->Init(CodeEventListener::REG_EXP_TAG);
     251           0 :   name_buffer_->AppendString(source);
     252             :   LogRecordedBuffer(code, SharedFunctionInfo(), name_buffer_->get(),
     253           0 :                     name_buffer_->size());
     254           0 : }
     255             : 
     256             : // Linux perf tool logging support
     257             : class PerfBasicLogger : public CodeEventLogger {
     258             :  public:
     259             :   explicit PerfBasicLogger(Isolate* isolate);
     260             :   ~PerfBasicLogger() override;
     261             : 
     262           0 :   void CodeMoveEvent(AbstractCode from, AbstractCode to) override {}
     263           0 :   void CodeDisableOptEvent(AbstractCode code,
     264           0 :                            SharedFunctionInfo shared) override {}
     265             : 
     266             :  private:
     267             :   void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
     268             :                          const char* name, int length) override;
     269             :   void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
     270             :                          int length) override;
     271             :   void WriteLogRecordedBuffer(uintptr_t address, int size, const char* name,
     272             :                               int name_length);
     273             : 
     274             :   // Extension added to V8 log file name to get the low-level log name.
     275             :   static const char kFilenameFormatString[];
     276             :   static const int kFilenameBufferPadding;
     277             : 
     278             :   FILE* perf_output_handle_;
     279             : };
     280             : 
     281             : const char PerfBasicLogger::kFilenameFormatString[] = "/tmp/perf-%d.map";
     282             : // Extra space for the PID in the filename
     283             : const int PerfBasicLogger::kFilenameBufferPadding = 16;
     284             : 
     285           0 : PerfBasicLogger::PerfBasicLogger(Isolate* isolate)
     286           0 :     : CodeEventLogger(isolate), perf_output_handle_(nullptr) {
     287             :   // Open the perf JIT dump file.
     288             :   int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
     289             :   ScopedVector<char> perf_dump_name(bufferSize);
     290             :   int size = SNPrintF(
     291             :       perf_dump_name,
     292             :       kFilenameFormatString,
     293           0 :       base::OS::GetCurrentProcessId());
     294           0 :   CHECK_NE(size, -1);
     295             :   perf_output_handle_ =
     296           0 :       base::OS::FOpen(perf_dump_name.start(), base::OS::LogFileOpenMode);
     297           0 :   CHECK_NOT_NULL(perf_output_handle_);
     298           0 :   setvbuf(perf_output_handle_, nullptr, _IOLBF, 0);
     299           0 : }
     300             : 
     301             : 
     302           0 : PerfBasicLogger::~PerfBasicLogger() {
     303           0 :   fclose(perf_output_handle_);
     304           0 :   perf_output_handle_ = nullptr;
     305           0 : }
     306             : 
     307           0 : void PerfBasicLogger::WriteLogRecordedBuffer(uintptr_t address, int size,
     308             :                                              const char* name,
     309             :                                              int name_length) {
     310             :   // Linux perf expects hex literals without a leading 0x, while some
     311             :   // implementations of printf might prepend one when using the %p format
     312             :   // for pointers, leading to wrongly formatted JIT symbols maps.
     313             :   //
     314             :   // Instead, we use V8PRIxPTR format string and cast pointer to uintpr_t,
     315             :   // so that we have control over the exact output format.
     316             :   base::OS::FPrint(perf_output_handle_, "%" V8PRIxPTR " %x %.*s\n", address,
     317           0 :                    size, name_length, name);
     318           0 : }
     319             : 
     320           0 : void PerfBasicLogger::LogRecordedBuffer(AbstractCode code, SharedFunctionInfo,
     321             :                                         const char* name, int length) {
     322           0 :   if (FLAG_perf_basic_prof_only_functions &&
     323           0 :       (code->kind() != AbstractCode::INTERPRETED_FUNCTION &&
     324           0 :        code->kind() != AbstractCode::BUILTIN &&
     325           0 :        code->kind() != AbstractCode::OPTIMIZED_FUNCTION)) {
     326           0 :     return;
     327             :   }
     328             : 
     329             :   WriteLogRecordedBuffer(static_cast<uintptr_t>(code->InstructionStart()),
     330           0 :                          code->InstructionSize(), name, length);
     331             : }
     332             : 
     333           0 : void PerfBasicLogger::LogRecordedBuffer(const wasm::WasmCode* code,
     334             :                                         const char* name, int length) {
     335             :   WriteLogRecordedBuffer(static_cast<uintptr_t>(code->instruction_start()),
     336             :                          code->instructions().length(), name, length);
     337           0 : }
     338             : 
     339             : // External CodeEventListener
     340          20 : ExternalCodeEventListener::ExternalCodeEventListener(Isolate* isolate)
     341          20 :     : is_listening_(false), isolate_(isolate), code_event_handler_(nullptr) {}
     342             : 
     343          20 : ExternalCodeEventListener::~ExternalCodeEventListener() {
     344          20 :   if (is_listening_) {
     345          20 :     StopListening();
     346             :   }
     347          20 : }
     348             : 
     349          20 : void ExternalCodeEventListener::LogExistingCode() {
     350          20 :   HandleScope scope(isolate_);
     351          20 :   ExistingCodeLogger logger(isolate_, this);
     352          20 :   logger.LogCodeObjects();
     353          20 :   logger.LogCompiledFunctions();
     354          20 : }
     355             : 
     356          20 : void ExternalCodeEventListener::StartListening(
     357             :     CodeEventHandler* code_event_handler) {
     358          20 :   if (is_listening_ || code_event_handler == nullptr) {
     359          20 :     return;
     360             :   }
     361          20 :   code_event_handler_ = code_event_handler;
     362          40 :   is_listening_ = isolate_->code_event_dispatcher()->AddListener(this);
     363          20 :   if (is_listening_) {
     364          20 :     LogExistingCode();
     365             :   }
     366             : }
     367             : 
     368          20 : void ExternalCodeEventListener::StopListening() {
     369          20 :   if (!is_listening_) {
     370          20 :     return;
     371             :   }
     372             : 
     373          40 :   isolate_->code_event_dispatcher()->RemoveListener(this);
     374          20 :   is_listening_ = false;
     375             : }
     376             : 
     377       20706 : void ExternalCodeEventListener::CodeCreateEvent(
     378             :     CodeEventListener::LogEventsAndTags tag, AbstractCode code,
     379             :     const char* comment) {
     380             :   CodeEvent code_event;
     381             :   code_event.code_start_address =
     382       20706 :       static_cast<uintptr_t>(code->InstructionStart());
     383       20706 :   code_event.code_size = static_cast<size_t>(code->InstructionSize());
     384       41412 :   code_event.function_name = isolate_->factory()->empty_string();
     385       20706 :   code_event.script_name = isolate_->factory()->empty_string();
     386       20706 :   code_event.script_line = 0;
     387       20706 :   code_event.script_column = 0;
     388       20706 :   code_event.code_type = GetCodeEventTypeForTag(tag);
     389       20706 :   code_event.comment = comment;
     390             : 
     391       20706 :   code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
     392       20706 : }
     393             : 
     394           0 : void ExternalCodeEventListener::CodeCreateEvent(
     395             :     CodeEventListener::LogEventsAndTags tag, AbstractCode code, Name name) {
     396             :   Handle<String> name_string =
     397           0 :       Name::ToFunctionName(isolate_, Handle<Name>(name, isolate_))
     398           0 :           .ToHandleChecked();
     399             : 
     400             :   CodeEvent code_event;
     401             :   code_event.code_start_address =
     402           0 :       static_cast<uintptr_t>(code->InstructionStart());
     403           0 :   code_event.code_size = static_cast<size_t>(code->InstructionSize());
     404           0 :   code_event.function_name = name_string;
     405           0 :   code_event.script_name = isolate_->factory()->empty_string();
     406           0 :   code_event.script_line = 0;
     407           0 :   code_event.script_column = 0;
     408           0 :   code_event.code_type = GetCodeEventTypeForTag(tag);
     409           0 :   code_event.comment = "";
     410             : 
     411           0 :   code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
     412           0 : }
     413             : 
     414           0 : void ExternalCodeEventListener::CodeCreateEvent(
     415             :     CodeEventListener::LogEventsAndTags tag, AbstractCode code,
     416             :     SharedFunctionInfo shared, Name name) {
     417             :   Handle<String> name_string =
     418           0 :       Name::ToFunctionName(isolate_, Handle<Name>(name, isolate_))
     419           0 :           .ToHandleChecked();
     420             : 
     421             :   CodeEvent code_event;
     422             :   code_event.code_start_address =
     423           0 :       static_cast<uintptr_t>(code->InstructionStart());
     424           0 :   code_event.code_size = static_cast<size_t>(code->InstructionSize());
     425           0 :   code_event.function_name = name_string;
     426           0 :   code_event.script_name = isolate_->factory()->empty_string();
     427           0 :   code_event.script_line = 0;
     428           0 :   code_event.script_column = 0;
     429           0 :   code_event.code_type = GetCodeEventTypeForTag(tag);
     430           0 :   code_event.comment = "";
     431             : 
     432           0 :   code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
     433           0 : }
     434             : 
     435         120 : void ExternalCodeEventListener::CodeCreateEvent(
     436             :     CodeEventListener::LogEventsAndTags tag, AbstractCode code,
     437             :     SharedFunctionInfo shared, Name source, int line, int column) {
     438             :   Handle<String> name_string =
     439         360 :       Name::ToFunctionName(isolate_, Handle<Name>(shared->Name(), isolate_))
     440         240 :           .ToHandleChecked();
     441             :   Handle<String> source_string =
     442         360 :       Name::ToFunctionName(isolate_, Handle<Name>(source, isolate_))
     443         240 :           .ToHandleChecked();
     444             : 
     445             :   CodeEvent code_event;
     446             :   code_event.code_start_address =
     447         120 :       static_cast<uintptr_t>(code->InstructionStart());
     448         120 :   code_event.code_size = static_cast<size_t>(code->InstructionSize());
     449         120 :   code_event.function_name = name_string;
     450         120 :   code_event.script_name = source_string;
     451         120 :   code_event.script_line = line;
     452         120 :   code_event.script_column = column;
     453         120 :   code_event.code_type = GetCodeEventTypeForTag(tag);
     454         120 :   code_event.comment = "";
     455             : 
     456         120 :   code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
     457         120 : }
     458             : 
     459           0 : void ExternalCodeEventListener::CodeCreateEvent(LogEventsAndTags tag,
     460             :                                                 const wasm::WasmCode* code,
     461             :                                                 wasm::WasmName name) {
     462             :   // TODO(mmarchini): handle later
     463           0 : }
     464             : 
     465           0 : void ExternalCodeEventListener::RegExpCodeCreateEvent(AbstractCode code,
     466             :                                                       String source) {
     467             :   CodeEvent code_event;
     468             :   code_event.code_start_address =
     469           0 :       static_cast<uintptr_t>(code->InstructionStart());
     470           0 :   code_event.code_size = static_cast<size_t>(code->InstructionSize());
     471           0 :   code_event.function_name = Handle<String>(source, isolate_);
     472           0 :   code_event.script_name = isolate_->factory()->empty_string();
     473           0 :   code_event.script_line = 0;
     474           0 :   code_event.script_column = 0;
     475           0 :   code_event.code_type = GetCodeEventTypeForTag(CodeEventListener::REG_EXP_TAG);
     476           0 :   code_event.comment = "";
     477             : 
     478           0 :   code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
     479           0 : }
     480             : 
     481             : // Low-level logging support.
     482             : class LowLevelLogger : public CodeEventLogger {
     483             :  public:
     484             :   LowLevelLogger(Isolate* isolate, const char* file_name);
     485             :   ~LowLevelLogger() override;
     486             : 
     487             :   void CodeMoveEvent(AbstractCode from, AbstractCode to) override;
     488           0 :   void CodeDisableOptEvent(AbstractCode code,
     489           0 :                            SharedFunctionInfo shared) override {}
     490             :   void SnapshotPositionEvent(HeapObject obj, int pos);
     491             :   void CodeMovingGCEvent() override;
     492             : 
     493             :  private:
     494             :   void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
     495             :                          const char* name, int length) override;
     496             :   void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
     497             :                          int length) override;
     498             : 
     499             :   // Low-level profiling event structures.
     500             :   struct CodeCreateStruct {
     501             :     static const char kTag = 'C';
     502             : 
     503             :     int32_t name_size;
     504             :     Address code_address;
     505             :     int32_t code_size;
     506             :   };
     507             : 
     508             : 
     509             :   struct CodeMoveStruct {
     510             :     static const char kTag = 'M';
     511             : 
     512             :     Address from_address;
     513             :     Address to_address;
     514             :   };
     515             : 
     516             : 
     517             :   static const char kCodeMovingGCTag = 'G';
     518             : 
     519             : 
     520             :   // Extension added to V8 log file name to get the low-level log name.
     521             :   static const char kLogExt[];
     522             : 
     523             :   void LogCodeInfo();
     524             :   void LogWriteBytes(const char* bytes, int size);
     525             : 
     526             :   template <typename T>
     527           0 :   void LogWriteStruct(const T& s) {
     528           0 :     char tag = T::kTag;
     529             :     LogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
     530             :     LogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
     531           0 :   }
     532             : 
     533             :   FILE* ll_output_handle_;
     534             : };
     535             : 
     536             : const char LowLevelLogger::kLogExt[] = ".ll";
     537             : 
     538           0 : LowLevelLogger::LowLevelLogger(Isolate* isolate, const char* name)
     539           0 :     : CodeEventLogger(isolate), ll_output_handle_(nullptr) {
     540             :   // Open the low-level log file.
     541           0 :   size_t len = strlen(name);
     542           0 :   ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLogExt)));
     543             :   MemCopy(ll_name.start(), name, len);
     544           0 :   MemCopy(ll_name.start() + len, kLogExt, sizeof(kLogExt));
     545             :   ll_output_handle_ =
     546           0 :       base::OS::FOpen(ll_name.start(), base::OS::LogFileOpenMode);
     547           0 :   setvbuf(ll_output_handle_, nullptr, _IOLBF, 0);
     548             : 
     549             :   LogCodeInfo();
     550           0 : }
     551             : 
     552             : 
     553           0 : LowLevelLogger::~LowLevelLogger() {
     554           0 :   fclose(ll_output_handle_);
     555           0 :   ll_output_handle_ = nullptr;
     556           0 : }
     557             : 
     558             : 
     559           0 : void LowLevelLogger::LogCodeInfo() {
     560             : #if V8_TARGET_ARCH_IA32
     561             :   const char arch[] = "ia32";
     562             : #elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
     563           0 :   const char arch[] = "x64";
     564             : #elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
     565             :   const char arch[] = "x32";
     566             : #elif V8_TARGET_ARCH_ARM
     567             :   const char arch[] = "arm";
     568             : #elif V8_TARGET_ARCH_PPC
     569             :   const char arch[] = "ppc";
     570             : #elif V8_TARGET_ARCH_MIPS
     571             :   const char arch[] = "mips";
     572             : #elif V8_TARGET_ARCH_ARM64
     573             :   const char arch[] = "arm64";
     574             : #elif V8_TARGET_ARCH_S390
     575             :   const char arch[] = "s390";
     576             : #else
     577             :   const char arch[] = "unknown";
     578             : #endif
     579             :   LogWriteBytes(arch, sizeof(arch));
     580           0 : }
     581             : 
     582           0 : void LowLevelLogger::LogRecordedBuffer(AbstractCode code, SharedFunctionInfo,
     583             :                                        const char* name, int length) {
     584             :   CodeCreateStruct event;
     585           0 :   event.name_size = length;
     586           0 :   event.code_address = code->InstructionStart();
     587           0 :   event.code_size = code->InstructionSize();
     588           0 :   LogWriteStruct(event);
     589             :   LogWriteBytes(name, length);
     590           0 :   LogWriteBytes(reinterpret_cast<const char*>(code->InstructionStart()),
     591           0 :                 code->InstructionSize());
     592           0 : }
     593             : 
     594           0 : void LowLevelLogger::LogRecordedBuffer(const wasm::WasmCode* code,
     595             :                                        const char* name, int length) {
     596             :   CodeCreateStruct event;
     597           0 :   event.name_size = length;
     598           0 :   event.code_address = code->instruction_start();
     599           0 :   event.code_size = code->instructions().length();
     600           0 :   LogWriteStruct(event);
     601             :   LogWriteBytes(name, length);
     602             :   LogWriteBytes(reinterpret_cast<const char*>(code->instruction_start()),
     603             :                 code->instructions().length());
     604           0 : }
     605             : 
     606           0 : void LowLevelLogger::CodeMoveEvent(AbstractCode from, AbstractCode to) {
     607             :   CodeMoveStruct event;
     608           0 :   event.from_address = from->InstructionStart();
     609           0 :   event.to_address = to->InstructionStart();
     610           0 :   LogWriteStruct(event);
     611           0 : }
     612             : 
     613           0 : void LowLevelLogger::LogWriteBytes(const char* bytes, int size) {
     614           0 :   size_t rv = fwrite(bytes, 1, size, ll_output_handle_);
     615             :   DCHECK(static_cast<size_t>(size) == rv);
     616             :   USE(rv);
     617           0 : }
     618             : 
     619             : 
     620           0 : void LowLevelLogger::CodeMovingGCEvent() {
     621           0 :   const char tag = kCodeMovingGCTag;
     622             : 
     623             :   LogWriteBytes(&tag, sizeof(tag));
     624           0 : }
     625             : 
     626         105 : class JitLogger : public CodeEventLogger {
     627             :  public:
     628             :   JitLogger(Isolate* isolate, JitCodeEventHandler code_event_handler);
     629             : 
     630             :   void CodeMoveEvent(AbstractCode from, AbstractCode to) override;
     631          10 :   void CodeDisableOptEvent(AbstractCode code,
     632          10 :                            SharedFunctionInfo shared) override {}
     633             :   void AddCodeLinePosInfoEvent(void* jit_handler_data, int pc_offset,
     634             :                                int position,
     635             :                                JitCodeEvent::PositionType position_type);
     636             : 
     637             :   void* StartCodePosInfoEvent();
     638             :   void EndCodePosInfoEvent(Address start_address, void* jit_handler_data);
     639             : 
     640             :  private:
     641             :   void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
     642             :                          const char* name, int length) override;
     643             :   void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
     644             :                          int length) override;
     645             : 
     646             :   JitCodeEventHandler code_event_handler_;
     647             :   base::Mutex logger_mutex_;
     648             : };
     649             : 
     650          35 : JitLogger::JitLogger(Isolate* isolate, JitCodeEventHandler code_event_handler)
     651          35 :     : CodeEventLogger(isolate), code_event_handler_(code_event_handler) {}
     652             : 
     653        5451 : void JitLogger::LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
     654             :                                   const char* name, int length) {
     655             :   JitCodeEvent event;
     656             :   memset(static_cast<void*>(&event), 0, sizeof(event));
     657             :   event.type = JitCodeEvent::CODE_ADDED;
     658        5451 :   event.code_start = reinterpret_cast<void*>(code->InstructionStart());
     659             :   event.code_type =
     660        5451 :       code->IsCode() ? JitCodeEvent::JIT_CODE : JitCodeEvent::BYTE_CODE;
     661        5451 :   event.code_len = code->InstructionSize();
     662             :   Handle<SharedFunctionInfo> shared_function_handle;
     663        5724 :   if (!shared.is_null() && shared->script()->IsScript()) {
     664             :     shared_function_handle =
     665             :         Handle<SharedFunctionInfo>(shared, shared->GetIsolate());
     666             :   }
     667        5451 :   event.script = ToApiHandle<v8::UnboundScript>(shared_function_handle);
     668        5451 :   event.name.str = name;
     669        5451 :   event.name.len = length;
     670        5451 :   event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);
     671        5451 :   code_event_handler_(&event);
     672        5451 : }
     673             : 
     674           0 : void JitLogger::LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
     675             :                                   int length) {
     676             :   JitCodeEvent event;
     677             :   memset(static_cast<void*>(&event), 0, sizeof(event));
     678             :   event.type = JitCodeEvent::CODE_ADDED;
     679           0 :   event.code_type = JitCodeEvent::JIT_CODE;
     680           0 :   event.code_start = code->instructions().start();
     681           0 :   event.code_len = code->instructions().length();
     682           0 :   event.name.str = name;
     683           0 :   event.name.len = length;
     684           0 :   event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);
     685           0 :   code_event_handler_(&event);
     686           0 : }
     687             : 
     688         171 : void JitLogger::CodeMoveEvent(AbstractCode from, AbstractCode to) {
     689         171 :   base::MutexGuard guard(&logger_mutex_);
     690             : 
     691             :   JitCodeEvent event;
     692         171 :   event.type = JitCodeEvent::CODE_MOVED;
     693             :   event.code_type =
     694         171 :       from->IsCode() ? JitCodeEvent::JIT_CODE : JitCodeEvent::BYTE_CODE;
     695         171 :   event.code_start = reinterpret_cast<void*>(from->InstructionStart());
     696         171 :   event.code_len = from->InstructionSize();
     697         171 :   event.new_code_start = reinterpret_cast<void*>(to->InstructionStart());
     698         171 :   event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);
     699             : 
     700         171 :   code_event_handler_(&event);
     701         171 : }
     702             : 
     703        2139 : void JitLogger::AddCodeLinePosInfoEvent(
     704             :     void* jit_handler_data,
     705             :     int pc_offset,
     706             :     int position,
     707             :     JitCodeEvent::PositionType position_type) {
     708             :   JitCodeEvent event;
     709             :   memset(static_cast<void*>(&event), 0, sizeof(event));
     710        2139 :   event.type = JitCodeEvent::CODE_ADD_LINE_POS_INFO;
     711        2139 :   event.user_data = jit_handler_data;
     712        2139 :   event.line_info.offset = pc_offset;
     713        2139 :   event.line_info.pos = position;
     714        2139 :   event.line_info.position_type = position_type;
     715        2139 :   event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);
     716             : 
     717        2139 :   code_event_handler_(&event);
     718        2139 : }
     719             : 
     720             : 
     721         230 : void* JitLogger::StartCodePosInfoEvent() {
     722             :   JitCodeEvent event;
     723             :   memset(static_cast<void*>(&event), 0, sizeof(event));
     724         230 :   event.type = JitCodeEvent::CODE_START_LINE_INFO_RECORDING;
     725         230 :   event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);
     726             : 
     727         230 :   code_event_handler_(&event);
     728         230 :   return event.user_data;
     729             : }
     730             : 
     731         230 : void JitLogger::EndCodePosInfoEvent(Address start_address,
     732             :                                     void* jit_handler_data) {
     733             :   JitCodeEvent event;
     734             :   memset(static_cast<void*>(&event), 0, sizeof(event));
     735         230 :   event.type = JitCodeEvent::CODE_END_LINE_INFO_RECORDING;
     736         230 :   event.code_start = reinterpret_cast<void*>(start_address);
     737         230 :   event.user_data = jit_handler_data;
     738         230 :   event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);
     739             : 
     740         230 :   code_event_handler_(&event);
     741         230 : }
     742             : 
     743             : 
     744             : // TODO(lpy): Keeping sampling thread inside V8 is a workaround currently,
     745             : // the reason is to reduce code duplication during migration to sampler library,
     746             : // sampling thread, as well as the sampler, will be moved to D8 eventually.
     747       62868 : class SamplingThread : public base::Thread {
     748             :  public:
     749             :   static const int kSamplingThreadStackSize = 64 * KB;
     750             : 
     751             :   SamplingThread(sampler::Sampler* sampler, int interval_microseconds)
     752             :       : base::Thread(
     753             :             base::Thread::Options("SamplingThread", kSamplingThreadStackSize)),
     754             :         sampler_(sampler),
     755       62883 :         interval_microseconds_(interval_microseconds) {}
     756           0 :   void Run() override {
     757           0 :     while (sampler_->IsProfiling()) {
     758           0 :       sampler_->DoSample();
     759             :       base::OS::Sleep(
     760           0 :           base::TimeDelta::FromMicroseconds(interval_microseconds_));
     761             :     }
     762           0 :   }
     763             : 
     764             :  private:
     765             :   sampler::Sampler* sampler_;
     766             :   const int interval_microseconds_;
     767             : };
     768             : 
     769             : 
     770             : // The Profiler samples pc and sp values for the main thread.
     771             : // Each sample is appended to a circular buffer.
     772             : // An independent thread removes data and writes it to the log.
     773             : // This design minimizes the time spent in the sampler.
     774             : //
     775           0 : class Profiler: public base::Thread {
     776             :  public:
     777             :   explicit Profiler(Isolate* isolate);
     778             :   void Engage();
     779             :   void Disengage();
     780             : 
     781             :   // Inserts collected profiling data into buffer.
     782           0 :   void Insert(v8::TickSample* sample) {
     783           0 :     if (paused_)
     784           0 :       return;
     785             : 
     786           0 :     if (Succ(head_) == static_cast<int>(base::Relaxed_Load(&tail_))) {
     787           0 :       overflow_ = true;
     788             :     } else {
     789           0 :       buffer_[head_] = *sample;
     790           0 :       head_ = Succ(head_);
     791           0 :       buffer_semaphore_.Signal();  // Tell we have an element.
     792             :     }
     793             :   }
     794             : 
     795             :   void Run() override;
     796             : 
     797             :   // Pause and Resume TickSample data collection.
     798           0 :   void Pause() { paused_ = true; }
     799           0 :   void Resume() { paused_ = false; }
     800             : 
     801             :  private:
     802             :   // Waits for a signal and removes profiling data.
     803           0 :   bool Remove(v8::TickSample* sample) {
     804           0 :     buffer_semaphore_.Wait();  // Wait for an element.
     805           0 :     *sample = buffer_[base::Relaxed_Load(&tail_)];
     806           0 :     bool result = overflow_;
     807             :     base::Relaxed_Store(
     808             :         &tail_, static_cast<base::Atomic32>(Succ(base::Relaxed_Load(&tail_))));
     809           0 :     overflow_ = false;
     810           0 :     return result;
     811             :   }
     812             : 
     813             :   // Returns the next index in the cyclic buffer.
     814           0 :   int Succ(int index) { return (index + 1) % kBufferSize; }
     815             : 
     816             :   Isolate* isolate_;
     817             :   // Cyclic buffer for communicating profiling samples
     818             :   // between the signal handler and the worker thread.
     819             :   static const int kBufferSize = 128;
     820             :   v8::TickSample buffer_[kBufferSize];  // Buffer storage.
     821             :   int head_;  // Index to the buffer head.
     822             :   base::Atomic32 tail_;             // Index to the buffer tail.
     823             :   bool overflow_;  // Tell whether a buffer overflow has occurred.
     824             :   // Semaphore used for buffer synchronization.
     825             :   base::Semaphore buffer_semaphore_;
     826             : 
     827             :   // Tells whether profiler is engaged, that is, processing thread is stated.
     828             :   bool engaged_;
     829             : 
     830             :   // Tells whether worker thread should continue running.
     831             :   base::Atomic32 running_;
     832             : 
     833             :   // Tells whether we are currently recording tick samples.
     834             :   bool paused_;
     835             : };
     836             : 
     837             : 
     838             : //
     839             : // Ticker used to provide ticks to the profiler and the sliding state
     840             : // window.
     841             : //
     842             : class Ticker: public sampler::Sampler {
     843             :  public:
     844       62883 :   Ticker(Isolate* isolate, int interval_microseconds)
     845             :       : sampler::Sampler(reinterpret_cast<v8::Isolate*>(isolate)),
     846             :         profiler_(nullptr),
     847      125766 :         sampling_thread_(new SamplingThread(this, interval_microseconds)) {}
     848             : 
     849      188604 :   ~Ticker() override {
     850       62868 :     if (IsActive()) Stop();
     851       62868 :     delete sampling_thread_;
     852      125736 :   }
     853             : 
     854           0 :   void SetProfiler(Profiler* profiler) {
     855             :     DCHECK_NULL(profiler_);
     856           0 :     profiler_ = profiler;
     857           0 :     IncreaseProfilingDepth();
     858           0 :     if (!IsActive()) Start();
     859           0 :     sampling_thread_->StartSynchronously();
     860           0 :   }
     861             : 
     862           0 :   void ClearProfiler() {
     863           0 :     profiler_ = nullptr;
     864           0 :     if (IsActive()) Stop();
     865           0 :     DecreaseProfilingDepth();
     866           0 :     sampling_thread_->Join();
     867           0 :   }
     868             : 
     869           0 :   void SampleStack(const v8::RegisterState& state) override {
     870           0 :     if (!profiler_) return;
     871           0 :     Isolate* isolate = reinterpret_cast<Isolate*>(this->isolate());
     872             :     TickSample sample;
     873           0 :     sample.Init(isolate, state, TickSample::kIncludeCEntryFrame, true);
     874           0 :     profiler_->Insert(&sample);
     875             :   }
     876             : 
     877             :  private:
     878             :   Profiler* profiler_;
     879             :   SamplingThread* sampling_thread_;
     880             : };
     881             : 
     882             : //
     883             : // Profiler implementation when invoking with --prof.
     884             : //
     885           0 : Profiler::Profiler(Isolate* isolate)
     886             :     : base::Thread(Options("v8:Profiler")),
     887             :       isolate_(isolate),
     888             :       head_(0),
     889             :       overflow_(false),
     890             :       buffer_semaphore_(0),
     891             :       engaged_(false),
     892           0 :       paused_(false) {
     893           0 :   base::Relaxed_Store(&tail_, 0);
     894           0 :   base::Relaxed_Store(&running_, 0);
     895           0 : }
     896             : 
     897             : 
     898           0 : void Profiler::Engage() {
     899           0 :   if (engaged_) return;
     900           0 :   engaged_ = true;
     901             : 
     902             :   std::vector<base::OS::SharedLibraryAddress> addresses =
     903           0 :       base::OS::GetSharedLibraryAddresses();
     904           0 :   for (const auto& address : addresses) {
     905           0 :     LOG(isolate_, SharedLibraryEvent(address.library_path, address.start,
     906             :                                      address.end, address.aslr_slide));
     907             :   }
     908             : 
     909             :   // Start thread processing the profiler buffer.
     910           0 :   base::Relaxed_Store(&running_, 1);
     911           0 :   Start();
     912             : 
     913             :   // Register to get ticks.
     914           0 :   Logger* logger = isolate_->logger();
     915           0 :   logger->ticker_->SetProfiler(this);
     916             : 
     917           0 :   logger->ProfilerBeginEvent();
     918             : }
     919             : 
     920             : 
     921           0 : void Profiler::Disengage() {
     922           0 :   if (!engaged_) return;
     923             : 
     924             :   // Stop receiving ticks.
     925           0 :   isolate_->logger()->ticker_->ClearProfiler();
     926             : 
     927             :   // Terminate the worker thread by setting running_ to false,
     928             :   // inserting a fake element in the queue and then wait for
     929             :   // the thread to terminate.
     930           0 :   base::Relaxed_Store(&running_, 0);
     931             :   v8::TickSample sample;
     932             :   // Reset 'paused_' flag, otherwise semaphore may not be signalled.
     933             :   Resume();
     934           0 :   Insert(&sample);
     935           0 :   Join();
     936             : 
     937           0 :   LOG(isolate_, UncheckedStringEvent("profiler", "end"));
     938             : }
     939             : 
     940             : 
     941           0 : void Profiler::Run() {
     942             :   v8::TickSample sample;
     943           0 :   bool overflow = Remove(&sample);
     944           0 :   while (base::Relaxed_Load(&running_)) {
     945           0 :     LOG(isolate_, TickEvent(&sample, overflow));
     946           0 :     overflow = Remove(&sample);
     947             :   }
     948           0 : }
     949             : 
     950             : 
     951             : //
     952             : // Logger class implementation.
     953             : //
     954             : 
     955       62882 : Logger::Logger(Isolate* isolate)
     956             :     : isolate_(isolate),
     957             :       ticker_(nullptr),
     958             :       profiler_(nullptr),
     959             :       log_events_(nullptr),
     960             :       is_logging_(false),
     961             :       log_(nullptr),
     962             :       perf_basic_logger_(nullptr),
     963             :       perf_jit_logger_(nullptr),
     964             :       ll_logger_(nullptr),
     965             :       jit_logger_(nullptr),
     966             :       is_initialized_(false),
     967      188646 :       existing_code_logger_(isolate) {}
     968             : 
     969      125734 : Logger::~Logger() {
     970      125735 :   delete log_;
     971      125734 : }
     972             : 
     973        1341 : void Logger::AddCodeEventListener(CodeEventListener* listener) {
     974        2682 :   bool result = isolate_->code_event_dispatcher()->AddListener(listener);
     975        1341 :   CHECK(result);
     976        1341 : }
     977             : 
     978        1240 : void Logger::RemoveCodeEventListener(CodeEventListener* listener) {
     979        2550 :   isolate_->code_event_dispatcher()->RemoveListener(listener);
     980        1240 : }
     981             : 
     982           0 : void Logger::ProfilerBeginEvent() {
     983           0 :   if (!log_->IsEnabled()) return;
     984           0 :   Log::MessageBuilder msg(log_);
     985           0 :   msg << "profiler" << kNext << "begin" << kNext << FLAG_prof_sampling_interval;
     986           0 :   msg.WriteToLogFile();
     987             : }
     988             : 
     989             : 
     990           0 : void Logger::StringEvent(const char* name, const char* value) {
     991           0 :   if (FLAG_log) UncheckedStringEvent(name, value);
     992           0 : }
     993             : 
     994             : 
     995           0 : void Logger::UncheckedStringEvent(const char* name, const char* value) {
     996           0 :   if (!log_->IsEnabled()) return;
     997           0 :   Log::MessageBuilder msg(log_);
     998           0 :   msg << name << kNext << value;
     999           0 :   msg.WriteToLogFile();
    1000             : }
    1001             : 
    1002             : 
    1003         122 : void Logger::IntPtrTEvent(const char* name, intptr_t value) {
    1004         122 :   if (FLAG_log) UncheckedIntPtrTEvent(name, value);
    1005         122 : }
    1006             : 
    1007             : 
    1008         122 : void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
    1009         244 :   if (!log_->IsEnabled()) return;
    1010         122 :   Log::MessageBuilder msg(log_);
    1011         122 :   msg << name << kNext;
    1012         122 :   msg.AppendFormatString("%" V8PRIdPTR, value);
    1013         122 :   msg.WriteToLogFile();
    1014             : }
    1015             : 
    1016           0 : void Logger::HandleEvent(const char* name, Address* location) {
    1017           0 :   if (!log_->IsEnabled() || !FLAG_log_handles) return;
    1018           0 :   Log::MessageBuilder msg(log_);
    1019           0 :   msg << name << kNext << reinterpret_cast<void*>(location);
    1020           0 :   msg.WriteToLogFile();
    1021             : }
    1022             : 
    1023             : 
    1024           0 : void Logger::ApiSecurityCheck() {
    1025           0 :   if (!log_->IsEnabled() || !FLAG_log_api) return;
    1026           0 :   Log::MessageBuilder msg(log_);
    1027           0 :   msg << "api" << kNext << "check-security";
    1028           0 :   msg.WriteToLogFile();
    1029             : }
    1030             : 
    1031           0 : void Logger::SharedLibraryEvent(const std::string& library_path,
    1032             :                                 uintptr_t start, uintptr_t end,
    1033             :                                 intptr_t aslr_slide) {
    1034           0 :   if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
    1035           0 :   Log::MessageBuilder msg(log_);
    1036           0 :   msg << "shared-library" << kNext << library_path.c_str() << kNext
    1037           0 :       << reinterpret_cast<void*>(start) << kNext << reinterpret_cast<void*>(end)
    1038           0 :       << kNext << aslr_slide;
    1039           0 :   msg.WriteToLogFile();
    1040             : }
    1041             : 
    1042           6 : void Logger::CodeDeoptEvent(Code code, DeoptimizeKind kind, Address pc,
    1043             :                             int fp_to_sp_delta) {
    1044          12 :   if (!log_->IsEnabled()) return;
    1045           6 :   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(code, pc);
    1046           6 :   Log::MessageBuilder msg(log_);
    1047          18 :   msg << "code-deopt" << kNext << timer_.Elapsed().InMicroseconds() << kNext
    1048           6 :       << code->CodeSize() << kNext
    1049          12 :       << reinterpret_cast<void*>(code->InstructionStart());
    1050             : 
    1051             :   // Deoptimization position.
    1052          12 :   std::ostringstream deopt_location;
    1053             :   int inlining_id = -1;
    1054             :   int script_offset = -1;
    1055           6 :   if (info.position.IsKnown()) {
    1056           6 :     info.position.Print(deopt_location, code);
    1057             :     inlining_id = info.position.InliningId();
    1058             :     script_offset = info.position.ScriptOffset();
    1059             :   } else {
    1060           0 :     deopt_location << "<unknown>";
    1061             :   }
    1062          18 :   msg << kNext << inlining_id << kNext << script_offset << kNext;
    1063           6 :   msg << Deoptimizer::MessageFor(kind) << kNext;
    1064          12 :   msg << deopt_location.str().c_str() << kNext
    1065          12 :       << DeoptimizeReasonToString(info.deopt_reason);
    1066           6 :   msg.WriteToLogFile();
    1067             : }
    1068             : 
    1069             : 
    1070           0 : void Logger::CurrentTimeEvent() {
    1071           0 :   if (!log_->IsEnabled()) return;
    1072             :   DCHECK(FLAG_log_internal_timer_events);
    1073           0 :   Log::MessageBuilder msg(log_);
    1074           0 :   msg << "current-time" << kNext << timer_.Elapsed().InMicroseconds();
    1075           0 :   msg.WriteToLogFile();
    1076             : }
    1077             : 
    1078             : 
    1079         509 : void Logger::TimerEvent(Logger::StartEnd se, const char* name) {
    1080        1018 :   if (!log_->IsEnabled()) return;
    1081         509 :   Log::MessageBuilder msg(log_);
    1082         509 :   switch (se) {
    1083             :     case START:
    1084         247 :       msg << "timer-event-start";
    1085         247 :       break;
    1086             :     case END:
    1087         247 :       msg << "timer-event-end";
    1088         247 :       break;
    1089             :     case STAMP:
    1090          15 :       msg << "timer-event";
    1091             :   }
    1092        1018 :   msg << kNext << name << kNext << timer_.Elapsed().InMicroseconds();
    1093         509 :   msg.WriteToLogFile();
    1094             : }
    1095             : 
    1096             : // static
    1097           0 : void Logger::EnterExternal(Isolate* isolate) {
    1098             :   DCHECK(FLAG_log_internal_timer_events);
    1099           0 :   LOG(isolate, TimerEvent(START, TimerEventExternal::name()));
    1100             :   DCHECK(isolate->current_vm_state() == JS);
    1101             :   isolate->set_current_vm_state(EXTERNAL);
    1102           0 : }
    1103             : 
    1104             : // static
    1105           0 : void Logger::LeaveExternal(Isolate* isolate) {
    1106             :   DCHECK(FLAG_log_internal_timer_events);
    1107           0 :   LOG(isolate, TimerEvent(END, TimerEventExternal::name()));
    1108             :   DCHECK(isolate->current_vm_state() == EXTERNAL);
    1109             :   isolate->set_current_vm_state(JS);
    1110           0 : }
    1111             : 
    1112             : // Instantiate template methods.
    1113             : #define V(TimerName, expose)                                           \
    1114             :   template void TimerEventScope<TimerEvent##TimerName>::LogTimerEvent( \
    1115             :       Logger::StartEnd se);
    1116             : TIMER_EVENTS_LIST(V)
    1117             : #undef V
    1118             : 
    1119           0 : void Logger::ApiNamedPropertyAccess(const char* tag, JSObject holder,
    1120             :                                     Object property_name) {
    1121             :   DCHECK(property_name->IsName());
    1122           0 :   if (!log_->IsEnabled() || !FLAG_log_api) return;
    1123           0 :   Log::MessageBuilder msg(log_);
    1124           0 :   msg << "api" << kNext << tag << kNext << holder->class_name() << kNext
    1125           0 :       << Name::cast(property_name);
    1126           0 :   msg.WriteToLogFile();
    1127             : }
    1128             : 
    1129           0 : void Logger::ApiIndexedPropertyAccess(const char* tag, JSObject holder,
    1130             :                                       uint32_t index) {
    1131           0 :   if (!log_->IsEnabled() || !FLAG_log_api) return;
    1132           0 :   Log::MessageBuilder msg(log_);
    1133           0 :   msg << "api" << kNext << tag << kNext << holder->class_name() << kNext
    1134             :       << index;
    1135           0 :   msg.WriteToLogFile();
    1136             : }
    1137             : 
    1138           0 : void Logger::ApiObjectAccess(const char* tag, JSObject object) {
    1139           0 :   if (!log_->IsEnabled() || !FLAG_log_api) return;
    1140           0 :   Log::MessageBuilder msg(log_);
    1141           0 :   msg << "api" << kNext << tag << kNext << object->class_name();
    1142           0 :   msg.WriteToLogFile();
    1143             : }
    1144             : 
    1145        2090 : void Logger::ApiEntryCall(const char* name) {
    1146        6120 :   if (!log_->IsEnabled() || !FLAG_log_api) return;
    1147         150 :   Log::MessageBuilder msg(log_);
    1148         150 :   msg << "api" << kNext << name;
    1149         150 :   msg.WriteToLogFile();
    1150             : }
    1151             : 
    1152             : 
    1153         636 : void Logger::NewEvent(const char* name, void* object, size_t size) {
    1154        1272 :   if (!log_->IsEnabled() || !FLAG_log) return;
    1155         636 :   Log::MessageBuilder msg(log_);
    1156         636 :   msg << "new" << kNext << name << kNext << object << kNext
    1157             :       << static_cast<unsigned int>(size);
    1158         636 :   msg.WriteToLogFile();
    1159             : }
    1160             : 
    1161             : 
    1162         608 : void Logger::DeleteEvent(const char* name, void* object) {
    1163        1824 :   if (!log_->IsEnabled() || !FLAG_log) return;
    1164           0 :   Log::MessageBuilder msg(log_);
    1165           0 :   msg << "delete" << kNext << name << kNext << object;
    1166           0 :   msg.WriteToLogFile();
    1167             : }
    1168             : 
    1169         445 : void Logger::CallbackEventInternal(const char* prefix, Name name,
    1170             :                                    Address entry_point) {
    1171         890 :   if (!FLAG_log_code || !log_->IsEnabled()) return;
    1172         445 :   Log::MessageBuilder msg(log_);
    1173         445 :   msg << kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT] << kNext
    1174         890 :       << kLogEventsNames[CodeEventListener::CALLBACK_TAG] << kNext << -2
    1175        1780 :       << kNext << timer_.Elapsed().InMicroseconds() << kNext
    1176        1335 :       << reinterpret_cast<void*>(entry_point) << kNext << 1 << kNext << prefix
    1177         445 :       << name;
    1178         445 :   msg.WriteToLogFile();
    1179             : }
    1180             : 
    1181         320 : void Logger::CallbackEvent(Name name, Address entry_point) {
    1182         320 :   CallbackEventInternal("", name, entry_point);
    1183         320 : }
    1184             : 
    1185          65 : void Logger::GetterCallbackEvent(Name name, Address entry_point) {
    1186          65 :   CallbackEventInternal("get ", name, entry_point);
    1187          65 : }
    1188             : 
    1189          60 : void Logger::SetterCallbackEvent(Name name, Address entry_point) {
    1190          60 :   CallbackEventInternal("set ", name, entry_point);
    1191          60 : }
    1192             : 
    1193             : namespace {
    1194             : 
    1195        5375 : void AppendCodeCreateHeader(Log::MessageBuilder& msg,
    1196             :                             CodeEventListener::LogEventsAndTags tag,
    1197             :                             AbstractCode::Kind kind, uint8_t* address, int size,
    1198             :                             base::ElapsedTimer* timer) {
    1199        5375 :   msg << kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT]
    1200       10750 :       << Logger::kNext << kLogEventsNames[tag] << Logger::kNext << kind
    1201       21500 :       << Logger::kNext << timer->Elapsed().InMicroseconds() << Logger::kNext
    1202        5375 :       << reinterpret_cast<void*>(address) << Logger::kNext << size
    1203        5375 :       << Logger::kNext;
    1204        5375 : }
    1205             : 
    1206        5375 : void AppendCodeCreateHeader(Log::MessageBuilder& msg,
    1207             :                             CodeEventListener::LogEventsAndTags tag,
    1208             :                             AbstractCode code, base::ElapsedTimer* timer) {
    1209             :   AppendCodeCreateHeader(msg, tag, code->kind(),
    1210        5375 :                          reinterpret_cast<uint8_t*>(code->InstructionStart()),
    1211       10750 :                          code->InstructionSize(), timer);
    1212        5375 : }
    1213             : 
    1214             : }  // namespace
    1215             : 
    1216        5175 : void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    1217             :                              AbstractCode code, const char* comment) {
    1218        5175 :   if (!is_listening_to_code_events()) return;
    1219       10350 :   if (!FLAG_log_code || !log_->IsEnabled()) return;
    1220        5175 :   Log::MessageBuilder msg(log_);
    1221        5175 :   AppendCodeCreateHeader(msg, tag, code, &timer_);
    1222        5175 :   msg << comment;
    1223        5175 :   msg.WriteToLogFile();
    1224             : }
    1225             : 
    1226           0 : void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    1227             :                              AbstractCode code, Name name) {
    1228           0 :   if (!is_listening_to_code_events()) return;
    1229           0 :   if (!FLAG_log_code || !log_->IsEnabled()) return;
    1230           0 :   Log::MessageBuilder msg(log_);
    1231           0 :   AppendCodeCreateHeader(msg, tag, code, &timer_);
    1232           0 :   msg << name;
    1233           0 :   msg.WriteToLogFile();
    1234             : }
    1235             : 
    1236           0 : void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    1237             :                              AbstractCode code, SharedFunctionInfo shared,
    1238             :                              Name name) {
    1239           0 :   if (!is_listening_to_code_events()) return;
    1240           0 :   if (!FLAG_log_code || !log_->IsEnabled()) return;
    1241           0 :   if (code == AbstractCode::cast(
    1242           0 :                   isolate_->builtins()->builtin(Builtins::kCompileLazy))) {
    1243             :     return;
    1244             :   }
    1245             : 
    1246           0 :   Log::MessageBuilder msg(log_);
    1247           0 :   AppendCodeCreateHeader(msg, tag, code, &timer_);
    1248           0 :   msg << name << kNext << reinterpret_cast<void*>(shared->address()) << kNext
    1249           0 :       << ComputeMarker(shared, code);
    1250           0 :   msg.WriteToLogFile();
    1251             : }
    1252             : 
    1253           0 : void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    1254           0 :                              const wasm::WasmCode* code, wasm::WasmName name) {
    1255           0 :   if (!is_listening_to_code_events()) return;
    1256           0 :   if (!FLAG_log_code || !log_->IsEnabled()) return;
    1257           0 :   Log::MessageBuilder msg(log_);
    1258             :   AppendCodeCreateHeader(msg, tag, AbstractCode::Kind::WASM_FUNCTION,
    1259             :                          code->instructions().start(),
    1260           0 :                          code->instructions().length(), &timer_);
    1261           0 :   if (name.is_empty()) {
    1262           0 :     msg << "<unknown wasm>";
    1263             :   } else {
    1264           0 :     msg.AppendString(name);
    1265             :   }
    1266             :   // We have to add two extra fields that allow the tick processor to group
    1267             :   // events for the same wasm function, even if it gets compiled again. For
    1268             :   // normal JS functions, we use the shared function info. For wasm, the pointer
    1269             :   // to the native module + function index works well enough.
    1270             :   // TODO(herhut) Clean up the tick processor code instead.
    1271             :   void* tag_ptr =
    1272           0 :       reinterpret_cast<byte*>(code->native_module()) + code->index();
    1273           0 :   msg << kNext << tag_ptr << kNext << ComputeMarker(code);
    1274           0 :   msg.WriteToLogFile();
    1275             : }
    1276             : 
    1277             : // Although, it is possible to extract source and line from
    1278             : // the SharedFunctionInfo object, we left it to caller
    1279             : // to leave logging functions free from heap allocations.
    1280         200 : void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    1281             :                              AbstractCode code, SharedFunctionInfo shared,
    1282             :                              Name source, int line, int column) {
    1283         400 :   if (!is_listening_to_code_events()) return;
    1284         400 :   if (!FLAG_log_code || !log_->IsEnabled()) return;
    1285             :   {
    1286         200 :     Log::MessageBuilder msg(log_);
    1287         200 :     AppendCodeCreateHeader(msg, tag, code, &timer_);
    1288         400 :     msg << shared->DebugName() << " " << source << ":" << line << ":" << column
    1289         400 :         << kNext << reinterpret_cast<void*>(shared->address()) << kNext
    1290         400 :         << ComputeMarker(shared, code);
    1291         200 :     msg.WriteToLogFile();
    1292             :   }
    1293             : 
    1294         200 :   if (!FLAG_log_source_code) return;
    1295           0 :   Object script_object = shared->script();
    1296           0 :   if (!script_object->IsScript()) return;
    1297             :   Script script = Script::cast(script_object);
    1298           0 :   if (!EnsureLogScriptSource(script)) return;
    1299             : 
    1300             :   // We log source code information in the form:
    1301             :   //
    1302             :   // code-source-info <addr>,<script>,<start>,<end>,<pos>,<inline-pos>,<fns>
    1303             :   //
    1304             :   // where
    1305             :   //   <addr> is code object address
    1306             :   //   <script> is script id
    1307             :   //   <start> is the starting position inside the script
    1308             :   //   <end> is the end position inside the script
    1309             :   //   <pos> is source position table encoded in the string,
    1310             :   //      it is a sequence of C<code-offset>O<script-offset>[I<inlining-id>]
    1311             :   //      where
    1312             :   //        <code-offset> is the offset within the code object
    1313             :   //        <script-offset> is the position within the script
    1314             :   //        <inlining-id> is the offset in the <inlining> table
    1315             :   //   <inlining> table is a sequence of strings of the form
    1316             :   //      F<function-id>O<script-offset>[I<inlining-id>]
    1317             :   //      where
    1318             :   //         <function-id> is an index into the <fns> function table
    1319             :   //   <fns> is the function table encoded as a sequence of strings
    1320             :   //      S<shared-function-info-address>
    1321           0 :   Log::MessageBuilder msg(log_);
    1322           0 :   msg << "code-source-info" << kNext
    1323           0 :       << reinterpret_cast<void*>(code->InstructionStart()) << kNext
    1324           0 :       << script->id() << kNext << shared->StartPosition() << kNext
    1325           0 :       << shared->EndPosition() << kNext;
    1326             : 
    1327           0 :   SourcePositionTableIterator iterator(code->source_position_table());
    1328             :   bool hasInlined = false;
    1329           0 :   for (; !iterator.done(); iterator.Advance()) {
    1330           0 :     SourcePosition pos = iterator.source_position();
    1331           0 :     msg << "C" << iterator.code_offset() << "O" << pos.ScriptOffset();
    1332           0 :     if (pos.isInlined()) {
    1333           0 :       msg << "I" << pos.InliningId();
    1334             :       hasInlined = true;
    1335             :     }
    1336             :   }
    1337           0 :   msg << kNext;
    1338             :   int maxInlinedId = -1;
    1339           0 :   if (hasInlined) {
    1340             :     PodArray<InliningPosition> inlining_positions =
    1341           0 :         DeoptimizationData::cast(Code::cast(code)->deoptimization_data())
    1342           0 :             ->InliningPositions();
    1343           0 :     for (int i = 0; i < inlining_positions->length(); i++) {
    1344             :       InliningPosition inlining_pos = inlining_positions->get(i);
    1345           0 :       msg << "F";
    1346           0 :       if (inlining_pos.inlined_function_id != -1) {
    1347             :         msg << inlining_pos.inlined_function_id;
    1348           0 :         if (inlining_pos.inlined_function_id > maxInlinedId) {
    1349             :           maxInlinedId = inlining_pos.inlined_function_id;
    1350             :         }
    1351             :       }
    1352             :       SourcePosition pos = inlining_pos.position;
    1353           0 :       msg << "O" << pos.ScriptOffset();
    1354           0 :       if (pos.isInlined()) {
    1355           0 :         msg << "I" << pos.InliningId();
    1356             :       }
    1357             :     }
    1358             :   }
    1359           0 :   msg << kNext;
    1360           0 :   if (hasInlined) {
    1361             :     DeoptimizationData deopt_data =
    1362           0 :         DeoptimizationData::cast(Code::cast(code)->deoptimization_data());
    1363             : 
    1364             :     msg << std::hex;
    1365           0 :     for (int i = 0; i <= maxInlinedId; i++) {
    1366           0 :       msg << "S"
    1367             :           << reinterpret_cast<void*>(
    1368           0 :                  deopt_data->GetInlinedFunction(i)->address());
    1369             :     }
    1370             :     msg << std::dec;
    1371             :   }
    1372           0 :   msg.WriteToLogFile();
    1373             : }
    1374             : 
    1375           1 : void Logger::CodeDisableOptEvent(AbstractCode code, SharedFunctionInfo shared) {
    1376           1 :   if (!is_listening_to_code_events()) return;
    1377           2 :   if (!FLAG_log_code || !log_->IsEnabled()) return;
    1378           1 :   Log::MessageBuilder msg(log_);
    1379           1 :   msg << kLogEventsNames[CodeEventListener::CODE_DISABLE_OPT_EVENT] << kNext
    1380           2 :       << shared->DebugName() << kNext
    1381           2 :       << GetBailoutReason(shared->disable_optimization_reason());
    1382           1 :   msg.WriteToLogFile();
    1383             : }
    1384             : 
    1385          24 : void Logger::CodeMovingGCEvent() {
    1386          24 :   if (!is_listening_to_code_events()) return;
    1387          48 :   if (!log_->IsEnabled() || !FLAG_ll_prof) return;
    1388           0 :   base::OS::SignalCodeMovingGC();
    1389             : }
    1390             : 
    1391           0 : void Logger::RegExpCodeCreateEvent(AbstractCode code, String source) {
    1392           0 :   if (!is_listening_to_code_events()) return;
    1393           0 :   if (!FLAG_log_code || !log_->IsEnabled()) return;
    1394           0 :   Log::MessageBuilder msg(log_);
    1395           0 :   AppendCodeCreateHeader(msg, CodeEventListener::REG_EXP_TAG, code, &timer_);
    1396           0 :   msg << source;
    1397           0 :   msg.WriteToLogFile();
    1398             : }
    1399             : 
    1400           0 : void Logger::CodeMoveEvent(AbstractCode from, AbstractCode to) {
    1401           0 :   if (!is_listening_to_code_events()) return;
    1402             :   MoveEventInternal(CodeEventListener::CODE_MOVE_EVENT, from->address(),
    1403           0 :                     to->address());
    1404             : }
    1405             : 
    1406             : namespace {
    1407             : 
    1408         387 : void CodeLinePosEvent(JitLogger* jit_logger, Address code_start,
    1409        7436 :                       SourcePositionTableIterator& iter) {
    1410         387 :   if (jit_logger) {
    1411         230 :     void* jit_handler_data = jit_logger->StartCodePosInfoEvent();
    1412        3388 :     for (; !iter.done(); iter.Advance()) {
    1413        1464 :       if (iter.is_statement()) {
    1414             :         jit_logger->AddCodeLinePosInfoEvent(
    1415             :             jit_handler_data, iter.code_offset(),
    1416             :             iter.source_position().ScriptOffset(),
    1417         675 :             JitCodeEvent::STATEMENT_POSITION);
    1418             :       }
    1419             :       jit_logger->AddCodeLinePosInfoEvent(jit_handler_data, iter.code_offset(),
    1420             :                                           iter.source_position().ScriptOffset(),
    1421        1464 :                                           JitCodeEvent::POSITION);
    1422             :     }
    1423         230 :     jit_logger->EndCodePosInfoEvent(code_start, jit_handler_data);
    1424             :   }
    1425         387 : }
    1426             : 
    1427             : }  // namespace
    1428             : 
    1429         387 : void Logger::CodeLinePosInfoRecordEvent(Address code_start,
    1430             :                                         ByteArray source_position_table) {
    1431         387 :   SourcePositionTableIterator iter(source_position_table);
    1432         387 :   CodeLinePosEvent(jit_logger_, code_start, iter);
    1433         387 : }
    1434             : 
    1435           0 : void Logger::CodeLinePosInfoRecordEvent(
    1436             :     Address code_start, Vector<const byte> source_position_table) {
    1437           0 :   SourcePositionTableIterator iter(source_position_table);
    1438           0 :   CodeLinePosEvent(jit_logger_, code_start, iter);
    1439           0 : }
    1440             : 
    1441           0 : void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
    1442           0 :   if (code_name == nullptr) return;  // Not a code object.
    1443           0 :   Log::MessageBuilder msg(log_);
    1444           0 :   msg << kLogEventsNames[CodeEventListener::SNAPSHOT_CODE_NAME_EVENT] << kNext
    1445           0 :       << pos << kNext << code_name;
    1446           0 :   msg.WriteToLogFile();
    1447             : }
    1448             : 
    1449             : 
    1450        2069 : void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
    1451        4138 :   if (!is_listening_to_code_events()) return;
    1452        2069 :   MoveEventInternal(CodeEventListener::SHARED_FUNC_MOVE_EVENT, from, to);
    1453             : }
    1454             : 
    1455        2069 : void Logger::MoveEventInternal(CodeEventListener::LogEventsAndTags event,
    1456             :                                Address from, Address to) {
    1457        4138 :   if (!FLAG_log_code || !log_->IsEnabled()) return;
    1458           0 :   Log::MessageBuilder msg(log_);
    1459           0 :   msg << kLogEventsNames[event] << kNext << reinterpret_cast<void*>(from)
    1460           0 :       << kNext << reinterpret_cast<void*>(to);
    1461           0 :   msg.WriteToLogFile();
    1462             : }
    1463             : 
    1464             : 
    1465          64 : void Logger::ResourceEvent(const char* name, const char* tag) {
    1466         128 :   if (!log_->IsEnabled() || !FLAG_log) return;
    1467          64 :   Log::MessageBuilder msg(log_);
    1468          64 :   msg << name << kNext << tag << kNext;
    1469             : 
    1470             :   uint32_t sec, usec;
    1471          64 :   if (base::OS::GetUserTime(&sec, &usec) != -1) {
    1472         192 :     msg << sec << kNext << usec << kNext;
    1473             :   }
    1474             :   msg.AppendFormatString("%.0f",
    1475          64 :                          V8::GetCurrentPlatform()->CurrentClockTimeMillis());
    1476          64 :   msg.WriteToLogFile();
    1477             : }
    1478             : 
    1479           0 : void Logger::SuspectReadEvent(Name name, Object obj) {
    1480           0 :   if (!log_->IsEnabled() || !FLAG_log_suspect) return;
    1481           0 :   Log::MessageBuilder msg(log_);
    1482             :   String class_name = obj->IsJSObject()
    1483           0 :                           ? JSObject::cast(obj)->class_name()
    1484           0 :                           : ReadOnlyRoots(isolate_).empty_string();
    1485           0 :   msg << "suspect-read" << kNext << class_name << kNext << name;
    1486           0 :   msg.WriteToLogFile();
    1487             : }
    1488             : 
    1489             : namespace {
    1490         244 : void AppendFunctionMessage(Log::MessageBuilder& msg, const char* reason,
    1491             :                            int script_id, double time_delta, int start_position,
    1492             :                            int end_position, base::ElapsedTimer* timer) {
    1493         244 :   msg << "function" << Logger::kNext << reason << Logger::kNext << script_id
    1494         488 :       << Logger::kNext << start_position << Logger::kNext << end_position
    1495         488 :       << Logger::kNext << time_delta << Logger::kNext
    1496         488 :       << timer->Elapsed().InMicroseconds() << Logger::kNext;
    1497         244 : }
    1498             : }  // namespace
    1499             : 
    1500         112 : void Logger::FunctionEvent(const char* reason, int script_id, double time_delta,
    1501             :                            int start_position, int end_position,
    1502             :                            String function_name) {
    1503         224 :   if (!log_->IsEnabled() || !FLAG_log_function_events) return;
    1504         112 :   Log::MessageBuilder msg(log_);
    1505             :   AppendFunctionMessage(msg, reason, script_id, time_delta, start_position,
    1506         112 :                         end_position, &timer_);
    1507         112 :   if (!function_name.is_null()) msg << function_name;
    1508         112 :   msg.WriteToLogFile();
    1509             : }
    1510             : 
    1511         132 : void Logger::FunctionEvent(const char* reason, int script_id, double time_delta,
    1512             :                            int start_position, int end_position,
    1513             :                            const char* function_name,
    1514             :                            size_t function_name_length) {
    1515         264 :   if (!log_->IsEnabled() || !FLAG_log_function_events) return;
    1516         132 :   Log::MessageBuilder msg(log_);
    1517             :   AppendFunctionMessage(msg, reason, script_id, time_delta, start_position,
    1518         132 :                         end_position, &timer_);
    1519         132 :   if (function_name_length > 0) {
    1520          91 :     msg.AppendString(function_name, function_name_length);
    1521             :   }
    1522         132 :   msg.WriteToLogFile();
    1523             : }
    1524             : 
    1525          54 : void Logger::CompilationCacheEvent(const char* action, const char* cache_type,
    1526             :                                    SharedFunctionInfo sfi) {
    1527         149 :   if (!log_->IsEnabled() || !FLAG_log_function_events) return;
    1528          13 :   Log::MessageBuilder msg(log_);
    1529             :   int script_id = -1;
    1530          26 :   if (sfi->script()->IsScript()) {
    1531          13 :     script_id = Script::cast(sfi->script())->id();
    1532             :   }
    1533          13 :   msg << "compilation-cache" << Logger::kNext << action << Logger::kNext
    1534          26 :       << cache_type << Logger::kNext << script_id << Logger::kNext
    1535          26 :       << sfi->StartPosition() << Logger::kNext << sfi->EndPosition()
    1536          39 :       << Logger::kNext << timer_.Elapsed().InMicroseconds();
    1537          13 :   msg.WriteToLogFile();
    1538             : }
    1539             : 
    1540         291 : void Logger::ScriptEvent(ScriptEventType type, int script_id) {
    1541         820 :   if (!log_->IsEnabled() || !FLAG_log_function_events) return;
    1542          53 :   Log::MessageBuilder msg(log_);
    1543          53 :   msg << "script" << Logger::kNext;
    1544          53 :   switch (type) {
    1545             :     case ScriptEventType::kReserveId:
    1546          13 :       msg << "reserve-id";
    1547          13 :       break;
    1548             :     case ScriptEventType::kCreate:
    1549          13 :       msg << "create";
    1550          13 :       break;
    1551             :     case ScriptEventType::kDeserialize:
    1552          27 :       msg << "deserialize";
    1553          27 :       break;
    1554             :     case ScriptEventType::kBackgroundCompile:
    1555           0 :       msg << "background-compile";
    1556           0 :       break;
    1557             :     case ScriptEventType::kStreamingCompile:
    1558           0 :       msg << "streaming-compile";
    1559           0 :       break;
    1560             :   }
    1561         106 :   msg << Logger::kNext << script_id << Logger::kNext
    1562         106 :       << timer_.Elapsed().InMicroseconds();
    1563          53 :   msg.WriteToLogFile();
    1564             : }
    1565             : 
    1566         237 : void Logger::ScriptDetails(Script script) {
    1567         711 :   if (!log_->IsEnabled() || !FLAG_log_function_events) return;
    1568             :   {
    1569          40 :     Log::MessageBuilder msg(log_);
    1570          80 :     msg << "script-details" << Logger::kNext << script->id() << Logger::kNext;
    1571          80 :     if (script->name()->IsString()) {
    1572          18 :       msg << String::cast(script->name());
    1573             :     }
    1574          80 :     msg << Logger::kNext << script->line_offset() << Logger::kNext
    1575          40 :         << script->column_offset() << Logger::kNext;
    1576          80 :     if (script->source_mapping_url()->IsString()) {
    1577           0 :       msg << String::cast(script->source_mapping_url());
    1578             :     }
    1579          40 :     msg.WriteToLogFile();
    1580             :   }
    1581          40 :   EnsureLogScriptSource(script);
    1582             : }
    1583             : 
    1584          40 : bool Logger::EnsureLogScriptSource(Script script) {
    1585          80 :   if (!log_->IsEnabled()) return false;
    1586          40 :   Log::MessageBuilder msg(log_);
    1587             :   // Make sure the script is written to the log file.
    1588          40 :   int script_id = script->id();
    1589          40 :   if (logged_source_code_.find(script_id) != logged_source_code_.end()) {
    1590             :     return true;
    1591             :   }
    1592             :   // This script has not been logged yet.
    1593             :   logged_source_code_.insert(script_id);
    1594          40 :   Object source_object = script->source();
    1595          40 :   if (!source_object->IsString()) return false;
    1596          40 :   String source_code = String::cast(source_object);
    1597          80 :   msg << "script-source" << kNext << script_id << kNext;
    1598             : 
    1599             :   // Log the script name.
    1600          80 :   if (script->name()->IsString()) {
    1601          18 :     msg << String::cast(script->name()) << kNext;
    1602             :   } else {
    1603          31 :     msg << "<unknown>" << kNext;
    1604             :   }
    1605             : 
    1606             :   // Log the source code.
    1607          40 :   msg << source_code;
    1608          40 :   msg.WriteToLogFile();
    1609          40 :   return true;
    1610             : }
    1611             : 
    1612           0 : void Logger::RuntimeCallTimerEvent() {
    1613           0 :   RuntimeCallStats* stats = isolate_->counters()->runtime_call_stats();
    1614           0 :   RuntimeCallCounter* counter = stats->current_counter();
    1615           0 :   if (counter == nullptr) return;
    1616           0 :   Log::MessageBuilder msg(log_);
    1617           0 :   msg << "active-runtime-timer" << kNext << counter->name();
    1618           0 :   msg.WriteToLogFile();
    1619             : }
    1620             : 
    1621           0 : void Logger::TickEvent(v8::TickSample* sample, bool overflow) {
    1622           0 :   if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
    1623           0 :   if (V8_UNLIKELY(FLAG_runtime_stats ==
    1624             :                   v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) {
    1625           0 :     RuntimeCallTimerEvent();
    1626             :   }
    1627           0 :   Log::MessageBuilder msg(log_);
    1628           0 :   msg << kLogEventsNames[CodeEventListener::TICK_EVENT] << kNext
    1629           0 :       << reinterpret_cast<void*>(sample->pc) << kNext
    1630           0 :       << timer_.Elapsed().InMicroseconds();
    1631           0 :   if (sample->has_external_callback) {
    1632           0 :     msg << kNext << 1 << kNext
    1633           0 :         << reinterpret_cast<void*>(sample->external_callback_entry);
    1634             :   } else {
    1635           0 :     msg << kNext << 0 << kNext << reinterpret_cast<void*>(sample->tos);
    1636             :   }
    1637           0 :   msg << kNext << static_cast<int>(sample->state);
    1638           0 :   if (overflow) msg << kNext << "overflow";
    1639           0 :   for (unsigned i = 0; i < sample->frames_count; ++i) {
    1640           0 :     msg << kNext << reinterpret_cast<void*>(sample->stack[i]);
    1641             :   }
    1642           0 :   msg.WriteToLogFile();
    1643             : }
    1644             : 
    1645           0 : void Logger::ICEvent(const char* type, bool keyed, Map map, Object key,
    1646             :                      char old_state, char new_state, const char* modifier,
    1647             :                      const char* slow_stub_reason) {
    1648           0 :   if (!log_->IsEnabled() || !FLAG_trace_ic) return;
    1649           0 :   Log::MessageBuilder msg(log_);
    1650           0 :   if (keyed) msg << "Keyed";
    1651             :   int line;
    1652             :   int column;
    1653           0 :   Address pc = isolate_->GetAbstractPC(&line, &column);
    1654           0 :   msg << type << kNext << reinterpret_cast<void*>(pc) << kNext << line << kNext
    1655           0 :       << column << kNext << old_state << kNext << new_state << kNext
    1656           0 :       << reinterpret_cast<void*>(map.ptr()) << kNext;
    1657           0 :   if (key->IsSmi()) {
    1658           0 :     msg << Smi::ToInt(key);
    1659           0 :   } else if (key->IsNumber()) {
    1660           0 :     msg << key->Number();
    1661           0 :   } else if (key->IsName()) {
    1662           0 :     msg << Name::cast(key);
    1663             :   }
    1664           0 :   msg << kNext << modifier << kNext;
    1665           0 :   if (slow_stub_reason != nullptr) {
    1666           0 :     msg << slow_stub_reason;
    1667             :   }
    1668           0 :   msg.WriteToLogFile();
    1669             : }
    1670             : 
    1671        7172 : void Logger::MapEvent(const char* type, Map from, Map to, const char* reason,
    1672             :                       HeapObject name_or_sfi) {
    1673             :   DisallowHeapAllocation no_gc;
    1674       14344 :   if (!log_->IsEnabled() || !FLAG_trace_maps) return;
    1675        7172 :   if (!to.is_null()) MapDetails(to);
    1676        7172 :   int line = -1;
    1677        7172 :   int column = -1;
    1678             :   Address pc = 0;
    1679             : 
    1680        7172 :   if (!isolate_->bootstrapper()->IsActive()) {
    1681        3747 :     pc = isolate_->GetAbstractPC(&line, &column);
    1682             :   }
    1683        7172 :   Log::MessageBuilder msg(log_);
    1684       14344 :   msg << "map" << kNext << type << kNext << timer_.Elapsed().InMicroseconds()
    1685       14344 :       << kNext << reinterpret_cast<void*>(from.ptr()) << kNext
    1686       14344 :       << reinterpret_cast<void*>(to.ptr()) << kNext
    1687       21516 :       << reinterpret_cast<void*>(pc) << kNext << line << kNext << column
    1688       14344 :       << kNext << reason << kNext;
    1689             : 
    1690        7172 :   if (!name_or_sfi.is_null()) {
    1691        5180 :     if (name_or_sfi->IsName()) {
    1692        5180 :       msg << Name::cast(name_or_sfi);
    1693           0 :     } else if (name_or_sfi->IsSharedFunctionInfo()) {
    1694           0 :       SharedFunctionInfo sfi = SharedFunctionInfo::cast(name_or_sfi);
    1695           0 :       msg << sfi->DebugName();
    1696             : #if V8_SFI_HAS_UNIQUE_ID
    1697             :       msg << " " << sfi->unique_id();
    1698             : #endif  // V8_SFI_HAS_UNIQUE_ID
    1699             :     }
    1700             :   }
    1701        7172 :   msg.WriteToLogFile();
    1702             : }
    1703             : 
    1704       15867 : void Logger::MapCreate(Map map) {
    1705       31734 :   if (!log_->IsEnabled() || !FLAG_trace_maps) return;
    1706             :   DisallowHeapAllocation no_gc;
    1707       15867 :   Log::MessageBuilder msg(log_);
    1708       47601 :   msg << "map-create" << kNext << timer_.Elapsed().InMicroseconds() << kNext
    1709       31734 :       << reinterpret_cast<void*>(map.ptr());
    1710       15867 :   msg.WriteToLogFile();
    1711             : }
    1712             : 
    1713       15955 : void Logger::MapDetails(Map map) {
    1714       31998 :   if (!log_->IsEnabled() || !FLAG_trace_maps) return;
    1715             :   DisallowHeapAllocation no_gc;
    1716       15867 :   Log::MessageBuilder msg(log_);
    1717       47601 :   msg << "map-details" << kNext << timer_.Elapsed().InMicroseconds() << kNext
    1718       31734 :       << reinterpret_cast<void*>(map.ptr()) << kNext;
    1719       15867 :   if (FLAG_trace_maps_details) {
    1720       15867 :     std::ostringstream buffer;
    1721       15867 :     map->PrintMapDetails(buffer);
    1722       31734 :     msg << buffer.str().c_str();
    1723             :   }
    1724       15867 :   msg.WriteToLogFile();
    1725             : }
    1726             : 
    1727           0 : void Logger::StopProfiler() {
    1728           0 :   if (!log_->IsEnabled()) return;
    1729           0 :   if (profiler_ != nullptr) {
    1730             :     profiler_->Pause();
    1731           0 :     is_logging_ = false;
    1732           0 :     RemoveCodeEventListener(this);
    1733             :   }
    1734             : }
    1735             : 
    1736             : // This function can be called when Log's mutex is acquired,
    1737             : // either from main or Profiler's thread.
    1738           0 : void Logger::LogFailure() {
    1739           0 :   StopProfiler();
    1740           0 : }
    1741             : 
    1742     2221532 : static void AddFunctionAndCode(SharedFunctionInfo sfi, AbstractCode code_object,
    1743             :                                Handle<SharedFunctionInfo>* sfis,
    1744             :                                Handle<AbstractCode>* code_objects, int offset) {
    1745     2221532 :   if (sfis != nullptr) {
    1746     2221532 :     sfis[offset] = Handle<SharedFunctionInfo>(sfi, sfi->GetIsolate());
    1747             :   }
    1748     2221532 :   if (code_objects != nullptr) {
    1749     2221532 :     code_objects[offset] = Handle<AbstractCode>(code_object, sfi->GetIsolate());
    1750             :   }
    1751     2221532 : }
    1752             : 
    1753        1576 : static int EnumerateCompiledFunctions(Heap* heap,
    1754             :                                       Handle<SharedFunctionInfo>* sfis,
    1755             :                                       Handle<AbstractCode>* code_objects) {
    1756        1576 :   HeapIterator iterator(heap);
    1757             :   DisallowHeapAllocation no_gc;
    1758             :   int compiled_funcs_count = 0;
    1759             : 
    1760             :   // Iterate the heap to find shared function info objects and record
    1761             :   // the unoptimized code for them.
    1762    46948680 :   for (HeapObject obj = iterator.next(); !obj.is_null();
    1763             :        obj = iterator.next()) {
    1764    23472764 :     if (obj->IsSharedFunctionInfo()) {
    1765     2035274 :       SharedFunctionInfo sfi = SharedFunctionInfo::cast(obj);
    1766     6105822 :       if (sfi->is_compiled() &&
    1767     7082950 :           (!sfi->script()->IsScript() ||
    1768     4046626 :            Script::cast(sfi->script())->HasValidSource())) {
    1769             :         AddFunctionAndCode(sfi, AbstractCode::cast(sfi->abstract_code()), sfis,
    1770     4041960 :                            code_objects, compiled_funcs_count);
    1771     2020980 :         ++compiled_funcs_count;
    1772             :       }
    1773    21437490 :     } else if (obj->IsJSFunction()) {
    1774             :       // Given that we no longer iterate over all optimized JSFunctions, we need
    1775             :       // to take care of this here.
    1776     2001070 :       JSFunction function = JSFunction::cast(obj);
    1777     4002140 :       SharedFunctionInfo sfi = SharedFunctionInfo::cast(function->shared());
    1778     2001070 :       Object maybe_script = sfi->script();
    1779     6003210 :       if (maybe_script->IsScript() &&
    1780     4040750 :           !Script::cast(maybe_script)->HasValidSource()) {
    1781          20 :         continue;
    1782             :       }
    1783             :       // TODO(jarin) This leaves out deoptimized code that might still be on the
    1784             :       // stack. Also note that we will not log optimized code objects that are
    1785             :       // only on a type feedback vector. We should make this mroe precise.
    1786     2001050 :       if (function->IsOptimized()) {
    1787             :         AddFunctionAndCode(sfi, AbstractCode::cast(function->code()), sfis,
    1788      401104 :                            code_objects, compiled_funcs_count);
    1789      200552 :         ++compiled_funcs_count;
    1790             :       }
    1791             :     }
    1792             :   }
    1793        1576 :   return compiled_funcs_count;
    1794             : }
    1795             : 
    1796        1576 : static int EnumerateWasmModuleObjects(
    1797             :     Heap* heap, Handle<WasmModuleObject>* module_objects) {
    1798        1576 :   HeapIterator iterator(heap);
    1799             :   DisallowHeapAllocation no_gc;
    1800             :   int module_objects_count = 0;
    1801             : 
    1802    46950488 :   for (HeapObject obj = iterator.next(); !obj.is_null();
    1803             :        obj = iterator.next()) {
    1804    23473668 :     if (obj->IsWasmModuleObject()) {
    1805             :       WasmModuleObject module = WasmModuleObject::cast(obj);
    1806           0 :       if (module_objects != nullptr) {
    1807           0 :         module_objects[module_objects_count] = handle(module, heap->isolate());
    1808             :       }
    1809           0 :       module_objects_count++;
    1810             :     }
    1811             :   }
    1812        1576 :   return module_objects_count;
    1813             : }
    1814             : 
    1815           0 : void Logger::LogCodeObject(Object object) {
    1816           0 :   existing_code_logger_.LogCodeObject(object);
    1817           0 : }
    1818             : 
    1819          35 : void Logger::LogCodeObjects() { existing_code_logger_.LogCodeObjects(); }
    1820             : 
    1821           0 : void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
    1822             :                                  Handle<AbstractCode> code) {
    1823           0 :   existing_code_logger_.LogExistingFunction(shared, code);
    1824           0 : }
    1825             : 
    1826         763 : void Logger::LogCompiledFunctions() {
    1827         768 :   existing_code_logger_.LogCompiledFunctions();
    1828         763 : }
    1829             : 
    1830         748 : void Logger::LogAccessorCallbacks() {
    1831         748 :   Heap* heap = isolate_->heap();
    1832         748 :   HeapIterator iterator(heap);
    1833             :   DisallowHeapAllocation no_gc;
    1834    22919422 :   for (HeapObject obj = iterator.next(); !obj.is_null();
    1835             :        obj = iterator.next()) {
    1836    22909083 :     if (!obj->IsAccessorInfo()) continue;
    1837        8843 :     AccessorInfo ai = AccessorInfo::cast(obj);
    1838       17686 :     if (!ai->name()->IsName()) continue;
    1839        8843 :     Address getter_entry = v8::ToCData<Address>(ai->getter());
    1840       17686 :     Name name = Name::cast(ai->name());
    1841        8843 :     if (getter_entry != 0) {
    1842             : #if USES_FUNCTION_DESCRIPTORS
    1843             :       getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(getter_entry);
    1844             : #endif
    1845       17686 :       PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
    1846             :     }
    1847        8843 :     Address setter_entry = v8::ToCData<Address>(ai->setter());
    1848        8843 :     if (setter_entry != 0) {
    1849             : #if USES_FUNCTION_DESCRIPTORS
    1850             :       setter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(setter_entry);
    1851             : #endif
    1852       17676 :       PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
    1853             :     }
    1854         748 :   }
    1855         748 : }
    1856             : 
    1857          17 : void Logger::LogAllMaps() {
    1858             :   DisallowHeapAllocation no_gc;
    1859          17 :   Heap* heap = isolate_->heap();
    1860          17 :   HeapIterator iterator(heap);
    1861      168436 :   for (HeapObject obj = iterator.next(); !obj.is_null();
    1862             :        obj = iterator.next()) {
    1863      165784 :     if (!obj->IsMap()) continue;
    1864        2618 :     Map map = Map::cast(obj);
    1865        2618 :     MapCreate(map);
    1866        2618 :     MapDetails(map);
    1867          17 :   }
    1868          17 : }
    1869             : 
    1870       62883 : static void AddIsolateIdIfNeeded(std::ostream& os,  // NOLINT
    1871             :                                  Isolate* isolate) {
    1872       62883 :   if (FLAG_logfile_per_isolate) {
    1873       66758 :     os << "isolate-" << isolate << "-" << base::OS::GetCurrentProcessId()
    1874       33379 :        << "-";
    1875             :   }
    1876       62883 : }
    1877             : 
    1878       62883 : static void PrepareLogFileName(std::ostream& os,  // NOLINT
    1879             :                                Isolate* isolate, const char* file_name) {
    1880             :   int dir_separator_count = 0;
    1881      439876 :   for (const char* p = file_name; *p; p++) {
    1882      376993 :     if (base::OS::isDirectorySeparator(*p)) dir_separator_count++;
    1883             :   }
    1884             : 
    1885      376993 :   for (const char* p = file_name; *p; p++) {
    1886      376993 :     if (dir_separator_count == 0) {
    1887       62883 :       AddIsolateIdIfNeeded(os, isolate);
    1888       62883 :       dir_separator_count--;
    1889             :     }
    1890      376993 :     if (*p == '%') {
    1891           0 :       p++;
    1892           0 :       switch (*p) {
    1893             :         case '\0':
    1894             :           // If there's a % at the end of the string we back up
    1895             :           // one character so we can escape the loop properly.
    1896             :           p--;
    1897             :           break;
    1898             :         case 'p':
    1899           0 :           os << base::OS::GetCurrentProcessId();
    1900           0 :           break;
    1901             :         case 't':
    1902             :           // %t expands to the current time in milliseconds.
    1903             :           os << static_cast<int64_t>(
    1904           0 :               V8::GetCurrentPlatform()->CurrentClockTimeMillis());
    1905             :           break;
    1906             :         case '%':
    1907             :           // %% expands (contracts really) to %.
    1908             :           os << '%';
    1909             :           break;
    1910             :         default:
    1911             :           // All other %'s expand to themselves.
    1912             :           os << '%' << *p;
    1913             :           break;
    1914             :       }
    1915             :     } else {
    1916      376993 :       if (base::OS::isDirectorySeparator(*p)) dir_separator_count--;
    1917      376993 :       os << *p;
    1918             :     }
    1919             :   }
    1920       62883 : }
    1921             : 
    1922             : 
    1923       62883 : bool Logger::SetUp(Isolate* isolate) {
    1924             :   // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
    1925       62883 :   if (is_initialized_) return true;
    1926       62883 :   is_initialized_ = true;
    1927             : 
    1928       62883 :   std::ostringstream log_file_name;
    1929      125766 :   std::ostringstream source_log_file_name;
    1930       62883 :   PrepareLogFileName(log_file_name, isolate, FLAG_logfile);
    1931      125766 :   log_ = new Log(this, log_file_name.str().c_str());
    1932             : 
    1933       62883 :   if (FLAG_perf_basic_prof) {
    1934           0 :     perf_basic_logger_ = new PerfBasicLogger(isolate);
    1935           0 :     AddCodeEventListener(perf_basic_logger_);
    1936             :   }
    1937             : 
    1938       62883 :   if (FLAG_perf_prof) {
    1939           0 :     perf_jit_logger_ = new PerfJitLogger(isolate);
    1940           0 :     AddCodeEventListener(perf_jit_logger_);
    1941             :   }
    1942             : 
    1943       62883 :   if (FLAG_ll_prof) {
    1944           0 :     ll_logger_ = new LowLevelLogger(isolate, log_file_name.str().c_str());
    1945           0 :     AddCodeEventListener(ll_logger_);
    1946             :   }
    1947             : 
    1948       62883 :   ticker_ = new Ticker(isolate, FLAG_prof_sampling_interval);
    1949             : 
    1950       62883 :   if (Log::InitLogAtStart()) {
    1951          61 :     is_logging_ = true;
    1952             :   }
    1953             : 
    1954             :   timer_.Start();
    1955             : 
    1956       62883 :   if (FLAG_prof_cpp) {
    1957           0 :     profiler_ = new Profiler(isolate);
    1958           0 :     is_logging_ = true;
    1959           0 :     profiler_->Engage();
    1960             :   }
    1961             : 
    1962       62883 :   if (is_logging_) {
    1963          61 :     AddCodeEventListener(this);
    1964             :   }
    1965             : 
    1966       62883 :   return true;
    1967             : }
    1968             : 
    1969             : 
    1970          60 : void Logger::SetCodeEventHandler(uint32_t options,
    1971             :                                  JitCodeEventHandler event_handler) {
    1972          60 :   if (jit_logger_) {
    1973             :     RemoveCodeEventListener(jit_logger_);
    1974          25 :     delete jit_logger_;
    1975          25 :     jit_logger_ = nullptr;
    1976             :   }
    1977             : 
    1978          60 :   if (event_handler) {
    1979          35 :     jit_logger_ = new JitLogger(isolate_, event_handler);
    1980          35 :     AddCodeEventListener(jit_logger_);
    1981          35 :     if (options & kJitCodeEventEnumExisting) {
    1982           5 :       HandleScope scope(isolate_);
    1983             :       LogCodeObjects();
    1984             :       LogCompiledFunctions();
    1985             :     }
    1986             :   }
    1987          60 : }
    1988             : 
    1989       62867 : sampler::Sampler* Logger::sampler() {
    1990       62867 :   return ticker_;
    1991             : }
    1992             : 
    1993      125734 : void Logger::StopProfilerThread() {
    1994      125734 :   if (profiler_ != nullptr) {
    1995           0 :     profiler_->Disengage();
    1996           0 :     delete profiler_;
    1997           0 :     profiler_ = nullptr;
    1998             :   }
    1999      125734 : }
    2000             : 
    2001       62985 : FILE* Logger::TearDown() {
    2002       62985 :   if (!is_initialized_) return nullptr;
    2003       62868 :   is_initialized_ = false;
    2004             : 
    2005             :   // Stop the profiler thread before closing the file.
    2006       62868 :   StopProfilerThread();
    2007             : 
    2008       62868 :   delete ticker_;
    2009       62868 :   ticker_ = nullptr;
    2010             : 
    2011       62868 :   if (perf_basic_logger_) {
    2012             :     RemoveCodeEventListener(perf_basic_logger_);
    2013           0 :     delete perf_basic_logger_;
    2014           0 :     perf_basic_logger_ = nullptr;
    2015             :   }
    2016             : 
    2017       62868 :   if (perf_jit_logger_) {
    2018             :     RemoveCodeEventListener(perf_jit_logger_);
    2019           0 :     delete perf_jit_logger_;
    2020           0 :     perf_jit_logger_ = nullptr;
    2021             :   }
    2022             : 
    2023       62868 :   if (ll_logger_) {
    2024             :     RemoveCodeEventListener(ll_logger_);
    2025           0 :     delete ll_logger_;
    2026           0 :     ll_logger_ = nullptr;
    2027             :   }
    2028             : 
    2029       62868 :   if (jit_logger_) {
    2030             :     RemoveCodeEventListener(jit_logger_);
    2031          10 :     delete jit_logger_;
    2032          10 :     jit_logger_ = nullptr;
    2033             :   }
    2034             : 
    2035       62868 :   return log_->Close();
    2036             : }
    2037             : 
    2038       83181 : void ExistingCodeLogger::LogCodeObject(Object object) {
    2039       83181 :   AbstractCode abstract_code = AbstractCode::cast(object);
    2040             :   CodeEventListener::LogEventsAndTags tag = CodeEventListener::STUB_TAG;
    2041             :   const char* description = "Unknown code from before profiling";
    2042       83181 :   switch (abstract_code->kind()) {
    2043             :     case AbstractCode::INTERPRETED_FUNCTION:
    2044             :     case AbstractCode::OPTIMIZED_FUNCTION:
    2045       26244 :       return;  // We log this later using LogCompiledFunctions.
    2046             :     case AbstractCode::BYTECODE_HANDLER:
    2047             :       return;  // We log it later by walking the dispatch table.
    2048             :     case AbstractCode::STUB:
    2049             :       description = "STUB code";
    2050             :       tag = CodeEventListener::STUB_TAG;
    2051          12 :       break;
    2052             :     case AbstractCode::REGEXP:
    2053             :       description = "Regular expression code";
    2054             :       tag = CodeEventListener::REG_EXP_TAG;
    2055           0 :       break;
    2056             :     case AbstractCode::BUILTIN:
    2057      114265 :       if (Code::cast(object)->is_interpreter_trampoline_builtin() &&
    2058             :           Code::cast(object) !=
    2059       57220 :               *BUILTIN_CODE(isolate_, InterpreterEntryTrampoline)) {
    2060             :         return;
    2061             :       }
    2062             :       description =
    2063      113850 :           isolate_->builtins()->name(abstract_code->GetCode()->builtin_index());
    2064             :       tag = CodeEventListener::BUILTIN_TAG;
    2065       56925 :       break;
    2066             :     case AbstractCode::WASM_FUNCTION:
    2067             :       description = "A Wasm function";
    2068             :       tag = CodeEventListener::FUNCTION_TAG;
    2069           0 :       break;
    2070             :     case AbstractCode::JS_TO_WASM_FUNCTION:
    2071             :       description = "A JavaScript to Wasm adapter";
    2072             :       tag = CodeEventListener::STUB_TAG;
    2073           0 :       break;
    2074             :     case AbstractCode::WASM_TO_JS_FUNCTION:
    2075             :       description = "A Wasm to JavaScript adapter";
    2076             :       tag = CodeEventListener::STUB_TAG;
    2077           0 :       break;
    2078             :     case AbstractCode::WASM_INTERPRETER_ENTRY:
    2079             :       description = "A Wasm to Interpreter adapter";
    2080             :       tag = CodeEventListener::STUB_TAG;
    2081           0 :       break;
    2082             :     case AbstractCode::C_WASM_ENTRY:
    2083             :       description = "A C to Wasm entry stub";
    2084             :       tag = CodeEventListener::STUB_TAG;
    2085           0 :       break;
    2086             :     case AbstractCode::NUMBER_OF_KINDS:
    2087           0 :       UNIMPLEMENTED();
    2088             :   }
    2089       93168 :   CALL_CODE_EVENT_HANDLER(CodeCreateEvent(tag, abstract_code, description))
    2090             : }
    2091             : 
    2092          55 : void ExistingCodeLogger::LogCodeObjects() {
    2093          55 :   Heap* heap = isolate_->heap();
    2094          55 :   HeapIterator iterator(heap);
    2095             :   DisallowHeapAllocation no_gc;
    2096      782050 :   for (HeapObject obj = iterator.next(); !obj.is_null();
    2097             :        obj = iterator.next()) {
    2098      390970 :     if (obj->IsCode()) LogCodeObject(obj);
    2099      390970 :     if (obj->IsBytecodeArray()) LogCodeObject(obj);
    2100          55 :   }
    2101          55 : }
    2102             : 
    2103         788 : void ExistingCodeLogger::LogCompiledFunctions() {
    2104         788 :   Heap* heap = isolate_->heap();
    2105             :   HandleScope scope(isolate_);
    2106             :   const int compiled_funcs_count =
    2107         788 :       EnumerateCompiledFunctions(heap, nullptr, nullptr);
    2108             :   ScopedVector<Handle<SharedFunctionInfo>> sfis(compiled_funcs_count);
    2109             :   ScopedVector<Handle<AbstractCode>> code_objects(compiled_funcs_count);
    2110         788 :   EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start());
    2111             : 
    2112             :   // During iteration, there can be heap allocation due to
    2113             :   // GetScriptLineNumber call.
    2114     1111554 :   for (int i = 0; i < compiled_funcs_count; ++i) {
    2115     3332298 :     if (sfis[i]->function_data()->IsInterpreterData()) {
    2116             :       LogExistingFunction(
    2117             :           sfis[i],
    2118             :           Handle<AbstractCode>(
    2119          24 :               AbstractCode::cast(sfis[i]->InterpreterTrampoline()), isolate_),
    2120          24 :           CodeEventListener::INTERPRETED_FUNCTION_TAG);
    2121             :     }
    2122     2221532 :     if (code_objects[i].is_identical_to(BUILTIN_CODE(isolate_, CompileLazy)))
    2123             :       continue;
    2124     1110766 :     LogExistingFunction(sfis[i], code_objects[i]);
    2125             :   }
    2126             : 
    2127             :   const int wasm_module_objects_count =
    2128         788 :       EnumerateWasmModuleObjects(heap, nullptr);
    2129             :   std::unique_ptr<Handle<WasmModuleObject>[]> module_objects(
    2130         788 :       new Handle<WasmModuleObject>[wasm_module_objects_count]);
    2131         788 :   EnumerateWasmModuleObjects(heap, module_objects.get());
    2132         788 :   for (int i = 0; i < wasm_module_objects_count; ++i) {
    2133           0 :     module_objects[i]->native_module()->LogWasmCodes(isolate_);
    2134             :   }
    2135         788 : }
    2136             : 
    2137     1110778 : void ExistingCodeLogger::LogExistingFunction(
    2138             :     Handle<SharedFunctionInfo> shared, Handle<AbstractCode> code,
    2139             :     CodeEventListener::LogEventsAndTags tag) {
    2140     2221556 :   if (shared->script()->IsScript()) {
    2141     1809348 :     Handle<Script> script(Script::cast(shared->script()), isolate_);
    2142      603116 :     int line_num = Script::GetLineNumber(script, shared->StartPosition()) + 1;
    2143             :     int column_num =
    2144      603116 :         Script::GetColumnNumber(script, shared->StartPosition()) + 1;
    2145     1206232 :     if (script->name()->IsString()) {
    2146        2535 :       Handle<String> script_name(String::cast(script->name()), isolate_);
    2147         845 :       if (line_num > 0) {
    2148        3380 :         CALL_CODE_EVENT_HANDLER(
    2149             :             CodeCreateEvent(Logger::ToNativeByScript(tag, *script), *code,
    2150             :                             *shared, *script_name, line_num, column_num))
    2151             :       } else {
    2152             :         // Can't distinguish eval and script here, so always use Script.
    2153           0 :         CALL_CODE_EVENT_HANDLER(CodeCreateEvent(
    2154             :             Logger::ToNativeByScript(CodeEventListener::SCRIPT_TAG, *script),
    2155             :             *code, *shared, *script_name))
    2156             :       }
    2157             :     } else {
    2158     2409028 :       CALL_CODE_EVENT_HANDLER(CodeCreateEvent(
    2159             :           Logger::ToNativeByScript(tag, *script), *code, *shared,
    2160             :           ReadOnlyRoots(isolate_).empty_string(), line_num, column_num))
    2161             :     }
    2162      507662 :   } else if (shared->IsApiFunction()) {
    2163             :     // API function.
    2164       19277 :     FunctionTemplateInfo fun_data = shared->get_api_func_data();
    2165       19277 :     Object raw_call_data = fun_data->call_code();
    2166       38554 :     if (!raw_call_data->IsUndefined(isolate_)) {
    2167       19187 :       CallHandlerInfo call_data = CallHandlerInfo::cast(raw_call_data);
    2168       19187 :       Object callback_obj = call_data->callback();
    2169       19187 :       Address entry_point = v8::ToCData<Address>(callback_obj);
    2170             : #if USES_FUNCTION_DESCRIPTORS
    2171             :       entry_point = *FUNCTION_ENTRYPOINT_ADDRESS(entry_point);
    2172             : #endif
    2173       57141 :       CALL_CODE_EVENT_HANDLER(CallbackEvent(shared->DebugName(), entry_point))
    2174             :     }
    2175             :   }
    2176     1110778 : }
    2177             : 
    2178             : #undef CALL_CODE_EVENT_HANDLER
    2179             : 
    2180             : }  // namespace internal
    2181      183867 : }  // namespace v8

Generated by: LCOV version 1.10