| 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 |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 226 } |
| 227 | 227 |
| 228 | 228 |
| 229 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 229 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
| 230 Register reg, | 230 Register reg, |
| 231 Strength strength) { | 231 Strength strength) { |
| 232 if (is_strong(strength)) { | 232 if (is_strong(strength)) { |
| 233 UNIMPLEMENTED(); | 233 UNIMPLEMENTED(); |
| 234 } | 234 } |
| 235 | 235 |
| 236 Output(BytecodeForBinaryOperation(op), reg.ToOperand()); | 236 Output(BytecodeForBinaryOperation(op), reg.ToRawOperand()); |
| 237 return *this; | 237 return *this; |
| 238 } | 238 } |
| 239 | 239 |
| 240 | 240 |
| 241 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, | 241 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, |
| 242 Strength strength) { | 242 Strength strength) { |
| 243 if (is_strong(strength)) { | 243 if (is_strong(strength)) { |
| 244 UNIMPLEMENTED(); | 244 UNIMPLEMENTED(); |
| 245 } | 245 } |
| 246 | 246 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 260 return *this; | 260 return *this; |
| 261 } | 261 } |
| 262 | 262 |
| 263 | 263 |
| 264 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( | 264 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( |
| 265 Token::Value op, Register reg, Strength strength) { | 265 Token::Value op, Register reg, Strength strength) { |
| 266 if (is_strong(strength)) { | 266 if (is_strong(strength)) { |
| 267 UNIMPLEMENTED(); | 267 UNIMPLEMENTED(); |
| 268 } | 268 } |
| 269 | 269 |
| 270 Output(BytecodeForCompareOperation(op), reg.ToOperand()); | 270 Output(BytecodeForCompareOperation(op), reg.ToRawOperand()); |
| 271 return *this; | 271 return *this; |
| 272 } | 272 } |
| 273 | 273 |
| 274 | 274 |
| 275 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( | 275 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( |
| 276 v8::internal::Smi* smi) { | 276 v8::internal::Smi* smi) { |
| 277 int32_t raw_smi = smi->value(); | 277 int32_t raw_smi = smi->value(); |
| 278 if (raw_smi == 0) { | 278 if (raw_smi == 0) { |
| 279 Output(Bytecode::kLdaZero); | 279 Output(Bytecode::kLdaZero); |
| 280 } else if (raw_smi >= -128 && raw_smi <= 127) { | 280 } else if (raw_smi >= -128 && raw_smi <= 127) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 } else { | 335 } else { |
| 336 LoadFalse(); | 336 LoadFalse(); |
| 337 } | 337 } |
| 338 return *this; | 338 return *this; |
| 339 } | 339 } |
| 340 | 340 |
| 341 | 341 |
| 342 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( | 342 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
| 343 Register reg) { | 343 Register reg) { |
| 344 if (!IsRegisterInAccumulator(reg)) { | 344 if (!IsRegisterInAccumulator(reg)) { |
| 345 Output(Bytecode::kLdar, reg.ToOperand()); | 345 Output(Bytecode::kLdar, reg.ToRawOperand()); |
| 346 } | 346 } |
| 347 return *this; | 347 return *this; |
| 348 } | 348 } |
| 349 | 349 |
| 350 | 350 |
| 351 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | 351 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
| 352 Register reg) { | 352 Register reg) { |
| 353 // TODO(oth): Avoid storing the accumulator in the register if the | |
| 354 // previous bytecode loaded the accumulator with the same register. | |
| 355 // | |
| 356 // TODO(oth): If the previous bytecode is a MOV into this register, | |
| 357 // the previous instruction can be removed. The logic for determining | |
| 358 // these redundant MOVs appears complex. | |
| 359 Output(Bytecode::kStar, reg.ToOperand()); | |
| 360 if (!IsRegisterInAccumulator(reg)) { | 353 if (!IsRegisterInAccumulator(reg)) { |
| 361 Output(Bytecode::kStar, reg.ToOperand()); | 354 Output(Bytecode::kStar, reg.ToRawOperand()); |
| 362 } | 355 } |
| 363 return *this; | 356 return *this; |
| 364 } | 357 } |
| 365 | 358 |
| 366 | 359 |
| 367 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 360 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
| 368 Register to) { | 361 Register to) { |
| 369 DCHECK(from != to); | 362 DCHECK(from != to); |
| 370 Output(Bytecode::kMov, from.ToOperand(), to.ToOperand()); | 363 if (FitsInReg8Operand(to) && FitsInReg8Operand(from)) { |
| 371 return *this; | 364 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); |
| 372 } | 365 } else if (FitsInReg16Operand(to) && FitsInReg16Operand(from)) { |
| 373 | 366 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); |
| 374 | |
| 375 BytecodeArrayBuilder& BytecodeArrayBuilder::ExchangeRegisters(Register reg0, | |
| 376 Register reg1) { | |
| 377 DCHECK(reg0 != reg1); | |
| 378 if (FitsInReg8Operand(reg0)) { | |
| 379 Output(Bytecode::kExchange, reg0.ToOperand(), reg1.ToWideOperand()); | |
| 380 } else if (FitsInReg8Operand(reg1)) { | |
| 381 Output(Bytecode::kExchange, reg1.ToOperand(), reg0.ToWideOperand()); | |
| 382 } else { | 367 } else { |
| 383 Output(Bytecode::kExchangeWide, reg0.ToWideOperand(), reg1.ToWideOperand()); | 368 UNIMPLEMENTED(); |
| 384 } | 369 } |
| 385 return *this; | 370 return *this; |
| 386 } | 371 } |
| 387 | 372 |
| 388 | 373 |
| 389 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( | 374 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( |
| 390 const Handle<String> name, int feedback_slot, LanguageMode language_mode, | 375 const Handle<String> name, int feedback_slot, LanguageMode language_mode, |
| 391 TypeofMode typeof_mode) { | 376 TypeofMode typeof_mode) { |
| 392 // TODO(rmcilroy): Potentially store language and typeof information in an | 377 // TODO(rmcilroy): Potentially store language and typeof information in an |
| 393 // operand rather than having extra bytecodes. | 378 // operand rather than having extra bytecodes. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 422 UNIMPLEMENTED(); | 407 UNIMPLEMENTED(); |
| 423 } | 408 } |
| 424 return *this; | 409 return *this; |
| 425 } | 410 } |
| 426 | 411 |
| 427 | 412 |
| 428 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, | 413 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
| 429 int slot_index) { | 414 int slot_index) { |
| 430 DCHECK(slot_index >= 0); | 415 DCHECK(slot_index >= 0); |
| 431 if (FitsInIdx8Operand(slot_index)) { | 416 if (FitsInIdx8Operand(slot_index)) { |
| 432 Output(Bytecode::kLdaContextSlot, context.ToOperand(), | 417 Output(Bytecode::kLdaContextSlot, context.ToRawOperand(), |
| 433 static_cast<uint8_t>(slot_index)); | 418 static_cast<uint8_t>(slot_index)); |
| 434 } else if (FitsInIdx16Operand(slot_index)) { | 419 } else if (FitsInIdx16Operand(slot_index)) { |
| 435 Output(Bytecode::kLdaContextSlotWide, context.ToOperand(), | 420 Output(Bytecode::kLdaContextSlotWide, context.ToRawOperand(), |
| 436 static_cast<uint16_t>(slot_index)); | 421 static_cast<uint16_t>(slot_index)); |
| 437 } else { | 422 } else { |
| 438 UNIMPLEMENTED(); | 423 UNIMPLEMENTED(); |
| 439 } | 424 } |
| 440 return *this; | 425 return *this; |
| 441 } | 426 } |
| 442 | 427 |
| 443 | 428 |
| 444 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, | 429 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
| 445 int slot_index) { | 430 int slot_index) { |
| 446 DCHECK(slot_index >= 0); | 431 DCHECK(slot_index >= 0); |
| 447 if (FitsInIdx8Operand(slot_index)) { | 432 if (FitsInIdx8Operand(slot_index)) { |
| 448 Output(Bytecode::kStaContextSlot, context.ToOperand(), | 433 Output(Bytecode::kStaContextSlot, context.ToRawOperand(), |
| 449 static_cast<uint8_t>(slot_index)); | 434 static_cast<uint8_t>(slot_index)); |
| 450 } else if (FitsInIdx16Operand(slot_index)) { | 435 } else if (FitsInIdx16Operand(slot_index)) { |
| 451 Output(Bytecode::kStaContextSlotWide, context.ToOperand(), | 436 Output(Bytecode::kStaContextSlotWide, context.ToRawOperand(), |
| 452 static_cast<uint16_t>(slot_index)); | 437 static_cast<uint16_t>(slot_index)); |
| 453 } else { | 438 } else { |
| 454 UNIMPLEMENTED(); | 439 UNIMPLEMENTED(); |
| 455 } | 440 } |
| 456 return *this; | 441 return *this; |
| 457 } | 442 } |
| 458 | 443 |
| 459 | 444 |
| 460 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( | 445 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
| 461 const Handle<String> name, TypeofMode typeof_mode) { | 446 const Handle<String> name, TypeofMode typeof_mode) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 490 return *this; | 475 return *this; |
| 491 } | 476 } |
| 492 | 477 |
| 493 | 478 |
| 494 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 479 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
| 495 Register object, const Handle<String> name, int feedback_slot, | 480 Register object, const Handle<String> name, int feedback_slot, |
| 496 LanguageMode language_mode) { | 481 LanguageMode language_mode) { |
| 497 Bytecode bytecode = BytecodeForLoadIC(language_mode); | 482 Bytecode bytecode = BytecodeForLoadIC(language_mode); |
| 498 size_t name_index = GetConstantPoolEntry(name); | 483 size_t name_index = GetConstantPoolEntry(name); |
| 499 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 484 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { |
| 500 Output(bytecode, object.ToOperand(), static_cast<uint8_t>(name_index), | 485 Output(bytecode, object.ToRawOperand(), static_cast<uint8_t>(name_index), |
| 501 static_cast<uint8_t>(feedback_slot)); | 486 static_cast<uint8_t>(feedback_slot)); |
| 502 } else if (FitsInIdx16Operand(name_index) && | 487 } else if (FitsInIdx16Operand(name_index) && |
| 503 FitsInIdx16Operand(feedback_slot)) { | 488 FitsInIdx16Operand(feedback_slot)) { |
| 504 Output(BytecodeForWideOperands(bytecode), object.ToOperand(), | 489 Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), |
| 505 static_cast<uint16_t>(name_index), | 490 static_cast<uint16_t>(name_index), |
| 506 static_cast<uint16_t>(feedback_slot)); | 491 static_cast<uint16_t>(feedback_slot)); |
| 507 } else { | 492 } else { |
| 508 UNIMPLEMENTED(); | 493 UNIMPLEMENTED(); |
| 509 } | 494 } |
| 510 return *this; | 495 return *this; |
| 511 } | 496 } |
| 512 | 497 |
| 513 | 498 |
| 514 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 499 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
| 515 Register object, int feedback_slot, LanguageMode language_mode) { | 500 Register object, int feedback_slot, LanguageMode language_mode) { |
| 516 Bytecode bytecode = BytecodeForKeyedLoadIC(language_mode); | 501 Bytecode bytecode = BytecodeForKeyedLoadIC(language_mode); |
| 517 if (FitsInIdx8Operand(feedback_slot)) { | 502 if (FitsInIdx8Operand(feedback_slot)) { |
| 518 Output(bytecode, object.ToOperand(), static_cast<uint8_t>(feedback_slot)); | 503 Output(bytecode, object.ToRawOperand(), |
| 504 static_cast<uint8_t>(feedback_slot)); |
| 519 } else if (FitsInIdx16Operand(feedback_slot)) { | 505 } else if (FitsInIdx16Operand(feedback_slot)) { |
| 520 Output(BytecodeForWideOperands(bytecode), object.ToOperand(), | 506 Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), |
| 521 static_cast<uint16_t>(feedback_slot)); | 507 static_cast<uint16_t>(feedback_slot)); |
| 522 } else { | 508 } else { |
| 523 UNIMPLEMENTED(); | 509 UNIMPLEMENTED(); |
| 524 } | 510 } |
| 525 return *this; | 511 return *this; |
| 526 } | 512 } |
| 527 | 513 |
| 528 | 514 |
| 529 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 515 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
| 530 Register object, const Handle<String> name, int feedback_slot, | 516 Register object, const Handle<String> name, int feedback_slot, |
| 531 LanguageMode language_mode) { | 517 LanguageMode language_mode) { |
| 532 Bytecode bytecode = BytecodeForStoreIC(language_mode); | 518 Bytecode bytecode = BytecodeForStoreIC(language_mode); |
| 533 size_t name_index = GetConstantPoolEntry(name); | 519 size_t name_index = GetConstantPoolEntry(name); |
| 534 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 520 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { |
| 535 Output(bytecode, object.ToOperand(), static_cast<uint8_t>(name_index), | 521 Output(bytecode, object.ToRawOperand(), static_cast<uint8_t>(name_index), |
| 536 static_cast<uint8_t>(feedback_slot)); | 522 static_cast<uint8_t>(feedback_slot)); |
| 537 } else if (FitsInIdx16Operand(name_index) && | 523 } else if (FitsInIdx16Operand(name_index) && |
| 538 FitsInIdx16Operand(feedback_slot)) { | 524 FitsInIdx16Operand(feedback_slot)) { |
| 539 Output(BytecodeForWideOperands(bytecode), object.ToOperand(), | 525 Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), |
| 540 static_cast<uint16_t>(name_index), | 526 static_cast<uint16_t>(name_index), |
| 541 static_cast<uint16_t>(feedback_slot)); | 527 static_cast<uint16_t>(feedback_slot)); |
| 542 } else { | 528 } else { |
| 543 UNIMPLEMENTED(); | 529 UNIMPLEMENTED(); |
| 544 } | 530 } |
| 545 return *this; | 531 return *this; |
| 546 } | 532 } |
| 547 | 533 |
| 548 | 534 |
| 549 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 535 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
| 550 Register object, Register key, int feedback_slot, | 536 Register object, Register key, int feedback_slot, |
| 551 LanguageMode language_mode) { | 537 LanguageMode language_mode) { |
| 552 Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode); | 538 Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode); |
| 553 if (FitsInIdx8Operand(feedback_slot)) { | 539 if (FitsInIdx8Operand(feedback_slot)) { |
| 554 Output(bytecode, object.ToOperand(), key.ToOperand(), | 540 Output(bytecode, object.ToRawOperand(), key.ToRawOperand(), |
| 555 static_cast<uint8_t>(feedback_slot)); | 541 static_cast<uint8_t>(feedback_slot)); |
| 556 } else if (FitsInIdx16Operand(feedback_slot)) { | 542 } else if (FitsInIdx16Operand(feedback_slot)) { |
| 557 Output(BytecodeForWideOperands(bytecode), object.ToOperand(), | 543 Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), |
| 558 key.ToOperand(), static_cast<uint16_t>(feedback_slot)); | 544 key.ToRawOperand(), static_cast<uint16_t>(feedback_slot)); |
| 559 } else { | 545 } else { |
| 560 UNIMPLEMENTED(); | 546 UNIMPLEMENTED(); |
| 561 } | 547 } |
| 562 return *this; | 548 return *this; |
| 563 } | 549 } |
| 564 | 550 |
| 565 | 551 |
| 566 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure( | 552 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure( |
| 567 Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) { | 553 Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) { |
| 568 size_t entry = GetConstantPoolEntry(shared_info); | 554 size_t entry = GetConstantPoolEntry(shared_info); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 static_cast<uint16_t>(constant_properties_entry), | 632 static_cast<uint16_t>(constant_properties_entry), |
| 647 static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags)); | 633 static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags)); |
| 648 } else { | 634 } else { |
| 649 UNIMPLEMENTED(); | 635 UNIMPLEMENTED(); |
| 650 } | 636 } |
| 651 return *this; | 637 return *this; |
| 652 } | 638 } |
| 653 | 639 |
| 654 | 640 |
| 655 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { | 641 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { |
| 656 Output(Bytecode::kPushContext, context.ToOperand()); | 642 Output(Bytecode::kPushContext, context.ToRawOperand()); |
| 657 return *this; | 643 return *this; |
| 658 } | 644 } |
| 659 | 645 |
| 660 | 646 |
| 661 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 647 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
| 662 Output(Bytecode::kPopContext, context.ToOperand()); | 648 Output(Bytecode::kPopContext, context.ToRawOperand()); |
| 663 return *this; | 649 return *this; |
| 664 } | 650 } |
| 665 | 651 |
| 666 | 652 |
| 667 bool BytecodeArrayBuilder::NeedToBooleanCast() { | 653 bool BytecodeArrayBuilder::NeedToBooleanCast() { |
| 668 if (!LastBytecodeInSameBlock()) { | 654 if (!LastBytecodeInSameBlock()) { |
| 669 return true; | 655 return true; |
| 670 } | 656 } |
| 671 PreviousBytecodeHelper previous_bytecode(*this); | 657 PreviousBytecodeHelper previous_bytecode(*this); |
| 672 switch (previous_bytecode.GetBytecode()) { | 658 switch (previous_bytecode.GetBytecode()) { |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 975 | 961 |
| 976 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { | 962 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { |
| 977 Output(Bytecode::kReturn); | 963 Output(Bytecode::kReturn); |
| 978 exit_seen_in_block_ = true; | 964 exit_seen_in_block_ = true; |
| 979 return *this; | 965 return *this; |
| 980 } | 966 } |
| 981 | 967 |
| 982 | 968 |
| 983 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( | 969 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( |
| 984 Register cache_info_triple) { | 970 Register cache_info_triple) { |
| 985 Output(Bytecode::kForInPrepare, cache_info_triple.ToOperand()); | 971 if (FitsInReg8Operand(cache_info_triple)) { |
| 972 Output(Bytecode::kForInPrepare, cache_info_triple.ToRawOperand()); |
| 973 } else if (FitsInReg16Operand(cache_info_triple)) { |
| 974 Output(Bytecode::kForInPrepareWide, cache_info_triple.ToRawOperand()); |
| 975 } else { |
| 976 UNIMPLEMENTED(); |
| 977 } |
| 986 return *this; | 978 return *this; |
| 987 } | 979 } |
| 988 | 980 |
| 989 | 981 |
| 990 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index, | 982 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index, |
| 991 Register cache_length) { | 983 Register cache_length) { |
| 992 Output(Bytecode::kForInDone, index.ToOperand(), cache_length.ToOperand()); | 984 Output(Bytecode::kForInDone, index.ToRawOperand(), |
| 985 cache_length.ToRawOperand()); |
| 993 return *this; | 986 return *this; |
| 994 } | 987 } |
| 995 | 988 |
| 996 | 989 |
| 997 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( | 990 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( |
| 998 Register receiver, Register index, Register cache_type_array_pair) { | 991 Register receiver, Register index, Register cache_type_array_pair) { |
| 999 Output(Bytecode::kForInNext, receiver.ToOperand(), index.ToOperand(), | 992 if (FitsInReg8Operand(receiver) && FitsInReg8Operand(index) && |
| 1000 cache_type_array_pair.ToOperand()); | 993 FitsInReg8Operand(cache_type_array_pair)) { |
| 994 Output(Bytecode::kForInNext, receiver.ToRawOperand(), index.ToRawOperand(), |
| 995 cache_type_array_pair.ToRawOperand()); |
| 996 } else if (FitsInReg16Operand(receiver) && FitsInReg16Operand(index) && |
| 997 FitsInReg16Operand(cache_type_array_pair)) { |
| 998 Output(Bytecode::kForInNextWide, receiver.ToRawOperand(), |
| 999 index.ToRawOperand(), cache_type_array_pair.ToRawOperand()); |
| 1000 } else { |
| 1001 UNIMPLEMENTED(); |
| 1002 } |
| 1001 return *this; | 1003 return *this; |
| 1002 } | 1004 } |
| 1003 | 1005 |
| 1004 | 1006 |
| 1005 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { | 1007 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { |
| 1006 Output(Bytecode::kForInStep, index.ToOperand()); | 1008 Output(Bytecode::kForInStep, index.ToRawOperand()); |
| 1007 return *this; | 1009 return *this; |
| 1008 } | 1010 } |
| 1009 | 1011 |
| 1010 | 1012 |
| 1011 void BytecodeArrayBuilder::LeaveBasicBlock() { | 1013 void BytecodeArrayBuilder::LeaveBasicBlock() { |
| 1012 last_block_end_ = bytecodes()->size(); | 1014 last_block_end_ = bytecodes()->size(); |
| 1013 exit_seen_in_block_ = false; | 1015 exit_seen_in_block_ = false; |
| 1014 } | 1016 } |
| 1015 | 1017 |
| 1016 | 1018 |
| 1017 void BytecodeArrayBuilder::EnsureReturn() { | 1019 void BytecodeArrayBuilder::EnsureReturn() { |
| 1018 if (!exit_seen_in_block_) { | 1020 if (!exit_seen_in_block_) { |
| 1019 LoadUndefined(); | 1021 LoadUndefined(); |
| 1020 Return(); | 1022 Return(); |
| 1021 } | 1023 } |
| 1022 } | 1024 } |
| 1023 | 1025 |
| 1024 | 1026 |
| 1025 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 1027 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| 1026 Register receiver, | 1028 Register receiver, |
| 1027 size_t arg_count, | 1029 size_t arg_count, |
| 1028 int feedback_slot) { | 1030 int feedback_slot) { |
| 1029 if (FitsInIdx8Operand(arg_count) && FitsInIdx8Operand(feedback_slot)) { | 1031 if (FitsInReg8Operand(callable) && FitsInReg8Operand(receiver) && |
| 1030 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), | 1032 FitsInIdx8Operand(arg_count) && FitsInIdx8Operand(feedback_slot)) { |
| 1033 Output(Bytecode::kCall, callable.ToRawOperand(), receiver.ToRawOperand(), |
| 1031 static_cast<uint8_t>(arg_count), | 1034 static_cast<uint8_t>(arg_count), |
| 1032 static_cast<uint8_t>(feedback_slot)); | 1035 static_cast<uint8_t>(feedback_slot)); |
| 1033 } else if (FitsInIdx16Operand(arg_count) && | 1036 } else if (FitsInReg16Operand(callable) && FitsInReg16Operand(receiver) && |
| 1037 FitsInIdx16Operand(arg_count) && |
| 1034 FitsInIdx16Operand(feedback_slot)) { | 1038 FitsInIdx16Operand(feedback_slot)) { |
| 1035 Output(Bytecode::kCallWide, callable.ToOperand(), receiver.ToOperand(), | 1039 Output(Bytecode::kCallWide, callable.ToRawOperand(), |
| 1036 static_cast<uint16_t>(arg_count), | 1040 receiver.ToRawOperand(), static_cast<uint16_t>(arg_count), |
| 1037 static_cast<uint16_t>(feedback_slot)); | 1041 static_cast<uint16_t>(feedback_slot)); |
| 1038 } else { | 1042 } else { |
| 1039 UNIMPLEMENTED(); | 1043 UNIMPLEMENTED(); |
| 1040 } | 1044 } |
| 1041 return *this; | 1045 return *this; |
| 1042 } | 1046 } |
| 1043 | 1047 |
| 1044 | 1048 |
| 1045 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 1049 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
| 1046 Register first_arg, | 1050 Register first_arg, |
| 1047 size_t arg_count) { | 1051 size_t arg_count) { |
| 1048 if (!first_arg.is_valid()) { | 1052 if (!first_arg.is_valid()) { |
| 1049 DCHECK_EQ(0u, arg_count); | 1053 DCHECK_EQ(0u, arg_count); |
| 1050 first_arg = Register(0); | 1054 first_arg = Register(0); |
| 1051 } | 1055 } |
| 1052 DCHECK(FitsInIdx8Operand(arg_count)); | 1056 |
| 1053 Output(Bytecode::kNew, constructor.ToOperand(), first_arg.ToOperand(), | 1057 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && |
| 1054 static_cast<uint8_t>(arg_count)); | 1058 FitsInIdx8Operand(arg_count)) { |
| 1059 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), |
| 1060 static_cast<uint8_t>(arg_count)); |
| 1061 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && |
| 1062 FitsInIdx16Operand(arg_count)) { |
| 1063 Output(Bytecode::kNewWide, constructor.ToRawOperand(), |
| 1064 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| 1065 } else { |
| 1066 UNIMPLEMENTED(); |
| 1067 } |
| 1055 return *this; | 1068 return *this; |
| 1056 } | 1069 } |
| 1057 | 1070 |
| 1058 | 1071 |
| 1059 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 1072 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| 1060 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { | 1073 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { |
| 1061 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); | 1074 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); |
| 1062 DCHECK(FitsInIdx16Operand(function_id)); | 1075 DCHECK(FitsInIdx16Operand(function_id)); |
| 1063 DCHECK(FitsInIdx8Operand(arg_count)); | |
| 1064 if (!first_arg.is_valid()) { | 1076 if (!first_arg.is_valid()) { |
| 1065 DCHECK_EQ(0u, arg_count); | 1077 DCHECK_EQ(0u, arg_count); |
| 1066 first_arg = Register(0); | 1078 first_arg = Register(0); |
| 1067 } | 1079 } |
| 1068 Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id), | 1080 if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count)) { |
| 1069 first_arg.ToOperand(), static_cast<uint8_t>(arg_count)); | 1081 Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id), |
| 1082 first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count)); |
| 1083 } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count)) { |
| 1084 Output(Bytecode::kCallRuntimeWide, static_cast<uint16_t>(function_id), |
| 1085 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| 1086 } else { |
| 1087 UNIMPLEMENTED(); |
| 1088 } |
| 1070 return *this; | 1089 return *this; |
| 1071 } | 1090 } |
| 1072 | 1091 |
| 1073 | 1092 |
| 1074 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( | 1093 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
| 1075 Runtime::FunctionId function_id, Register first_arg, size_t arg_count, | 1094 Runtime::FunctionId function_id, Register first_arg, size_t arg_count, |
| 1076 Register first_return) { | 1095 Register first_return) { |
| 1077 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); | 1096 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); |
| 1078 DCHECK(FitsInIdx16Operand(function_id)); | 1097 DCHECK(FitsInIdx16Operand(function_id)); |
| 1079 DCHECK(FitsInIdx8Operand(arg_count)); | |
| 1080 if (!first_arg.is_valid()) { | 1098 if (!first_arg.is_valid()) { |
| 1081 DCHECK_EQ(0u, arg_count); | 1099 DCHECK_EQ(0u, arg_count); |
| 1082 first_arg = Register(0); | 1100 first_arg = Register(0); |
| 1083 } | 1101 } |
| 1084 Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), | 1102 if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count) && |
| 1085 first_arg.ToOperand(), static_cast<uint8_t>(arg_count), | 1103 FitsInReg8Operand(first_return)) { |
| 1086 first_return.ToOperand()); | 1104 Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), |
| 1105 first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count), |
| 1106 first_return.ToRawOperand()); |
| 1107 } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count) && |
| 1108 FitsInReg16Operand(first_return)) { |
| 1109 Output(Bytecode::kCallRuntimeForPairWide, |
| 1110 static_cast<uint16_t>(function_id), first_arg.ToRawOperand(), |
| 1111 static_cast<uint16_t>(arg_count), first_return.ToRawOperand()); |
| 1112 } else { |
| 1113 UNIMPLEMENTED(); |
| 1114 } |
| 1087 return *this; | 1115 return *this; |
| 1088 } | 1116 } |
| 1089 | 1117 |
| 1090 | 1118 |
| 1091 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, | 1119 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, |
| 1092 Register receiver, | 1120 Register receiver, |
| 1093 size_t arg_count) { | 1121 size_t arg_count) { |
| 1094 DCHECK(FitsInIdx16Operand(context_index)); | 1122 DCHECK(FitsInIdx16Operand(context_index)); |
| 1095 DCHECK(FitsInIdx8Operand(arg_count)); | 1123 if (FitsInReg8Operand(receiver) && FitsInIdx8Operand(arg_count)) { |
| 1096 Output(Bytecode::kCallJSRuntime, static_cast<uint16_t>(context_index), | 1124 Output(Bytecode::kCallJSRuntime, static_cast<uint16_t>(context_index), |
| 1097 receiver.ToOperand(), static_cast<uint8_t>(arg_count)); | 1125 receiver.ToRawOperand(), static_cast<uint8_t>(arg_count)); |
| 1126 } else if (FitsInReg16Operand(receiver) && FitsInIdx16Operand(arg_count)) { |
| 1127 Output(Bytecode::kCallJSRuntimeWide, static_cast<uint16_t>(context_index), |
| 1128 receiver.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| 1129 } else { |
| 1130 UNIMPLEMENTED(); |
| 1131 } |
| 1098 return *this; | 1132 return *this; |
| 1099 } | 1133 } |
| 1100 | 1134 |
| 1101 | 1135 |
| 1102 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 1136 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
| 1103 LanguageMode language_mode) { | 1137 LanguageMode language_mode) { |
| 1104 Output(BytecodeForDelete(language_mode), object.ToOperand()); | 1138 Output(BytecodeForDelete(language_mode), object.ToRawOperand()); |
| 1105 return *this; | 1139 return *this; |
| 1106 } | 1140 } |
| 1107 | 1141 |
| 1108 | 1142 |
| 1109 BytecodeArrayBuilder& BytecodeArrayBuilder::DeleteLookupSlot() { | 1143 BytecodeArrayBuilder& BytecodeArrayBuilder::DeleteLookupSlot() { |
| 1110 Output(Bytecode::kDeleteLookupSlot); | 1144 Output(Bytecode::kDeleteLookupSlot); |
| 1111 return *this; | 1145 return *this; |
| 1112 } | 1146 } |
| 1113 | 1147 |
| 1114 | 1148 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1204 if (temporary_register_count_ > 0) { | 1238 if (temporary_register_count_ > 0) { |
| 1205 DCHECK(reg.index() >= first_temporary_register().index() && | 1239 DCHECK(reg.index() >= first_temporary_register().index() && |
| 1206 reg.index() <= last_temporary_register().index()); | 1240 reg.index() <= last_temporary_register().index()); |
| 1207 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); | 1241 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); |
| 1208 } else { | 1242 } else { |
| 1209 return false; | 1243 return false; |
| 1210 } | 1244 } |
| 1211 } | 1245 } |
| 1212 | 1246 |
| 1213 | 1247 |
| 1214 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { | |
| 1215 if (reg.is_function_context() || reg.is_function_closure() || | |
| 1216 reg.is_new_target()) { | |
| 1217 return true; | |
| 1218 } else if (reg.is_parameter()) { | |
| 1219 int parameter_index = reg.ToParameterIndex(parameter_count_); | |
| 1220 return parameter_index >= 0 && parameter_index < parameter_count_; | |
| 1221 } else if (reg.index() < fixed_register_count()) { | |
| 1222 return true; | |
| 1223 } else { | |
| 1224 return TemporaryRegisterIsLive(reg); | |
| 1225 } | |
| 1226 } | |
| 1227 | |
| 1228 | |
| 1229 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, | 1248 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, |
| 1230 uint32_t operand_value) const { | 1249 uint32_t operand_value) const { |
| 1231 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); | 1250 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); |
| 1232 switch (operand_type) { | 1251 switch (operand_type) { |
| 1233 case OperandType::kNone: | 1252 case OperandType::kNone: |
| 1234 return false; | 1253 return false; |
| 1235 case OperandType::kCount16: | 1254 case OperandType::kRegCount16: |
| 1236 case OperandType::kIdx16: | 1255 case OperandType::kIdx16: |
| 1237 return static_cast<uint16_t>(operand_value) == operand_value; | 1256 return static_cast<uint16_t>(operand_value) == operand_value; |
| 1238 case OperandType::kCount8: | 1257 case OperandType::kRegCount8: |
| 1239 case OperandType::kImm8: | 1258 case OperandType::kImm8: |
| 1240 case OperandType::kIdx8: | 1259 case OperandType::kIdx8: |
| 1241 return static_cast<uint8_t>(operand_value) == operand_value; | 1260 return static_cast<uint8_t>(operand_value) == operand_value; |
| 1242 case OperandType::kMaybeReg8: | 1261 case OperandType::kMaybeReg8: |
| 1243 if (operand_value == 0) { | 1262 if (operand_value == 0) { |
| 1244 return true; | 1263 return true; |
| 1245 } | 1264 } |
| 1246 // Fall-through to kReg8 case. | 1265 // Fall-through to kReg8 case. |
| 1247 case OperandType::kReg8: | 1266 case OperandType::kReg8: |
| 1248 return RegisterIsValid( | 1267 return RegisterIsValid(Register::FromRawOperand(operand_value), |
| 1249 Register::FromOperand(static_cast<uint8_t>(operand_value))); | 1268 operand_type); |
| 1250 case OperandType::kRegPair8: { | 1269 case OperandType::kRegPair8: |
| 1251 Register reg0 = | 1270 case OperandType::kRegPair16: { |
| 1252 Register::FromOperand(static_cast<uint8_t>(operand_value)); | 1271 Register reg0 = Register::FromRawOperand(operand_value); |
| 1253 Register reg1 = Register(reg0.index() + 1); | 1272 Register reg1 = Register(reg0.index() + 1); |
| 1254 return RegisterIsValid(reg0) && RegisterIsValid(reg1); | 1273 return RegisterIsValid(reg0, operand_type) && |
| 1274 RegisterIsValid(reg1, operand_type); |
| 1255 } | 1275 } |
| 1256 case OperandType::kRegTriple8: { | 1276 case OperandType::kRegTriple8: |
| 1257 Register reg0 = | 1277 case OperandType::kRegTriple16: { |
| 1258 Register::FromOperand(static_cast<uint8_t>(operand_value)); | 1278 Register reg0 = Register::FromRawOperand(operand_value); |
| 1259 Register reg1 = Register(reg0.index() + 1); | 1279 Register reg1 = Register(reg0.index() + 1); |
| 1260 Register reg2 = Register(reg0.index() + 2); | 1280 Register reg2 = Register(reg0.index() + 2); |
| 1261 return RegisterIsValid(reg0) && RegisterIsValid(reg1) && | 1281 return RegisterIsValid(reg0, operand_type) && |
| 1262 RegisterIsValid(reg2); | 1282 RegisterIsValid(reg1, operand_type) && |
| 1283 RegisterIsValid(reg2, operand_type); |
| 1263 } | 1284 } |
| 1264 case OperandType::kReg16: | 1285 case OperandType::kMaybeReg16: |
| 1265 if (bytecode != Bytecode::kExchange && | 1286 if (operand_value == 0) { |
| 1266 bytecode != Bytecode::kExchangeWide) { | 1287 return true; |
| 1267 return false; | |
| 1268 } | 1288 } |
| 1269 return RegisterIsValid( | 1289 // Fall-through to kReg16 case. |
| 1270 Register::FromWideOperand(static_cast<uint16_t>(operand_value))); | 1290 case OperandType::kReg16: { |
| 1291 Register reg = Register::FromRawOperand(operand_value); |
| 1292 return RegisterIsValid(reg, operand_type); |
| 1293 } |
| 1271 } | 1294 } |
| 1272 UNREACHABLE(); | 1295 UNREACHABLE(); |
| 1273 return false; | 1296 return false; |
| 1274 } | 1297 } |
| 1275 | 1298 |
| 1276 | 1299 |
| 1300 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, |
| 1301 OperandType reg_type) const { |
| 1302 switch (Bytecodes::SizeOfOperand(reg_type)) { |
| 1303 case OperandSize::kByte: |
| 1304 if (!FitsInReg8Operand(reg)) { return false; } |
| 1305 break; |
| 1306 case OperandSize::kShort: |
| 1307 if (!FitsInReg16Operand(reg)) { return false; } |
| 1308 break; |
| 1309 case OperandSize::kNone: |
| 1310 UNREACHABLE(); |
| 1311 return false; |
| 1312 } |
| 1313 |
| 1314 if (reg.is_function_context() || reg.is_function_closure() || |
| 1315 reg.is_new_target()) { |
| 1316 return true; |
| 1317 } else if (reg.is_parameter()) { |
| 1318 int parameter_index = reg.ToParameterIndex(parameter_count_); |
| 1319 return parameter_index >= 0 && parameter_index < parameter_count_; |
| 1320 } else if (reg.index() < fixed_register_count()) { |
| 1321 return true; |
| 1322 } else { |
| 1323 return TemporaryRegisterIsLive(reg); |
| 1324 } |
| 1325 } |
| 1326 |
| 1327 |
| 1277 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { | 1328 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { |
| 1278 return last_bytecode_start_ < bytecodes()->size() && | 1329 return last_bytecode_start_ < bytecodes()->size() && |
| 1279 last_bytecode_start_ >= last_block_end_; | 1330 last_bytecode_start_ >= last_block_end_; |
| 1280 } | 1331 } |
| 1281 | 1332 |
| 1282 | 1333 |
| 1283 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { | 1334 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { |
| 1284 if (LastBytecodeInSameBlock()) { | 1335 if (LastBytecodeInSameBlock()) { |
| 1285 PreviousBytecodeHelper previous_bytecode(*this); | 1336 PreviousBytecodeHelper previous_bytecode(*this); |
| 1286 Bytecode bytecode = previous_bytecode.GetBytecode(); | 1337 Bytecode bytecode = previous_bytecode.GetBytecode(); |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1604 | 1655 |
| 1605 | 1656 |
| 1606 // static | 1657 // static |
| 1607 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { | 1658 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { |
| 1608 return kMinInt16 <= value.index() && value.index() <= kMaxInt16; | 1659 return kMinInt16 <= value.index() && value.index() <= kMaxInt16; |
| 1609 } | 1660 } |
| 1610 | 1661 |
| 1611 } // namespace interpreter | 1662 } // namespace interpreter |
| 1612 } // namespace internal | 1663 } // namespace internal |
| 1613 } // namespace v8 | 1664 } // namespace v8 |
| OLD | NEW |