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] = { 42 #define ENTRY(Name, ...) \ 43 { BytecodeTraits<__VA_ARGS__>::kSingleScaleSize, \ 44 BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize, \ 45 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize }, 46 BYTECODE_LIST(ENTRY) 47 #undef ENTRY 48 }; 49 50 const OperandSize* const Bytecodes::kOperandSizes[][3] = { 51 #define ENTRY(Name, ...) \ 52 { BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes, \ 53 BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes, \ 54 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes }, 55 BYTECODE_LIST(ENTRY) 56 #undef ENTRY 57 }; 58 // clang-format on 59 60 // static 61 const char* Bytecodes::ToString(Bytecode bytecode) { 62 switch (bytecode) { 63 #define CASE(Name, ...) \ 64 case Bytecode::k##Name: \ 65 return #Name; 66 BYTECODE_LIST(CASE) 67 #undef CASE 68 } 69 UNREACHABLE(); 70 return ""; 71 } 72 73 // static 74 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { 75 static const char kSeparator = '.'; 76 77 std::string value(ToString(bytecode)); 78 if (operand_scale > OperandScale::kSingle) { 79 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); 80 std::string suffix = ToString(prefix_bytecode); 81 return value.append(1, kSeparator).append(suffix); 82 } else { 83 return value; 84 } 85 } 86 87 // static 88 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { 89 DCHECK(!IsDebugBreak(bytecode)); 90 if (bytecode == Bytecode::kWide) { 91 return Bytecode::kDebugBreakWide; 92 } 93 if (bytecode == Bytecode::kExtraWide) { 94 return Bytecode::kDebugBreakExtraWide; 95 } 96 int bytecode_size = Size(bytecode, OperandScale::kSingle); 97 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \ 98 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ 99 return Bytecode::k##Name; \ 100 } 101 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) 102 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES 103 UNREACHABLE(); 104 return Bytecode::kIllegal; 105 } 106 107 // static 108 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, 109 OperandScale operand_scale) { 110 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); 111 // TODO(oth): restore this to a statically determined constant. 112 int offset = 1; 113 for (int operand_index = 0; operand_index < i; ++operand_index) { 114 OperandSize operand_size = 115 GetOperandSize(bytecode, operand_index, operand_scale); 116 offset += static_cast<int>(operand_size); 117 } 118 return offset; 119 } 120 121 // static 122 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { 123 switch (bytecode) { 124 case Bytecode::kJumpIfToBooleanTrue: 125 return Bytecode::kJumpIfTrue; 126 case Bytecode::kJumpIfToBooleanFalse: 127 return Bytecode::kJumpIfFalse; 128 case Bytecode::kJumpIfToBooleanTrueConstant: 129 return Bytecode::kJumpIfTrueConstant; 130 case Bytecode::kJumpIfToBooleanFalseConstant: 131 return Bytecode::kJumpIfFalseConstant; 132 default: 133 break; 134 } 135 UNREACHABLE(); 136 return Bytecode::kIllegal; 137 } 138 139 // static 140 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { 141 switch (bytecode) { 142 #define CASE(Name, ...) case Bytecode::k##Name: 143 DEBUG_BREAK_BYTECODE_LIST(CASE); 144 #undef CASE 145 return true; 146 default: 147 break; 148 } 149 return false; 150 } 151 152 // static 153 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { 154 switch (operand_type) { 155 #define CASE(Name, _) \ 156 case OperandType::k##Name: \ 157 return true; 158 REGISTER_OPERAND_TYPE_LIST(CASE) 159 #undef CASE 160 #define CASE(Name, _) \ 161 case OperandType::k##Name: \ 162 break; 163 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 164 #undef CASE 165 } 166 return false; 167 } 168 169 // static 170 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { 171 switch (operand_type) { 172 #define CASE(Name, _) \ 173 case OperandType::k##Name: \ 174 return true; 175 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) 176 #undef CASE 177 #define CASE(Name, _) \ 178 case OperandType::k##Name: \ 179 break; 180 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 181 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) 182 #undef CASE 183 } 184 return false; 185 } 186 187 // static 188 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { 189 switch (operand_type) { 190 #define CASE(Name, _) \ 191 case OperandType::k##Name: \ 192 return true; 193 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) 194 #undef CASE 195 #define CASE(Name, _) \ 196 case OperandType::k##Name: \ 197 break; 198 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 199 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) 200 #undef CASE 201 } 202 return false; 203 } 204 205 // static 206 bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) { 207 if (operand_scale == OperandScale::kSingle) { 208 switch (bytecode) { 209 case Bytecode::kLdaZero: 210 case Bytecode::kLdaSmi: 211 case Bytecode::kLdaNull: 212 case Bytecode::kLdaTheHole: 213 case Bytecode::kLdaConstant: 214 case Bytecode::kLdaUndefined: 215 case Bytecode::kLdaGlobal: 216 case Bytecode::kLdaNamedProperty: 217 case Bytecode::kLdaKeyedProperty: 218 case Bytecode::kLdaContextSlot: 219 case Bytecode::kLdaCurrentContextSlot: 220 case Bytecode::kAdd: 221 case Bytecode::kSub: 222 case Bytecode::kMul: 223 case Bytecode::kAddSmi: 224 case Bytecode::kSubSmi: 225 case Bytecode::kInc: 226 case Bytecode::kDec: 227 case Bytecode::kTypeOf: 228 case Bytecode::kCall: 229 case Bytecode::kCallProperty: 230 case Bytecode::kNew: 231 return true; 232 default: 233 return false; 234 } 235 } 236 return false; 237 } 238 239 // static 240 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { 241 for (int i = 0; i < NumberOfOperands(bytecode); i++) { 242 if (OperandIsScalable(bytecode, i)) return true; 243 } 244 return false; 245 } 246 247 // static 248 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { 249 switch (operand_type) { 250 #define CASE(Name, _) \ 251 case OperandType::k##Name: \ 252 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; 253 OPERAND_TYPE_LIST(CASE) 254 #undef CASE 255 } 256 UNREACHABLE(); 257 return false; 258 } 259 260 // static 261 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, 262 OperandScale operand_scale) { 263 DCHECK_LE(operand_type, OperandType::kLast); 264 DCHECK_GE(operand_scale, OperandScale::kSingle); 265 DCHECK_LE(operand_scale, OperandScale::kLast); 266 STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 && 267 OperandScale::kLast == OperandScale::kQuadruple); 268 int scale_index = static_cast<int>(operand_scale) >> 1; 269 // clang-format off 270 static const OperandSize kOperandSizes[][3] = { 271 #define ENTRY(Name, ...) \ 272 { OperandScaler<OperandType::k##Name, \ 273 OperandScale::kSingle>::kOperandSize, \ 274 OperandScaler<OperandType::k##Name, \ 275 OperandScale::kDouble>::kOperandSize, \ 276 OperandScaler<OperandType::k##Name, \ 277 OperandScale::kQuadruple>::kOperandSize }, 278 OPERAND_TYPE_LIST(ENTRY) 279 #undef ENTRY 280 }; 281 // clang-format on 282 return kOperandSizes[static_cast<size_t>(operand_type)][scale_index]; 283 } 284 285 // static 286 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, 287 OperandScale operand_scale) { 288 return operand_scale == OperandScale::kSingle || 289 Bytecodes::IsBytecodeWithScalableOperands(bytecode); 290 } 291 292 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { 293 return os << Bytecodes::ToString(bytecode); 294 } 295 296 } // namespace interpreter 297 } // namespace internal 298 } // namespace v8 299