GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../tools/code_cache/cache_builder.cc Lines: 66 69 95.7 %
Date: 2020-05-27 22:15:15 Branches: 25 30 83.3 %

Line Branch Exec Source
1
#include "cache_builder.h"
2
#include "debug_utils-inl.h"
3
#include "node_native_module.h"
4
#include "util.h"
5
6
#include <iostream>
7
#include <map>
8
#include <sstream>
9
#include <vector>
10
#include <cstdlib>
11
12
namespace node {
13
namespace native_module {
14
15
using v8::Context;
16
using v8::Function;
17
using v8::Isolate;
18
using v8::Local;
19
using v8::MaybeLocal;
20
using v8::ScriptCompiler;
21
22
352
static std::string GetDefName(const std::string& id) {
23
352
  char buf[64] = {0};
24
352
  size_t size = id.size();
25
352
  CHECK_LT(size, sizeof(buf));
26
6836
  for (size_t i = 0; i < size; ++i) {
27
6484
    char ch = id[i];
28

6484
    buf[i] = (ch == '-' || ch == '/') ? '_' : ch;
29
  }
30
352
  return buf;
31
}
32
33
352
static std::string FormatSize(size_t size) {
34
352
  char buf[64] = {0};
35
352
  if (size < 1024) {
36
9
    snprintf(buf, sizeof(buf), "%.2fB", static_cast<double>(size));
37
343
  } else if (size < 1024 * 1024) {
38
343
    snprintf(buf, sizeof(buf), "%.2fKB", static_cast<double>(size / 1024));
39
  } else {
40
    snprintf(
41
        buf, sizeof(buf), "%.2fMB", static_cast<double>(size / 1024 / 1024));
42
  }
43
352
  return buf;
44
}
45
46
176
static std::string GetDefinition(const std::string& id,
47
                                 size_t size,
48
                                 const uint8_t* data) {
49
352
  std::stringstream ss;
50
176
  ss << "static const uint8_t " << GetDefName(id) << "[] = {\n";
51
801184
  for (size_t i = 0; i < size; ++i) {
52
801008
    uint8_t ch = data[i];
53
801008
    ss << std::to_string(ch) << (i == size - 1 ? '\n' : ',');
54
  }
55
176
  ss << "};";
56
352
  return ss.str();
57
}
58
59
176
static void GetInitializer(const std::string& id, std::stringstream& ss) {
60
352
  std::string def_name = GetDefName(id);
61
176
  ss << "  code_cache.emplace(\n";
62
176
  ss << "    \"" << id << "\",\n";
63
176
  ss << "    std::make_unique<v8::ScriptCompiler::CachedData>(\n";
64
176
  ss << "      " << def_name << ",\n";
65
176
  ss << "      static_cast<int>(arraysize(" << def_name << ")), policy\n";
66
176
  ss << "    )\n";
67
176
  ss << "  );";
68
176
}
69
70
1
static std::string GenerateCodeCache(
71
    const std::map<std::string, ScriptCompiler::CachedData*>& data) {
72
2
  std::stringstream ss;
73
  ss << R"(#include <cinttypes>
74
#include "node_native_module_env.h"
75
76
// This file is generated by mkcodecache (tools/code_cache/mkcodecache.cc)
77
78
namespace node {
79
namespace native_module {
80
81
const bool has_code_cache = true;
82
83
1
)";
84
85
1
  size_t total = 0;
86
177
  for (const auto& x : data) {
87
176
    const std::string& id = x.first;
88
176
    ScriptCompiler::CachedData* cached_data = x.second;
89
176
    total += cached_data->length;
90
352
    std::string def = GetDefinition(id, cached_data->length, cached_data->data);
91
176
    ss << def << "\n\n";
92
352
    std::string size_str = FormatSize(cached_data->length);
93
352
    std::string total_str = FormatSize(total);
94
    per_process::Debug(DebugCategory::CODE_CACHE,
95
                       "Generated cache for %s, size = %s, total = %s\n",
96
352
                       id.c_str(),
97
352
                       size_str.c_str(),
98
352
                       total_str.c_str());
99
  }
100
101
  ss << R"(void NativeModuleEnv::InitializeCodeCache() {
102
  NativeModuleCacheMap& code_cache =
103
      *NativeModuleLoader::GetInstance()->code_cache();
104
  CHECK(code_cache.empty());
105
  auto policy = v8::ScriptCompiler::CachedData::BufferPolicy::BufferNotOwned;
106
1
)";
107
108
177
  for (const auto& x : data) {
109
176
    GetInitializer(x.first, ss);
110
176
    ss << "\n\n";
111
  }
112
113
  ss << R"(
114
}
115
116
}  // namespace native_module
117
}  // namespace node
118
1
)";
119
2
  return ss.str();
120
}
121
122
1
std::string CodeCacheBuilder::Generate(Local<Context> context) {
123
1
  NativeModuleLoader* loader = NativeModuleLoader::GetInstance();
124
2
  std::vector<std::string> ids = loader->GetModuleIds();
125
126
2
  std::map<std::string, ScriptCompiler::CachedData*> data;
127
128
224
  for (const auto& id : ids) {
129
    // TODO(joyeecheung): we can only compile the modules that can be
130
    // required here because the parameters for other types of builtins
131
    // are still very flexible. We should look into auto-generating
132
    // the parameters from the source somehow.
133
223
    if (loader->CanBeRequired(id.c_str())) {
134
      NativeModuleLoader::Result result;
135
176
      USE(loader->CompileAsModule(context, id.c_str(), &result));
136
      ScriptCompiler::CachedData* cached_data =
137
176
          loader->GetCodeCache(id.c_str());
138
176
      if (cached_data == nullptr) {
139
        // TODO(joyeecheung): display syntax errors
140
        std::cerr << "Failed to compile " << id << "\n";
141
      } else {
142
176
        data.emplace(id, cached_data);
143
      }
144
    }
145
  }
146
147
2
  return GenerateCodeCache(data);
148
}
149
150
}  // namespace native_module
151

3
}  // namespace node