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 <iomanip> | 7 #include <iomanip> |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/globals.h" |
10 #include "src/interpreter/bytecode-traits.h" | 11 #include "src/interpreter/bytecode-traits.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 namespace interpreter { | 15 namespace interpreter { |
15 | 16 |
16 // clang-format off | 17 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kMaxOperands; |
17 STATIC_CONST_MEMBER_DEFINITION | |
18 const OperandType* const Bytecodes::kOperandTypes[] = { | |
19 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes, | |
20 BYTECODE_LIST(ENTRY) | |
21 #undef ENTRY | |
22 }; | |
23 | |
24 STATIC_CONST_MEMBER_DEFINITION | |
25 const OperandTypeInfo* const Bytecodes::kOperandTypeInfos[] = { | |
26 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos, | |
27 BYTECODE_LIST(ENTRY) | |
28 #undef ENTRY | |
29 }; | |
30 | |
31 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kOperandCount[] = { | |
32 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount, | |
33 BYTECODE_LIST(ENTRY) | |
34 #undef ENTRY | |
35 }; | |
36 | |
37 STATIC_CONST_MEMBER_DEFINITION | |
38 const AccumulatorUse Bytecodes::kAccumulatorUse[] = { | |
39 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kAccumulatorUse, | |
40 BYTECODE_LIST(ENTRY) | |
41 #undef ENTRY | |
42 }; | |
43 | |
44 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kBytecodeSizes[][3] = { | |
45 #define ENTRY(Name, ...) \ | |
46 { BytecodeTraits<__VA_ARGS__>::kSingleScaleSize, \ | |
47 BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize, \ | |
48 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize }, | |
49 BYTECODE_LIST(ENTRY) | |
50 #undef ENTRY | |
51 }; | |
52 | |
53 STATIC_CONST_MEMBER_DEFINITION | |
54 const OperandSize* const Bytecodes::kOperandSizes[][3] = { | |
55 #define ENTRY(Name, ...) \ | |
56 { BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes, \ | |
57 BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes, \ | |
58 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes }, | |
59 BYTECODE_LIST(ENTRY) | |
60 #undef ENTRY | |
61 }; | |
62 // clang-format on | |
63 | 18 |
64 // static | 19 // static |
65 const char* Bytecodes::ToString(Bytecode bytecode) { | 20 const char* Bytecodes::ToString(Bytecode bytecode) { |
66 switch (bytecode) { | 21 switch (bytecode) { |
67 #define CASE(Name, ...) \ | 22 #define CASE(Name, ...) \ |
68 case Bytecode::k##Name: \ | 23 case Bytecode::k##Name: \ |
69 return #Name; | 24 return #Name; |
70 BYTECODE_LIST(CASE) | 25 BYTECODE_LIST(CASE) |
71 #undef CASE | 26 #undef CASE |
72 } | 27 } |
73 UNREACHABLE(); | 28 UNREACHABLE(); |
74 return ""; | 29 return ""; |
75 } | 30 } |
76 | 31 |
77 // static | 32 // static |
78 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { | 33 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { |
79 static const char kSeparator = '.'; | 34 static const char kSeparator = '.'; |
80 | 35 |
81 std::string value(ToString(bytecode)); | 36 std::string value(ToString(bytecode)); |
82 if (operand_scale > OperandScale::kSingle) { | 37 if (operand_scale > OperandScale::kSingle) { |
83 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); | 38 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); |
84 std::string suffix = ToString(prefix_bytecode); | 39 std::string suffix = ToString(prefix_bytecode); |
85 return value.append(1, kSeparator).append(suffix); | 40 return value.append(1, kSeparator).append(suffix); |
86 } else { | 41 } else { |
87 return value; | 42 return value; |
88 } | 43 } |
89 } | 44 } |
90 | 45 |
91 // static | 46 // static |
| 47 const char* Bytecodes::AccumulatorUseToString(AccumulatorUse accumulator_use) { |
| 48 switch (accumulator_use) { |
| 49 case AccumulatorUse::kNone: |
| 50 return "None"; |
| 51 case AccumulatorUse::kRead: |
| 52 return "Read"; |
| 53 case AccumulatorUse::kWrite: |
| 54 return "Write"; |
| 55 case AccumulatorUse::kReadWrite: |
| 56 return "ReadWrite"; |
| 57 } |
| 58 UNREACHABLE(); |
| 59 return ""; |
| 60 } |
| 61 |
| 62 // static |
| 63 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { |
| 64 switch (operand_type) { |
| 65 #define CASE(Name, _) \ |
| 66 case OperandType::k##Name: \ |
| 67 return #Name; |
| 68 OPERAND_TYPE_LIST(CASE) |
| 69 #undef CASE |
| 70 } |
| 71 UNREACHABLE(); |
| 72 return ""; |
| 73 } |
| 74 |
| 75 // static |
| 76 const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) { |
| 77 switch (operand_scale) { |
| 78 #define CASE(Name, _) \ |
| 79 case OperandScale::k##Name: \ |
| 80 return #Name; |
| 81 OPERAND_SCALE_LIST(CASE) |
| 82 #undef CASE |
| 83 } |
| 84 UNREACHABLE(); |
| 85 return ""; |
| 86 } |
| 87 |
| 88 // static |
| 89 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { |
| 90 switch (operand_size) { |
| 91 case OperandSize::kNone: |
| 92 return "None"; |
| 93 case OperandSize::kByte: |
| 94 return "Byte"; |
| 95 case OperandSize::kShort: |
| 96 return "Short"; |
| 97 case OperandSize::kQuad: |
| 98 return "Quad"; |
| 99 } |
| 100 UNREACHABLE(); |
| 101 return ""; |
| 102 } |
| 103 |
| 104 // static |
| 105 uint8_t Bytecodes::ToByte(Bytecode bytecode) { |
| 106 DCHECK_LE(bytecode, Bytecode::kLast); |
| 107 return static_cast<uint8_t>(bytecode); |
| 108 } |
| 109 |
| 110 // static |
| 111 Bytecode Bytecodes::FromByte(uint8_t value) { |
| 112 Bytecode bytecode = static_cast<Bytecode>(value); |
| 113 DCHECK(bytecode <= Bytecode::kLast); |
| 114 return bytecode; |
| 115 } |
| 116 |
| 117 // static |
92 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { | 118 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { |
93 DCHECK(!IsDebugBreak(bytecode)); | 119 DCHECK(!IsDebugBreak(bytecode)); |
94 if (bytecode == Bytecode::kWide) { | 120 if (bytecode == Bytecode::kWide) { |
95 return Bytecode::kDebugBreakWide; | 121 return Bytecode::kDebugBreakWide; |
96 } | 122 } |
97 if (bytecode == Bytecode::kExtraWide) { | 123 if (bytecode == Bytecode::kExtraWide) { |
98 return Bytecode::kDebugBreakExtraWide; | 124 return Bytecode::kDebugBreakExtraWide; |
99 } | 125 } |
100 int bytecode_size = Size(bytecode, OperandScale::kSingle); | 126 int bytecode_size = Size(bytecode, OperandScale::kSingle); |
101 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \ | 127 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \ |
102 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ | 128 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ |
103 return Bytecode::k##Name; \ | 129 return Bytecode::k##Name; \ |
104 } | 130 } |
105 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) | 131 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) |
106 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES | 132 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES |
107 UNREACHABLE(); | 133 UNREACHABLE(); |
108 return Bytecode::kIllegal; | 134 return Bytecode::kIllegal; |
109 } | 135 } |
110 | 136 |
111 // static | 137 // static |
| 138 int Bytecodes::Size(Bytecode bytecode, OperandScale operand_scale) { |
| 139 int size = 1; |
| 140 for (int i = 0; i < NumberOfOperands(bytecode); i++) { |
| 141 OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale); |
| 142 int delta = static_cast<int>(operand_size); |
| 143 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta))); |
| 144 size += delta; |
| 145 } |
| 146 return size; |
| 147 } |
| 148 |
| 149 // static |
| 150 size_t Bytecodes::ReturnCount(Bytecode bytecode) { |
| 151 return bytecode == Bytecode::kReturn ? 1 : 0; |
| 152 } |
| 153 |
| 154 // static |
| 155 int Bytecodes::NumberOfOperands(Bytecode bytecode) { |
| 156 DCHECK(bytecode <= Bytecode::kLast); |
| 157 switch (bytecode) { |
| 158 #define CASE(Name, ...) \ |
| 159 case Bytecode::k##Name: \ |
| 160 return BytecodeTraits<__VA_ARGS__>::kOperandCount; |
| 161 BYTECODE_LIST(CASE) |
| 162 #undef CASE |
| 163 } |
| 164 UNREACHABLE(); |
| 165 return 0; |
| 166 } |
| 167 |
| 168 // static |
| 169 int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) { |
| 170 DCHECK(bytecode <= Bytecode::kLast); |
| 171 switch (bytecode) { |
| 172 #define CASE(Name, ...) \ |
| 173 case Bytecode::k##Name: \ |
| 174 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ |
| 175 return Name##Trait::kRegisterOperandCount; |
| 176 BYTECODE_LIST(CASE) |
| 177 #undef CASE |
| 178 } |
| 179 UNREACHABLE(); |
| 180 return false; |
| 181 } |
| 182 |
| 183 // static |
| 184 Bytecode Bytecodes::OperandScaleToPrefixBytecode(OperandScale operand_scale) { |
| 185 switch (operand_scale) { |
| 186 case OperandScale::kQuadruple: |
| 187 return Bytecode::kExtraWide; |
| 188 case OperandScale::kDouble: |
| 189 return Bytecode::kWide; |
| 190 default: |
| 191 UNREACHABLE(); |
| 192 return Bytecode::kIllegal; |
| 193 } |
| 194 } |
| 195 |
| 196 // static |
| 197 bool Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) { |
| 198 return operand_scale != OperandScale::kSingle; |
| 199 } |
| 200 |
| 201 // static |
| 202 OperandScale Bytecodes::PrefixBytecodeToOperandScale(Bytecode bytecode) { |
| 203 switch (bytecode) { |
| 204 case Bytecode::kExtraWide: |
| 205 case Bytecode::kDebugBreakExtraWide: |
| 206 return OperandScale::kQuadruple; |
| 207 case Bytecode::kWide: |
| 208 case Bytecode::kDebugBreakWide: |
| 209 return OperandScale::kDouble; |
| 210 default: |
| 211 UNREACHABLE(); |
| 212 return OperandScale::kSingle; |
| 213 } |
| 214 } |
| 215 |
| 216 // static |
| 217 AccumulatorUse Bytecodes::GetAccumulatorUse(Bytecode bytecode) { |
| 218 DCHECK(bytecode <= Bytecode::kLast); |
| 219 switch (bytecode) { |
| 220 #define CASE(Name, ...) \ |
| 221 case Bytecode::k##Name: \ |
| 222 return BytecodeTraits<__VA_ARGS__>::kAccumulatorUse; |
| 223 BYTECODE_LIST(CASE) |
| 224 #undef CASE |
| 225 } |
| 226 UNREACHABLE(); |
| 227 return AccumulatorUse::kNone; |
| 228 } |
| 229 |
| 230 // static |
| 231 bool Bytecodes::ReadsAccumulator(Bytecode bytecode) { |
| 232 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kRead) == |
| 233 AccumulatorUse::kRead; |
| 234 } |
| 235 |
| 236 // static |
| 237 bool Bytecodes::WritesAccumulator(Bytecode bytecode) { |
| 238 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) == |
| 239 AccumulatorUse::kWrite; |
| 240 } |
| 241 |
| 242 // static |
| 243 bool Bytecodes::WritesBooleanToAccumulator(Bytecode bytecode) { |
| 244 switch (bytecode) { |
| 245 case Bytecode::kLdaTrue: |
| 246 case Bytecode::kLdaFalse: |
| 247 case Bytecode::kToBooleanLogicalNot: |
| 248 case Bytecode::kLogicalNot: |
| 249 case Bytecode::kTestEqual: |
| 250 case Bytecode::kTestNotEqual: |
| 251 case Bytecode::kTestEqualStrict: |
| 252 case Bytecode::kTestLessThan: |
| 253 case Bytecode::kTestLessThanOrEqual: |
| 254 case Bytecode::kTestGreaterThan: |
| 255 case Bytecode::kTestGreaterThanOrEqual: |
| 256 case Bytecode::kTestInstanceOf: |
| 257 case Bytecode::kTestIn: |
| 258 case Bytecode::kForInContinue: |
| 259 return true; |
| 260 default: |
| 261 return false; |
| 262 } |
| 263 } |
| 264 |
| 265 // static |
| 266 bool Bytecodes::IsAccumulatorLoadWithoutEffects(Bytecode bytecode) { |
| 267 switch (bytecode) { |
| 268 case Bytecode::kLdaZero: |
| 269 case Bytecode::kLdaSmi: |
| 270 case Bytecode::kLdaUndefined: |
| 271 case Bytecode::kLdaNull: |
| 272 case Bytecode::kLdaTheHole: |
| 273 case Bytecode::kLdaTrue: |
| 274 case Bytecode::kLdaFalse: |
| 275 case Bytecode::kLdaConstant: |
| 276 case Bytecode::kLdar: |
| 277 return true; |
| 278 default: |
| 279 return false; |
| 280 } |
| 281 } |
| 282 |
| 283 // static |
| 284 bool Bytecodes::IsJumpWithoutEffects(Bytecode bytecode) { |
| 285 return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode); |
| 286 } |
| 287 |
| 288 // static |
| 289 bool Bytecodes::IsRegisterLoadWithoutEffects(Bytecode bytecode) { |
| 290 switch (bytecode) { |
| 291 case Bytecode::kMov: |
| 292 case Bytecode::kPopContext: |
| 293 case Bytecode::kPushContext: |
| 294 case Bytecode::kStar: |
| 295 case Bytecode::kLdrUndefined: |
| 296 return true; |
| 297 default: |
| 298 return false; |
| 299 } |
| 300 } |
| 301 |
| 302 // static |
| 303 bool Bytecodes::IsWithoutExternalSideEffects(Bytecode bytecode) { |
| 304 // These bytecodes only manipulate interpreter frame state and will |
| 305 // never throw. |
| 306 return (IsAccumulatorLoadWithoutEffects(bytecode) || |
| 307 IsRegisterLoadWithoutEffects(bytecode) || |
| 308 bytecode == Bytecode::kNop || IsJumpWithoutEffects(bytecode)); |
| 309 } |
| 310 |
| 311 // static |
| 312 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
| 313 DCHECK_LE(bytecode, Bytecode::kLast); |
| 314 DCHECK_LT(i, NumberOfOperands(bytecode)); |
| 315 DCHECK_GE(i, 0); |
| 316 return GetOperandTypes(bytecode)[i]; |
| 317 } |
| 318 |
| 319 // static |
| 320 const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) { |
| 321 DCHECK_LE(bytecode, Bytecode::kLast); |
| 322 switch (bytecode) { |
| 323 #define CASE(Name, ...) \ |
| 324 case Bytecode::k##Name: \ |
| 325 return BytecodeTraits<__VA_ARGS__>::GetOperandTypes(); |
| 326 BYTECODE_LIST(CASE) |
| 327 #undef CASE |
| 328 } |
| 329 UNREACHABLE(); |
| 330 return nullptr; |
| 331 } |
| 332 |
| 333 // static |
| 334 const OperandTypeInfo* Bytecodes::GetOperandTypeInfos(Bytecode bytecode) { |
| 335 DCHECK(bytecode <= Bytecode::kLast); |
| 336 switch (bytecode) { |
| 337 #define CASE(Name, ...) \ |
| 338 case Bytecode::k##Name: \ |
| 339 return BytecodeTraits<__VA_ARGS__>::GetOperandTypeInfos(); |
| 340 BYTECODE_LIST(CASE) |
| 341 #undef CASE |
| 342 } |
| 343 UNREACHABLE(); |
| 344 return nullptr; |
| 345 } |
| 346 |
| 347 // static |
| 348 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, |
| 349 OperandScale operand_scale) { |
| 350 DCHECK_LT(i, NumberOfOperands(bytecode)); |
| 351 OperandType operand_type = GetOperandType(bytecode, i); |
| 352 return SizeOfOperand(operand_type, operand_scale); |
| 353 } |
| 354 |
| 355 // static |
112 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, | 356 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, |
113 OperandScale operand_scale) { | 357 OperandScale operand_scale) { |
114 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); | 358 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); |
115 // TODO(oth): restore this to a statically determined constant. | 359 // TODO(oth): restore this to a statically determined constant. |
116 int offset = 1; | 360 int offset = 1; |
117 for (int operand_index = 0; operand_index < i; ++operand_index) { | 361 for (int operand_index = 0; operand_index < i; ++operand_index) { |
118 OperandSize operand_size = | 362 OperandSize operand_size = |
119 GetOperandSize(bytecode, operand_index, operand_scale); | 363 GetOperandSize(bytecode, operand_index, operand_scale); |
120 offset += static_cast<int>(operand_size); | 364 offset += static_cast<int>(operand_size); |
121 } | 365 } |
122 return offset; | 366 return offset; |
123 } | 367 } |
124 | 368 |
125 // static | 369 // static |
| 370 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, |
| 371 OperandScale operand_scale) { |
| 372 DCHECK_LE(operand_type, OperandType::kLast); |
| 373 DCHECK_GE(operand_scale, OperandScale::kSingle); |
| 374 DCHECK_LE(operand_scale, OperandScale::kLast); |
| 375 return static_cast<OperandSize>( |
| 376 ScaledOperandSize(operand_type, operand_scale)); |
| 377 } |
| 378 |
| 379 // static |
| 380 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { |
| 381 return bytecode == Bytecode::kJumpIfTrue || |
| 382 bytecode == Bytecode::kJumpIfFalse || |
| 383 bytecode == Bytecode::kJumpIfToBooleanTrue || |
| 384 bytecode == Bytecode::kJumpIfToBooleanFalse || |
| 385 bytecode == Bytecode::kJumpIfNotHole || |
| 386 bytecode == Bytecode::kJumpIfNull || |
| 387 bytecode == Bytecode::kJumpIfUndefined; |
| 388 } |
| 389 |
| 390 // static |
| 391 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { |
| 392 return bytecode == Bytecode::kJumpIfTrueConstant || |
| 393 bytecode == Bytecode::kJumpIfFalseConstant || |
| 394 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
| 395 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || |
| 396 bytecode == Bytecode::kJumpIfNotHoleConstant || |
| 397 bytecode == Bytecode::kJumpIfNullConstant || |
| 398 bytecode == Bytecode::kJumpIfUndefinedConstant; |
| 399 } |
| 400 |
| 401 // static |
| 402 bool Bytecodes::IsConditionalJump(Bytecode bytecode) { |
| 403 return IsConditionalJumpImmediate(bytecode) || |
| 404 IsConditionalJumpConstant(bytecode); |
| 405 } |
| 406 |
| 407 |
| 408 // static |
| 409 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) { |
| 410 return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpLoop || |
| 411 IsConditionalJumpImmediate(bytecode); |
| 412 } |
| 413 |
| 414 |
| 415 // static |
| 416 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { |
| 417 return bytecode == Bytecode::kJumpConstant || |
| 418 IsConditionalJumpConstant(bytecode); |
| 419 } |
| 420 |
| 421 // static |
| 422 bool Bytecodes::IsJump(Bytecode bytecode) { |
| 423 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); |
| 424 } |
| 425 |
| 426 // static |
| 427 bool Bytecodes::IsJumpIfToBoolean(Bytecode bytecode) { |
| 428 return bytecode == Bytecode::kJumpIfToBooleanTrue || |
| 429 bytecode == Bytecode::kJumpIfToBooleanFalse || |
| 430 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
| 431 bytecode == Bytecode::kJumpIfToBooleanFalseConstant; |
| 432 } |
| 433 |
| 434 // static |
126 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { | 435 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { |
127 switch (bytecode) { | 436 switch (bytecode) { |
128 case Bytecode::kJumpIfToBooleanTrue: | 437 case Bytecode::kJumpIfToBooleanTrue: |
129 return Bytecode::kJumpIfTrue; | 438 return Bytecode::kJumpIfTrue; |
130 case Bytecode::kJumpIfToBooleanFalse: | 439 case Bytecode::kJumpIfToBooleanFalse: |
131 return Bytecode::kJumpIfFalse; | 440 return Bytecode::kJumpIfFalse; |
132 case Bytecode::kJumpIfToBooleanTrueConstant: | 441 case Bytecode::kJumpIfToBooleanTrueConstant: |
133 return Bytecode::kJumpIfTrueConstant; | 442 return Bytecode::kJumpIfTrueConstant; |
134 case Bytecode::kJumpIfToBooleanFalseConstant: | 443 case Bytecode::kJumpIfToBooleanFalseConstant: |
135 return Bytecode::kJumpIfFalseConstant; | 444 return Bytecode::kJumpIfFalseConstant; |
136 default: | 445 default: |
137 break; | 446 break; |
138 } | 447 } |
139 UNREACHABLE(); | 448 UNREACHABLE(); |
140 return Bytecode::kIllegal; | 449 return Bytecode::kIllegal; |
141 } | 450 } |
142 | 451 |
143 // static | 452 // static |
| 453 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { |
| 454 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || |
| 455 bytecode == Bytecode::kNew; |
| 456 } |
| 457 |
| 458 // static |
| 459 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { |
| 460 return bytecode == Bytecode::kCallRuntime || |
| 461 bytecode == Bytecode::kCallRuntimeForPair || |
| 462 bytecode == Bytecode::kInvokeIntrinsic; |
| 463 } |
| 464 |
| 465 // static |
144 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { | 466 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { |
145 switch (bytecode) { | 467 switch (bytecode) { |
146 #define CASE(Name, ...) case Bytecode::k##Name: | 468 #define CASE(Name, ...) case Bytecode::k##Name: |
147 DEBUG_BREAK_BYTECODE_LIST(CASE); | 469 DEBUG_BREAK_BYTECODE_LIST(CASE); |
148 #undef CASE | 470 #undef CASE |
149 return true; | 471 return true; |
150 default: | 472 default: |
151 break; | 473 break; |
152 } | 474 } |
153 return false; | 475 return false; |
154 } | 476 } |
155 | 477 |
156 // static | 478 // static |
| 479 bool Bytecodes::IsLdarOrStar(Bytecode bytecode) { |
| 480 return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar; |
| 481 } |
| 482 |
| 483 // static |
| 484 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { |
| 485 switch (bytecode) { |
| 486 #define CASE(Name, ...) \ |
| 487 case Bytecode::k##Name: \ |
| 488 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ |
| 489 return Name##Trait::IsScalable(); |
| 490 BYTECODE_LIST(CASE) |
| 491 #undef CASE |
| 492 } |
| 493 UNREACHABLE(); |
| 494 return false; |
| 495 } |
| 496 |
| 497 // static |
| 498 bool Bytecodes::IsPrefixScalingBytecode(Bytecode bytecode) { |
| 499 switch (bytecode) { |
| 500 case Bytecode::kExtraWide: |
| 501 case Bytecode::kDebugBreakExtraWide: |
| 502 case Bytecode::kWide: |
| 503 case Bytecode::kDebugBreakWide: |
| 504 return true; |
| 505 default: |
| 506 return false; |
| 507 } |
| 508 } |
| 509 |
| 510 // static |
| 511 bool Bytecodes::PutsNameInAccumulator(Bytecode bytecode) { |
| 512 return bytecode == Bytecode::kTypeOf; |
| 513 } |
| 514 |
| 515 // static |
| 516 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { |
| 517 return bytecode == Bytecode::kReturn || IsJump(bytecode); |
| 518 } |
| 519 |
| 520 // static |
| 521 bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) { |
| 522 return operand_type == OperandType::kMaybeReg; |
| 523 } |
| 524 |
| 525 // static |
157 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { | 526 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { |
158 switch (operand_type) { | 527 switch (operand_type) { |
159 #define CASE(Name, _) \ | 528 #define CASE(Name, _) \ |
160 case OperandType::k##Name: \ | 529 case OperandType::k##Name: \ |
161 return true; | 530 return true; |
162 REGISTER_OPERAND_TYPE_LIST(CASE) | 531 REGISTER_OPERAND_TYPE_LIST(CASE) |
163 #undef CASE | 532 #undef CASE |
164 #define CASE(Name, _) \ | 533 #define CASE(Name, _) \ |
165 case OperandType::k##Name: \ | 534 case OperandType::k##Name: \ |
166 break; | 535 break; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 case Bytecode::kNew: | 596 case Bytecode::kNew: |
228 return true; | 597 return true; |
229 default: | 598 default: |
230 return false; | 599 return false; |
231 } | 600 } |
232 } | 601 } |
233 return false; | 602 return false; |
234 } | 603 } |
235 | 604 |
236 // static | 605 // static |
237 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { | 606 int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) { |
238 for (int i = 0; i < NumberOfOperands(bytecode); i++) { | 607 switch (operand_type) { |
239 if (OperandIsScalable(bytecode, i)) return true; | 608 case OperandType::kMaybeReg: |
| 609 case OperandType::kReg: |
| 610 case OperandType::kRegOut: |
| 611 return 1; |
| 612 case OperandType::kRegPair: |
| 613 case OperandType::kRegOutPair: |
| 614 return 2; |
| 615 case OperandType::kRegOutTriple: |
| 616 return 3; |
| 617 default: |
| 618 return 0; |
240 } | 619 } |
241 return false; | 620 return 0; |
242 } | 621 } |
243 | 622 |
244 // static | 623 // static |
245 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { | 624 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { |
246 switch (operand_type) { | 625 switch (operand_type) { |
247 #define CASE(Name, _) \ | 626 #define CASE(Name, _) \ |
248 case OperandType::k##Name: \ | 627 case OperandType::k##Name: \ |
249 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; | 628 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; |
250 OPERAND_TYPE_LIST(CASE) | 629 OPERAND_TYPE_LIST(CASE) |
251 #undef CASE | 630 #undef CASE |
252 } | 631 } |
253 UNREACHABLE(); | 632 UNREACHABLE(); |
254 return false; | 633 return false; |
255 } | 634 } |
256 | 635 |
257 // static | 636 // static |
258 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, | 637 OperandSize Bytecodes::SizeForSignedOperand(int value) { |
259 OperandScale operand_scale) { | 638 if (value >= kMinInt8 && value <= kMaxInt8) { |
260 DCHECK_LE(operand_type, OperandType::kLast); | 639 return OperandSize::kByte; |
261 DCHECK_GE(operand_scale, OperandScale::kSingle); | 640 } else if (value >= kMinInt16 && value <= kMaxInt16) { |
262 DCHECK_LE(operand_scale, OperandScale::kLast); | 641 return OperandSize::kShort; |
263 STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 && | 642 } else { |
264 OperandScale::kLast == OperandScale::kQuadruple); | 643 return OperandSize::kQuad; |
265 int scale_index = static_cast<int>(operand_scale) >> 1; | 644 } |
266 // clang-format off | |
267 static const OperandSize kOperandSizes[][3] = { | |
268 #define ENTRY(Name, ...) \ | |
269 { OperandScaler<OperandType::k##Name, \ | |
270 OperandScale::kSingle>::kOperandSize, \ | |
271 OperandScaler<OperandType::k##Name, \ | |
272 OperandScale::kDouble>::kOperandSize, \ | |
273 OperandScaler<OperandType::k##Name, \ | |
274 OperandScale::kQuadruple>::kOperandSize }, | |
275 OPERAND_TYPE_LIST(ENTRY) | |
276 #undef ENTRY | |
277 }; | |
278 // clang-format on | |
279 return kOperandSizes[static_cast<size_t>(operand_type)][scale_index]; | |
280 } | 645 } |
281 | 646 |
282 // static | 647 // static |
| 648 OperandSize Bytecodes::SizeForUnsignedOperand(uint32_t value) { |
| 649 if (value <= kMaxUInt8) { |
| 650 return OperandSize::kByte; |
| 651 } else if (value <= kMaxUInt16) { |
| 652 return OperandSize::kShort; |
| 653 } else { |
| 654 return OperandSize::kQuad; |
| 655 } |
| 656 } |
| 657 |
| 658 // static |
283 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, | 659 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, |
284 OperandScale operand_scale) { | 660 OperandScale operand_scale) { |
285 return operand_scale == OperandScale::kSingle || | 661 return operand_scale == OperandScale::kSingle || |
286 Bytecodes::IsBytecodeWithScalableOperands(bytecode); | 662 Bytecodes::IsBytecodeWithScalableOperands(bytecode); |
287 } | 663 } |
288 | 664 |
289 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { | 665 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
290 return os << Bytecodes::ToString(bytecode); | 666 return os << Bytecodes::ToString(bytecode); |
291 } | 667 } |
292 | 668 |
| 669 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) { |
| 670 return os << Bytecodes::AccumulatorUseToString(use); |
| 671 } |
| 672 |
| 673 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { |
| 674 return os << Bytecodes::OperandSizeToString(operand_size); |
| 675 } |
| 676 |
| 677 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) { |
| 678 return os << Bytecodes::OperandScaleToString(operand_scale); |
| 679 } |
| 680 |
| 681 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { |
| 682 return os << Bytecodes::OperandTypeToString(operand_type); |
| 683 } |
| 684 |
293 } // namespace interpreter | 685 } // namespace interpreter |
294 } // namespace internal | 686 } // namespace internal |
295 } // namespace v8 | 687 } // namespace v8 |
OLD | NEW |