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 12namespace v8 { 13namespace internal { 14namespace interpreter { 15 16// clang-format off 17const OperandType* const Bytecodes::kOperandTypes[] = { 18#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes, 19 BYTECODE_LIST(ENTRY) 20#undef ENTRY 21}; 22 23const OperandTypeInfo* const Bytecodes::kOperandTypeInfos[] = { 24#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos, 25 BYTECODE_LIST(ENTRY) 26#undef ENTRY 27}; 28 29const int Bytecodes::kOperandCount[] = { 30#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount, 31 BYTECODE_LIST(ENTRY) 32#undef ENTRY 33}; 34 35const ImplicitRegisterUse Bytecodes::kImplicitRegisterUse[] = { 36#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kImplicitRegisterUse, 37 BYTECODE_LIST(ENTRY) 38#undef ENTRY 39}; 40 41const uint8_t 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 57const 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 76const OperandSize 77Bytecodes::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// Make sure kFirstShortStar and kLastShortStar are set correctly. 98#define ASSERT_SHORT_STAR_RANGE(Name, ...) \ 99 STATIC_ASSERT(Bytecode::k##Name >= Bytecode::kFirstShortStar && \ 100 Bytecode::k##Name <= Bytecode::kLastShortStar); 101SHORT_STAR_BYTECODE_LIST(ASSERT_SHORT_STAR_RANGE) 102#undef ASSERT_SHORT_STAR_RANGE 103 104// static 105const char* Bytecodes::ToString(Bytecode bytecode) { 106 switch (bytecode) { 107#define CASE(Name, ...) \ 108 case Bytecode::k##Name: \ 109 return #Name; 110 BYTECODE_LIST(CASE) 111#undef CASE 112 } 113 UNREACHABLE(); 114} 115 116// static 117std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale, 118 const char* separator) { 119 std::string value(ToString(bytecode)); 120 if (operand_scale > OperandScale::kSingle) { 121 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); 122 std::string suffix = ToString(prefix_bytecode); 123 return value.append(separator).append(suffix); 124 } else { 125 return value; 126 } 127} 128 129// static 130Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { 131 DCHECK(!IsDebugBreak(bytecode)); 132 if (bytecode == Bytecode::kWide) { 133 return Bytecode::kDebugBreakWide; 134 } 135 if (bytecode == Bytecode::kExtraWide) { 136 return Bytecode::kDebugBreakExtraWide; 137 } 138 int bytecode_size = Size(bytecode, OperandScale::kSingle); 139#define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \ 140 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ 141 return Bytecode::k##Name; \ 142 } 143 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) 144#undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES 145 UNREACHABLE(); 146} 147 148// static 149int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, 150 OperandScale operand_scale) { 151 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); 152 // TODO(oth): restore this to a statically determined constant. 153 int offset = 1; 154 for (int operand_index = 0; operand_index < i; ++operand_index) { 155 OperandSize operand_size = 156 GetOperandSize(bytecode, operand_index, operand_scale); 157 offset += static_cast<int>(operand_size); 158 } 159 return offset; 160} 161 162// static 163Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { 164 switch (bytecode) { 165 case Bytecode::kJumpIfToBooleanTrue: 166 return Bytecode::kJumpIfTrue; 167 case Bytecode::kJumpIfToBooleanFalse: 168 return Bytecode::kJumpIfFalse; 169 case Bytecode::kJumpIfToBooleanTrueConstant: 170 return Bytecode::kJumpIfTrueConstant; 171 case Bytecode::kJumpIfToBooleanFalseConstant: 172 return Bytecode::kJumpIfFalseConstant; 173 default: 174 break; 175 } 176 UNREACHABLE(); 177} 178 179// static 180bool Bytecodes::IsDebugBreak(Bytecode bytecode) { 181 switch (bytecode) { 182#define CASE(Name, ...) case Bytecode::k##Name: 183 DEBUG_BREAK_BYTECODE_LIST(CASE); 184#undef CASE 185 return true; 186 default: 187 break; 188 } 189 return false; 190} 191 192// static 193bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { 194 switch (operand_type) { 195#define CASE(Name, _) \ 196 case OperandType::k##Name: \ 197 return true; 198 REGISTER_OPERAND_TYPE_LIST(CASE) 199#undef CASE 200#define CASE(Name, _) \ 201 case OperandType::k##Name: \ 202 break; 203 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 204#undef CASE 205 } 206 return false; 207} 208 209// static 210bool Bytecodes::IsRegisterListOperandType(OperandType operand_type) { 211 switch (operand_type) { 212 case OperandType::kRegList: 213 case OperandType::kRegOutList: 214 return true; 215 default: 216 return false; 217 } 218} 219 220bool Bytecodes::MakesCallAlongCriticalPath(Bytecode bytecode) { 221 if (IsCallOrConstruct(bytecode) || IsCallRuntime(bytecode)) return true; 222 switch (bytecode) { 223 case Bytecode::kCreateWithContext: 224 case Bytecode::kCreateBlockContext: 225 case Bytecode::kCreateCatchContext: 226 case Bytecode::kCreateRegExpLiteral: 227 case Bytecode::kGetIterator: 228 return true; 229 default: 230 return false; 231 } 232} 233 234// static 235bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { 236 switch (operand_type) { 237#define CASE(Name, _) \ 238 case OperandType::k##Name: \ 239 return true; 240 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) 241#undef CASE 242#define CASE(Name, _) \ 243 case OperandType::k##Name: \ 244 break; 245 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 246 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) 247#undef CASE 248 } 249 return false; 250} 251 252// static 253bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { 254 switch (operand_type) { 255#define CASE(Name, _) \ 256 case OperandType::k##Name: \ 257 return true; 258 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) 259#undef CASE 260#define CASE(Name, _) \ 261 case OperandType::k##Name: \ 262 break; 263 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 264 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) 265#undef CASE 266 } 267 return false; 268} 269 270// static 271bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) { 272 if (operand_scale == OperandScale::kSingle) { 273 switch (bytecode) { 274 // Short-star lookahead is required for correctness on kDebugBreak0. The 275 // handler for all short-star codes re-reads the opcode from the bytecode 276 // array and would not work correctly if it instead read kDebugBreak0. 277 case Bytecode::kDebugBreak0: 278 279 case Bytecode::kLdaZero: 280 case Bytecode::kLdaSmi: 281 case Bytecode::kLdaNull: 282 case Bytecode::kLdaTheHole: 283 case Bytecode::kLdaConstant: 284 case Bytecode::kLdaUndefined: 285 case Bytecode::kLdaGlobal: 286 case Bytecode::kGetNamedProperty: 287 case Bytecode::kGetKeyedProperty: 288 case Bytecode::kLdaContextSlot: 289 case Bytecode::kLdaImmutableContextSlot: 290 case Bytecode::kLdaCurrentContextSlot: 291 case Bytecode::kLdaImmutableCurrentContextSlot: 292 case Bytecode::kAdd: 293 case Bytecode::kSub: 294 case Bytecode::kMul: 295 case Bytecode::kAddSmi: 296 case Bytecode::kSubSmi: 297 case Bytecode::kInc: 298 case Bytecode::kDec: 299 case Bytecode::kTypeOf: 300 case Bytecode::kCallAnyReceiver: 301 case Bytecode::kCallProperty: 302 case Bytecode::kCallProperty0: 303 case Bytecode::kCallProperty1: 304 case Bytecode::kCallProperty2: 305 case Bytecode::kCallUndefinedReceiver: 306 case Bytecode::kCallUndefinedReceiver0: 307 case Bytecode::kCallUndefinedReceiver1: 308 case Bytecode::kCallUndefinedReceiver2: 309 case Bytecode::kConstruct: 310 case Bytecode::kConstructWithSpread: 311 case Bytecode::kCreateObjectLiteral: 312 case Bytecode::kCreateArrayLiteral: 313 case Bytecode::kThrowReferenceErrorIfHole: 314 case Bytecode::kGetTemplateObject: 315 return true; 316 default: 317 return false; 318 } 319 } 320 return false; 321} 322 323// static 324bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { 325 for (int i = 0; i < NumberOfOperands(bytecode); i++) { 326 if (OperandIsScalable(bytecode, i)) return true; 327 } 328 return false; 329} 330 331// static 332bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { 333 switch (operand_type) { 334#define CASE(Name, _) \ 335 case OperandType::k##Name: \ 336 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; 337 OPERAND_TYPE_LIST(CASE) 338#undef CASE 339 } 340 UNREACHABLE(); 341} 342 343// static 344bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, 345 OperandScale operand_scale) { 346 return (operand_scale == OperandScale::kSingle && 347 (!IsShortStar(bytecode) || bytecode == Bytecode::kStar0)) || 348 Bytecodes::IsBytecodeWithScalableOperands(bytecode); 349} 350 351std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { 352 return os << Bytecodes::ToString(bytecode); 353} 354 355} // namespace interpreter 356} // namespace internal 357} // namespace v8 358