1 // Copyright 2018 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 #ifndef V8_DIAGNOSTICS_CODE_TRACER_H_ 6 #define V8_DIAGNOSTICS_CODE_TRACER_H_ 7 8 #include "src/base/optional.h" 9 #include "src/common/globals.h" 10 #include "src/flags/flags.h" 11 #include "src/utils/allocation.h" 12 #include "src/utils/ostreams.h" 13 #include "src/utils/utils.h" 14 #include "src/utils/vector.h" 15 16 namespace v8 { 17 namespace internal { 18 19 class CodeTracer final : public Malloced { 20 public: CodeTracer(int isolate_id)21 explicit CodeTracer(int isolate_id) : file_(nullptr), scope_depth_(0) { 22 if (!ShouldRedirect()) { 23 file_ = stdout; 24 return; 25 } 26 27 if (FLAG_redirect_code_traces_to != nullptr) { 28 StrNCpy(filename_, FLAG_redirect_code_traces_to, filename_.length()); 29 } else if (isolate_id >= 0) { 30 SNPrintF(filename_, "code-%d-%d.asm", base::OS::GetCurrentProcessId(), 31 isolate_id); 32 } else { 33 SNPrintF(filename_, "code-%d.asm", base::OS::GetCurrentProcessId()); 34 } 35 36 WriteChars(filename_.begin(), "", 0, false); 37 } 38 39 class Scope { 40 public: Scope(CodeTracer * tracer)41 explicit Scope(CodeTracer* tracer) : tracer_(tracer) { tracer->OpenFile(); } ~Scope()42 ~Scope() { tracer_->CloseFile(); } 43 file()44 FILE* file() const { return tracer_->file(); } 45 46 private: 47 CodeTracer* tracer_; 48 }; 49 50 class StreamScope : public Scope { 51 public: StreamScope(CodeTracer * tracer)52 explicit StreamScope(CodeTracer* tracer) : Scope(tracer) { 53 FILE* file = this->file(); 54 if (file == stdout) { 55 stdout_stream_.emplace(); 56 } else { 57 file_stream_.emplace(file); 58 } 59 } 60 stream()61 std::ostream& stream() { 62 if (stdout_stream_.has_value()) return stdout_stream_.value(); 63 return file_stream_.value(); 64 } 65 66 private: 67 // Exactly one of these two will be initialized. 68 base::Optional<StdoutStream> stdout_stream_; 69 base::Optional<OFStream> file_stream_; 70 }; 71 OpenFile()72 void OpenFile() { 73 if (!ShouldRedirect()) { 74 return; 75 } 76 77 if (file_ == nullptr) { 78 file_ = base::OS::FOpen(filename_.begin(), "ab"); 79 CHECK_WITH_MSG(file_ != nullptr, 80 "could not open file. If on Android, try passing " 81 "--redirect-code-traces-to=/sdcard/Download/<file-name>"); 82 } 83 84 scope_depth_++; 85 } 86 CloseFile()87 void CloseFile() { 88 if (!ShouldRedirect()) { 89 return; 90 } 91 92 if (--scope_depth_ == 0) { 93 DCHECK_NOT_NULL(file_); 94 fclose(file_); 95 file_ = nullptr; 96 } 97 } 98 file()99 FILE* file() const { return file_; } 100 101 private: ShouldRedirect()102 static bool ShouldRedirect() { return FLAG_redirect_code_traces; } 103 104 EmbeddedVector<char, 128> filename_; 105 FILE* file_; 106 int scope_depth_; 107 }; 108 109 } // namespace internal 110 } // namespace v8 111 112 #endif // V8_DIAGNOSTICS_CODE_TRACER_H_ 113