Chromium Code Reviews| 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 #define OPERANDS(x) OperandInfo##x | |
|
rmcilroy
2015/07/24 18:34:48
Is this required?
| |
| 6 | |
| 5 #include "src/interpreter/bytecodes.h" | 7 #include "src/interpreter/bytecodes.h" |
| 6 | 8 |
| 7 namespace v8 { | 9 namespace v8 { |
| 8 namespace internal { | 10 namespace internal { |
| 9 namespace interpreter { | 11 namespace interpreter { |
| 10 | 12 |
| 13 static const int kMaxOperands = 3; | |
| 14 | |
| 15 template <enum Operand O> | |
| 16 struct OperandInfo { | |
| 17 static const int is_explicit; | |
|
rmcilroy
2015/07/24 18:34:48
instead of having is_explicit, could we just speci
| |
| 18 static const int size; | |
| 19 }; | |
| 20 | |
| 21 #define OPERAND_INFO(op, sz) \ | |
| 22 template <> \ | |
| 23 struct OperandInfo<Operand::k##op> { \ | |
| 24 static const int is_explicit = (sz == 0) ? 0 : 1; \ | |
| 25 static const int size = sz; \ | |
| 26 } | |
| 27 | |
| 28 OPERAND_INFO(None, 0); | |
| 29 OPERAND_INFO(Imm0, 0); | |
|
rmcilroy
2015/07/24 18:34:48
What is Imm0? Seems unrequired.
| |
| 30 OPERAND_INFO(Imm8, 1); | |
| 31 OPERAND_INFO(Smi, 4); | |
|
rmcilroy
2015/07/24 18:34:47
As mentioned offline, this can't be a 4 byte opera
| |
| 32 OPERAND_INFO(Reg, 1); | |
| 33 | |
| 34 | |
| 35 template <enum Bytecode B> | |
| 36 struct BytecodeInfo { | |
| 37 // Size of byte code and operands | |
| 38 static const int size; | |
| 39 // Number of operands | |
| 40 static const int number_of_operands; | |
| 41 // Packed operand values | |
| 42 static const int operands; | |
| 43 }; | |
| 44 | |
| 45 | |
| 46 // Packing operands into a single integer (makes indexing easier) | |
| 47 static const int kOperandShift = 4; | |
| 48 STATIC_ASSERT(static_cast<int>(Operand::kLast) < ((1 << kOperandShift) - 1)); | |
| 49 #define PACK_OPERAND(op, i) (static_cast<int>(op) << (i * kOperandShift)) | |
| 50 #define PACK_OPERANDS(op0, op1, op2) \ | |
| 51 PACK_OPERAND(op0, 0) | PACK_OPERAND(op1, 1) | PACK_OPERAND(op2, 2) | |
|
rmcilroy
2015/07/24 18:34:48
I personally don't think it's worth packing operan
| |
| 52 #define UNPACK_OPERAND(op, pos) (Operand)(op >> (pos * kOperandShift)) | |
| 53 | |
| 54 // Generator of BytecodeInfos for each bytecode. | |
| 55 #define BYTECODE_INFO(code, op0, op1, op2) \ | |
|
rmcilroy
2015/07/24 18:34:48
As much as I like pre-processor magic </sarcasm> -
| |
| 56 template <> \ | |
| 57 struct BytecodeInfo<Bytecode::code> { \ | |
| 58 static const int size = 1 + OperandInfo<op0>::size + \ | |
| 59 OperandInfo<op1>::size + OperandInfo<op2>::size; \ | |
| 60 static const int number_of_operands = OperandInfo<op0>::is_explicit + \ | |
| 61 OperandInfo<op1>::is_explicit + \ | |
| 62 OperandInfo<op2>::is_explicit; \ | |
| 63 static const int operands = PACK_OPERANDS(op0, op1, op2); \ | |
| 64 } | |
| 65 | |
| 66 // Bytecode declarations | |
| 67 BYTECODE_INFO(kLoadSmi0, Operand::kReg, Operand::kNone, Operand::kNone); | |
| 68 BYTECODE_INFO(kLoadSmi8, Operand::kReg, Operand::kImm8, Operand::kNone); | |
| 69 BYTECODE_INFO(kLoadSmi, Operand::kReg, Operand::kSmi, Operand::kNone); | |
| 70 BYTECODE_INFO(kMove, Operand::kReg, Operand::kReg, Operand::kNone); | |
| 71 BYTECODE_INFO(kAdd, Operand::kReg, Operand::kReg, Operand::kReg); | |
| 72 BYTECODE_INFO(kSub, Operand::kReg, Operand::kReg, Operand::kReg); | |
| 73 BYTECODE_INFO(kMul, Operand::kReg, Operand::kReg, Operand::kReg); | |
| 74 BYTECODE_INFO(kDiv, Operand::kReg, Operand::kReg, Operand::kReg); | |
| 75 BYTECODE_INFO(kMod, Operand::kReg, Operand::kReg, Operand::kReg); | |
| 76 BYTECODE_INFO(kReturn, Operand::kNone, Operand::kNone, Operand::kNone); | |
|
rmcilroy
2015/07/24 18:34:48
I would really like this list of declarations to b
| |
| 77 | |
| 78 | |
| 11 // static | 79 // static |
| 12 const char* Bytecodes::ToString(Bytecode bytecode) { | 80 const char* Bytecodes::ToString(Bytecode bytecode) { |
| 13 switch (bytecode) { | 81 switch (bytecode) { |
| 14 #define CASE(Name, _) \ | 82 #define CASE(Name) \ |
| 15 case Bytecode::k##Name: \ | 83 case Bytecode::k##Name: \ |
| 16 return #Name; | 84 return #Name; |
| 17 BYTECODE_LIST(CASE) | 85 BYTECODE_LIST(CASE) |
| 18 #undef CASE | 86 #undef CASE |
| 19 } | 87 } |
| 20 UNREACHABLE(); | 88 UNREACHABLE(); |
| 21 return ""; | 89 return ""; |
| 22 } | 90 } |
| 23 | 91 |
| 24 | 92 |
| 25 // static | 93 // static |
| 26 const int Bytecodes::NumberOfArguments(Bytecode bytecode) { | 94 Bytecode Bytecodes::FromByte(uint8_t value) { |
| 95 Bytecode code = static_cast<Bytecode>(value); | |
| 96 CHECK(code <= Bytecode::kLast); | |
| 97 return code; | |
| 98 } | |
| 99 | |
| 100 | |
| 101 // static | |
| 102 const int Bytecodes::NumberOfOperands(Bytecode bytecode) { | |
| 27 switch (bytecode) { | 103 switch (bytecode) { |
| 28 #define CASE(Name, arg_count) \ | 104 #define CASE(Name) \ |
| 29 case Bytecode::k##Name: \ | 105 case Bytecode::k##Name: \ |
| 30 return arg_count; | 106 return BytecodeInfo<Bytecode::k##Name>::number_of_operands; |
| 31 BYTECODE_LIST(CASE) | 107 BYTECODE_LIST(CASE) |
| 32 #undef CASE | 108 #undef CASE |
| 33 } | 109 } |
| 34 UNREACHABLE(); | 110 UNREACHABLE(); |
| 35 return 0; | 111 return 0; |
| 36 } | 112 } |
| 37 | 113 |
| 38 | 114 |
| 39 // static | 115 // static |
| 116 const Operand Bytecodes::GetOperand(Bytecode bytecode, int i) { | |
| 117 CHECK(i < kMaxOperands); | |
| 118 | |
| 119 int packed = 0; | |
| 120 switch (bytecode) { | |
| 121 #define CASE(Name) \ | |
| 122 case Bytecode::k##Name: \ | |
| 123 packed = BytecodeInfo<Bytecode::k##Name>::operands; | |
| 124 BYTECODE_LIST(CASE) | |
| 125 #undef CASE | |
| 126 } | |
| 127 return UNPACK_OPERAND(packed, i); | |
| 128 } | |
| 129 | |
| 130 | |
| 131 // static | |
| 132 const int Bytecodes::GetOperandSize(Operand operand) { | |
| 133 switch (operand) { | |
| 134 #define CASE(Name) \ | |
| 135 case Operand::k##Name: \ | |
| 136 return OperandInfo<Operand::k##Name>::size; | |
| 137 OPERAND_LIST(CASE) | |
| 138 #undef CASE | |
| 139 } | |
| 140 UNREACHABLE(); | |
| 141 return 0; | |
| 142 } | |
| 143 | |
| 144 | |
| 145 // static | |
| 40 const int Bytecodes::Size(Bytecode bytecode) { | 146 const int Bytecodes::Size(Bytecode bytecode) { |
| 41 return NumberOfArguments(bytecode) + 1; | 147 switch (bytecode) { |
| 148 #define CASE(Name) \ | |
| 149 case Bytecode::k##Name: \ | |
| 150 return BytecodeInfo<Bytecode::k##Name>::size; | |
| 151 BYTECODE_LIST(CASE) | |
| 152 #undef CASE | |
| 153 } | |
| 154 UNREACHABLE(); | |
| 155 return 0; | |
| 42 } | 156 } |
| 43 | 157 |
| 44 | 158 |
| 45 #define CHECK_SIZE(Name, arg_count) \ | 159 // static |
| 46 STATIC_ASSERT(arg_count <= Bytecodes::kMaximumNumberOfArguments); | 160 const int Bytecodes::MaximumNumberOfOperands() { |
| 47 BYTECODE_LIST(CHECK_SIZE) | 161 // TODO(oth): STATIC_ASSERT on number of operands. |
| 48 #undef CHECK_SIZE | 162 return kMaxOperands; |
| 163 } | |
| 164 | |
| 165 | |
| 166 // static | |
| 167 const int Bytecodes::MaximumSize() { | |
| 168 // TODO(oth): Maximum size of bytecode and associated operands | |
| 169 STATIC_ASSERT(BytecodeInfo<Bytecode::kLoadSmi>::size == 6); | |
| 170 return 6; | |
| 171 } | |
| 49 | 172 |
| 50 | 173 |
| 51 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { | 174 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
| 52 return os << Bytecodes::ToString(bytecode); | 175 return os << Bytecodes::ToString(bytecode); |
| 53 } | 176 } |
| 54 | 177 |
| 55 } // namespace interpreter | 178 } // namespace interpreter |
| 56 } // namespace internal | 179 } // namespace internal |
| 57 } // namespace v8 | 180 } // namespace v8 |
| OLD | NEW |