OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #define OPERANDS(x) OperandInfo##x | |
rmcilroy
2015/07/24 18:34:48
Is this required?
| |
6 | |
5 #include "src/interpreter/bytecodes.h" | 7 #include "src/interpreter/bytecodes.h" |
6 | 8 |
7 namespace v8 { | 9 namespace v8 { |
8 namespace internal { | 10 namespace internal { |
9 namespace interpreter { | 11 namespace interpreter { |
10 | 12 |
13 static const int kMaxOperands = 3; | |
14 | |
15 template <enum Operand O> | |
16 struct OperandInfo { | |
17 static const int is_explicit; | |
rmcilroy
2015/07/24 18:34:48
instead of having is_explicit, could we just speci
| |
18 static const int size; | |
19 }; | |
20 | |
21 #define OPERAND_INFO(op, sz) \ | |
22 template <> \ | |
23 struct OperandInfo<Operand::k##op> { \ | |
24 static const int is_explicit = (sz == 0) ? 0 : 1; \ | |
25 static const int size = sz; \ | |
26 } | |
27 | |
28 OPERAND_INFO(None, 0); | |
29 OPERAND_INFO(Imm0, 0); | |
rmcilroy
2015/07/24 18:34:48
What is Imm0? Seems unrequired.
| |
30 OPERAND_INFO(Imm8, 1); | |
31 OPERAND_INFO(Smi, 4); | |
rmcilroy
2015/07/24 18:34:47
As mentioned offline, this can't be a 4 byte opera
| |
32 OPERAND_INFO(Reg, 1); | |
33 | |
34 | |
35 template <enum Bytecode B> | |
36 struct BytecodeInfo { | |
37 // Size of byte code and operands | |
38 static const int size; | |
39 // Number of operands | |
40 static const int number_of_operands; | |
41 // Packed operand values | |
42 static const int operands; | |
43 }; | |
44 | |
45 | |
46 // Packing operands into a single integer (makes indexing easier) | |
47 static const int kOperandShift = 4; | |
48 STATIC_ASSERT(static_cast<int>(Operand::kLast) < ((1 << kOperandShift) - 1)); | |
49 #define PACK_OPERAND(op, i) (static_cast<int>(op) << (i * kOperandShift)) | |
50 #define PACK_OPERANDS(op0, op1, op2) \ | |
51 PACK_OPERAND(op0, 0) | PACK_OPERAND(op1, 1) | PACK_OPERAND(op2, 2) | |
rmcilroy
2015/07/24 18:34:48
I personally don't think it's worth packing operan
| |
52 #define UNPACK_OPERAND(op, pos) (Operand)(op >> (pos * kOperandShift)) | |
53 | |
54 // Generator of BytecodeInfos for each bytecode. | |
55 #define BYTECODE_INFO(code, op0, op1, op2) \ | |
rmcilroy
2015/07/24 18:34:48
As much as I like pre-processor magic </sarcasm> -
| |
56 template <> \ | |
57 struct BytecodeInfo<Bytecode::code> { \ | |
58 static const int size = 1 + OperandInfo<op0>::size + \ | |
59 OperandInfo<op1>::size + OperandInfo<op2>::size; \ | |
60 static const int number_of_operands = OperandInfo<op0>::is_explicit + \ | |
61 OperandInfo<op1>::is_explicit + \ | |
62 OperandInfo<op2>::is_explicit; \ | |
63 static const int operands = PACK_OPERANDS(op0, op1, op2); \ | |
64 } | |
65 | |
66 // Bytecode declarations | |
67 BYTECODE_INFO(kLoadSmi0, Operand::kReg, Operand::kNone, Operand::kNone); | |
68 BYTECODE_INFO(kLoadSmi8, Operand::kReg, Operand::kImm8, Operand::kNone); | |
69 BYTECODE_INFO(kLoadSmi, Operand::kReg, Operand::kSmi, Operand::kNone); | |
70 BYTECODE_INFO(kMove, Operand::kReg, Operand::kReg, Operand::kNone); | |
71 BYTECODE_INFO(kAdd, Operand::kReg, Operand::kReg, Operand::kReg); | |
72 BYTECODE_INFO(kSub, Operand::kReg, Operand::kReg, Operand::kReg); | |
73 BYTECODE_INFO(kMul, Operand::kReg, Operand::kReg, Operand::kReg); | |
74 BYTECODE_INFO(kDiv, Operand::kReg, Operand::kReg, Operand::kReg); | |
75 BYTECODE_INFO(kMod, Operand::kReg, Operand::kReg, Operand::kReg); | |
76 BYTECODE_INFO(kReturn, Operand::kNone, Operand::kNone, Operand::kNone); | |
rmcilroy
2015/07/24 18:34:48
I would really like this list of declarations to b
| |
77 | |
78 | |
11 // static | 79 // static |
12 const char* Bytecodes::ToString(Bytecode bytecode) { | 80 const char* Bytecodes::ToString(Bytecode bytecode) { |
13 switch (bytecode) { | 81 switch (bytecode) { |
14 #define CASE(Name, _) \ | 82 #define CASE(Name) \ |
15 case Bytecode::k##Name: \ | 83 case Bytecode::k##Name: \ |
16 return #Name; | 84 return #Name; |
17 BYTECODE_LIST(CASE) | 85 BYTECODE_LIST(CASE) |
18 #undef CASE | 86 #undef CASE |
19 } | 87 } |
20 UNREACHABLE(); | 88 UNREACHABLE(); |
21 return ""; | 89 return ""; |
22 } | 90 } |
23 | 91 |
24 | 92 |
25 // static | 93 // static |
26 const int Bytecodes::NumberOfArguments(Bytecode bytecode) { | 94 Bytecode Bytecodes::FromByte(uint8_t value) { |
95 Bytecode code = static_cast<Bytecode>(value); | |
96 CHECK(code <= Bytecode::kLast); | |
97 return code; | |
98 } | |
99 | |
100 | |
101 // static | |
102 const int Bytecodes::NumberOfOperands(Bytecode bytecode) { | |
27 switch (bytecode) { | 103 switch (bytecode) { |
28 #define CASE(Name, arg_count) \ | 104 #define CASE(Name) \ |
29 case Bytecode::k##Name: \ | 105 case Bytecode::k##Name: \ |
30 return arg_count; | 106 return BytecodeInfo<Bytecode::k##Name>::number_of_operands; |
31 BYTECODE_LIST(CASE) | 107 BYTECODE_LIST(CASE) |
32 #undef CASE | 108 #undef CASE |
33 } | 109 } |
34 UNREACHABLE(); | 110 UNREACHABLE(); |
35 return 0; | 111 return 0; |
36 } | 112 } |
37 | 113 |
38 | 114 |
39 // static | 115 // static |
116 const Operand Bytecodes::GetOperand(Bytecode bytecode, int i) { | |
117 CHECK(i < kMaxOperands); | |
118 | |
119 int packed = 0; | |
120 switch (bytecode) { | |
121 #define CASE(Name) \ | |
122 case Bytecode::k##Name: \ | |
123 packed = BytecodeInfo<Bytecode::k##Name>::operands; | |
124 BYTECODE_LIST(CASE) | |
125 #undef CASE | |
126 } | |
127 return UNPACK_OPERAND(packed, i); | |
128 } | |
129 | |
130 | |
131 // static | |
132 const int Bytecodes::GetOperandSize(Operand operand) { | |
133 switch (operand) { | |
134 #define CASE(Name) \ | |
135 case Operand::k##Name: \ | |
136 return OperandInfo<Operand::k##Name>::size; | |
137 OPERAND_LIST(CASE) | |
138 #undef CASE | |
139 } | |
140 UNREACHABLE(); | |
141 return 0; | |
142 } | |
143 | |
144 | |
145 // static | |
40 const int Bytecodes::Size(Bytecode bytecode) { | 146 const int Bytecodes::Size(Bytecode bytecode) { |
41 return NumberOfArguments(bytecode) + 1; | 147 switch (bytecode) { |
148 #define CASE(Name) \ | |
149 case Bytecode::k##Name: \ | |
150 return BytecodeInfo<Bytecode::k##Name>::size; | |
151 BYTECODE_LIST(CASE) | |
152 #undef CASE | |
153 } | |
154 UNREACHABLE(); | |
155 return 0; | |
42 } | 156 } |
43 | 157 |
44 | 158 |
45 #define CHECK_SIZE(Name, arg_count) \ | 159 // static |
46 STATIC_ASSERT(arg_count <= Bytecodes::kMaximumNumberOfArguments); | 160 const int Bytecodes::MaximumNumberOfOperands() { |
47 BYTECODE_LIST(CHECK_SIZE) | 161 // TODO(oth): STATIC_ASSERT on number of operands. |
48 #undef CHECK_SIZE | 162 return kMaxOperands; |
163 } | |
164 | |
165 | |
166 // static | |
167 const int Bytecodes::MaximumSize() { | |
168 // TODO(oth): Maximum size of bytecode and associated operands | |
169 STATIC_ASSERT(BytecodeInfo<Bytecode::kLoadSmi>::size == 6); | |
170 return 6; | |
171 } | |
49 | 172 |
50 | 173 |
51 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { | 174 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
52 return os << Bytecodes::ToString(bytecode); | 175 return os << Bytecodes::ToString(bytecode); |
53 } | 176 } |
54 | 177 |
55 } // namespace interpreter | 178 } // namespace interpreter |
56 } // namespace internal | 179 } // namespace internal |
57 } // namespace v8 | 180 } // namespace v8 |
OLD | NEW |