generate-bytecodes-builtins-list.cc 3.98 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <fstream>
#include <iostream>

#include "src/interpreter/bytecodes.h"

namespace v8 {
namespace internal {
namespace interpreter {

14 15 16
const int kIllegalBytecodeHandler = -1;
const int kIllegalBytecodeHandlerEncoding = 255;

17
void WriteBytecode(std::ofstream& out, Bytecode bytecode,
18 19 20
                   OperandScale operand_scale, int* count, int offset_table[],
                   int table_index) {
  DCHECK_NOT_NULL(count);
21
  if (Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
22 23 24 25 26 27 28 29 30 31 32 33
    std::string name = Bytecodes::ToString(bytecode, operand_scale, "");

    // The handler for Star0 is used for all short star codes. Rename it to
    // something more generic.
    if (bytecode == Bytecode::kStar0) {
      DCHECK_EQ(operand_scale, OperandScale::kSingle);
      name = "ShortStar";
    }

    out << " \\\n  V(" << name << "Handler, interpreter::OperandScale::k"
        << operand_scale << ", interpreter::Bytecode::k"
        << Bytecodes::ToString(bytecode) << ")";
34 35 36
    offset_table[table_index] = *count;
    (*count)++;
  } else {
37
    offset_table[table_index] = kIllegalBytecodeHandler;
38 39 40 41 42 43 44 45 46
  }
}

void WriteHeader(const char* header_filename) {
  std::ofstream out(header_filename);

  out << "// Automatically generated from interpreter/bytecodes.h\n"
      << "// The following list macro is used to populate the builtins list\n"
      << "// with the bytecode handlers\n\n"
47
      << "#include <stdint.h>\n\n"
48
      << "#ifndef V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n"
49 50 51
      << "#define V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n\n"
      << "namespace v8 {\n"
      << "namespace internal {\n\n"
52
      << "#define BUILTIN_LIST_BYTECODE_HANDLERS(V)";
53 54 55 56 57 58 59 60 61 62

  constexpr int kTableSize =
      BytecodeOperands::kOperandScaleCount * Bytecodes::kBytecodeCount;
  int offset_table[kTableSize];
  int count = 0;
  int index = 0;

#define ADD_BYTECODES(Name, ...)                                             \
  WriteBytecode(out, Bytecode::k##Name, operand_scale, &count, offset_table, \
                index++);
63 64
  OperandScale operand_scale = OperandScale::kSingle;
  BYTECODE_LIST(ADD_BYTECODES)
65
  int single_count = count;
66 67
  operand_scale = OperandScale::kDouble;
  BYTECODE_LIST(ADD_BYTECODES)
68
  int wide_count = count - single_count;
69 70 71
  operand_scale = OperandScale::kQuadruple;
  BYTECODE_LIST(ADD_BYTECODES)
#undef ADD_BYTECODES
72 73
  int extra_wide_count = count - wide_count - single_count;
  CHECK_GT(single_count, wide_count);
74 75
  CHECK_EQ(single_count,
           Bytecodes::kBytecodeCount - Bytecodes::kShortStarCount + 1);
76
  CHECK_EQ(wide_count, extra_wide_count);
77 78 79 80 81 82 83 84 85
  out << "\n\nconstexpr int kNumberOfBytecodeHandlers = " << single_count
      << ";\n"
      << "constexpr int kNumberOfWideBytecodeHandlers = " << wide_count
      << ";\n\n"
      << "constexpr uint8_t kIllegalBytecodeHandlerEncoding = "
      << kIllegalBytecodeHandlerEncoding << ";\n\n"
      << "// Mapping from Bytecode to a dense form with all the illegal\n"
      << "// wide Bytecodes removed. Used to index into the builtins table.\n"
      << "constexpr uint8_t kWideBytecodeToBuiltinsMapping["
86
      << Bytecodes::kBytecodeCount << "] = {    \n";
87

88 89
  for (int i = Bytecodes::kBytecodeCount; i < 2 * Bytecodes::kBytecodeCount;
       ++i) {
90 91 92 93 94
    int offset = offset_table[i];
    if (offset == kIllegalBytecodeHandler) {
      offset = kIllegalBytecodeHandlerEncoding;
    } else {
      offset -= single_count;
95
    }
96
    out << offset << ", ";
97 98
  }

99
  out << "};\n\n"
100 101 102
      << "}  // namespace internal\n"
      << "}  // namespace v8\n"
      << "#endif  // V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n";
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
}

}  // namespace interpreter
}  // namespace internal
}  // namespace v8

int main(int argc, const char* argv[]) {
  if (argc != 2) {
    std::cerr << "Usage: " << argv[0] << " <output filename>\n";
    std::exit(1);
  }

  v8::internal::interpreter::WriteHeader(argv[1]);

  return 0;
}