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 #include "src/interpreter/bytecodes.h" | 5 #include "src/interpreter/bytecodes.h" |
| 6 | 6 |
| 7 #include "src/frames.h" | 7 #include "src/frames.h" |
| 8 #include "src/interpreter/bytecode-traits.h" | 8 #include "src/interpreter/bytecode-traits.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 #undef CASE | 22 #undef CASE |
| 23 } | 23 } |
| 24 UNREACHABLE(); | 24 UNREACHABLE(); |
| 25 return ""; | 25 return ""; |
| 26 } | 26 } |
| 27 | 27 |
| 28 | 28 |
| 29 // static | 29 // static |
| 30 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { | 30 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { |
| 31 switch (operand_type) { | 31 switch (operand_type) { |
| 32 #define CASE(Name, _) \ | 32 #define CASE(Name, _, __) \ |
| 33 case OperandType::k##Name: \ | 33 case OperandType::k##Name: \ |
| 34 return #Name; | 34 return #Name; |
| 35 OPERAND_TYPE_LIST(CASE) | 35 OPERAND_TYPE_LIST(CASE) |
| 36 #undef CASE | 36 #undef CASE |
| 37 } | 37 } |
| 38 UNREACHABLE(); | 38 UNREACHABLE(); |
| 39 return ""; | 39 return ""; |
| 40 } | 40 } |
| 41 | 41 |
| 42 | 42 |
| 43 // static | 43 // static |
| 44 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { | 44 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { |
| 45 switch (operand_size) { | 45 switch (operand_size) { |
| 46 case OperandSize::kNone: | 46 case OperandSize::kNone: |
| 47 return "None"; | 47 return "None"; |
| 48 case OperandSize::kByte: | 48 case OperandSize::kByte: |
| 49 return "Byte"; | 49 return "Byte"; |
| 50 case OperandSize::kShort: | 50 case OperandSize::kShort: |
| 51 return "Short"; | 51 return "Short"; |
| 52 case OperandSize::kQuad: | |
| 53 return "Quad"; | |
| 52 } | 54 } |
| 53 UNREACHABLE(); | 55 UNREACHABLE(); |
| 54 return ""; | 56 return ""; |
| 55 } | 57 } |
| 56 | 58 |
| 57 | 59 |
| 58 // static | 60 // static |
| 59 uint8_t Bytecodes::ToByte(Bytecode bytecode) { | 61 uint8_t Bytecodes::ToByte(Bytecode bytecode) { |
| 60 DCHECK(bytecode <= Bytecode::kLast); | 62 DCHECK(bytecode <= Bytecode::kLast); |
| 61 return static_cast<uint8_t>(bytecode); | 63 return static_cast<uint8_t>(bytecode); |
| 62 } | 64 } |
| 63 | 65 |
| 64 | 66 |
| 65 // static | 67 // static |
| 66 Bytecode Bytecodes::FromByte(uint8_t value) { | 68 Bytecode Bytecodes::FromByte(uint8_t value) { |
| 67 Bytecode bytecode = static_cast<Bytecode>(value); | 69 Bytecode bytecode = static_cast<Bytecode>(value); |
| 68 DCHECK(bytecode <= Bytecode::kLast); | 70 DCHECK(bytecode <= Bytecode::kLast); |
| 69 return bytecode; | 71 return bytecode; |
| 70 } | 72 } |
| 71 | 73 |
| 72 | 74 |
| 73 // static | 75 // static |
| 74 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { | 76 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode, int operand_scale) { |
| 75 switch (Size(bytecode)) { | 77 int bytecode_size = Size(bytecode, operand_scale); |
| 76 #define CASE(Name, ...) \ | 78 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \ |
| 77 case BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize: \ | 79 if (bytecode_size == Size(Bytecode::k##Name, operand_scale)) { \ |
| 78 return Bytecode::k##Name; | 80 return Bytecode::k##Name; \ |
| 79 DEBUG_BREAK_BYTECODE_LIST(CASE) | |
| 80 #undef CASE | |
| 81 default: | |
| 82 break; | |
| 83 } | 81 } |
| 82 DEBUG_BREAK_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) | |
| 83 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES | |
| 84 UNREACHABLE(); | 84 UNREACHABLE(); |
| 85 return static_cast<Bytecode>(-1); | 85 return static_cast<Bytecode>(-1); |
| 86 } | 86 } |
| 87 | 87 |
| 88 // static | 88 // static |
| 89 int Bytecodes::Size(Bytecode bytecode) { | 89 int Bytecodes::Size(Bytecode bytecode, int operand_scale) { |
| 90 DCHECK(bytecode <= Bytecode::kLast); | 90 int size = 1; |
| 91 switch (bytecode) { | 91 for (int i = 0; i < NumberOfOperands(bytecode); i++) { |
| 92 #define CASE(Name, ...) \ | 92 OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale); |
| 93 case Bytecode::k##Name: \ | 93 int delta = static_cast<int>(operand_size); |
| 94 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize; | 94 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta))); |
| 95 BYTECODE_LIST(CASE) | 95 size += delta; |
| 96 #undef CASE | |
| 97 } | 96 } |
| 98 UNREACHABLE(); | 97 return size; |
| 99 return 0; | |
| 100 } | 98 } |
| 101 | 99 |
| 102 | 100 |
| 103 // static | 101 // static |
| 104 int Bytecodes::NumberOfOperands(Bytecode bytecode) { | 102 int Bytecodes::NumberOfOperands(Bytecode bytecode) { |
| 105 DCHECK(bytecode <= Bytecode::kLast); | 103 DCHECK(bytecode <= Bytecode::kLast); |
| 106 switch (bytecode) { | 104 switch (bytecode) { |
| 107 #define CASE(Name, ...) \ | 105 #define CASE(Name, ...) \ |
| 108 case Bytecode::k##Name: \ | 106 case Bytecode::k##Name: \ |
| 109 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount; | 107 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 124 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ | 122 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ |
| 125 return Name##Trait::kRegisterOperandCount; | 123 return Name##Trait::kRegisterOperandCount; |
| 126 BYTECODE_LIST(CASE) | 124 BYTECODE_LIST(CASE) |
| 127 #undef CASE | 125 #undef CASE |
| 128 } | 126 } |
| 129 UNREACHABLE(); | 127 UNREACHABLE(); |
| 130 return false; | 128 return false; |
| 131 } | 129 } |
| 132 | 130 |
| 133 // static | 131 // static |
| 132 int Bytecodes::GetPrefixBytecodeScale(Bytecode bytecode) { | |
| 133 switch (bytecode) { | |
|
rmcilroy
2016/03/10 16:45:37
Could we make this DCHECK if it is passed a non-pr
oth
2016/03/11 16:26:12
Not really, this is one of the main ways of determ
oth
2016/03/17 13:48:38
Done.
| |
| 134 case Bytecode::kExtraWide: | |
| 135 return 4; | |
| 136 case Bytecode::kWide: | |
| 137 return 2; | |
| 138 default: | |
| 139 return 1; | |
| 140 } | |
| 141 } | |
| 142 | |
| 143 // static | |
| 134 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { | 144 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
| 135 DCHECK(bytecode <= Bytecode::kLast); | 145 DCHECK(bytecode <= Bytecode::kLast); |
| 136 switch (bytecode) { | 146 switch (bytecode) { |
| 137 #define CASE(Name, ...) \ | 147 #define CASE(Name, ...) \ |
| 138 case Bytecode::k##Name: \ | 148 case Bytecode::k##Name: \ |
| 139 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandType(i); | 149 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandType(i); |
| 140 BYTECODE_LIST(CASE) | 150 BYTECODE_LIST(CASE) |
| 141 #undef CASE | 151 #undef CASE |
| 142 } | 152 } |
| 143 UNREACHABLE(); | 153 UNREACHABLE(); |
| 144 return OperandType::kNone; | 154 return OperandType::kNone; |
| 145 } | 155 } |
| 146 | 156 |
| 157 // TODO(oth): TEMPORARY | |
| 158 namespace { | |
| 159 | |
| 160 template <OperandTypeTrait O> | |
| 161 struct OperandScaler { | |
| 162 static int Multiply(int size, int scale) { return 0; } | |
| 163 }; | |
| 164 | |
| 165 template <> | |
| 166 struct OperandScaler<OperandTypeTrait::kFixed> { | |
| 167 static int Multiply(int size, int scale) { return size; } | |
| 168 }; | |
| 169 | |
| 170 template <> | |
| 171 struct OperandScaler<OperandTypeTrait::kScalable> { | |
| 172 static int Multiply(int size, int scale) { return size * scale; } | |
| 173 }; | |
| 174 | |
| 175 } // namespace | |
| 176 | |
| 177 // TODO(oth): TEMPORARY | |
| 178 static int ScaledOperandSize(OperandType operand_type, int scale) { | |
| 179 switch (operand_type) { | |
| 180 #define CASE(Name, Size, Trait) \ | |
| 181 case OperandType::k##Name: \ | |
| 182 return OperandScaler<Trait>::Multiply(static_cast<int>(Size), scale); | |
| 183 OPERAND_TYPE_LIST(CASE) | |
| 184 #undef CASE | |
| 185 } | |
| 186 UNREACHABLE(); | |
| 187 return 0; | |
| 188 } | |
| 189 | |
| 147 | 190 |
| 148 // static | 191 // static |
| 149 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i) { | 192 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, int scale) { |
| 150 DCHECK(bytecode <= Bytecode::kLast); | 193 OperandType op_type = GetOperandType(bytecode, i); |
| 151 switch (bytecode) { | 194 return static_cast<OperandSize>(ScaledOperandSize(op_type, scale)); |
| 152 #define CASE(Name, ...) \ | |
| 153 case Bytecode::k##Name: \ | |
| 154 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandSize(i); | |
| 155 BYTECODE_LIST(CASE) | |
| 156 #undef CASE | |
| 157 } | |
| 158 UNREACHABLE(); | |
| 159 return OperandSize::kNone; | |
| 160 } | 195 } |
| 161 | 196 |
| 162 | |
| 163 // static | 197 // static |
| 164 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { | 198 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { |
| 165 DCHECK(bytecode <= Bytecode::kLast); | 199 DCHECK(bytecode <= Bytecode::kLast); |
| 166 switch (bytecode) { | 200 switch (bytecode) { |
| 167 #define CASE(Name, ...) \ | 201 #define CASE(Name, ...) \ |
| 168 case Bytecode::k##Name: \ | 202 case Bytecode::k##Name: \ |
| 169 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ | 203 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ |
| 170 return Name##Trait::kRegisterOperandBitmap; | 204 return Name##Trait::kRegisterOperandBitmap; |
| 171 BYTECODE_LIST(CASE) | 205 BYTECODE_LIST(CASE) |
| 172 #undef CASE | 206 #undef CASE |
| 173 } | 207 } |
| 174 UNREACHABLE(); | 208 UNREACHABLE(); |
| 175 return false; | 209 return false; |
| 176 } | 210 } |
| 177 | 211 |
| 178 // static | 212 // static |
| 179 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i) { | 213 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, int scale) { |
| 180 DCHECK(bytecode <= Bytecode::kLast); | 214 int offset = 1; |
| 181 switch (bytecode) { | 215 for (int operand_index = 0; operand_index < i; ++operand_index) { |
| 182 #define CASE(Name, ...) \ | 216 OperandSize operand_size = GetOperandSize(bytecode, operand_index, scale); |
| 183 case Bytecode::k##Name: \ | 217 offset += static_cast<int>(operand_size); |
| 184 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandOffset(i); | |
| 185 BYTECODE_LIST(CASE) | |
| 186 #undef CASE | |
| 187 } | 218 } |
| 188 UNREACHABLE(); | 219 return offset; |
| 189 return 0; | 220 } |
| 221 | |
| 222 // static | |
| 223 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, int scale) { | |
| 224 return static_cast<OperandSize>(ScaledOperandSize(operand_type, scale)); | |
| 190 } | 225 } |
| 191 | 226 |
| 192 | 227 |
| 193 // static | |
| 194 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type) { | |
| 195 switch (operand_type) { | |
| 196 #define CASE(Name, Size) \ | |
| 197 case OperandType::k##Name: \ | |
| 198 return Size; | |
| 199 OPERAND_TYPE_LIST(CASE) | |
| 200 #undef CASE | |
| 201 } | |
| 202 UNREACHABLE(); | |
| 203 return OperandSize::kNone; | |
| 204 } | |
| 205 | |
| 206 | |
| 207 // static | 228 // static |
| 208 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { | 229 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { |
| 209 return bytecode == Bytecode::kJumpIfTrue || | 230 return bytecode == Bytecode::kJumpIfTrue || |
| 210 bytecode == Bytecode::kJumpIfFalse || | 231 bytecode == Bytecode::kJumpIfFalse || |
| 211 bytecode == Bytecode::kJumpIfToBooleanTrue || | 232 bytecode == Bytecode::kJumpIfToBooleanTrue || |
| 212 bytecode == Bytecode::kJumpIfToBooleanFalse || | 233 bytecode == Bytecode::kJumpIfToBooleanFalse || |
| 213 bytecode == Bytecode::kJumpIfNotHole || | 234 bytecode == Bytecode::kJumpIfNotHole || |
| 214 bytecode == Bytecode::kJumpIfNull || | 235 bytecode == Bytecode::kJumpIfNull || |
| 215 bytecode == Bytecode::kJumpIfUndefined; | 236 bytecode == Bytecode::kJumpIfUndefined; |
| 216 } | 237 } |
| 217 | 238 |
| 218 | 239 |
| 219 // static | 240 // static |
| 220 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { | 241 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { |
| 221 return bytecode == Bytecode::kJumpIfTrueConstant || | 242 return bytecode == Bytecode::kJumpIfTrueConstant || |
| 222 bytecode == Bytecode::kJumpIfFalseConstant || | 243 bytecode == Bytecode::kJumpIfFalseConstant || |
| 223 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || | 244 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
| 224 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || | 245 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || |
| 225 bytecode == Bytecode::kJumpIfNotHoleConstant || | 246 bytecode == Bytecode::kJumpIfNotHoleConstant || |
| 226 bytecode == Bytecode::kJumpIfNullConstant || | 247 bytecode == Bytecode::kJumpIfNullConstant || |
| 227 bytecode == Bytecode::kJumpIfUndefinedConstant; | 248 bytecode == Bytecode::kJumpIfUndefinedConstant; |
| 228 } | 249 } |
| 229 | 250 |
| 230 | |
| 231 // static | |
| 232 bool Bytecodes::IsConditionalJumpConstantWide(Bytecode bytecode) { | |
| 233 return bytecode == Bytecode::kJumpIfTrueConstantWide || | |
| 234 bytecode == Bytecode::kJumpIfFalseConstantWide || | |
| 235 bytecode == Bytecode::kJumpIfToBooleanTrueConstantWide || | |
| 236 bytecode == Bytecode::kJumpIfToBooleanFalseConstantWide || | |
| 237 bytecode == Bytecode::kJumpIfNotHoleConstantWide || | |
| 238 bytecode == Bytecode::kJumpIfNullConstantWide || | |
| 239 bytecode == Bytecode::kJumpIfUndefinedConstantWide; | |
| 240 } | |
| 241 | |
| 242 | |
| 243 // static | 251 // static |
| 244 bool Bytecodes::IsConditionalJump(Bytecode bytecode) { | 252 bool Bytecodes::IsConditionalJump(Bytecode bytecode) { |
| 245 return IsConditionalJumpImmediate(bytecode) || | 253 return IsConditionalJumpImmediate(bytecode) || |
| 246 IsConditionalJumpConstant(bytecode) || | 254 IsConditionalJumpConstant(bytecode); |
| 247 IsConditionalJumpConstantWide(bytecode); | |
| 248 } | 255 } |
| 249 | 256 |
| 250 | 257 |
| 251 // static | 258 // static |
| 252 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) { | 259 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) { |
| 253 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode); | 260 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode); |
| 254 } | 261 } |
| 255 | 262 |
| 256 | 263 |
| 257 // static | 264 // static |
| 258 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { | 265 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { |
| 259 return bytecode == Bytecode::kJumpConstant || | 266 return bytecode == Bytecode::kJumpConstant || |
| 260 IsConditionalJumpConstant(bytecode); | 267 IsConditionalJumpConstant(bytecode); |
| 261 } | 268 } |
| 262 | 269 |
| 263 | |
| 264 // static | |
| 265 bool Bytecodes::IsJumpConstantWide(Bytecode bytecode) { | |
| 266 return bytecode == Bytecode::kJumpConstantWide || | |
| 267 IsConditionalJumpConstantWide(bytecode); | |
| 268 } | |
| 269 | |
| 270 | |
| 271 // static | 270 // static |
| 272 bool Bytecodes::IsJump(Bytecode bytecode) { | 271 bool Bytecodes::IsJump(Bytecode bytecode) { |
| 273 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode) || | 272 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); |
| 274 IsJumpConstantWide(bytecode); | |
| 275 } | 273 } |
| 276 | 274 |
| 277 | 275 |
| 278 // static | 276 // static |
| 279 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { | 277 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { |
| 280 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || | 278 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || |
| 281 bytecode == Bytecode::kNew || bytecode == Bytecode::kCallWide || | 279 bytecode == Bytecode::kNew; |
| 282 bytecode == Bytecode::kTailCallWide || bytecode == Bytecode::kNewWide; | |
| 283 } | 280 } |
| 284 | 281 |
| 285 // static | 282 // static |
| 286 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { | 283 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { |
| 287 return bytecode == Bytecode::kCallRuntime || | 284 return bytecode == Bytecode::kCallRuntime || |
| 288 bytecode == Bytecode::kCallRuntimeWide || | 285 bytecode == Bytecode::kCallRuntimeForPair; |
| 289 bytecode == Bytecode::kCallRuntimeForPair || | |
| 290 bytecode == Bytecode::kCallRuntimeForPairWide; | |
| 291 } | 286 } |
| 292 | 287 |
| 293 // static | 288 // static |
| 294 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { | 289 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { |
| 295 switch (bytecode) { | 290 switch (bytecode) { |
| 296 #define CASE(Name, ...) case Bytecode::k##Name: | 291 #define CASE(Name, ...) case Bytecode::k##Name: |
| 297 DEBUG_BREAK_BYTECODE_LIST(CASE); | 292 DEBUG_BREAK_BYTECODE_LIST(CASE); |
| 298 #undef CASE | 293 #undef CASE |
| 299 return true; | 294 return true; |
| 300 default: | 295 default: |
| 301 break; | 296 break; |
| 302 } | 297 } |
| 303 return false; | 298 return false; |
| 304 } | 299 } |
| 305 | 300 |
| 306 // static | 301 // static |
| 302 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { | |
| 303 switch (bytecode) { | |
| 304 #define CASE(Name, ...) \ | |
| 305 case Bytecode::k##Name: \ | |
| 306 typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ | |
| 307 return Name##Trait::IsScalable(); | |
| 308 BYTECODE_LIST(CASE) | |
| 309 #undef CASE | |
| 310 } | |
| 311 UNREACHABLE(); | |
| 312 return false; | |
| 313 } | |
| 314 | |
| 315 // static | |
| 307 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { | 316 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { |
| 308 return bytecode == Bytecode::kReturn || IsJump(bytecode); | 317 return bytecode == Bytecode::kReturn || IsJump(bytecode); |
| 309 } | 318 } |
| 310 | 319 |
| 311 // static | 320 // static |
| 321 bool Bytecodes::IsFlagOperandType(OperandType operand_type) { | |
| 322 return operand_type == OperandType::kFlag8; | |
| 323 } | |
| 324 | |
| 325 // static | |
| 312 bool Bytecodes::IsIndexOperandType(OperandType operand_type) { | 326 bool Bytecodes::IsIndexOperandType(OperandType operand_type) { |
| 313 return operand_type == OperandType::kIdx8 || | 327 return operand_type == OperandType::kIdx; |
| 314 operand_type == OperandType::kIdx16; | |
| 315 } | 328 } |
| 316 | 329 |
| 317 // static | 330 // static |
| 318 bool Bytecodes::IsImmediateOperandType(OperandType operand_type) { | 331 bool Bytecodes::IsImmediateOperandType(OperandType operand_type) { |
| 319 return operand_type == OperandType::kImm8; | 332 return operand_type == OperandType::kImm; |
| 320 } | 333 } |
| 321 | 334 |
| 322 // static | 335 // static |
| 323 bool Bytecodes::IsRegisterCountOperandType(OperandType operand_type) { | 336 bool Bytecodes::IsRegisterCountOperandType(OperandType operand_type) { |
| 324 return (operand_type == OperandType::kRegCount8 || | 337 return operand_type == OperandType::kRegCount; |
| 325 operand_type == OperandType::kRegCount16); | |
| 326 } | 338 } |
| 327 | 339 |
| 328 // static | 340 // static |
| 329 bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) { | 341 bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) { |
| 330 return (operand_type == OperandType::kMaybeReg8 || | 342 return operand_type == OperandType::kMaybeReg; |
| 331 operand_type == OperandType::kMaybeReg16); | 343 } |
| 344 | |
| 345 // static | |
| 346 bool Bytecodes::IsRuntimeIdOperandType(OperandType operand_type) { | |
|
rmcilroy
2016/03/10 16:45:37
Wondering whether these IsXXXOperandType are neces
oth
2016/03/11 16:26:12
Done. Removed all except the still useful IsRegist
| |
| 347 return operand_type == OperandType::kRuntimeId; | |
| 332 } | 348 } |
| 333 | 349 |
| 334 // static | 350 // static |
| 335 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { | 351 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { |
| 336 switch (operand_type) { | 352 switch (operand_type) { |
| 337 #define CASE(Name, _) \ | 353 #define CASE(Name, _, __) \ |
| 338 case OperandType::k##Name: \ | 354 case OperandType::k##Name: \ |
| 339 return true; | 355 return true; |
| 340 REGISTER_OPERAND_TYPE_LIST(CASE) | 356 REGISTER_OPERAND_TYPE_LIST(CASE) |
| 341 #undef CASE | 357 #undef CASE |
| 342 #define CASE(Name, _) \ | 358 #define CASE(Name, _, __) \ |
| 343 case OperandType::k##Name: \ | 359 case OperandType::k##Name: \ |
| 344 break; | 360 break; |
| 345 NON_REGISTER_OPERAND_TYPE_LIST(CASE) | 361 NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
| 346 #undef CASE | 362 #undef CASE |
| 347 } | 363 } |
| 348 return false; | 364 return false; |
| 349 } | 365 } |
| 350 | 366 |
| 351 // static | 367 // static |
| 352 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { | 368 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { |
| 353 switch (operand_type) { | 369 switch (operand_type) { |
| 354 #define CASE(Name, _) \ | 370 #define CASE(Name, _, __) \ |
| 355 case OperandType::k##Name: \ | 371 case OperandType::k##Name: \ |
| 356 return true; | 372 return true; |
| 357 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) | 373 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) |
| 358 #undef CASE | 374 #undef CASE |
| 359 #define CASE(Name, _) \ | 375 #define CASE(Name, _, __) \ |
| 360 case OperandType::k##Name: \ | 376 case OperandType::k##Name: \ |
| 361 break; | 377 break; |
| 362 NON_REGISTER_OPERAND_TYPE_LIST(CASE) | 378 NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
| 363 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) | 379 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) |
| 364 #undef CASE | 380 #undef CASE |
| 365 } | 381 } |
| 366 return false; | 382 return false; |
| 367 } | 383 } |
| 368 | 384 |
| 369 // static | 385 // static |
| 370 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { | 386 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { |
| 371 switch (operand_type) { | 387 switch (operand_type) { |
| 372 #define CASE(Name, _) \ | 388 #define CASE(Name, _, __) \ |
| 373 case OperandType::k##Name: \ | 389 case OperandType::k##Name: \ |
| 374 return true; | 390 return true; |
| 375 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) | 391 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) |
| 376 #undef CASE | 392 #undef CASE |
| 377 #define CASE(Name, _) \ | 393 #define CASE(Name, _, __) \ |
| 378 case OperandType::k##Name: \ | 394 case OperandType::k##Name: \ |
| 379 break; | 395 break; |
| 380 NON_REGISTER_OPERAND_TYPE_LIST(CASE) | 396 NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
| 381 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) | 397 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) |
| 382 #undef CASE | 398 #undef CASE |
| 383 } | 399 } |
| 384 return false; | 400 return false; |
| 385 } | 401 } |
| 386 | 402 |
| 387 namespace { | 403 namespace { |
| 388 static Register DecodeRegister(const uint8_t* operand_start, | 404 static Register DecodeRegister(const uint8_t* operand_start, |
| 389 OperandType operand_type) { | 405 OperandType operand_type, int operand_scale) { |
| 390 switch (Bytecodes::SizeOfOperand(operand_type)) { | 406 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { |
| 391 case OperandSize::kByte: | 407 case OperandSize::kByte: |
| 392 return Register::FromOperand(*operand_start); | 408 return Register::FromOperand(*operand_start); |
| 393 case OperandSize::kShort: | 409 case OperandSize::kShort: |
| 394 return Register::FromWideOperand(ReadUnalignedUInt16(operand_start)); | 410 return Register::FromWideOperand(ReadUnalignedUInt16(operand_start)); |
| 411 case OperandSize::kQuad: | |
| 412 return Register::FromWideOperand(ReadUnalignedUInt32(operand_start)); | |
| 395 case OperandSize::kNone: { | 413 case OperandSize::kNone: { |
| 396 UNREACHABLE(); | 414 UNREACHABLE(); |
| 397 } | 415 } |
| 398 } | 416 } |
| 399 return Register(); | 417 return Register(); |
| 400 } | 418 } |
| 419 | |
| 420 static uint32_t DecodeUnsignedOperand(const uint8_t* operand_start, | |
| 421 OperandType operand_type, | |
| 422 int operand_scale) { | |
| 423 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { | |
| 424 case OperandSize::kByte: | |
| 425 return *operand_start; | |
| 426 case OperandSize::kShort: | |
| 427 return ReadUnalignedUInt16(operand_start); | |
| 428 case OperandSize::kQuad: | |
| 429 return ReadUnalignedUInt32(operand_start); | |
| 430 case OperandSize::kNone: | |
| 431 UNREACHABLE(); | |
| 432 } | |
| 433 return 0; | |
| 434 } | |
| 435 | |
| 436 static int32_t DecodeSignedOperand(const uint8_t* operand_start, | |
| 437 OperandType operand_type, | |
| 438 int operand_scale) { | |
| 439 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { | |
| 440 case OperandSize::kByte: | |
| 441 return static_cast<int8_t>(*operand_start); | |
| 442 case OperandSize::kShort: | |
| 443 return static_cast<int16_t>(ReadUnalignedUInt16(operand_start)); | |
| 444 case OperandSize::kQuad: | |
| 445 return static_cast<int32_t>(ReadUnalignedUInt32(operand_start)); | |
| 446 case OperandSize::kNone: | |
| 447 UNREACHABLE(); | |
| 448 } | |
| 449 return 0; | |
| 450 } | |
| 401 } // namespace | 451 } // namespace |
| 402 | 452 |
| 403 | 453 |
| 404 // static | 454 // static |
| 405 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, | 455 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, |
| 406 int parameter_count) { | 456 int parameter_count) { |
| 407 Vector<char> buf = Vector<char>::New(50); | 457 Vector<char> buf = Vector<char>::New(50); |
| 408 | 458 |
| 409 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); | 459 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); |
| 410 int bytecode_size = Bytecodes::Size(bytecode); | 460 int prefix_offset = 0; |
| 461 int operand_scale = Bytecodes::GetPrefixBytecodeScale(bytecode); | |
| 462 if (operand_scale > 1) { | |
| 463 prefix_offset += 1; | |
| 464 bytecode = Bytecodes::FromByte(bytecode_start[1]); | |
| 465 } | |
| 411 | 466 |
| 412 for (int i = 0; i < bytecode_size; i++) { | 467 int bytecode_size = Bytecodes::Size(bytecode, operand_scale); |
| 468 | |
| 469 for (int i = 0; i < prefix_offset + bytecode_size; i++) { | |
| 413 SNPrintF(buf, "%02x ", bytecode_start[i]); | 470 SNPrintF(buf, "%02x ", bytecode_start[i]); |
| 414 os << buf.start(); | 471 os << buf.start(); |
| 415 } | 472 } |
| 416 const int kBytecodeColumnSize = 6; | 473 const int kBytecodeColumnSize = 6; |
| 417 for (int i = bytecode_size; i < kBytecodeColumnSize; i++) { | 474 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) { |
| 418 os << " "; | 475 os << " "; |
| 419 } | 476 } |
| 420 | 477 |
| 421 os << bytecode << " "; | 478 os << bytecode; |
| 479 if (operand_scale == 2) { | |
| 480 os << "." << Bytecodes::ToString(Bytecode::kWide); | |
| 481 } else if (operand_scale == 4) { | |
| 482 os << "." << Bytecodes::ToString(Bytecode::kExtraWide); | |
| 483 } | |
| 484 os << " "; | |
| 422 | 485 |
| 423 // Operands for the debug break are from the original instruction. | 486 // Operands for the debug break are from the original instruction. |
| 424 if (IsDebugBreak(bytecode)) return os; | 487 if (IsDebugBreak(bytecode)) return os; |
| 425 | 488 |
| 426 int number_of_operands = NumberOfOperands(bytecode); | 489 int number_of_operands = NumberOfOperands(bytecode); |
| 427 int range = 0; | 490 int range = 0; |
| 428 for (int i = 0; i < number_of_operands; i++) { | 491 for (int i = 0; i < number_of_operands; i++) { |
| 429 OperandType op_type = GetOperandType(bytecode, i); | 492 OperandType op_type = GetOperandType(bytecode, i); |
| 430 const uint8_t* operand_start = | 493 const uint8_t* operand_start = |
| 431 &bytecode_start[GetOperandOffset(bytecode, i)]; | 494 &bytecode_start[prefix_offset + |
| 495 GetOperandOffset(bytecode, i, operand_scale)]; | |
| 432 switch (op_type) { | 496 switch (op_type) { |
| 433 case interpreter::OperandType::kRegCount8: | 497 case interpreter::OperandType::kRegCount: |
| 434 os << "#" << static_cast<unsigned int>(*operand_start); | 498 os << "#" |
| 499 << DecodeUnsignedOperand(operand_start, op_type, operand_scale); | |
| 435 break; | 500 break; |
| 436 case interpreter::OperandType::kRegCount16: | 501 case interpreter::OperandType::kIdx: |
| 437 os << '#' << ReadUnalignedUInt16(operand_start); | 502 case interpreter::OperandType::kRuntimeId: |
| 503 os << "[" | |
| 504 << DecodeUnsignedOperand(operand_start, op_type, operand_scale) | |
| 505 << "]"; | |
| 438 break; | 506 break; |
| 439 case interpreter::OperandType::kIdx8: | 507 case interpreter::OperandType::kImm: |
| 440 os << "[" << static_cast<unsigned int>(*operand_start) << "]"; | 508 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale) |
| 509 << "]"; | |
| 441 break; | 510 break; |
| 442 case interpreter::OperandType::kIdx16: | 511 case interpreter::OperandType::kFlag8: |
| 443 os << "[" << ReadUnalignedUInt16(operand_start) << "]"; | 512 os << "#" |
| 513 << DecodeUnsignedOperand(operand_start, op_type, operand_scale); | |
| 444 break; | 514 break; |
| 445 case interpreter::OperandType::kImm8: | 515 case interpreter::OperandType::kMaybeReg: |
| 446 os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start)); | 516 case interpreter::OperandType::kReg: |
| 447 break; | 517 case interpreter::OperandType::kRegOut: { |
| 448 case interpreter::OperandType::kMaybeReg8: | 518 Register reg = DecodeRegister(operand_start, op_type, operand_scale); |
| 449 case interpreter::OperandType::kMaybeReg16: | |
| 450 case interpreter::OperandType::kReg8: | |
| 451 case interpreter::OperandType::kReg16: | |
| 452 case interpreter::OperandType::kRegOut8: | |
| 453 case interpreter::OperandType::kRegOut16: { | |
| 454 Register reg = DecodeRegister(operand_start, op_type); | |
| 455 os << reg.ToString(parameter_count); | 519 os << reg.ToString(parameter_count); |
| 456 break; | 520 break; |
| 457 } | 521 } |
| 458 case interpreter::OperandType::kRegOutTriple8: | 522 case interpreter::OperandType::kRegOutTriple: |
| 459 case interpreter::OperandType::kRegOutTriple16: | |
| 460 range += 1; | 523 range += 1; |
| 461 case interpreter::OperandType::kRegOutPair8: | 524 case interpreter::OperandType::kRegOutPair: |
| 462 case interpreter::OperandType::kRegOutPair16: | 525 case interpreter::OperandType::kRegPair: { |
| 463 case interpreter::OperandType::kRegPair8: | |
| 464 case interpreter::OperandType::kRegPair16: { | |
| 465 range += 1; | 526 range += 1; |
| 466 Register first_reg = DecodeRegister(operand_start, op_type); | 527 Register first_reg = |
| 528 DecodeRegister(operand_start, op_type, operand_scale); | |
| 467 Register last_reg = Register(first_reg.index() + range); | 529 Register last_reg = Register(first_reg.index() + range); |
| 468 os << first_reg.ToString(parameter_count) << "-" | 530 os << first_reg.ToString(parameter_count) << "-" |
| 469 << last_reg.ToString(parameter_count); | 531 << last_reg.ToString(parameter_count); |
| 470 break; | 532 break; |
| 471 } | 533 } |
| 472 case interpreter::OperandType::kNone: | 534 case interpreter::OperandType::kNone: |
| 473 UNREACHABLE(); | 535 UNREACHABLE(); |
| 474 break; | 536 break; |
| 475 } | 537 } |
| 476 if (i != number_of_operands - 1) { | 538 if (i != number_of_operands - 1) { |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 639 } else { | 701 } else { |
| 640 std::ostringstream s; | 702 std::ostringstream s; |
| 641 s << "r" << index(); | 703 s << "r" << index(); |
| 642 return s.str(); | 704 return s.str(); |
| 643 } | 705 } |
| 644 } | 706 } |
| 645 | 707 |
| 646 } // namespace interpreter | 708 } // namespace interpreter |
| 647 } // namespace internal | 709 } // namespace internal |
| 648 } // namespace v8 | 710 } // namespace v8 |
| OLD | NEW |