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 3 // found in the LICENSE file. 4 5 #include "src/interpreter/bytecodes.h" 6 7 #include <iomanip> 8 9 #include "src/base/bits.h" 10 #include "src/interpreter/bytecode-traits.h" 11 12 namespace v8 { 13 namespace internal { 14 namespace interpreter { 15 16 // clang-format off 17 const OperandType* const Bytecodes::kOperandTypes[] = { 18 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes, 19 BYTECODE_LIST(ENTRY) 20 #undef ENTRY 21 }; 22 23 const OperandTypeInfo* const Bytecodes::kOperandTypeInfos[] = { 24 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos, 25 BYTECODE_LIST(ENTRY) 26 #undef ENTRY 27 }; 28 29 const int Bytecodes::kOperandCount[] = { 30 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount, 31 BYTECODE_LIST(ENTRY) 32 #undef ENTRY 33 }; 34 35 const AccumulatorUse Bytecodes::kAccumulatorUse[] = { 36 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kAccumulatorUse, 37 BYTECODE_LIST(ENTRY) 38 #undef ENTRY 39 }; 40 41 const int Bytecodes::kBytecodeSizes[3][kBytecodeCount] = { 42 { 43 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kSingleScaleSize, 44 BYTECODE_LIST(ENTRY) 45 #undef ENTRY 46 }, { 47 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize, 48 BYTECODE_LIST(ENTRY) 49 #undef ENTRY 50 }, { 51 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize, 52 BYTECODE_LIST(ENTRY) 53 #undef ENTRY 54 } 55 }; 56 57 const OperandSize* const Bytecodes::kOperandSizes[3][kBytecodeCount] = { 58 { 59 #define ENTRY(Name, ...) \ 60 BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes, 61 BYTECODE_LIST(ENTRY) 62 #undef ENTRY 63 }, { 64 #define ENTRY(Name, ...) \ 65 BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes, 66 BYTECODE_LIST(ENTRY) 67 #undef ENTRY 68 }, { 69 #define ENTRY(Name, ...) \ 70 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes, 71 BYTECODE_LIST(ENTRY) 72 #undef ENTRY 73 } 74 }; 75 76 const OperandSize 77 Bytecodes::kOperandKindSizes[3][BytecodeOperands::kOperandTypeCount] = { 78 { 79 #define ENTRY(Name, ...) \ 80 OperandScaler<OperandType::k##Name, OperandScale::kSingle>::kOperandSize, 81 OPERAND_TYPE_LIST(ENTRY) 82 #undef ENTRY 83 }, { 84 #define ENTRY(Name, ...) \ 85 OperandScaler<OperandType::k##Name, OperandScale::kDouble>::kOperandSize, 86 OPERAND_TYPE_LIST(ENTRY) 87 #undef ENTRY 88 }, { 89 #define ENTRY(Name, ...) \ 90 OperandScaler<OperandType::k##Name, OperandScale::kQuadruple>::kOperandSize, 91 OPERAND_TYPE_LIST(ENTRY) 92 #undef ENTRY 93 } 94 }; 95 // clang-format on 96 97 // static 98 const char* Bytecodes::ToString(Bytecode bytecode) { 99 switch (bytecode) { 100 #define CASE(Name, ...) \ 101 case Bytecode::k##Name: \ 102 return #Name; 103 BYTECODE_LIST(CASE) 104 #undef CASE 105 } 106 UNREACHABLE(); 107 } 108 109 // static 110 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { 111 static const char kSeparator = '.'; 112 113 std::string value(ToString(bytecode)); 114 if (operand_scale > OperandScale::kSingle) { 115 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); 116 std::string suffix = ToString(prefix_bytecode); 117 return value.append(1, kSeparator).append(suffix); 118 } else { 119 return value; 120 } 121 } 122 123 // static 124 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { 125 DCHECK(!IsDebugBreak(bytecode)); 126 if (bytecode == Bytecode::kWide) { 127 return Bytecode::kDebugBreakWide; 128 } 129 if (bytecode == Bytecode::kExtraWide) { 130 return Bytecode::kDebugBreakExtraWide; 131 } 132 int bytecode_size = Size(bytecode, OperandScale::kSingle); 133 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \ 134 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ 135 return Bytecode::k##Name; \ 136 } 137 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) 138 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES 139 UNREACHABLE(); 140 } 141 142 // static 143 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, 144 OperandScale operand_scale) { 145 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); 146 // TODO(oth): restore this to a statically determined constant. 147 int offset = 1; 148 for (int operand_index = 0; operand_index < i; ++operand_index) { 149 OperandSize operand_size = 150 GetOperandSize(bytecode, operand_index, operand_scale); 151 offset += static_cast<int>(operand_size); 152 } 153 return offset; 154 } 155 156 // static 157 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { 158 switch (bytecode) { 159 case Bytecode::kJumpIfToBooleanTrue: 160 return Bytecode::kJumpIfTrue; 161 case Bytecode::kJumpIfToBooleanFalse: 162 return Bytecode::kJumpIfFalse; 163 case Bytecode::kJumpIfToBooleanTrueConstant: 164 return Bytecode::kJumpIfTrueConstant; 165 case Bytecode::kJumpIfToBooleanFalseConstant: 166 return Bytecode::kJumpIfFalseConstant; 167 default: 168 break; 169 } 170 UNREACHABLE(); 171 } 172 173 // static 174 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { 175 switch (bytecode) { 176 #define CASE(Name, ...) case Bytecode::k##Name: 177 DEBUG_BREAK_BYTECODE_LIST(CASE); 178 #undef CASE 179 return true; 180 default: 181 break; 182 } 183 return false; 184 } 185 186 // static 187 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { 188 switch (operand_type) { 189 #define CASE(Name, _) \ 190 case OperandType::k##Name: \ 191 return true; 192 REGISTER_OPERAND_TYPE_LIST(CASE) 193 #undef CASE 194 #define CASE(Name, _) \ 195 case OperandType::k##Name: \ 196 break; 197 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 198 #undef CASE 199 } 200 return false; 201 } 202 203 // static 204 bool Bytecodes::IsRegisterListOperandType(OperandType operand_type) { 205 switch (operand_type) { 206 case OperandType::kRegList: 207 case OperandType::kRegOutList: 208 return true; 209 default: 210 return false; 211 } 212 } 213 214 bool Bytecodes::MakesCallAlongCriticalPath(Bytecode bytecode) { 215 if (IsCallOrConstruct(bytecode) || IsCallRuntime(bytecode)) return true; 216 switch (bytecode) { 217 case Bytecode::kCreateWithContext: 218 case Bytecode::kCreateBlockContext: 219 case Bytecode::kCreateCatchContext: 220 case Bytecode::kCreateRegExpLiteral: 221 return true; 222 default: 223 return false; 224 } 225 } 226 227 // static 228 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { 229 switch (operand_type) { 230 #define CASE(Name, _) \ 231 case OperandType::k##Name: \ 232 return true; 233 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) 234 #undef CASE 235 #define CASE(Name, _) \ 236 case OperandType::k##Name: \ 237 break; 238 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 239 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) 240 #undef CASE 241 } 242 return false; 243 } 244 245 // static 246 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { 247 switch (operand_type) { 248 #define CASE(Name, _) \ 249 case OperandType::k##Name: \ 250 return true; 251 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) 252 #undef CASE 253 #define CASE(Name, _) \ 254 case OperandType::k##Name: \ 255 break; 256 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 257 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) 258 #undef CASE 259 } 260 return false; 261 } 262 263 // static 264 bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) { 265 if (operand_scale == OperandScale::kSingle) { 266 switch (bytecode) { 267 case Bytecode::kLdaZero: 268 case Bytecode::kLdaSmi: 269 case Bytecode::kLdaNull: 270 case Bytecode::kLdaTheHole: 271 case Bytecode::kLdaConstant: 272 case Bytecode::kLdaUndefined: 273 case Bytecode::kLdaGlobal: 274 case Bytecode::kLdaNamedProperty: 275 case Bytecode::kLdaKeyedProperty: 276 case Bytecode::kLdaContextSlot: 277 case Bytecode::kLdaCurrentContextSlot: 278 case Bytecode::kAdd: 279 case Bytecode::kSub: 280 case Bytecode::kMul: 281 case Bytecode::kAddSmi: 282 case Bytecode::kSubSmi: 283 case Bytecode::kInc: 284 case Bytecode::kDec: 285 case Bytecode::kTypeOf: 286 case Bytecode::kCallAnyReceiver: 287 case Bytecode::kCallProperty: 288 case Bytecode::kCallProperty0: 289 case Bytecode::kCallProperty1: 290 case Bytecode::kCallProperty2: 291 case Bytecode::kCallUndefinedReceiver: 292 case Bytecode::kCallUndefinedReceiver0: 293 case Bytecode::kCallUndefinedReceiver1: 294 case Bytecode::kCallUndefinedReceiver2: 295 case Bytecode::kConstruct: 296 case Bytecode::kConstructWithSpread: 297 return true; 298 default: 299 return false; 300 } 301 } 302 return false; 303 } 304 305 // static 306 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { 307 for (int i = 0; i < NumberOfOperands(bytecode); i++) { 308 if (OperandIsScalable(bytecode, i)) return true; 309 } 310 return false; 311 } 312 313 // static 314 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { 315 switch (operand_type) { 316 #define CASE(Name, _) \ 317 case OperandType::k##Name: \ 318 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; 319 OPERAND_TYPE_LIST(CASE) 320 #undef CASE 321 } 322 UNREACHABLE(); 323 } 324 325 // static 326 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, 327 OperandScale operand_scale) { 328 return operand_scale == OperandScale::kSingle || 329 Bytecodes::IsBytecodeWithScalableOperands(bytecode); 330 } 331 332 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { 333 return os << Bytecodes::ToString(bytecode); 334 } 335 336 } // namespace interpreter 337 } // namespace internal 338 } // namespace v8 339