1 // Copyright 2017 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 "src/interpreter/setup-interpreter.h"
6 
7 #include "src/handles-inl.h"
8 #include "src/interpreter/bytecodes.h"
9 #include "src/interpreter/interpreter-generator.h"
10 #include "src/interpreter/interpreter.h"
11 #include "src/objects-inl.h"
12 
13 namespace v8 {
14 namespace internal {
15 namespace interpreter {
16 
17 namespace {
PrintBuiltinSize(Bytecode bytecode,OperandScale operand_scale,Handle<Code> code)18 void PrintBuiltinSize(Bytecode bytecode, OperandScale operand_scale,
19                       Handle<Code> code) {
20   PrintF(stdout, "Ignition Handler, %s, %d\n",
21          Bytecodes::ToString(bytecode, operand_scale).c_str(),
22          code->InstructionSize());
23 }
24 }  // namespace
25 
26 // static
InstallBytecodeHandlers(Interpreter * interpreter)27 void SetupInterpreter::InstallBytecodeHandlers(Interpreter* interpreter) {
28   DCHECK(!interpreter->IsDispatchTableInitialized());
29   HandleScope scope(interpreter->isolate_);
30   // Canonicalize handles, so that we can share constant pool entries pointing
31   // to code targets without dereferencing their handles.
32   CanonicalHandleScope canonical(interpreter->isolate_);
33   Address* dispatch_table = interpreter->dispatch_table_;
34 
35   // Generate bytecode handlers for all bytecodes and scales.
36   const OperandScale kOperandScales[] = {
37 #define VALUE(Name, _) OperandScale::k##Name,
38       OPERAND_SCALE_LIST(VALUE)
39 #undef VALUE
40   };
41 
42   for (OperandScale operand_scale : kOperandScales) {
43 #define GENERATE_CODE(Name, ...)                                \
44   InstallBytecodeHandler(interpreter->isolate_, dispatch_table, \
45                          Bytecode::k##Name, operand_scale);
46     BYTECODE_LIST(GENERATE_CODE)
47 #undef GENERATE_CODE
48   }
49 
50   // Fill unused entries will the illegal bytecode handler.
51   size_t illegal_index = Interpreter::GetDispatchTableIndex(
52       Bytecode::kIllegal, OperandScale::kSingle);
53   for (size_t index = 0; index < Interpreter::kDispatchTableSize; ++index) {
54     if (dispatch_table[index] == kNullAddress) {
55       dispatch_table[index] = dispatch_table[illegal_index];
56     }
57   }
58 
59   // Generate the DeserializeLazy handlers, one for each operand scale.
60   Heap* heap = interpreter->isolate_->heap();
61   DCHECK_EQ(Smi::kZero, heap->deserialize_lazy_handler());
62   heap->SetDeserializeLazyHandler(*GenerateDeserializeLazyHandler(
63       interpreter->isolate_, OperandScale::kSingle));
64   DCHECK_EQ(Smi::kZero, heap->deserialize_lazy_handler_wide());
65   heap->SetDeserializeLazyHandlerWide(*GenerateDeserializeLazyHandler(
66       interpreter->isolate_, OperandScale::kDouble));
67   DCHECK_EQ(Smi::kZero, heap->deserialize_lazy_handler_extra_wide());
68   heap->SetDeserializeLazyHandlerExtraWide(*GenerateDeserializeLazyHandler(
69       interpreter->isolate_, OperandScale::kQuadruple));
70 
71   // Initialization should have been successful.
72   DCHECK(interpreter->IsDispatchTableInitialized());
73 }
74 
75 // static
InstallBytecodeHandler(Isolate * isolate,Address * dispatch_table,Bytecode bytecode,OperandScale operand_scale)76 void SetupInterpreter::InstallBytecodeHandler(Isolate* isolate,
77                                               Address* dispatch_table,
78                                               Bytecode bytecode,
79                                               OperandScale operand_scale) {
80   if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return;
81 
82   size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale);
83   // Here we explicitly set the bytecode handler to not be a builtin with an
84   // index of kNoBuiltinId.
85   // TODO(delphick): Use builtins version instead.
86   Handle<Code> code = GenerateBytecodeHandler(isolate, bytecode, operand_scale,
87                                               Builtins::kNoBuiltinId);
88   dispatch_table[index] = code->entry();
89 
90   if (FLAG_print_builtin_size) PrintBuiltinSize(bytecode, operand_scale, code);
91 
92 #ifdef ENABLE_DISASSEMBLER
93   if (FLAG_print_builtin_code) {
94     std::string name = Bytecodes::ToString(bytecode, operand_scale);
95     code->PrintBuiltinCode(isolate, name.c_str());
96   }
97 #endif  // ENABLE_DISASSEMBLER
98 }
99 
100 }  // namespace interpreter
101 }  // namespace internal
102 }  // namespace v8
103