1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
// 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->InstructionSize());
}
} // 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] == kNullAddress) {
dispatch_table[index] = dispatch_table[illegal_index];
}
}
// Generate the DeserializeLazy handlers, one for each operand scale.
Heap* heap = interpreter->isolate_->heap();
DCHECK_EQ(Smi::kZero, heap->deserialize_lazy_handler());
heap->SetDeserializeLazyHandler(*GenerateDeserializeLazyHandler(
interpreter->isolate_, OperandScale::kSingle));
DCHECK_EQ(Smi::kZero, heap->deserialize_lazy_handler_wide());
heap->SetDeserializeLazyHandlerWide(*GenerateDeserializeLazyHandler(
interpreter->isolate_, OperandScale::kDouble));
DCHECK_EQ(Smi::kZero, heap->deserialize_lazy_handler_extra_wide());
heap->SetDeserializeLazyHandlerExtraWide(*GenerateDeserializeLazyHandler(
interpreter->isolate_, OperandScale::kQuadruple));
// Initialization should have been successful.
DCHECK(interpreter->IsDispatchTableInitialized());
}
// static
void SetupInterpreter::InstallBytecodeHandler(Isolate* isolate,
Address* dispatch_table,
Bytecode bytecode,
OperandScale operand_scale) {
if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return;
size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale);
// Here we explicitly set the bytecode handler to not be a builtin with an
// index of kNoBuiltinId.
// TODO(delphick): Use builtins version instead.
Handle<Code> code = GenerateBytecodeHandler(isolate, bytecode, operand_scale,
Builtins::kNoBuiltinId);
dispatch_table[index] = code->entry();
if (FLAG_print_builtin_size) PrintBuiltinSize(bytecode, operand_scale, code);
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_builtin_code) {
std::string name = Bytecodes::ToString(bytecode, operand_scale);
code->PrintBuiltinCode(isolate, name.c_str());
}
#endif // ENABLE_DISASSEMBLER
}
} // namespace interpreter
} // namespace internal
} // namespace v8
|