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: 60 73 82.2 %
Date: 2019-05-05 22:32:45 Branches: 24 36 66.7 %

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

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

1
  if (ret == 0 && strcmp(env_buf, "mkcodecache") == 0) {
151
    log_progress = true;
152
  }
153
2
  return GenerateCodeCache(data, log_progress);
154
}
155
156
}  // namespace native_module
157

3
}  // namespace node