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