blob: efb0b81bf97bfa1b732c63e11a9e1c98d62473fe [file] [log] [blame]
// Copyright 2017 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 "src/interpreter/setup-interpreter.h"
#include "src/handles-inl.h"
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/interpreter-generator.h"
#include "src/interpreter/interpreter.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
namespace interpreter {
namespace {
void PrintBuiltinSize(Bytecode bytecode, OperandScale operand_scale,
Handle<Code> code) {
PrintF(stdout, "Ignition Handler, %s, %d\n",
Bytecodes::ToString(bytecode, operand_scale).c_str(),
code->instruction_size());
}
} // namespace
// static
void SetupInterpreter::InstallBytecodeHandlers(Interpreter* interpreter) {
DCHECK(!interpreter->IsDispatchTableInitialized());
HandleScope scope(interpreter->isolate_);
// Canonicalize handles, so that we can share constant pool entries pointing
// to code targets without dereferencing their handles.
CanonicalHandleScope canonical(interpreter->isolate_);
Address* dispatch_table = interpreter->dispatch_table_;
// Generate bytecode handlers for all bytecodes and scales.
const OperandScale kOperandScales[] = {
#define VALUE(Name, _) OperandScale::k##Name,
OPERAND_SCALE_LIST(VALUE)
#undef VALUE
};
for (OperandScale operand_scale : kOperandScales) {
#define GENERATE_CODE(Name, ...) \
InstallBytecodeHandler(interpreter->isolate_, dispatch_table, \
Bytecode::k##Name, operand_scale);
BYTECODE_LIST(GENERATE_CODE)
#undef GENERATE_CODE
}
// Fill unused entries will the illegal bytecode handler.
size_t illegal_index = Interpreter::GetDispatchTableIndex(
Bytecode::kIllegal, OperandScale::kSingle);
for (size_t index = 0; index < Interpreter::kDispatchTableSize; ++index) {
if (dispatch_table[index] == nullptr) {
dispatch_table[index] = dispatch_table[illegal_index];
}
}
// Initialization should have been successful.
DCHECK(interpreter->IsDispatchTableInitialized());
}
// static
bool SetupInterpreter::ReuseExistingHandler(Address* dispatch_table,
Bytecode bytecode,
OperandScale operand_scale) {
size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale);
switch (bytecode) {
case Bytecode::kLdaImmutableContextSlot:
STATIC_ASSERT(static_cast<int>(Bytecode::kLdaContextSlot) <
static_cast<int>(Bytecode::kLdaImmutableContextSlot));
dispatch_table[index] = dispatch_table[Interpreter::GetDispatchTableIndex(
Bytecode::kLdaContextSlot, operand_scale)];
return true;
case Bytecode::kLdaImmutableCurrentContextSlot:
STATIC_ASSERT(
static_cast<int>(Bytecode::kLdaCurrentContextSlot) <
static_cast<int>(Bytecode::kLdaImmutableCurrentContextSlot));
dispatch_table[index] = dispatch_table[Interpreter::GetDispatchTableIndex(
Bytecode::kLdaCurrentContextSlot, operand_scale)];
return true;
default:
return false;
}
return false;
}
// static
void SetupInterpreter::InstallBytecodeHandler(Isolate* isolate,
Address* dispatch_table,
Bytecode bytecode,
OperandScale operand_scale) {
if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return;
if (ReuseExistingHandler(dispatch_table, bytecode, operand_scale)) return;
size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale);
Handle<Code> code = GenerateBytecodeHandler(isolate, bytecode, operand_scale);
dispatch_table[index] = code->entry();
if (FLAG_print_builtin_size) PrintBuiltinSize(bytecode, operand_scale, code);
}
} // namespace interpreter
} // namespace internal
} // namespace v8