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 10namespace v8 { 11namespace internal { 12namespace interpreter { 13 14const int kIllegalBytecodeHandler = -1; 15const int kIllegalBytecodeHandlerEncoding = 255; 16 17void 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 41void 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 109int 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