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 #include <fstream>
6 #include <iostream>
7
8 #include "src/interpreter/bytecodes.h"
9
10 namespace v8 {
11 namespace internal {
12 namespace interpreter {
13
14 const int kIllegalBytecodeHandler = -1;
15 const int kIllegalBytecodeHandlerEncoding = 255;
16
WriteBytecode(std::ofstream& out, Bytecode bytecode, OperandScale operand_scale, int* count, int offset_table[], int table_index)17 void WriteBytecode(std::ofstream& out, Bytecode bytecode,
18 OperandScale operand_scale, int* count, int offset_table[],
19 int table_index) {
20 DCHECK_NOT_NULL(count);
21 if (Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
22 std::string name = Bytecodes::ToString(bytecode, operand_scale, "");
23
24 // The handler for Star0 is used for all short star codes. Rename it to
25 // something more generic.
26 if (bytecode == Bytecode::kStar0) {
27 DCHECK_EQ(operand_scale, OperandScale::kSingle);
28 name = "ShortStar";
29 }
30
31 out << " \\\n V(" << name << "Handler, interpreter::OperandScale::k"
32 << operand_scale << ", interpreter::Bytecode::k"
33 << Bytecodes::ToString(bytecode) << ")";
34 offset_table[table_index] = *count;
35 (*count)++;
36 } else {
37 offset_table[table_index] = kIllegalBytecodeHandler;
38 }
39 }
40
WriteHeader(const char* header_filename)41 void WriteHeader(const char* header_filename) {
42 std::ofstream out(header_filename);
43
44 out << "// Automatically generated from interpreter/bytecodes.h\n"
45 << "// The following list macro is used to populate the builtins list\n"
46 << "// with the bytecode handlers\n\n"
47 << "#include <stdint.h>\n\n"
48 << "#ifndef V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n"
49 << "#define V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n\n"
50 << "namespace v8 {\n"
51 << "namespace internal {\n\n"
52 << "#define BUILTIN_LIST_BYTECODE_HANDLERS(V)";
53
54 constexpr int kTableSize =
55 BytecodeOperands::kOperandScaleCount * Bytecodes::kBytecodeCount;
56 int offset_table[kTableSize];
57 int count = 0;
58 int index = 0;
59
60 #define ADD_BYTECODES(Name, ...) \
61 WriteBytecode(out, Bytecode::k##Name, operand_scale, &count, offset_table, \
62 index++);
63 OperandScale operand_scale = OperandScale::kSingle;
64 BYTECODE_LIST(ADD_BYTECODES)
65 int single_count = count;
66 operand_scale = OperandScale::kDouble;
67 BYTECODE_LIST(ADD_BYTECODES)
68 int wide_count = count - single_count;
69 operand_scale = OperandScale::kQuadruple;
70 BYTECODE_LIST(ADD_BYTECODES)
71 #undef ADD_BYTECODES
72 int extra_wide_count = count - wide_count - single_count;
73 CHECK_GT(single_count, wide_count);
74 CHECK_EQ(single_count,
75 Bytecodes::kBytecodeCount - Bytecodes::kShortStarCount + 1);
76 CHECK_EQ(wide_count, extra_wide_count);
77 out << "\n\nconstexpr int kNumberOfBytecodeHandlers = " << single_count
78 << ";\n"
79 << "constexpr int kNumberOfWideBytecodeHandlers = " << wide_count
80 << ";\n\n"
81 << "constexpr uint8_t kIllegalBytecodeHandlerEncoding = "
82 << kIllegalBytecodeHandlerEncoding << ";\n\n"
83 << "// Mapping from Bytecode to a dense form with all the illegal\n"
84 << "// wide Bytecodes removed. Used to index into the builtins table.\n"
85 << "constexpr uint8_t kWideBytecodeToBuiltinsMapping["
86 << Bytecodes::kBytecodeCount << "] = { \n";
87
88 for (int i = Bytecodes::kBytecodeCount; i < 2 * Bytecodes::kBytecodeCount;
89 ++i) {
90 int offset = offset_table[i];
91 if (offset == kIllegalBytecodeHandler) {
92 offset = kIllegalBytecodeHandlerEncoding;
93 } else {
94 offset -= single_count;
95 }
96 out << offset << ", ";
97 }
98
99 out << "};\n\n"
100 << "} // namespace internal\n"
101 << "} // namespace v8\n"
102 << "#endif // V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n";
103 }
104
105 } // namespace interpreter
106 } // namespace internal
107 } // namespace v8
108
main(int argc, const char* argv[])109 int main(int argc, const char* argv[]) {
110 if (argc != 2) {
111 std::cerr << "Usage: " << argv[0] << " <output filename>\n";
112 std::exit(1);
113 }
114
115 v8::internal::interpreter::WriteHeader(argv[1]);
116
117 return 0;
118 }
119