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 |