Home | History | Annotate | Download | only in interpreter
      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 "src/frames.h"
      8 #include "src/interpreter/bytecode-traits.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 namespace interpreter {
     13 
     14 
     15 // static
     16 const char* Bytecodes::ToString(Bytecode bytecode) {
     17   switch (bytecode) {
     18 #define CASE(Name, ...)   \
     19   case Bytecode::k##Name: \
     20     return #Name;
     21     BYTECODE_LIST(CASE)
     22 #undef CASE
     23   }
     24   UNREACHABLE();
     25   return "";
     26 }
     27 
     28 
     29 // static
     30 const char* Bytecodes::OperandTypeToString(OperandType operand_type) {
     31   switch (operand_type) {
     32 #define CASE(Name, _)        \
     33   case OperandType::k##Name: \
     34     return #Name;
     35     OPERAND_TYPE_LIST(CASE)
     36 #undef CASE
     37   }
     38   UNREACHABLE();
     39   return "";
     40 }
     41 
     42 
     43 // static
     44 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) {
     45   switch (operand_size) {
     46     case OperandSize::kNone:
     47       return "None";
     48     case OperandSize::kByte:
     49       return "Byte";
     50     case OperandSize::kShort:
     51       return "Short";
     52   }
     53   UNREACHABLE();
     54   return "";
     55 }
     56 
     57 
     58 // static
     59 uint8_t Bytecodes::ToByte(Bytecode bytecode) {
     60   return static_cast<uint8_t>(bytecode);
     61 }
     62 
     63 
     64 // static
     65 Bytecode Bytecodes::FromByte(uint8_t value) {
     66   Bytecode bytecode = static_cast<Bytecode>(value);
     67   DCHECK(bytecode <= Bytecode::kLast);
     68   return bytecode;
     69 }
     70 
     71 
     72 // static
     73 int Bytecodes::Size(Bytecode bytecode) {
     74   DCHECK(bytecode <= Bytecode::kLast);
     75   switch (bytecode) {
     76 #define CASE(Name, ...)   \
     77   case Bytecode::k##Name: \
     78     return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize;
     79     BYTECODE_LIST(CASE)
     80 #undef CASE
     81   }
     82   UNREACHABLE();
     83   return 0;
     84 }
     85 
     86 
     87 // static
     88 int Bytecodes::NumberOfOperands(Bytecode bytecode) {
     89   DCHECK(bytecode <= Bytecode::kLast);
     90   switch (bytecode) {
     91 #define CASE(Name, ...)   \
     92   case Bytecode::k##Name: \
     93     return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount;
     94     BYTECODE_LIST(CASE)
     95 #undef CASE
     96   }
     97   UNREACHABLE();
     98   return 0;
     99 }
    100 
    101 
    102 // static
    103 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) {
    104   DCHECK(bytecode <= Bytecode::kLast);
    105   switch (bytecode) {
    106 #define CASE(Name, ...)   \
    107   case Bytecode::k##Name: \
    108     return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandType(i);
    109     BYTECODE_LIST(CASE)
    110 #undef CASE
    111   }
    112   UNREACHABLE();
    113   return OperandType::kNone;
    114 }
    115 
    116 
    117 // static
    118 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i) {
    119   DCHECK(bytecode <= Bytecode::kLast);
    120   switch (bytecode) {
    121 #define CASE(Name, ...)   \
    122   case Bytecode::k##Name: \
    123     return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandSize(i);
    124     BYTECODE_LIST(CASE)
    125 #undef CASE
    126   }
    127   UNREACHABLE();
    128   return OperandSize::kNone;
    129 }
    130 
    131 
    132 // static
    133 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i) {
    134   DCHECK(bytecode <= Bytecode::kLast);
    135   switch (bytecode) {
    136 #define CASE(Name, ...)   \
    137   case Bytecode::k##Name: \
    138     return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandOffset(i);
    139     BYTECODE_LIST(CASE)
    140 #undef CASE
    141   }
    142   UNREACHABLE();
    143   return 0;
    144 }
    145 
    146 
    147 // static
    148 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type) {
    149   switch (operand_type) {
    150 #define CASE(Name, Size)     \
    151   case OperandType::k##Name: \
    152     return Size;
    153     OPERAND_TYPE_LIST(CASE)
    154 #undef CASE
    155   }
    156   UNREACHABLE();
    157   return OperandSize::kNone;
    158 }
    159 
    160 
    161 // static
    162 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) {
    163   return bytecode == Bytecode::kJumpIfTrue ||
    164          bytecode == Bytecode::kJumpIfFalse ||
    165          bytecode == Bytecode::kJumpIfToBooleanTrue ||
    166          bytecode == Bytecode::kJumpIfToBooleanFalse ||
    167          bytecode == Bytecode::kJumpIfNull ||
    168          bytecode == Bytecode::kJumpIfUndefined;
    169 }
    170 
    171 
    172 // static
    173 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) {
    174   return bytecode == Bytecode::kJumpIfTrueConstant ||
    175          bytecode == Bytecode::kJumpIfFalseConstant ||
    176          bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
    177          bytecode == Bytecode::kJumpIfToBooleanFalseConstant ||
    178          bytecode == Bytecode::kJumpIfNullConstant ||
    179          bytecode == Bytecode::kJumpIfUndefinedConstant;
    180 }
    181 
    182 
    183 // static
    184 bool Bytecodes::IsConditionalJumpConstantWide(Bytecode bytecode) {
    185   return bytecode == Bytecode::kJumpIfTrueConstantWide ||
    186          bytecode == Bytecode::kJumpIfFalseConstantWide ||
    187          bytecode == Bytecode::kJumpIfToBooleanTrueConstantWide ||
    188          bytecode == Bytecode::kJumpIfToBooleanFalseConstantWide ||
    189          bytecode == Bytecode::kJumpIfNullConstantWide ||
    190          bytecode == Bytecode::kJumpIfUndefinedConstantWide;
    191 }
    192 
    193 
    194 // static
    195 bool Bytecodes::IsConditionalJump(Bytecode bytecode) {
    196   return IsConditionalJumpImmediate(bytecode) ||
    197          IsConditionalJumpConstant(bytecode) ||
    198          IsConditionalJumpConstantWide(bytecode);
    199 }
    200 
    201 
    202 // static
    203 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) {
    204   return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode);
    205 }
    206 
    207 
    208 // static
    209 bool Bytecodes::IsJumpConstant(Bytecode bytecode) {
    210   return bytecode == Bytecode::kJumpConstant ||
    211          IsConditionalJumpConstant(bytecode);
    212 }
    213 
    214 
    215 // static
    216 bool Bytecodes::IsJumpConstantWide(Bytecode bytecode) {
    217   return bytecode == Bytecode::kJumpConstantWide ||
    218          IsConditionalJumpConstantWide(bytecode);
    219 }
    220 
    221 
    222 // static
    223 bool Bytecodes::IsJump(Bytecode bytecode) {
    224   return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode) ||
    225          IsJumpConstantWide(bytecode);
    226 }
    227 
    228 
    229 // static
    230 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) {
    231   return bytecode == Bytecode::kReturn || IsJump(bytecode);
    232 }
    233 
    234 
    235 // static
    236 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
    237                                 int parameter_count) {
    238   Vector<char> buf = Vector<char>::New(50);
    239 
    240   Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
    241   int bytecode_size = Bytecodes::Size(bytecode);
    242 
    243   for (int i = 0; i < bytecode_size; i++) {
    244     SNPrintF(buf, "%02x ", bytecode_start[i]);
    245     os << buf.start();
    246   }
    247   const int kBytecodeColumnSize = 6;
    248   for (int i = bytecode_size; i < kBytecodeColumnSize; i++) {
    249     os << "   ";
    250   }
    251 
    252   os << bytecode << " ";
    253 
    254   int number_of_operands = NumberOfOperands(bytecode);
    255   for (int i = 0; i < number_of_operands; i++) {
    256     OperandType op_type = GetOperandType(bytecode, i);
    257     const uint8_t* operand_start =
    258         &bytecode_start[GetOperandOffset(bytecode, i)];
    259     switch (op_type) {
    260       case interpreter::OperandType::kCount8:
    261         os << "#" << static_cast<unsigned int>(*operand_start);
    262         break;
    263       case interpreter::OperandType::kCount16:
    264         os << '#' << ReadUnalignedUInt16(operand_start);
    265         break;
    266       case interpreter::OperandType::kIdx8:
    267         os << "[" << static_cast<unsigned int>(*operand_start) << "]";
    268         break;
    269       case interpreter::OperandType::kIdx16:
    270         os << "[" << ReadUnalignedUInt16(operand_start) << "]";
    271         break;
    272       case interpreter::OperandType::kImm8:
    273         os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start));
    274         break;
    275       case interpreter::OperandType::kReg8:
    276       case interpreter::OperandType::kMaybeReg8: {
    277         Register reg = Register::FromOperand(*operand_start);
    278         if (reg.is_function_context()) {
    279           os << "<context>";
    280         } else if (reg.is_function_closure()) {
    281           os << "<closure>";
    282         } else if (reg.is_new_target()) {
    283           os << "<new.target>";
    284         } else if (reg.is_parameter()) {
    285           int parameter_index = reg.ToParameterIndex(parameter_count);
    286           if (parameter_index == 0) {
    287             os << "<this>";
    288           } else {
    289             os << "a" << parameter_index - 1;
    290           }
    291         } else {
    292           os << "r" << reg.index();
    293         }
    294         break;
    295       }
    296       case interpreter::OperandType::kRegPair8: {
    297         Register reg = Register::FromOperand(*operand_start);
    298         if (reg.is_parameter()) {
    299           int parameter_index = reg.ToParameterIndex(parameter_count);
    300           DCHECK_NE(parameter_index, 0);
    301           os << "a" << parameter_index - 1 << "-" << parameter_index;
    302         } else {
    303           os << "r" << reg.index() << "-" << reg.index() + 1;
    304         }
    305         break;
    306       }
    307       case interpreter::OperandType::kReg16: {
    308         Register reg =
    309             Register::FromWideOperand(ReadUnalignedUInt16(operand_start));
    310         if (reg.is_parameter()) {
    311           int parameter_index = reg.ToParameterIndex(parameter_count);
    312           DCHECK_NE(parameter_index, 0);
    313           os << "a" << parameter_index - 1;
    314         } else {
    315           os << "r" << reg.index();
    316         }
    317         break;
    318       }
    319       case interpreter::OperandType::kNone:
    320         UNREACHABLE();
    321         break;
    322     }
    323     if (i != number_of_operands - 1) {
    324       os << ", ";
    325     }
    326   }
    327   return os;
    328 }
    329 
    330 
    331 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
    332   return os << Bytecodes::ToString(bytecode);
    333 }
    334 
    335 
    336 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) {
    337   return os << Bytecodes::OperandTypeToString(operand_type);
    338 }
    339 
    340 
    341 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) {
    342   return os << Bytecodes::OperandSizeToString(operand_size);
    343 }
    344 
    345 
    346 static const int kLastParamRegisterIndex =
    347     -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize;
    348 static const int kFunctionClosureRegisterIndex =
    349     -InterpreterFrameConstants::kFunctionFromRegisterPointer / kPointerSize;
    350 static const int kFunctionContextRegisterIndex =
    351     -InterpreterFrameConstants::kContextFromRegisterPointer / kPointerSize;
    352 static const int kNewTargetRegisterIndex =
    353     -InterpreterFrameConstants::kNewTargetFromRegisterPointer / kPointerSize;
    354 
    355 
    356 // Registers occupy range 0-127 in 8-bit value leaving 128 unused values.
    357 // Parameter indices are biased with the negative value kLastParamRegisterIndex
    358 // for ease of access in the interpreter.
    359 static const int kMaxParameterIndex = 128 + kLastParamRegisterIndex;
    360 
    361 
    362 Register Register::FromParameterIndex(int index, int parameter_count) {
    363   DCHECK_GE(index, 0);
    364   DCHECK_LT(index, parameter_count);
    365   DCHECK_LE(parameter_count, kMaxParameterIndex + 1);
    366   int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
    367   DCHECK_LT(register_index, 0);
    368   DCHECK_GE(register_index, kMinInt8);
    369   return Register(register_index);
    370 }
    371 
    372 
    373 int Register::ToParameterIndex(int parameter_count) const {
    374   DCHECK(is_parameter());
    375   return index() - kLastParamRegisterIndex + parameter_count - 1;
    376 }
    377 
    378 
    379 Register Register::function_closure() {
    380   return Register(kFunctionClosureRegisterIndex);
    381 }
    382 
    383 
    384 bool Register::is_function_closure() const {
    385   return index() == kFunctionClosureRegisterIndex;
    386 }
    387 
    388 
    389 Register Register::function_context() {
    390   return Register(kFunctionContextRegisterIndex);
    391 }
    392 
    393 
    394 bool Register::is_function_context() const {
    395   return index() == kFunctionContextRegisterIndex;
    396 }
    397 
    398 
    399 Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
    400 
    401 
    402 bool Register::is_new_target() const {
    403   return index() == kNewTargetRegisterIndex;
    404 }
    405 
    406 
    407 int Register::MaxParameterIndex() { return kMaxParameterIndex; }
    408 
    409 
    410 uint8_t Register::ToOperand() const {
    411   DCHECK_GE(index_, kMinInt8);
    412   DCHECK_LE(index_, kMaxInt8);
    413   return static_cast<uint8_t>(-index_);
    414 }
    415 
    416 
    417 Register Register::FromOperand(uint8_t operand) {
    418   return Register(-static_cast<int8_t>(operand));
    419 }
    420 
    421 
    422 uint16_t Register::ToWideOperand() const {
    423   DCHECK_GE(index_, kMinInt16);
    424   DCHECK_LE(index_, kMaxInt16);
    425   return static_cast<uint16_t>(-index_);
    426 }
    427 
    428 
    429 Register Register::FromWideOperand(uint16_t operand) {
    430   return Register(-static_cast<int16_t>(operand));
    431 }
    432 
    433 
    434 bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
    435                              Register reg4, Register reg5) {
    436   if (reg1.index() + 1 != reg2.index()) {
    437     return false;
    438   }
    439   if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) {
    440     return false;
    441   }
    442   if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) {
    443     return false;
    444   }
    445   if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) {
    446     return false;
    447   }
    448   return true;
    449 }
    450 
    451 }  // namespace interpreter
    452 }  // namespace internal
    453 }  // namespace v8
    454