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 #include "src/interpreter/bytecodes.h" | 5 #include "src/interpreter/bytecodes.h" |
6 | 6 |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 #include "src/interpreter/bytecode-traits.h" | 8 #include "src/interpreter/bytecode-traits.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 11 matching lines...) Expand all Loading... | |
22 #undef CASE | 22 #undef CASE |
23 } | 23 } |
24 UNREACHABLE(); | 24 UNREACHABLE(); |
25 return ""; | 25 return ""; |
26 } | 26 } |
27 | 27 |
28 | 28 |
29 // static | 29 // static |
30 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { | 30 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { |
31 switch (operand_type) { | 31 switch (operand_type) { |
32 #define CASE(Name, _) \ | 32 #define CASE(Name, _, __) \ |
33 case OperandType::k##Name: \ | 33 case OperandType::k##Name: \ |
34 return #Name; | 34 return #Name; |
35 OPERAND_TYPE_LIST(CASE) | 35 OPERAND_TYPE_LIST(CASE) |
36 #undef CASE | 36 #undef CASE |
37 } | 37 } |
38 UNREACHABLE(); | 38 UNREACHABLE(); |
39 return ""; | 39 return ""; |
40 } | 40 } |
41 | 41 |
42 | 42 |
43 // static | 43 // static |
44 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { | 44 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { |
45 switch (operand_size) { | 45 switch (operand_size) { |
46 case OperandSize::kNone: | 46 case OperandSize::kNone: |
47 return "None"; | 47 return "None"; |
48 case OperandSize::kByte: | 48 case OperandSize::kByte: |
49 return "Byte"; | 49 return "Byte"; |
50 case OperandSize::kShort: | 50 case OperandSize::kShort: |
51 return "Short"; | 51 return "Short"; |
52 case OperandSize::kQuad: | |
53 return "Quad"; | |
52 } | 54 } |
53 UNREACHABLE(); | 55 UNREACHABLE(); |
54 return ""; | 56 return ""; |
55 } | 57 } |
56 | 58 |
57 | 59 |
58 // static | 60 // static |
59 uint8_t Bytecodes::ToByte(Bytecode bytecode) { | 61 uint8_t Bytecodes::ToByte(Bytecode bytecode) { |
60 DCHECK(bytecode <= Bytecode::kLast); | 62 DCHECK(bytecode <= Bytecode::kLast); |
61 return static_cast<uint8_t>(bytecode); | 63 return static_cast<uint8_t>(bytecode); |
62 } | 64 } |
63 | 65 |
64 | 66 |
65 // static | 67 // static |
66 Bytecode Bytecodes::FromByte(uint8_t value) { | 68 Bytecode Bytecodes::FromByte(uint8_t value) { |
67 Bytecode bytecode = static_cast<Bytecode>(value); | 69 Bytecode bytecode = static_cast<Bytecode>(value); |
68 DCHECK(bytecode <= Bytecode::kLast); | 70 DCHECK(bytecode <= Bytecode::kLast); |
69 return bytecode; | 71 return bytecode; |
70 } | 72 } |
71 | 73 |
72 | 74 |
73 // static | 75 // static |
74 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { | 76 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode, int operand_scale) { |
75 switch (Size(bytecode)) { | 77 int bytecode_size = Size(bytecode, operand_scale); |
76 #define CASE(Name, ...) \ | 78 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \ |
77 case BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize: \ | 79 if (bytecode_size == Size(Bytecode::k##Name, operand_scale)) { \ |
78 return Bytecode::k##Name; | 80 return Bytecode::k##Name; \ |
79 DEBUG_BREAK_BYTECODE_LIST(CASE) | |
80 #undef CASE | |
81 default: | |
82 break; | |
83 } | 81 } |
82 DEBUG_BREAK_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) | |
83 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES | |
84 UNREACHABLE(); | 84 UNREACHABLE(); |
85 return static_cast<Bytecode>(-1); | 85 return static_cast<Bytecode>(-1); |
86 } | 86 } |
87 | 87 |
88 // static | 88 // static |
89 int Bytecodes::Size(Bytecode bytecode) { | 89 int Bytecodes::Size(Bytecode bytecode, int operand_scale) { |
90 DCHECK(bytecode <= Bytecode::kLast); | 90 int size = 1; |
91 switch (bytecode) { | 91 for (int i = 0; i < NumberOfOperands(bytecode); i++) { |
92 #define CASE(Name, ...) \ | 92 OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale); |
93 case Bytecode::k##Name: \ | 93 int delta = static_cast<int>(operand_size); |
94 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize; | 94 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta))); |
95 BYTECODE_LIST(CASE) | 95 size += delta; |
96 #undef CASE | |
97 } | 96 } |
98 UNREACHABLE(); | 97 return size; |
99 return 0; | |
100 } | 98 } |
101 | 99 |
102 | 100 |
103 // static | 101 // static |
104 int Bytecodes::NumberOfOperands(Bytecode bytecode) { | 102 int Bytecodes::NumberOfOperands(Bytecode bytecode) { |
105 DCHECK(bytecode <= Bytecode::kLast); | 103 DCHECK(bytecode <= Bytecode::kLast); |
106 switch (bytecode) { | 104 switch (bytecode) { |
107 #define CASE(Name, ...) \ | 105 #define CASE(Name, ...) \ |
108 case Bytecode::k##Name: \ | 106 case Bytecode::k##Name: \ |
109 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount; | 107 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount; |
(...skipping 14 matching lines...) Expand all Loading... | |
124 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ | 122 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ |
125 return Name##Trait::kRegisterOperandCount; | 123 return Name##Trait::kRegisterOperandCount; |
126 BYTECODE_LIST(CASE) | 124 BYTECODE_LIST(CASE) |
127 #undef CASE | 125 #undef CASE |
128 } | 126 } |
129 UNREACHABLE(); | 127 UNREACHABLE(); |
130 return false; | 128 return false; |
131 } | 129 } |
132 | 130 |
133 // static | 131 // static |
132 int Bytecodes::GetPrefixBytecodeScale(Bytecode bytecode) { | |
133 switch (bytecode) { | |
rmcilroy
2016/03/10 16:45:37
Could we make this DCHECK if it is passed a non-pr
oth
2016/03/11 16:26:12
Not really, this is one of the main ways of determ
oth
2016/03/17 13:48:38
Done.
| |
134 case Bytecode::kExtraWide: | |
135 return 4; | |
136 case Bytecode::kWide: | |
137 return 2; | |
138 default: | |
139 return 1; | |
140 } | |
141 } | |
142 | |
143 // static | |
134 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { | 144 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
135 DCHECK(bytecode <= Bytecode::kLast); | 145 DCHECK(bytecode <= Bytecode::kLast); |
136 switch (bytecode) { | 146 switch (bytecode) { |
137 #define CASE(Name, ...) \ | 147 #define CASE(Name, ...) \ |
138 case Bytecode::k##Name: \ | 148 case Bytecode::k##Name: \ |
139 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandType(i); | 149 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandType(i); |
140 BYTECODE_LIST(CASE) | 150 BYTECODE_LIST(CASE) |
141 #undef CASE | 151 #undef CASE |
142 } | 152 } |
143 UNREACHABLE(); | 153 UNREACHABLE(); |
144 return OperandType::kNone; | 154 return OperandType::kNone; |
145 } | 155 } |
146 | 156 |
157 // TODO(oth): TEMPORARY | |
158 namespace { | |
159 | |
160 template <OperandTypeTrait O> | |
161 struct OperandScaler { | |
162 static int Multiply(int size, int scale) { return 0; } | |
163 }; | |
164 | |
165 template <> | |
166 struct OperandScaler<OperandTypeTrait::kFixed> { | |
167 static int Multiply(int size, int scale) { return size; } | |
168 }; | |
169 | |
170 template <> | |
171 struct OperandScaler<OperandTypeTrait::kScalable> { | |
172 static int Multiply(int size, int scale) { return size * scale; } | |
173 }; | |
174 | |
175 } // namespace | |
176 | |
177 // TODO(oth): TEMPORARY | |
178 static int ScaledOperandSize(OperandType operand_type, int scale) { | |
179 switch (operand_type) { | |
180 #define CASE(Name, Size, Trait) \ | |
181 case OperandType::k##Name: \ | |
182 return OperandScaler<Trait>::Multiply(static_cast<int>(Size), scale); | |
183 OPERAND_TYPE_LIST(CASE) | |
184 #undef CASE | |
185 } | |
186 UNREACHABLE(); | |
187 return 0; | |
188 } | |
189 | |
147 | 190 |
148 // static | 191 // static |
149 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i) { | 192 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, int scale) { |
150 DCHECK(bytecode <= Bytecode::kLast); | 193 OperandType op_type = GetOperandType(bytecode, i); |
151 switch (bytecode) { | 194 return static_cast<OperandSize>(ScaledOperandSize(op_type, scale)); |
152 #define CASE(Name, ...) \ | |
153 case Bytecode::k##Name: \ | |
154 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandSize(i); | |
155 BYTECODE_LIST(CASE) | |
156 #undef CASE | |
157 } | |
158 UNREACHABLE(); | |
159 return OperandSize::kNone; | |
160 } | 195 } |
161 | 196 |
162 | |
163 // static | 197 // static |
164 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { | 198 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { |
165 DCHECK(bytecode <= Bytecode::kLast); | 199 DCHECK(bytecode <= Bytecode::kLast); |
166 switch (bytecode) { | 200 switch (bytecode) { |
167 #define CASE(Name, ...) \ | 201 #define CASE(Name, ...) \ |
168 case Bytecode::k##Name: \ | 202 case Bytecode::k##Name: \ |
169 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ | 203 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ |
170 return Name##Trait::kRegisterOperandBitmap; | 204 return Name##Trait::kRegisterOperandBitmap; |
171 BYTECODE_LIST(CASE) | 205 BYTECODE_LIST(CASE) |
172 #undef CASE | 206 #undef CASE |
173 } | 207 } |
174 UNREACHABLE(); | 208 UNREACHABLE(); |
175 return false; | 209 return false; |
176 } | 210 } |
177 | 211 |
178 // static | 212 // static |
179 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i) { | 213 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, int scale) { |
180 DCHECK(bytecode <= Bytecode::kLast); | 214 int offset = 1; |
181 switch (bytecode) { | 215 for (int operand_index = 0; operand_index < i; ++operand_index) { |
182 #define CASE(Name, ...) \ | 216 OperandSize operand_size = GetOperandSize(bytecode, operand_index, scale); |
183 case Bytecode::k##Name: \ | 217 offset += static_cast<int>(operand_size); |
184 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandOffset(i); | |
185 BYTECODE_LIST(CASE) | |
186 #undef CASE | |
187 } | 218 } |
188 UNREACHABLE(); | 219 return offset; |
189 return 0; | 220 } |
221 | |
222 // static | |
223 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, int scale) { | |
224 return static_cast<OperandSize>(ScaledOperandSize(operand_type, scale)); | |
190 } | 225 } |
191 | 226 |
192 | 227 |
193 // static | |
194 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type) { | |
195 switch (operand_type) { | |
196 #define CASE(Name, Size) \ | |
197 case OperandType::k##Name: \ | |
198 return Size; | |
199 OPERAND_TYPE_LIST(CASE) | |
200 #undef CASE | |
201 } | |
202 UNREACHABLE(); | |
203 return OperandSize::kNone; | |
204 } | |
205 | |
206 | |
207 // static | 228 // static |
208 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { | 229 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { |
209 return bytecode == Bytecode::kJumpIfTrue || | 230 return bytecode == Bytecode::kJumpIfTrue || |
210 bytecode == Bytecode::kJumpIfFalse || | 231 bytecode == Bytecode::kJumpIfFalse || |
211 bytecode == Bytecode::kJumpIfToBooleanTrue || | 232 bytecode == Bytecode::kJumpIfToBooleanTrue || |
212 bytecode == Bytecode::kJumpIfToBooleanFalse || | 233 bytecode == Bytecode::kJumpIfToBooleanFalse || |
213 bytecode == Bytecode::kJumpIfNotHole || | 234 bytecode == Bytecode::kJumpIfNotHole || |
214 bytecode == Bytecode::kJumpIfNull || | 235 bytecode == Bytecode::kJumpIfNull || |
215 bytecode == Bytecode::kJumpIfUndefined; | 236 bytecode == Bytecode::kJumpIfUndefined; |
216 } | 237 } |
217 | 238 |
218 | 239 |
219 // static | 240 // static |
220 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { | 241 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { |
221 return bytecode == Bytecode::kJumpIfTrueConstant || | 242 return bytecode == Bytecode::kJumpIfTrueConstant || |
222 bytecode == Bytecode::kJumpIfFalseConstant || | 243 bytecode == Bytecode::kJumpIfFalseConstant || |
223 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || | 244 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
224 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || | 245 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || |
225 bytecode == Bytecode::kJumpIfNotHoleConstant || | 246 bytecode == Bytecode::kJumpIfNotHoleConstant || |
226 bytecode == Bytecode::kJumpIfNullConstant || | 247 bytecode == Bytecode::kJumpIfNullConstant || |
227 bytecode == Bytecode::kJumpIfUndefinedConstant; | 248 bytecode == Bytecode::kJumpIfUndefinedConstant; |
228 } | 249 } |
229 | 250 |
230 | |
231 // static | |
232 bool Bytecodes::IsConditionalJumpConstantWide(Bytecode bytecode) { | |
233 return bytecode == Bytecode::kJumpIfTrueConstantWide || | |
234 bytecode == Bytecode::kJumpIfFalseConstantWide || | |
235 bytecode == Bytecode::kJumpIfToBooleanTrueConstantWide || | |
236 bytecode == Bytecode::kJumpIfToBooleanFalseConstantWide || | |
237 bytecode == Bytecode::kJumpIfNotHoleConstantWide || | |
238 bytecode == Bytecode::kJumpIfNullConstantWide || | |
239 bytecode == Bytecode::kJumpIfUndefinedConstantWide; | |
240 } | |
241 | |
242 | |
243 // static | 251 // static |
244 bool Bytecodes::IsConditionalJump(Bytecode bytecode) { | 252 bool Bytecodes::IsConditionalJump(Bytecode bytecode) { |
245 return IsConditionalJumpImmediate(bytecode) || | 253 return IsConditionalJumpImmediate(bytecode) || |
246 IsConditionalJumpConstant(bytecode) || | 254 IsConditionalJumpConstant(bytecode); |
247 IsConditionalJumpConstantWide(bytecode); | |
248 } | 255 } |
249 | 256 |
250 | 257 |
251 // static | 258 // static |
252 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) { | 259 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) { |
253 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode); | 260 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode); |
254 } | 261 } |
255 | 262 |
256 | 263 |
257 // static | 264 // static |
258 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { | 265 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { |
259 return bytecode == Bytecode::kJumpConstant || | 266 return bytecode == Bytecode::kJumpConstant || |
260 IsConditionalJumpConstant(bytecode); | 267 IsConditionalJumpConstant(bytecode); |
261 } | 268 } |
262 | 269 |
263 | |
264 // static | |
265 bool Bytecodes::IsJumpConstantWide(Bytecode bytecode) { | |
266 return bytecode == Bytecode::kJumpConstantWide || | |
267 IsConditionalJumpConstantWide(bytecode); | |
268 } | |
269 | |
270 | |
271 // static | 270 // static |
272 bool Bytecodes::IsJump(Bytecode bytecode) { | 271 bool Bytecodes::IsJump(Bytecode bytecode) { |
273 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode) || | 272 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); |
274 IsJumpConstantWide(bytecode); | |
275 } | 273 } |
276 | 274 |
277 | 275 |
278 // static | 276 // static |
279 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { | 277 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { |
280 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || | 278 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || |
281 bytecode == Bytecode::kNew || bytecode == Bytecode::kCallWide || | 279 bytecode == Bytecode::kNew; |
282 bytecode == Bytecode::kTailCallWide || bytecode == Bytecode::kNewWide; | |
283 } | 280 } |
284 | 281 |
285 // static | 282 // static |
286 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { | 283 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { |
287 return bytecode == Bytecode::kCallRuntime || | 284 return bytecode == Bytecode::kCallRuntime || |
288 bytecode == Bytecode::kCallRuntimeWide || | 285 bytecode == Bytecode::kCallRuntimeForPair; |
289 bytecode == Bytecode::kCallRuntimeForPair || | |
290 bytecode == Bytecode::kCallRuntimeForPairWide; | |
291 } | 286 } |
292 | 287 |
293 // static | 288 // static |
294 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { | 289 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { |
295 switch (bytecode) { | 290 switch (bytecode) { |
296 #define CASE(Name, ...) case Bytecode::k##Name: | 291 #define CASE(Name, ...) case Bytecode::k##Name: |
297 DEBUG_BREAK_BYTECODE_LIST(CASE); | 292 DEBUG_BREAK_BYTECODE_LIST(CASE); |
298 #undef CASE | 293 #undef CASE |
299 return true; | 294 return true; |
300 default: | 295 default: |
301 break; | 296 break; |
302 } | 297 } |
303 return false; | 298 return false; |
304 } | 299 } |
305 | 300 |
306 // static | 301 // static |
302 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { | |
303 switch (bytecode) { | |
304 #define CASE(Name, ...) \ | |
305 case Bytecode::k##Name: \ | |
306 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ | |
307 return Name##Trait::IsScalable(); | |
308 BYTECODE_LIST(CASE) | |
309 #undef CASE | |
310 } | |
311 UNREACHABLE(); | |
312 return false; | |
313 } | |
314 | |
315 // static | |
307 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { | 316 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { |
308 return bytecode == Bytecode::kReturn || IsJump(bytecode); | 317 return bytecode == Bytecode::kReturn || IsJump(bytecode); |
309 } | 318 } |
310 | 319 |
311 // static | 320 // static |
321 bool Bytecodes::IsFlagOperandType(OperandType operand_type) { | |
322 return operand_type == OperandType::kFlag8; | |
323 } | |
324 | |
325 // static | |
312 bool Bytecodes::IsIndexOperandType(OperandType operand_type) { | 326 bool Bytecodes::IsIndexOperandType(OperandType operand_type) { |
313 return operand_type == OperandType::kIdx8 || | 327 return operand_type == OperandType::kIdx; |
314 operand_type == OperandType::kIdx16; | |
315 } | 328 } |
316 | 329 |
317 // static | 330 // static |
318 bool Bytecodes::IsImmediateOperandType(OperandType operand_type) { | 331 bool Bytecodes::IsImmediateOperandType(OperandType operand_type) { |
319 return operand_type == OperandType::kImm8; | 332 return operand_type == OperandType::kImm; |
320 } | 333 } |
321 | 334 |
322 // static | 335 // static |
323 bool Bytecodes::IsRegisterCountOperandType(OperandType operand_type) { | 336 bool Bytecodes::IsRegisterCountOperandType(OperandType operand_type) { |
324 return (operand_type == OperandType::kRegCount8 || | 337 return operand_type == OperandType::kRegCount; |
325 operand_type == OperandType::kRegCount16); | |
326 } | 338 } |
327 | 339 |
328 // static | 340 // static |
329 bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) { | 341 bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) { |
330 return (operand_type == OperandType::kMaybeReg8 || | 342 return operand_type == OperandType::kMaybeReg; |
331 operand_type == OperandType::kMaybeReg16); | 343 } |
344 | |
345 // static | |
346 bool Bytecodes::IsRuntimeIdOperandType(OperandType operand_type) { | |
rmcilroy
2016/03/10 16:45:37
Wondering whether these IsXXXOperandType are neces
oth
2016/03/11 16:26:12
Done. Removed all except the still useful IsRegist
| |
347 return operand_type == OperandType::kRuntimeId; | |
332 } | 348 } |
333 | 349 |
334 // static | 350 // static |
335 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { | 351 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { |
336 switch (operand_type) { | 352 switch (operand_type) { |
337 #define CASE(Name, _) \ | 353 #define CASE(Name, _, __) \ |
338 case OperandType::k##Name: \ | 354 case OperandType::k##Name: \ |
339 return true; | 355 return true; |
340 REGISTER_OPERAND_TYPE_LIST(CASE) | 356 REGISTER_OPERAND_TYPE_LIST(CASE) |
341 #undef CASE | 357 #undef CASE |
342 #define CASE(Name, _) \ | 358 #define CASE(Name, _, __) \ |
343 case OperandType::k##Name: \ | 359 case OperandType::k##Name: \ |
344 break; | 360 break; |
345 NON_REGISTER_OPERAND_TYPE_LIST(CASE) | 361 NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
346 #undef CASE | 362 #undef CASE |
347 } | 363 } |
348 return false; | 364 return false; |
349 } | 365 } |
350 | 366 |
351 // static | 367 // static |
352 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { | 368 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { |
353 switch (operand_type) { | 369 switch (operand_type) { |
354 #define CASE(Name, _) \ | 370 #define CASE(Name, _, __) \ |
355 case OperandType::k##Name: \ | 371 case OperandType::k##Name: \ |
356 return true; | 372 return true; |
357 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) | 373 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) |
358 #undef CASE | 374 #undef CASE |
359 #define CASE(Name, _) \ | 375 #define CASE(Name, _, __) \ |
360 case OperandType::k##Name: \ | 376 case OperandType::k##Name: \ |
361 break; | 377 break; |
362 NON_REGISTER_OPERAND_TYPE_LIST(CASE) | 378 NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
363 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) | 379 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) |
364 #undef CASE | 380 #undef CASE |
365 } | 381 } |
366 return false; | 382 return false; |
367 } | 383 } |
368 | 384 |
369 // static | 385 // static |
370 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { | 386 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { |
371 switch (operand_type) { | 387 switch (operand_type) { |
372 #define CASE(Name, _) \ | 388 #define CASE(Name, _, __) \ |
373 case OperandType::k##Name: \ | 389 case OperandType::k##Name: \ |
374 return true; | 390 return true; |
375 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) | 391 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) |
376 #undef CASE | 392 #undef CASE |
377 #define CASE(Name, _) \ | 393 #define CASE(Name, _, __) \ |
378 case OperandType::k##Name: \ | 394 case OperandType::k##Name: \ |
379 break; | 395 break; |
380 NON_REGISTER_OPERAND_TYPE_LIST(CASE) | 396 NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
381 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) | 397 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) |
382 #undef CASE | 398 #undef CASE |
383 } | 399 } |
384 return false; | 400 return false; |
385 } | 401 } |
386 | 402 |
387 namespace { | 403 namespace { |
388 static Register DecodeRegister(const uint8_t* operand_start, | 404 static Register DecodeRegister(const uint8_t* operand_start, |
389 OperandType operand_type) { | 405 OperandType operand_type, int operand_scale) { |
390 switch (Bytecodes::SizeOfOperand(operand_type)) { | 406 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { |
391 case OperandSize::kByte: | 407 case OperandSize::kByte: |
392 return Register::FromOperand(*operand_start); | 408 return Register::FromOperand(*operand_start); |
393 case OperandSize::kShort: | 409 case OperandSize::kShort: |
394 return Register::FromWideOperand(ReadUnalignedUInt16(operand_start)); | 410 return Register::FromWideOperand(ReadUnalignedUInt16(operand_start)); |
411 case OperandSize::kQuad: | |
412 return Register::FromWideOperand(ReadUnalignedUInt32(operand_start)); | |
395 case OperandSize::kNone: { | 413 case OperandSize::kNone: { |
396 UNREACHABLE(); | 414 UNREACHABLE(); |
397 } | 415 } |
398 } | 416 } |
399 return Register(); | 417 return Register(); |
400 } | 418 } |
419 | |
420 static uint32_t DecodeUnsignedOperand(const uint8_t* operand_start, | |
421 OperandType operand_type, | |
422 int operand_scale) { | |
423 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { | |
424 case OperandSize::kByte: | |
425 return *operand_start; | |
426 case OperandSize::kShort: | |
427 return ReadUnalignedUInt16(operand_start); | |
428 case OperandSize::kQuad: | |
429 return ReadUnalignedUInt32(operand_start); | |
430 case OperandSize::kNone: | |
431 UNREACHABLE(); | |
432 } | |
433 return 0; | |
434 } | |
435 | |
436 static int32_t DecodeSignedOperand(const uint8_t* operand_start, | |
437 OperandType operand_type, | |
438 int operand_scale) { | |
439 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { | |
440 case OperandSize::kByte: | |
441 return static_cast<int8_t>(*operand_start); | |
442 case OperandSize::kShort: | |
443 return static_cast<int16_t>(ReadUnalignedUInt16(operand_start)); | |
444 case OperandSize::kQuad: | |
445 return static_cast<int32_t>(ReadUnalignedUInt32(operand_start)); | |
446 case OperandSize::kNone: | |
447 UNREACHABLE(); | |
448 } | |
449 return 0; | |
450 } | |
401 } // namespace | 451 } // namespace |
402 | 452 |
403 | 453 |
404 // static | 454 // static |
405 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, | 455 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, |
406 int parameter_count) { | 456 int parameter_count) { |
407 Vector<char> buf = Vector<char>::New(50); | 457 Vector<char> buf = Vector<char>::New(50); |
408 | 458 |
409 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); | 459 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); |
410 int bytecode_size = Bytecodes::Size(bytecode); | 460 int prefix_offset = 0; |
461 int operand_scale = Bytecodes::GetPrefixBytecodeScale(bytecode); | |
462 if (operand_scale > 1) { | |
463 prefix_offset += 1; | |
464 bytecode = Bytecodes::FromByte(bytecode_start[1]); | |
465 } | |
411 | 466 |
412 for (int i = 0; i < bytecode_size; i++) { | 467 int bytecode_size = Bytecodes::Size(bytecode, operand_scale); |
468 | |
469 for (int i = 0; i < prefix_offset + bytecode_size; i++) { | |
413 SNPrintF(buf, "%02x ", bytecode_start[i]); | 470 SNPrintF(buf, "%02x ", bytecode_start[i]); |
414 os << buf.start(); | 471 os << buf.start(); |
415 } | 472 } |
416 const int kBytecodeColumnSize = 6; | 473 const int kBytecodeColumnSize = 6; |
417 for (int i = bytecode_size; i < kBytecodeColumnSize; i++) { | 474 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) { |
418 os << " "; | 475 os << " "; |
419 } | 476 } |
420 | 477 |
421 os << bytecode << " "; | 478 os << bytecode; |
479 if (operand_scale == 2) { | |
480 os << "." << Bytecodes::ToString(Bytecode::kWide); | |
481 } else if (operand_scale == 4) { | |
482 os << "." << Bytecodes::ToString(Bytecode::kExtraWide); | |
483 } | |
484 os << " "; | |
422 | 485 |
423 // Operands for the debug break are from the original instruction. | 486 // Operands for the debug break are from the original instruction. |
424 if (IsDebugBreak(bytecode)) return os; | 487 if (IsDebugBreak(bytecode)) return os; |
425 | 488 |
426 int number_of_operands = NumberOfOperands(bytecode); | 489 int number_of_operands = NumberOfOperands(bytecode); |
427 int range = 0; | 490 int range = 0; |
428 for (int i = 0; i < number_of_operands; i++) { | 491 for (int i = 0; i < number_of_operands; i++) { |
429 OperandType op_type = GetOperandType(bytecode, i); | 492 OperandType op_type = GetOperandType(bytecode, i); |
430 const uint8_t* operand_start = | 493 const uint8_t* operand_start = |
431 &bytecode_start[GetOperandOffset(bytecode, i)]; | 494 &bytecode_start[prefix_offset + |
495 GetOperandOffset(bytecode, i, operand_scale)]; | |
432 switch (op_type) { | 496 switch (op_type) { |
433 case interpreter::OperandType::kRegCount8: | 497 case interpreter::OperandType::kRegCount: |
434 os << "#" << static_cast<unsigned int>(*operand_start); | 498 os << "#" |
499 << DecodeUnsignedOperand(operand_start, op_type, operand_scale); | |
435 break; | 500 break; |
436 case interpreter::OperandType::kRegCount16: | 501 case interpreter::OperandType::kIdx: |
437 os << '#' << ReadUnalignedUInt16(operand_start); | 502 case interpreter::OperandType::kRuntimeId: |
503 os << "[" | |
504 << DecodeUnsignedOperand(operand_start, op_type, operand_scale) | |
505 << "]"; | |
438 break; | 506 break; |
439 case interpreter::OperandType::kIdx8: | 507 case interpreter::OperandType::kImm: |
440 os << "[" << static_cast<unsigned int>(*operand_start) << "]"; | 508 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale) |
509 << "]"; | |
441 break; | 510 break; |
442 case interpreter::OperandType::kIdx16: | 511 case interpreter::OperandType::kFlag8: |
443 os << "[" << ReadUnalignedUInt16(operand_start) << "]"; | 512 os << "#" |
513 << DecodeUnsignedOperand(operand_start, op_type, operand_scale); | |
444 break; | 514 break; |
445 case interpreter::OperandType::kImm8: | 515 case interpreter::OperandType::kMaybeReg: |
446 os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start)); | 516 case interpreter::OperandType::kReg: |
447 break; | 517 case interpreter::OperandType::kRegOut: { |
448 case interpreter::OperandType::kMaybeReg8: | 518 Register reg = DecodeRegister(operand_start, op_type, operand_scale); |
449 case interpreter::OperandType::kMaybeReg16: | |
450 case interpreter::OperandType::kReg8: | |
451 case interpreter::OperandType::kReg16: | |
452 case interpreter::OperandType::kRegOut8: | |
453 case interpreter::OperandType::kRegOut16: { | |
454 Register reg = DecodeRegister(operand_start, op_type); | |
455 os << reg.ToString(parameter_count); | 519 os << reg.ToString(parameter_count); |
456 break; | 520 break; |
457 } | 521 } |
458 case interpreter::OperandType::kRegOutTriple8: | 522 case interpreter::OperandType::kRegOutTriple: |
459 case interpreter::OperandType::kRegOutTriple16: | |
460 range += 1; | 523 range += 1; |
461 case interpreter::OperandType::kRegOutPair8: | 524 case interpreter::OperandType::kRegOutPair: |
462 case interpreter::OperandType::kRegOutPair16: | 525 case interpreter::OperandType::kRegPair: { |
463 case interpreter::OperandType::kRegPair8: | |
464 case interpreter::OperandType::kRegPair16: { | |
465 range += 1; | 526 range += 1; |
466 Register first_reg = DecodeRegister(operand_start, op_type); | 527 Register first_reg = |
528 DecodeRegister(operand_start, op_type, operand_scale); | |
467 Register last_reg = Register(first_reg.index() + range); | 529 Register last_reg = Register(first_reg.index() + range); |
468 os << first_reg.ToString(parameter_count) << "-" | 530 os << first_reg.ToString(parameter_count) << "-" |
469 << last_reg.ToString(parameter_count); | 531 << last_reg.ToString(parameter_count); |
470 break; | 532 break; |
471 } | 533 } |
472 case interpreter::OperandType::kNone: | 534 case interpreter::OperandType::kNone: |
473 UNREACHABLE(); | 535 UNREACHABLE(); |
474 break; | 536 break; |
475 } | 537 } |
476 if (i != number_of_operands - 1) { | 538 if (i != number_of_operands - 1) { |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
639 } else { | 701 } else { |
640 std::ostringstream s; | 702 std::ostringstream s; |
641 s << "r" << index(); | 703 s << "r" << index(); |
642 return s.str(); | 704 return s.str(); |
643 } | 705 } |
644 } | 706 } |
645 | 707 |
646 } // namespace interpreter | 708 } // namespace interpreter |
647 } // namespace internal | 709 } // namespace internal |
648 } // namespace v8 | 710 } // namespace v8 |
OLD | NEW |