• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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