tools: implement mkcodecache as an executable · nodejs/node@4fd7193 (original) (raw)

``

1

`+

#include "cache_builder.h"

`

``

2

`+

#include

`

``

3

`+

#include

`

``

4

`+

#include

`

``

5

`+

#include

`

``

6

`+

#include

`

``

7

`+

#include "util.h"

`

``

8

+

``

9

`+

#include "node_native_module.h"

`

``

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

`+

static std::string GetDefName(const std::string& id) {

`

``

22

`+

char buf[64] = {0};

`

``

23

`+

size_t size = id.size();

`

``

24

`+

CHECK_LT(size, sizeof(buf));

`

``

25

`+

for (size_t i = 0; i < size; ++i) {

`

``

26

`+

char ch = id[i];

`

``

27

`+

buf[i] = (ch == '-' || ch == '/') ? '_' : ch;

`

``

28

`+

}

`

``

29

`+

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(size));

`

``

36

`+

} else if (size < 1024 * 1024) {

`

``

37

`+

snprintf(buf, sizeof(buf), "%.2fKB", static_cast(size / 1024));

`

``

38

`+

} else {

`

``

39

`+

snprintf(

`

``

40

`+

buf, sizeof(buf), "%.2fMB", static_cast(size / 1024 / 1024));

`

``

41

`+

}

`

``

42

`+

return buf;

`

``

43

`+

}

`

``

44

+

``

45

`+

static std::string GetDefinition(const std::string& id,

`

``

46

`+

size_t size,

`

``

47

`+

const uint8_t* data) {

`

``

48

`+

std::stringstream ss;

`

``

49

`+

ss << "static const uint8_t " << GetDefName(id) << "[] = {\n";

`

``

50

`+

for (size_t i = 0; i < size; ++i) {

`

``

51

`+

uint8_t ch = data[i];

`

``

52

`+

ss << std::to_string(ch) << (i == size - 1 ? '\n' : ',');

`

``

53

`+

}

`

``

54

`+

ss << "};";

`

``

55

`+

return ss.str();

`

``

56

`+

}

`

``

57

+

``

58

`+

static std::string GetInitializer(const std::string& id) {

`

``

59

`+

std::string def_name = GetDefName(id);

`

``

60

`+

char buf[256] = {0};

`

``

61

`+

snprintf(buf,

`

``

62

`+

sizeof(buf),

`

``

63

`+

"code_cache->emplace(\n"

`

``

64

`+

" "%s",\n"

`

``

65

`+

" std::make_uniquev8::ScriptCompiler::CachedData"

`

``

66

`+

"(%s, static_cast(arraysize(%s)), policy)\n"

`

``

67

`+

");",

`

``

68

`+

id.c_str(),

`

``

69

`+

def_name.c_str(),

`

``

70

`+

def_name.c_str());

`

``

71

`+

return buf;

`

``

72

`+

}

`

``

73

+

``

74

`+

static std::string GenerateCodeCache(

`

``

75

`+

std::map<std::string, ScriptCompiler::CachedData*> data,

`

``

76

`+

std::vectorstd::string ids,

`

``

77

`+

bool log_progress) {

`

``

78

`+

std::stringstream ss;

`

``

79

`+

ss << R"(#include

`

``

80

`+

#include "node_native_module_env.h"

`

``

81

+

``

82

`+

// This file is generated by tools/mkcodecache

`

``

83

`` +

// and is used when configure is run with `--code-cache-path`

``

``

84

+

``

85

`+

namespace node {

`

``

86

`+

namespace native_module {

`

``

87

`+

)";

`

``

88

+

``

89

`+

size_t total = 0;

`

``

90

`+

for (const auto& x : data) {

`

``

91

`+

const std::string& id = x.first;

`

``

92

`+

ScriptCompiler::CachedData* cached_data = x.second;

`

``

93

`+

total += cached_data->length;

`

``

94

`+

std::string def = GetDefinition(id, cached_data->length, cached_data->data);

`

``

95

`+

ss << def << "\n\n";

`

``

96

`+

if (log_progress) {

`

``

97

`+

std::cout << "Generated cache for " << id

`

``

98

`+

<< ", size = " << FormatSize(cached_data->length)

`

``

99

`+

<< ", total = " << FormatSize(total) << "\n";

`

``

100

`+

}

`

``

101

`+

}

`

``

102

+

``

103

`+

ss << R"(void NativeModuleEnv::InitializeCodeCache() {

`

``

104

`+

NativeModuleCacheMap* code_cache =

`

``

105

`+

NativeModuleLoader::GetInstance()->code_cache();

`

``

106

`+

if (!code_cache->empty()) {

`

``

107

`+

return;

`

``

108

`+

}

`

``

109

`+

auto policy = v8::ScriptCompiler::CachedData::BufferPolicy::BufferNotOwned;

`

``

110

`+

)";

`

``

111

+

``

112

`+

for (const auto& x : data) {

`

``

113

`+

const std::string& id = x.first;

`

``

114

`+

ss << GetInitializer(id) << "\n\n";

`

``

115

`+

}

`

``

116

+

``

117

`+

ss << R"(}

`

``

118

+

``

119

`+

} // namespace native_module

`

``

120

`+

} // namespace node

`

``

121

`+

)";

`

``

122

`+

return ss.str();

`

``

123

`+

}

`

``

124

+

``

125

`+

std::string CodeCacheBuilder::Generate(Local context) {

`

``

126

`+

NativeModuleLoader* loader = NativeModuleLoader::GetInstance();

`

``

127

`+

std::vectorstd::string ids = loader->GetModuleIds();

`

``

128

+

``

129

`+

std::vectorstd::string modules;

`

``

130

`+

modules.reserve(ids.size());

`

``

131

+

``

132

`+

std::map<std::string, ScriptCompiler::CachedData*> data;

`

``

133

+

``

134

`+

NativeModuleLoader::Result result;

`

``

135

`+

for (const auto& id : ids) {

`

``

136

`+

// TODO(joyeecheung): we can only compile the modules that can be

`

``

137

`+

// required here because the parameters for other types of builtins

`

``

138

`+

// are still very flexible. We should look into auto-generating

`

``

139

`+

// the paramters from the source somehow.

`

``

140

`+

if (loader->CanBeRequired(id.c_str())) {

`

``

141

`+

modules.push_back(id);

`

``

142

`+

USE(loader->CompileAsModule(context, id.c_str(), &result));

`

``

143

`+

ScriptCompiler::CachedData* cached_data =

`

``

144

`+

loader->GetCodeCache(id.c_str());

`

``

145

`+

if (cached_data == nullptr) {

`

``

146

`+

// TODO(joyeecheung): display syntax errors

`

``

147

`+

std::cerr << "Failed to complile " << id << "\n";

`

``

148

`+

} else {

`

``

149

`+

data.emplace(id, cached_data);

`

``

150

`+

}

`

``

151

`+

}

`

``

152

`+

}

`

``

153

+

``

154

`+

char env_buf[32];

`

``

155

`+

size_t env_size = sizeof(env_buf);

`

``

156

`+

int ret = uv_os_getenv("NODE_DEBUG", env_buf, &env_size);

`

``

157

`+

bool log_progress = false;

`

``

158

`+

if (ret == 0 && strcmp(env_buf, "mkcodecache") == 0) {

`

``

159

`+

log_progress = true;

`

``

160

`+

}

`

``

161

`+

return GenerateCodeCache(data, modules, log_progress);

`

``

162

`+

}

`

``

163

+

``

164

`+

} // namespace native_module

`

``

165

`+

} // namespace node

`