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/bytecode-array-builder.h" | 5 #include "src/interpreter/bytecode-array-builder.h" |
| 6 | 6 |
| 7 namespace v8 { | 7 namespace v8 { |
| 8 namespace internal { | 8 namespace internal { |
| 9 namespace interpreter { | 9 namespace interpreter { |
| 10 | 10 |
| 11 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) | 11 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) |
| 12 : isolate_(isolate), | 12 : isolate_(isolate), |
| 13 bytecodes_(zone), | 13 bytecodes_(zone), |
| 14 bytecode_generated_(false), | 14 bytecode_generated_(false), |
| 15 constants_map_(isolate->heap(), zone), | 15 constants_map_(isolate->heap(), zone), |
| 16 constants_(zone), | 16 constants_(zone), |
| 17 forward_labels_(zone), | |
| 18 bound_labels_(zone), | |
| 17 parameter_count_(-1), | 19 parameter_count_(-1), |
| 18 local_register_count_(-1), | 20 local_register_count_(-1), |
| 19 temporary_register_count_(0), | 21 temporary_register_count_(0), |
| 20 temporary_register_next_(0) {} | 22 temporary_register_next_(0) {} |
| 21 | 23 |
| 22 | 24 |
| 23 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { | 25 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { |
| 24 local_register_count_ = number_of_locals; | 26 local_register_count_ = number_of_locals; |
| 25 temporary_register_next_ = local_register_count_; | 27 temporary_register_next_ = local_register_count_; |
| 26 } | 28 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 } | 71 } |
| 70 | 72 |
| 71 Handle<BytecodeArray> output = | 73 Handle<BytecodeArray> output = |
| 72 factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size, | 74 factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size, |
| 73 parameter_count_, constant_pool); | 75 parameter_count_, constant_pool); |
| 74 bytecode_generated_ = true; | 76 bytecode_generated_ = true; |
| 75 return output; | 77 return output; |
| 76 } | 78 } |
| 77 | 79 |
| 78 | 80 |
| 79 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value binop, | 81 template <size_t N> |
| 82 void BytecodeArrayBuilder::RawOutputAt(ZoneVector<uint8_t>::iterator pos, | |
| 83 uint8_t(&bytes)[N]) { | |
| 84 DCHECK_EQ(Bytecodes::NumberOfOperands(Bytecodes::FromByte(bytes[0])), N - 1); | |
| 85 for (int i = 1; i < static_cast<int>(N); i++) { | |
| 86 DCHECK(OperandIsValid(Bytecodes::FromByte(bytes[0]), i - 1, bytes[i])); | |
| 87 } | |
| 88 | |
| 89 if (bytecodes()->end() == pos) { | |
|
rmcilroy
2015/09/18 10:42:23
I'm not keen on having the Output operators do pat
oth
2015/09/23 10:46:55
Done.
| |
| 90 bytecodes()->insert(pos, bytes, bytes + N); | |
| 91 } else { | |
| 92 std::copy(bytes, bytes + N, pos); | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 | |
| 97 void BytecodeArrayBuilder::Output(const ZoneVector<uint8_t>::iterator& pos, | |
| 98 Bytecode bytecode, uint8_t operand0) { | |
| 99 uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0}; | |
| 100 RawOutputAt(pos, bytes); | |
| 101 } | |
| 102 | |
| 103 | |
| 104 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0, | |
| 105 uint8_t operand1, uint8_t operand2) { | |
| 106 uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0, operand1, operand2}; | |
| 107 RawOutputAt(bytecodes()->end(), bytes); | |
| 108 } | |
| 109 | |
| 110 | |
| 111 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0, | |
| 112 uint8_t operand1) { | |
| 113 uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0, operand1}; | |
| 114 RawOutputAt(bytecodes()->end(), bytes); | |
| 115 } | |
| 116 | |
| 117 | |
| 118 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0) { | |
| 119 uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0}; | |
| 120 RawOutputAt(bytecodes()->end(), bytes); | |
| 121 } | |
| 122 | |
| 123 | |
| 124 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | |
| 125 uint8_t bytes[] = {Bytecodes::ToByte(bytecode)}; | |
| 126 RawOutputAt(bytecodes()->end(), bytes); | |
| 127 } | |
| 128 | |
| 129 | |
| 130 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | |
| 80 Register reg) { | 131 Register reg) { |
| 81 Output(BytecodeForBinaryOperation(binop), reg.ToOperand()); | 132 Output(BytecodeForBinaryOperation(op), reg.ToOperand()); |
| 82 return *this; | 133 return *this; |
| 83 } | 134 } |
| 84 | 135 |
| 136 | |
| 137 BytecodeArrayBuilder& BytecodeArrayBuilder::Add(Register reg) { | |
| 138 return BinaryOperation(Token::Value::ADD, reg); | |
| 139 } | |
| 140 | |
| 141 | |
| 142 BytecodeArrayBuilder& BytecodeArrayBuilder::Subtract(Register reg) { | |
| 143 return BinaryOperation(Token::Value::SUB, reg); | |
| 144 } | |
| 145 | |
| 146 | |
| 147 BytecodeArrayBuilder& BytecodeArrayBuilder::Multiply(Register reg) { | |
| 148 return BinaryOperation(Token::Value::MUL, reg); | |
| 149 } | |
| 150 | |
| 151 | |
| 152 BytecodeArrayBuilder& BytecodeArrayBuilder::Divide(Register reg) { | |
| 153 return BinaryOperation(Token::Value::DIV, reg); | |
| 154 } | |
| 155 | |
| 156 | |
| 157 BytecodeArrayBuilder& BytecodeArrayBuilder::Modulo(Register reg) { | |
| 158 return BinaryOperation(Token::Value::MOD, reg); | |
| 159 } | |
| 160 | |
| 161 | |
| 162 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op, | |
| 163 Register reg) { | |
| 164 Output(BytecodeForCompareOperation(op), reg.ToOperand()); | |
| 165 return *this; | |
| 166 } | |
| 167 | |
| 85 | 168 |
| 86 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( | 169 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( |
| 87 v8::internal::Smi* smi) { | 170 v8::internal::Smi* smi) { |
| 88 int32_t raw_smi = smi->value(); | 171 int32_t raw_smi = smi->value(); |
| 89 if (raw_smi == 0) { | 172 if (raw_smi == 0) { |
| 90 Output(Bytecode::kLdaZero); | 173 Output(Bytecode::kLdaZero); |
| 91 } else if (raw_smi >= -128 && raw_smi <= 127) { | 174 } else if (raw_smi >= -128 && raw_smi <= 127) { |
| 92 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); | 175 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); |
| 93 } else { | 176 } else { |
| 94 LoadLiteral(Handle<Object>(smi, isolate_)); | 177 LoadLiteral(Handle<Object>(smi, isolate_)); |
| 95 } | 178 } |
| 96 return *this; | 179 return *this; |
| 97 } | 180 } |
| 98 | 181 |
| 99 | 182 |
| 100 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { | 183 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { |
| 101 size_t entry = GetConstantPoolEntry(object); | 184 size_t entry = GetConstantPoolEntry(object); |
| 102 if (FitsInByteOperand(entry)) { | 185 if (FitsInIdxOperand(entry)) { |
| 103 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry)); | 186 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry)); |
| 104 } else { | 187 } else { |
| 105 UNIMPLEMENTED(); | 188 UNIMPLEMENTED(); |
| 106 } | 189 } |
| 107 return *this; | 190 return *this; |
| 108 } | 191 } |
| 109 | 192 |
| 110 | 193 |
| 194 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(int value) { | |
| 195 Handle<Object> v = isolate()->factory()->NewNumberFromInt(value); | |
| 196 if (v->IsSmi()) { | |
| 197 return LoadLiteral(Smi::cast(*v)); | |
| 198 } else { | |
| 199 return LoadLiteral(v); | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 | |
| 204 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(double value) { | |
| 205 return LoadLiteral(isolate()->factory()->NewNumber(value)); | |
| 206 } | |
| 207 | |
| 208 | |
| 111 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { | 209 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { |
| 112 Output(Bytecode::kLdaUndefined); | 210 Output(Bytecode::kLdaUndefined); |
| 113 return *this; | 211 return *this; |
| 114 } | 212 } |
| 115 | 213 |
| 116 | 214 |
| 117 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() { | 215 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() { |
| 118 Output(Bytecode::kLdaNull); | 216 Output(Bytecode::kLdaNull); |
| 119 return *this; | 217 return *this; |
| 120 } | 218 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 151 return *this; | 249 return *this; |
| 152 } | 250 } |
| 153 | 251 |
| 154 | 252 |
| 155 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 253 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
| 156 Register object, int feedback_slot, LanguageMode language_mode) { | 254 Register object, int feedback_slot, LanguageMode language_mode) { |
| 157 if (!is_sloppy(language_mode)) { | 255 if (!is_sloppy(language_mode)) { |
| 158 UNIMPLEMENTED(); | 256 UNIMPLEMENTED(); |
| 159 } | 257 } |
| 160 | 258 |
| 161 if (FitsInByteOperand(feedback_slot)) { | 259 if (FitsInIdxOperand(feedback_slot)) { |
| 162 Output(Bytecode::kLoadIC, object.ToOperand(), | 260 Output(Bytecode::kLoadIC, object.ToOperand(), |
| 163 static_cast<uint8_t>(feedback_slot)); | 261 static_cast<uint8_t>(feedback_slot)); |
| 164 } else { | 262 } else { |
| 165 UNIMPLEMENTED(); | 263 UNIMPLEMENTED(); |
| 166 } | 264 } |
| 167 return *this; | 265 return *this; |
| 168 } | 266 } |
| 169 | 267 |
| 170 | 268 |
| 171 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 269 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
| 172 Register object, int feedback_slot, LanguageMode language_mode) { | 270 Register object, int feedback_slot, LanguageMode language_mode) { |
| 173 if (!is_sloppy(language_mode)) { | 271 if (!is_sloppy(language_mode)) { |
| 174 UNIMPLEMENTED(); | 272 UNIMPLEMENTED(); |
| 175 } | 273 } |
| 176 | 274 |
| 177 if (FitsInByteOperand(feedback_slot)) { | 275 if (FitsInIdxOperand(feedback_slot)) { |
| 178 Output(Bytecode::kKeyedLoadIC, object.ToOperand(), | 276 Output(Bytecode::kKeyedLoadIC, object.ToOperand(), |
| 179 static_cast<uint8_t>(feedback_slot)); | 277 static_cast<uint8_t>(feedback_slot)); |
| 180 } else { | 278 } else { |
| 181 UNIMPLEMENTED(); | 279 UNIMPLEMENTED(); |
| 182 } | 280 } |
| 183 return *this; | 281 return *this; |
| 184 } | 282 } |
| 185 | 283 |
| 186 | 284 |
| 187 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 285 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
| 188 Register object, Register name, int feedback_slot, | 286 Register object, Register name, int feedback_slot, |
| 189 LanguageMode language_mode) { | 287 LanguageMode language_mode) { |
| 190 if (!is_sloppy(language_mode)) { | 288 if (!is_sloppy(language_mode)) { |
| 191 UNIMPLEMENTED(); | 289 UNIMPLEMENTED(); |
| 192 } | 290 } |
| 193 | 291 |
| 194 if (FitsInByteOperand(feedback_slot)) { | 292 if (FitsInIdxOperand(feedback_slot)) { |
| 195 Output(Bytecode::kStoreIC, object.ToOperand(), name.ToOperand(), | 293 Output(Bytecode::kStoreIC, object.ToOperand(), name.ToOperand(), |
| 196 static_cast<uint8_t>(feedback_slot)); | 294 static_cast<uint8_t>(feedback_slot)); |
| 197 } else { | 295 } else { |
| 198 UNIMPLEMENTED(); | 296 UNIMPLEMENTED(); |
| 199 } | 297 } |
| 200 return *this; | 298 return *this; |
| 201 } | 299 } |
| 202 | 300 |
| 203 | 301 |
| 204 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 302 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
| 205 Register object, Register key, int feedback_slot, | 303 Register object, Register key, int feedback_slot, |
| 206 LanguageMode language_mode) { | 304 LanguageMode language_mode) { |
| 207 if (!is_sloppy(language_mode)) { | 305 if (!is_sloppy(language_mode)) { |
| 208 UNIMPLEMENTED(); | 306 UNIMPLEMENTED(); |
| 209 } | 307 } |
| 210 | 308 |
| 211 if (FitsInByteOperand(feedback_slot)) { | 309 if (FitsInIdxOperand(feedback_slot)) { |
| 212 Output(Bytecode::kKeyedStoreIC, object.ToOperand(), key.ToOperand(), | 310 Output(Bytecode::kKeyedStoreIC, object.ToOperand(), key.ToOperand(), |
| 213 static_cast<uint8_t>(feedback_slot)); | 311 static_cast<uint8_t>(feedback_slot)); |
| 214 } else { | 312 } else { |
| 215 UNIMPLEMENTED(); | 313 UNIMPLEMENTED(); |
| 216 } | 314 } |
| 217 return *this; | 315 return *this; |
| 218 } | 316 } |
| 219 | 317 |
| 220 | 318 |
| 319 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { | |
| 320 auto forward_labels_iterator = forward_labels_.find(label); | |
| 321 if (forward_labels_.end() != forward_labels_iterator) { | |
| 322 // Label is forward referred to, update the referring jump instruction. | |
| 323 ZoneVector<uint8_t>::iterator it = bytecodes()->begin() + label->offset(); | |
| 324 OutputJump(Bytecodes::FromByte(*it), it, bytecodes()->end()); | |
| 325 forward_labels_.erase(forward_labels_iterator); | |
| 326 // Now treat as if the label will only be back referred to. | |
| 327 } | |
| 328 | |
| 329 DCHECK(bound_labels_.end() == bound_labels_.find(label)); | |
| 330 label->bind_to(bytecodes()->size()); | |
| 331 bound_labels_.insert(label); | |
| 332 return *this; | |
| 333 } | |
| 334 | |
| 335 | |
| 336 // static | |
| 337 bool BytecodeArrayBuilder::IsJumpWithSmi8Operand(Bytecode jump_bytecode) { | |
| 338 return jump_bytecode == Bytecode::kJumpSmi8 || | |
| 339 jump_bytecode == Bytecode::kJumpIfTrueSmi8 || | |
| 340 jump_bytecode == Bytecode::kJumpIfFalseSmi8; | |
| 341 } | |
| 342 | |
| 343 | |
| 344 // static | |
| 345 Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand( | |
| 346 Bytecode jump_bytecode) { | |
| 347 switch (jump_bytecode) { | |
| 348 case Bytecode::kJumpSmi8: | |
| 349 return Bytecode::kJumpConstant; | |
| 350 case Bytecode::kJumpIfTrueSmi8: | |
| 351 return Bytecode::kJumpIfTrueConstant; | |
| 352 case Bytecode::kJumpIfFalseSmi8: | |
| 353 return Bytecode::kJumpIfFalseConstant; | |
| 354 default: | |
| 355 UNREACHABLE(); | |
| 356 return Bytecode::kJumpConstant; | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 | |
| 361 void BytecodeArrayBuilder::OutputJump( | |
| 362 Bytecode jump_bytecode, const ZoneVector<uint8_t>::iterator& jump_location, | |
| 363 const ZoneVector<uint8_t>::iterator& jump_target) { | |
| 364 DCHECK(IsJumpWithSmi8Operand(jump_bytecode)); | |
| 365 | |
| 366 int delta = static_cast<int>(jump_target - jump_location); | |
| 367 if (FitsInImm8Operand(delta)) { | |
| 368 Output(jump_location, jump_bytecode, static_cast<uint8_t>(delta)); | |
| 369 } else { | |
| 370 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); | |
| 371 if (FitsInIdxOperand(entry)) { | |
| 372 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); | |
| 373 Output(jump_location, jump_bytecode, static_cast<uint8_t>(entry)); | |
| 374 } else { | |
| 375 UNIMPLEMENTED(); | |
| 376 } | |
| 377 } | |
| 378 } | |
| 379 | |
| 380 | |
| 381 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(Bytecode jump_bytecode, | |
| 382 BytecodeLabel* label) { | |
| 383 if (bound_labels_.find(label) != bound_labels_.end()) { | |
| 384 // Label has been bound already so this is a backwards jump. | |
| 385 OutputJump(jump_bytecode, bytecodes()->end(), | |
| 386 bytecodes()->begin() + label->offset()); | |
| 387 } else { | |
| 388 // Label has not yet been bound so this is a forward reference | |
| 389 // that will be patched when the label is bound. | |
| 390 DCHECK(forward_labels_.find(label) == forward_labels_.end()); | |
| 391 label->bind_to(bytecodes()->size()); | |
| 392 forward_labels_.insert(label); | |
| 393 OutputJump(jump_bytecode, bytecodes()->end(), bytecodes()->end()); | |
| 394 } | |
| 395 return *this; | |
| 396 } | |
| 397 | |
| 398 | |
| 399 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | |
| 400 return Jump(Bytecode::kJumpSmi8, label); | |
| 401 } | |
| 402 | |
| 403 | |
| 404 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { | |
| 405 return Jump(Bytecode::kJumpIfTrueSmi8, label); | |
| 406 } | |
| 407 | |
| 408 | |
| 409 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { | |
| 410 return Jump(Bytecode::kJumpIfFalseSmi8, label); | |
| 411 } | |
| 412 | |
| 413 | |
| 221 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { | 414 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { |
| 222 Output(Bytecode::kReturn); | 415 Output(Bytecode::kReturn); |
| 223 return *this; | 416 return *this; |
| 224 } | 417 } |
| 225 | 418 |
| 226 | 419 |
| 227 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 420 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| 228 Register receiver, | 421 Register receiver, |
| 229 size_t arg_count) { | 422 size_t arg_count) { |
| 230 if (FitsInByteOperand(arg_count)) { | 423 if (FitsInIdxOperand(arg_count)) { |
| 231 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), | 424 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), |
| 232 static_cast<uint8_t>(arg_count)); | 425 static_cast<uint8_t>(arg_count)); |
| 233 } else { | 426 } else { |
| 234 UNIMPLEMENTED(); | 427 UNIMPLEMENTED(); |
| 235 } | 428 } |
| 236 return *this; | 429 return *this; |
| 237 } | 430 } |
| 238 | 431 |
| 239 | 432 |
| 240 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 433 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 292 } else { | 485 } else { |
| 293 return (reg.index() >= 0 && reg.index() < temporary_register_next_); | 486 return (reg.index() >= 0 && reg.index() < temporary_register_next_); |
| 294 } | 487 } |
| 295 } | 488 } |
| 296 } | 489 } |
| 297 UNREACHABLE(); | 490 UNREACHABLE(); |
| 298 return false; | 491 return false; |
| 299 } | 492 } |
| 300 | 493 |
| 301 | 494 |
| 302 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0, | |
| 303 uint8_t operand1, uint8_t operand2) { | |
| 304 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3); | |
| 305 DCHECK(OperandIsValid(bytecode, 0, operand0) && | |
| 306 OperandIsValid(bytecode, 1, operand1) && | |
| 307 OperandIsValid(bytecode, 2, operand2)); | |
| 308 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
| 309 bytecodes_.push_back(operand0); | |
| 310 bytecodes_.push_back(operand1); | |
| 311 bytecodes_.push_back(operand2); | |
| 312 } | |
| 313 | |
| 314 | |
| 315 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0, | |
| 316 uint8_t operand1) { | |
| 317 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2); | |
| 318 DCHECK(OperandIsValid(bytecode, 0, operand0) && | |
| 319 OperandIsValid(bytecode, 1, operand1)); | |
| 320 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
| 321 bytecodes_.push_back(operand0); | |
| 322 bytecodes_.push_back(operand1); | |
| 323 } | |
| 324 | |
| 325 | |
| 326 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0) { | |
| 327 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1); | |
| 328 DCHECK(OperandIsValid(bytecode, 0, operand0)); | |
| 329 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
| 330 bytecodes_.push_back(operand0); | |
| 331 } | |
| 332 | |
| 333 | |
| 334 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | |
| 335 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); | |
| 336 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
| 337 } | |
| 338 | |
| 339 | |
| 340 // static | 495 // static |
| 341 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { | 496 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { |
| 342 switch (op) { | 497 switch (op) { |
| 343 case Token::Value::ADD: | 498 case Token::Value::ADD: |
| 344 return Bytecode::kAdd; | 499 return Bytecode::kAdd; |
| 345 case Token::Value::SUB: | 500 case Token::Value::SUB: |
| 346 return Bytecode::kSub; | 501 return Bytecode::kSub; |
| 347 case Token::Value::MUL: | 502 case Token::Value::MUL: |
| 348 return Bytecode::kMul; | 503 return Bytecode::kMul; |
| 349 case Token::Value::DIV: | 504 case Token::Value::DIV: |
| 350 return Bytecode::kDiv; | 505 return Bytecode::kDiv; |
| 351 case Token::Value::MOD: | 506 case Token::Value::MOD: |
| 352 return Bytecode::kMod; | 507 return Bytecode::kMod; |
| 353 default: | 508 default: |
| 354 UNIMPLEMENTED(); | 509 UNIMPLEMENTED(); |
| 355 return static_cast<Bytecode>(-1); | 510 return static_cast<Bytecode>(-1); |
| 356 } | 511 } |
| 357 } | 512 } |
| 358 | 513 |
| 359 | 514 |
| 360 // static | 515 // static |
| 361 bool BytecodeArrayBuilder::FitsInByteOperand(int value) { | 516 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) { |
| 517 switch (op) { | |
| 518 case Token::Value::EQ: | |
| 519 return Bytecode::kTestEqual; | |
| 520 case Token::Value::NE: | |
| 521 return Bytecode::kTestNotEqual; | |
| 522 case Token::Value::EQ_STRICT: | |
| 523 return Bytecode::kTestEqualStrict; | |
| 524 case Token::Value::NE_STRICT: | |
| 525 return Bytecode::kTestNotEqualStrict; | |
| 526 case Token::Value::LT: | |
| 527 return Bytecode::kTestLessThan; | |
| 528 case Token::Value::GT: | |
| 529 return Bytecode::kTestGreaterThan; | |
| 530 case Token::Value::LTE: | |
| 531 return Bytecode::kTestLessThanEqual; | |
| 532 case Token::Value::GTE: | |
| 533 return Bytecode::kTestGreaterThanEqual; | |
| 534 case Token::Value::INSTANCEOF: | |
| 535 return Bytecode::kTestInstanceOf; | |
| 536 case Token::Value::IN: | |
| 537 return Bytecode::kTestIn; | |
| 538 default: | |
| 539 UNIMPLEMENTED(); | |
| 540 return static_cast<Bytecode>(-1); | |
| 541 } | |
| 542 } | |
| 543 | |
| 544 | |
| 545 // static | |
| 546 bool BytecodeArrayBuilder::FitsInIdxOperand(int value) { | |
| 362 return 0 <= value && value <= 255; | 547 return 0 <= value && value <= 255; |
| 363 } | 548 } |
| 364 | 549 |
| 365 | 550 |
| 366 // static | 551 // static |
| 367 bool BytecodeArrayBuilder::FitsInByteOperand(size_t value) { | 552 bool BytecodeArrayBuilder::FitsInIdxOperand(size_t value) { |
| 368 return value <= 255; | 553 return value <= 255; |
| 369 } | 554 } |
| 370 | 555 |
| 371 | 556 |
| 557 // static | |
| 558 bool BytecodeArrayBuilder::FitsInImm8Operand(int value) { | |
| 559 return -128 <= value && value < 127; | |
| 560 } | |
| 561 | |
| 562 | |
| 372 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) | 563 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) |
| 373 : builder_(builder), count_(0), last_register_index_(-1) {} | 564 : builder_(builder), count_(0), last_register_index_(-1) {} |
| 374 | 565 |
| 375 | 566 |
| 376 TemporaryRegisterScope::~TemporaryRegisterScope() { | 567 TemporaryRegisterScope::~TemporaryRegisterScope() { |
| 377 while (count_-- != 0) { | 568 while (count_-- != 0) { |
| 378 builder_->ReturnTemporaryRegister(last_register_index_--); | 569 builder_->ReturnTemporaryRegister(last_register_index_--); |
| 379 } | 570 } |
| 380 } | 571 } |
| 381 | 572 |
| 382 | 573 |
| 383 Register TemporaryRegisterScope::NewRegister() { | 574 Register TemporaryRegisterScope::NewRegister() { |
| 384 count_++; | 575 count_++; |
| 385 last_register_index_ = builder_->BorrowTemporaryRegister(); | 576 last_register_index_ = builder_->BorrowTemporaryRegister(); |
| 386 return Register(last_register_index_); | 577 return Register(last_register_index_); |
| 387 } | 578 } |
| 388 | 579 |
| 389 } // namespace interpreter | 580 } // namespace interpreter |
| 390 } // namespace internal | 581 } // namespace internal |
| 391 } // namespace v8 | 582 } // namespace v8 |
| OLD | NEW |