Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 7063017: Rename TypeRecording...Stub into ...Stub. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 // As the then-branch, but move double-value to result before shifting. 399 // As the then-branch, but move double-value to result before shifting.
400 __ xorl(result, double_value); 400 __ xorl(result, double_value);
401 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1)); 401 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
402 __ shll_cl(result); 402 __ shll_cl(result);
403 } 403 }
404 404
405 __ bind(&done); 405 __ bind(&done);
406 } 406 }
407 407
408 408
409 Handle<Code> GetTypeRecordingUnaryOpStub(int key, 409 Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info) {
410 TRUnaryOpIC::TypeInfo type_info) { 410 UnaryOpStub stub(key, type_info);
411 TypeRecordingUnaryOpStub stub(key, type_info);
412 return stub.GetCode(); 411 return stub.GetCode();
413 } 412 }
414 413
415 414
416 void TypeRecordingUnaryOpStub::Generate(MacroAssembler* masm) { 415 void UnaryOpStub::Generate(MacroAssembler* masm) {
417 switch (operand_type_) { 416 switch (operand_type_) {
418 case TRUnaryOpIC::UNINITIALIZED: 417 case UnaryOpIC::UNINITIALIZED:
419 GenerateTypeTransition(masm); 418 GenerateTypeTransition(masm);
420 break; 419 break;
421 case TRUnaryOpIC::SMI: 420 case UnaryOpIC::SMI:
422 GenerateSmiStub(masm); 421 GenerateSmiStub(masm);
423 break; 422 break;
424 case TRUnaryOpIC::HEAP_NUMBER: 423 case UnaryOpIC::HEAP_NUMBER:
425 GenerateHeapNumberStub(masm); 424 GenerateHeapNumberStub(masm);
426 break; 425 break;
427 case TRUnaryOpIC::GENERIC: 426 case UnaryOpIC::GENERIC:
428 GenerateGenericStub(masm); 427 GenerateGenericStub(masm);
429 break; 428 break;
430 } 429 }
431 } 430 }
432 431
433 432
434 void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 433 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
435 __ pop(rcx); // Save return address. 434 __ pop(rcx); // Save return address.
436 __ push(rax); 435 __ push(rax);
437 // Left and right arguments are now on top. 436 // Left and right arguments are now on top.
438 // Push this stub's key. Although the operation and the type info are 437 // Push this stub's key. Although the operation and the type info are
439 // encoded into the key, the encoding is opaque, so push them too. 438 // encoded into the key, the encoding is opaque, so push them too.
440 __ Push(Smi::FromInt(MinorKey())); 439 __ Push(Smi::FromInt(MinorKey()));
441 __ Push(Smi::FromInt(op_)); 440 __ Push(Smi::FromInt(op_));
442 __ Push(Smi::FromInt(operand_type_)); 441 __ Push(Smi::FromInt(operand_type_));
443 442
444 __ push(rcx); // Push return address. 443 __ push(rcx); // Push return address.
445 444
446 // Patch the caller to an appropriate specialized stub and return the 445 // Patch the caller to an appropriate specialized stub and return the
447 // operation result to the caller of the stub. 446 // operation result to the caller of the stub.
448 __ TailCallExternalReference( 447 __ TailCallExternalReference(
449 ExternalReference(IC_Utility(IC::kTypeRecordingUnaryOp_Patch), 448 ExternalReference(IC_Utility(IC::kUnaryOp_Patch),
450 masm->isolate()), 449 masm->isolate()),
451 4, 450 4,
452 1); 451 1);
453 } 452 }
454 453
455 454
456 // TODO(svenpanne): Use virtual functions instead of switch. 455 // TODO(svenpanne): Use virtual functions instead of switch.
457 void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 456 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
458 switch (op_) { 457 switch (op_) {
459 case Token::SUB: 458 case Token::SUB:
460 GenerateSmiStubSub(masm); 459 GenerateSmiStubSub(masm);
461 break; 460 break;
462 case Token::BIT_NOT: 461 case Token::BIT_NOT:
463 GenerateSmiStubBitNot(masm); 462 GenerateSmiStubBitNot(masm);
464 break; 463 break;
465 default: 464 default:
466 UNREACHABLE(); 465 UNREACHABLE();
467 } 466 }
468 } 467 }
469 468
470 469
471 void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { 470 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
472 Label slow; 471 Label slow;
473 GenerateSmiCodeSub(masm, &slow, &slow, Label::kNear, Label::kNear); 472 GenerateSmiCodeSub(masm, &slow, &slow, Label::kNear, Label::kNear);
474 __ bind(&slow); 473 __ bind(&slow);
475 GenerateTypeTransition(masm); 474 GenerateTypeTransition(masm);
476 } 475 }
477 476
478 477
479 void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { 478 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
480 Label non_smi; 479 Label non_smi;
481 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear); 480 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
482 __ bind(&non_smi); 481 __ bind(&non_smi);
483 GenerateTypeTransition(masm); 482 GenerateTypeTransition(masm);
484 } 483 }
485 484
486 485
487 void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, 486 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
488 Label* non_smi, 487 Label* non_smi,
489 Label* slow, 488 Label* slow,
490 Label::Distance non_smi_near, 489 Label::Distance non_smi_near,
491 Label::Distance slow_near) { 490 Label::Distance slow_near) {
492 Label done; 491 Label done;
493 __ JumpIfNotSmi(rax, non_smi, non_smi_near); 492 __ JumpIfNotSmi(rax, non_smi, non_smi_near);
494 __ SmiNeg(rax, rax, &done, Label::kNear); 493 __ SmiNeg(rax, rax, &done, Label::kNear);
495 __ jmp(slow, slow_near); 494 __ jmp(slow, slow_near);
496 __ bind(&done); 495 __ bind(&done);
497 __ ret(0); 496 __ ret(0);
498 } 497 }
499 498
500 499
501 void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot( 500 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
502 MacroAssembler* masm, 501 Label* non_smi,
503 Label* non_smi, 502 Label::Distance non_smi_near) {
504 Label::Distance non_smi_near) {
505 __ JumpIfNotSmi(rax, non_smi, non_smi_near); 503 __ JumpIfNotSmi(rax, non_smi, non_smi_near);
506 __ SmiNot(rax, rax); 504 __ SmiNot(rax, rax);
507 __ ret(0); 505 __ ret(0);
508 } 506 }
509 507
510 508
511 // TODO(svenpanne): Use virtual functions instead of switch. 509 // TODO(svenpanne): Use virtual functions instead of switch.
512 void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { 510 void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
513 switch (op_) { 511 switch (op_) {
514 case Token::SUB: 512 case Token::SUB:
515 GenerateHeapNumberStubSub(masm); 513 GenerateHeapNumberStubSub(masm);
516 break; 514 break;
517 case Token::BIT_NOT: 515 case Token::BIT_NOT:
518 GenerateHeapNumberStubBitNot(masm); 516 GenerateHeapNumberStubBitNot(masm);
519 break; 517 break;
520 default: 518 default:
521 UNREACHABLE(); 519 UNREACHABLE();
522 } 520 }
523 } 521 }
524 522
525 523
526 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) { 524 void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
527 Label non_smi, slow, call_builtin; 525 Label non_smi, slow, call_builtin;
528 GenerateSmiCodeSub(masm, &non_smi, &call_builtin, Label::kNear); 526 GenerateSmiCodeSub(masm, &non_smi, &call_builtin, Label::kNear);
529 __ bind(&non_smi); 527 __ bind(&non_smi);
530 GenerateHeapNumberCodeSub(masm, &slow); 528 GenerateHeapNumberCodeSub(masm, &slow);
531 __ bind(&slow); 529 __ bind(&slow);
532 GenerateTypeTransition(masm); 530 GenerateTypeTransition(masm);
533 __ bind(&call_builtin); 531 __ bind(&call_builtin);
534 GenerateGenericCodeFallback(masm); 532 GenerateGenericCodeFallback(masm);
535 } 533 }
536 534
537 535
538 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot( 536 void UnaryOpStub::GenerateHeapNumberStubBitNot(
539 MacroAssembler* masm) { 537 MacroAssembler* masm) {
540 Label non_smi, slow; 538 Label non_smi, slow;
541 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear); 539 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
542 __ bind(&non_smi); 540 __ bind(&non_smi);
543 GenerateHeapNumberCodeBitNot(masm, &slow); 541 GenerateHeapNumberCodeBitNot(masm, &slow);
544 __ bind(&slow); 542 __ bind(&slow);
545 GenerateTypeTransition(masm); 543 GenerateTypeTransition(masm);
546 } 544 }
547 545
548 546
549 void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, 547 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
550 Label* slow) { 548 Label* slow) {
551 // Check if the operand is a heap number. 549 // Check if the operand is a heap number.
552 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 550 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
553 Heap::kHeapNumberMapRootIndex); 551 Heap::kHeapNumberMapRootIndex);
554 __ j(not_equal, slow); 552 __ j(not_equal, slow);
555 553
556 // Operand is a float, negate its value by flipping the sign bit. 554 // Operand is a float, negate its value by flipping the sign bit.
557 if (mode_ == UNARY_OVERWRITE) { 555 if (mode_ == UNARY_OVERWRITE) {
558 __ Set(kScratchRegister, 0x01); 556 __ Set(kScratchRegister, 0x01);
559 __ shl(kScratchRegister, Immediate(63)); 557 __ shl(kScratchRegister, Immediate(63));
560 __ xor_(FieldOperand(rax, HeapNumber::kValueOffset), kScratchRegister); 558 __ xor_(FieldOperand(rax, HeapNumber::kValueOffset), kScratchRegister);
(...skipping 19 matching lines...) Expand all
580 __ Set(kScratchRegister, 0x01); 578 __ Set(kScratchRegister, 0x01);
581 __ shl(kScratchRegister, Immediate(63)); 579 __ shl(kScratchRegister, Immediate(63));
582 __ xor_(rdx, kScratchRegister); // Flip sign. 580 __ xor_(rdx, kScratchRegister); // Flip sign.
583 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); 581 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx);
584 __ movq(rax, rcx); 582 __ movq(rax, rcx);
585 } 583 }
586 __ ret(0); 584 __ ret(0);
587 } 585 }
588 586
589 587
590 void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot( 588 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
591 MacroAssembler* masm, 589 Label* slow) {
592 Label* slow) {
593 // Check if the operand is a heap number. 590 // Check if the operand is a heap number.
594 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 591 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
595 Heap::kHeapNumberMapRootIndex); 592 Heap::kHeapNumberMapRootIndex);
596 __ j(not_equal, slow); 593 __ j(not_equal, slow);
597 594
598 // Convert the heap number in rax to an untagged integer in rcx. 595 // Convert the heap number in rax to an untagged integer in rcx.
599 IntegerConvert(masm, rax, rax); 596 IntegerConvert(masm, rax, rax);
600 597
601 // Do the bitwise operation and smi tag the result. 598 // Do the bitwise operation and smi tag the result.
602 __ notl(rax); 599 __ notl(rax);
603 __ Integer32ToSmi(rax, rax); 600 __ Integer32ToSmi(rax, rax);
604 __ ret(0); 601 __ ret(0);
605 } 602 }
606 603
607 604
608 // TODO(svenpanne): Use virtual functions instead of switch. 605 // TODO(svenpanne): Use virtual functions instead of switch.
609 void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { 606 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
610 switch (op_) { 607 switch (op_) {
611 case Token::SUB: 608 case Token::SUB:
612 GenerateGenericStubSub(masm); 609 GenerateGenericStubSub(masm);
613 break; 610 break;
614 case Token::BIT_NOT: 611 case Token::BIT_NOT:
615 GenerateGenericStubBitNot(masm); 612 GenerateGenericStubBitNot(masm);
616 break; 613 break;
617 default: 614 default:
618 UNREACHABLE(); 615 UNREACHABLE();
619 } 616 }
620 } 617 }
621 618
622 619
623 void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { 620 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
624 Label non_smi, slow; 621 Label non_smi, slow;
625 GenerateSmiCodeSub(masm, &non_smi, &slow, Label::kNear); 622 GenerateSmiCodeSub(masm, &non_smi, &slow, Label::kNear);
626 __ bind(&non_smi); 623 __ bind(&non_smi);
627 GenerateHeapNumberCodeSub(masm, &slow); 624 GenerateHeapNumberCodeSub(masm, &slow);
628 __ bind(&slow); 625 __ bind(&slow);
629 GenerateGenericCodeFallback(masm); 626 GenerateGenericCodeFallback(masm);
630 } 627 }
631 628
632 629
633 void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { 630 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
634 Label non_smi, slow; 631 Label non_smi, slow;
635 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear); 632 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
636 __ bind(&non_smi); 633 __ bind(&non_smi);
637 GenerateHeapNumberCodeBitNot(masm, &slow); 634 GenerateHeapNumberCodeBitNot(masm, &slow);
638 __ bind(&slow); 635 __ bind(&slow);
639 GenerateGenericCodeFallback(masm); 636 GenerateGenericCodeFallback(masm);
640 } 637 }
641 638
642 639
643 void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback( 640 void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
644 MacroAssembler* masm) {
645 // Handle the slow case by jumping to the JavaScript builtin. 641 // Handle the slow case by jumping to the JavaScript builtin.
646 __ pop(rcx); // pop return address 642 __ pop(rcx); // pop return address
647 __ push(rax); 643 __ push(rax);
648 __ push(rcx); // push return address 644 __ push(rcx); // push return address
649 switch (op_) { 645 switch (op_) {
650 case Token::SUB: 646 case Token::SUB:
651 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); 647 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
652 break; 648 break;
653 case Token::BIT_NOT: 649 case Token::BIT_NOT:
654 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); 650 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
655 break; 651 break;
656 default: 652 default:
657 UNREACHABLE(); 653 UNREACHABLE();
658 } 654 }
659 } 655 }
660 656
661 657
662 const char* TypeRecordingUnaryOpStub::GetName() { 658 const char* UnaryOpStub::GetName() {
663 if (name_ != NULL) return name_; 659 if (name_ != NULL) return name_;
664 const int kMaxNameLength = 100; 660 const int kMaxNameLength = 100;
665 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( 661 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
666 kMaxNameLength); 662 kMaxNameLength);
667 if (name_ == NULL) return "OOM"; 663 if (name_ == NULL) return "OOM";
668 const char* op_name = Token::Name(op_); 664 const char* op_name = Token::Name(op_);
669 const char* overwrite_name = NULL; // Make g++ happy. 665 const char* overwrite_name = NULL; // Make g++ happy.
670 switch (mode_) { 666 switch (mode_) {
671 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; 667 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
672 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; 668 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
673 } 669 }
674 670
675 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 671 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
676 "TypeRecordingUnaryOpStub_%s_%s_%s", 672 "UnaryOpStub_%s_%s_%s",
677 op_name, 673 op_name,
678 overwrite_name, 674 overwrite_name,
679 TRUnaryOpIC::GetName(operand_type_)); 675 UnaryOpIC::GetName(operand_type_));
680 return name_; 676 return name_;
681 } 677 }
682 678
683 679
684 Handle<Code> GetTypeRecordingBinaryOpStub(int key, 680 Handle<Code> GetBinaryOpStub(int key,
685 TRBinaryOpIC::TypeInfo type_info, 681 BinaryOpIC::TypeInfo type_info,
686 TRBinaryOpIC::TypeInfo result_type_info) { 682 BinaryOpIC::TypeInfo result_type_info) {
687 TypeRecordingBinaryOpStub stub(key, type_info, result_type_info); 683 BinaryOpStub stub(key, type_info, result_type_info);
688 return stub.GetCode(); 684 return stub.GetCode();
689 } 685 }
690 686
691 687
692 void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 688 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
693 __ pop(rcx); // Save return address. 689 __ pop(rcx); // Save return address.
694 __ push(rdx); 690 __ push(rdx);
695 __ push(rax); 691 __ push(rax);
696 // Left and right arguments are now on top. 692 // Left and right arguments are now on top.
697 // Push this stub's key. Although the operation and the type info are 693 // Push this stub's key. Although the operation and the type info are
698 // encoded into the key, the encoding is opaque, so push them too. 694 // encoded into the key, the encoding is opaque, so push them too.
699 __ Push(Smi::FromInt(MinorKey())); 695 __ Push(Smi::FromInt(MinorKey()));
700 __ Push(Smi::FromInt(op_)); 696 __ Push(Smi::FromInt(op_));
701 __ Push(Smi::FromInt(operands_type_)); 697 __ Push(Smi::FromInt(operands_type_));
702 698
703 __ push(rcx); // Push return address. 699 __ push(rcx); // Push return address.
704 700
705 // Patch the caller to an appropriate specialized stub and return the 701 // Patch the caller to an appropriate specialized stub and return the
706 // operation result to the caller of the stub. 702 // operation result to the caller of the stub.
707 __ TailCallExternalReference( 703 __ TailCallExternalReference(
708 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch), 704 ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
709 masm->isolate()), 705 masm->isolate()),
710 5, 706 5,
711 1); 707 1);
712 } 708 }
713 709
714 710
715 void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) { 711 void BinaryOpStub::Generate(MacroAssembler* masm) {
716 switch (operands_type_) { 712 switch (operands_type_) {
717 case TRBinaryOpIC::UNINITIALIZED: 713 case BinaryOpIC::UNINITIALIZED:
718 GenerateTypeTransition(masm); 714 GenerateTypeTransition(masm);
719 break; 715 break;
720 case TRBinaryOpIC::SMI: 716 case BinaryOpIC::SMI:
721 GenerateSmiStub(masm); 717 GenerateSmiStub(masm);
722 break; 718 break;
723 case TRBinaryOpIC::INT32: 719 case BinaryOpIC::INT32:
724 UNREACHABLE(); 720 UNREACHABLE();
725 // The int32 case is identical to the Smi case. We avoid creating this 721 // The int32 case is identical to the Smi case. We avoid creating this
726 // ic state on x64. 722 // ic state on x64.
727 break; 723 break;
728 case TRBinaryOpIC::HEAP_NUMBER: 724 case BinaryOpIC::HEAP_NUMBER:
729 GenerateHeapNumberStub(masm); 725 GenerateHeapNumberStub(masm);
730 break; 726 break;
731 case TRBinaryOpIC::ODDBALL: 727 case BinaryOpIC::ODDBALL:
732 GenerateOddballStub(masm); 728 GenerateOddballStub(masm);
733 break; 729 break;
734 case TRBinaryOpIC::BOTH_STRING: 730 case BinaryOpIC::BOTH_STRING:
735 GenerateBothStringStub(masm); 731 GenerateBothStringStub(masm);
736 break; 732 break;
737 case TRBinaryOpIC::STRING: 733 case BinaryOpIC::STRING:
738 GenerateStringStub(masm); 734 GenerateStringStub(masm);
739 break; 735 break;
740 case TRBinaryOpIC::GENERIC: 736 case BinaryOpIC::GENERIC:
741 GenerateGeneric(masm); 737 GenerateGeneric(masm);
742 break; 738 break;
743 default: 739 default:
744 UNREACHABLE(); 740 UNREACHABLE();
745 } 741 }
746 } 742 }
747 743
748 744
749 const char* TypeRecordingBinaryOpStub::GetName() { 745 const char* BinaryOpStub::GetName() {
750 if (name_ != NULL) return name_; 746 if (name_ != NULL) return name_;
751 const int kMaxNameLength = 100; 747 const int kMaxNameLength = 100;
752 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( 748 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
753 kMaxNameLength); 749 kMaxNameLength);
754 if (name_ == NULL) return "OOM"; 750 if (name_ == NULL) return "OOM";
755 const char* op_name = Token::Name(op_); 751 const char* op_name = Token::Name(op_);
756 const char* overwrite_name; 752 const char* overwrite_name;
757 switch (mode_) { 753 switch (mode_) {
758 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 754 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
759 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 755 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
760 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 756 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
761 default: overwrite_name = "UnknownOverwrite"; break; 757 default: overwrite_name = "UnknownOverwrite"; break;
762 } 758 }
763 759
764 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 760 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
765 "TypeRecordingBinaryOpStub_%s_%s_%s", 761 "BinaryOpStub_%s_%s_%s",
766 op_name, 762 op_name,
767 overwrite_name, 763 overwrite_name,
768 TRBinaryOpIC::GetName(operands_type_)); 764 BinaryOpIC::GetName(operands_type_));
769 return name_; 765 return name_;
770 } 766 }
771 767
772 768
773 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, 769 void BinaryOpStub::GenerateSmiCode(
770 MacroAssembler* masm,
774 Label* slow, 771 Label* slow,
775 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { 772 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
776 773
777 // Arguments to TypeRecordingBinaryOpStub are in rdx and rax. 774 // Arguments to BinaryOpStub are in rdx and rax.
778 Register left = rdx; 775 Register left = rdx;
779 Register right = rax; 776 Register right = rax;
780 777
781 // We only generate heapnumber answers for overflowing calculations 778 // We only generate heapnumber answers for overflowing calculations
782 // for the four basic arithmetic operations and logical right shift by 0. 779 // for the four basic arithmetic operations and logical right shift by 0.
783 bool generate_inline_heapnumber_results = 780 bool generate_inline_heapnumber_results =
784 (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) && 781 (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) &&
785 (op_ == Token::ADD || op_ == Token::SUB || 782 (op_ == Token::ADD || op_ == Token::SUB ||
786 op_ == Token::MUL || op_ == Token::DIV || op_ == Token::SHR); 783 op_ == Token::MUL || op_ == Token::DIV || op_ == Token::SHR);
787 784
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 // values that could be smi. 910 // values that could be smi.
914 __ bind(&not_smis); 911 __ bind(&not_smis);
915 Comment done_comment(masm, "-- Enter non-smi code"); 912 Comment done_comment(masm, "-- Enter non-smi code");
916 FloatingPointHelper::NumbersToSmis(masm, left, right, rbx, rdi, rcx, 913 FloatingPointHelper::NumbersToSmis(masm, left, right, rbx, rdi, rcx,
917 &smi_values, &fail); 914 &smi_values, &fail);
918 __ jmp(&smi_values); 915 __ jmp(&smi_values);
919 __ bind(&fail); 916 __ bind(&fail);
920 } 917 }
921 918
922 919
923 void TypeRecordingBinaryOpStub::GenerateFloatingPointCode( 920 void BinaryOpStub::GenerateFloatingPointCode(MacroAssembler* masm,
924 MacroAssembler* masm, 921 Label* allocation_failure,
925 Label* allocation_failure, 922 Label* non_numeric_failure) {
926 Label* non_numeric_failure) {
927 switch (op_) { 923 switch (op_) {
928 case Token::ADD: 924 case Token::ADD:
929 case Token::SUB: 925 case Token::SUB:
930 case Token::MUL: 926 case Token::MUL:
931 case Token::DIV: { 927 case Token::DIV: {
932 FloatingPointHelper::LoadSSE2UnknownOperands(masm, non_numeric_failure); 928 FloatingPointHelper::LoadSSE2UnknownOperands(masm, non_numeric_failure);
933 929
934 switch (op_) { 930 switch (op_) {
935 case Token::ADD: __ addsd(xmm0, xmm1); break; 931 case Token::ADD: __ addsd(xmm0, xmm1); break;
936 case Token::SUB: __ subsd(xmm0, xmm1); break; 932 case Token::SUB: __ subsd(xmm0, xmm1); break;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 __ Integer32ToSmi(rdx, rbx); 1011 __ Integer32ToSmi(rdx, rbx);
1016 __ jmp(allocation_failure); 1012 __ jmp(allocation_failure);
1017 } 1013 }
1018 break; 1014 break;
1019 } 1015 }
1020 default: UNREACHABLE(); break; 1016 default: UNREACHABLE(); break;
1021 } 1017 }
1022 // No fall-through from this generated code. 1018 // No fall-through from this generated code.
1023 if (FLAG_debug_code) { 1019 if (FLAG_debug_code) {
1024 __ Abort("Unexpected fall-through in " 1020 __ Abort("Unexpected fall-through in "
1025 "TypeRecordingBinaryStub::GenerateFloatingPointCode."); 1021 "BinaryStub::GenerateFloatingPointCode.");
1026 } 1022 }
1027 } 1023 }
1028 1024
1029 1025
1030 void TypeRecordingBinaryOpStub::GenerateStringAddCode(MacroAssembler* masm) { 1026 void BinaryOpStub::GenerateStringAddCode(MacroAssembler* masm) {
1031 ASSERT(op_ == Token::ADD); 1027 ASSERT(op_ == Token::ADD);
1032 Label left_not_string, call_runtime; 1028 Label left_not_string, call_runtime;
1033 1029
1034 // Registers containing left and right operands respectively. 1030 // Registers containing left and right operands respectively.
1035 Register left = rdx; 1031 Register left = rdx;
1036 Register right = rax; 1032 Register right = rax;
1037 1033
1038 // Test if left operand is a string. 1034 // Test if left operand is a string.
1039 __ JumpIfSmi(left, &left_not_string, Label::kNear); 1035 __ JumpIfSmi(left, &left_not_string, Label::kNear);
1040 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx); 1036 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx);
(...skipping 10 matching lines...) Expand all
1051 1047
1052 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); 1048 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
1053 GenerateRegisterArgsPush(masm); 1049 GenerateRegisterArgsPush(masm);
1054 __ TailCallStub(&string_add_right_stub); 1050 __ TailCallStub(&string_add_right_stub);
1055 1051
1056 // Neither argument is a string. 1052 // Neither argument is a string.
1057 __ bind(&call_runtime); 1053 __ bind(&call_runtime);
1058 } 1054 }
1059 1055
1060 1056
1061 void TypeRecordingBinaryOpStub::GenerateCallRuntimeCode(MacroAssembler* masm) { 1057 void BinaryOpStub::GenerateCallRuntimeCode(MacroAssembler* masm) {
1062 GenerateRegisterArgsPush(masm); 1058 GenerateRegisterArgsPush(masm);
1063 switch (op_) { 1059 switch (op_) {
1064 case Token::ADD: 1060 case Token::ADD:
1065 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); 1061 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
1066 break; 1062 break;
1067 case Token::SUB: 1063 case Token::SUB:
1068 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); 1064 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
1069 break; 1065 break;
1070 case Token::MUL: 1066 case Token::MUL:
1071 __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION); 1067 __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
(...skipping 21 matching lines...) Expand all
1093 break; 1089 break;
1094 case Token::SHR: 1090 case Token::SHR:
1095 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); 1091 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
1096 break; 1092 break;
1097 default: 1093 default:
1098 UNREACHABLE(); 1094 UNREACHABLE();
1099 } 1095 }
1100 } 1096 }
1101 1097
1102 1098
1103 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 1099 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
1104 Label call_runtime; 1100 Label call_runtime;
1105 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || 1101 if (result_type_ == BinaryOpIC::UNINITIALIZED ||
1106 result_type_ == TRBinaryOpIC::SMI) { 1102 result_type_ == BinaryOpIC::SMI) {
1107 // Only allow smi results. 1103 // Only allow smi results.
1108 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS); 1104 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS);
1109 } else { 1105 } else {
1110 // Allow heap number result and don't make a transition if a heap number 1106 // Allow heap number result and don't make a transition if a heap number
1111 // cannot be allocated. 1107 // cannot be allocated.
1112 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); 1108 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
1113 } 1109 }
1114 1110
1115 // Code falls through if the result is not returned as either a smi or heap 1111 // Code falls through if the result is not returned as either a smi or heap
1116 // number. 1112 // number.
1117 GenerateTypeTransition(masm); 1113 GenerateTypeTransition(masm);
1118 1114
1119 if (call_runtime.is_linked()) { 1115 if (call_runtime.is_linked()) {
1120 __ bind(&call_runtime); 1116 __ bind(&call_runtime);
1121 GenerateCallRuntimeCode(masm); 1117 GenerateCallRuntimeCode(masm);
1122 } 1118 }
1123 } 1119 }
1124 1120
1125 1121
1126 void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) { 1122 void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
1127 ASSERT(operands_type_ == TRBinaryOpIC::STRING); 1123 ASSERT(operands_type_ == BinaryOpIC::STRING);
1128 ASSERT(op_ == Token::ADD); 1124 ASSERT(op_ == Token::ADD);
1129 GenerateStringAddCode(masm); 1125 GenerateStringAddCode(masm);
1130 // Try to add arguments as strings, otherwise, transition to the generic 1126 // Try to add arguments as strings, otherwise, transition to the generic
1131 // TRBinaryOpIC type. 1127 // BinaryOpIC type.
1132 GenerateTypeTransition(masm); 1128 GenerateTypeTransition(masm);
1133 } 1129 }
1134 1130
1135 1131
1136 void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) { 1132 void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
1137 Label call_runtime; 1133 Label call_runtime;
1138 ASSERT(operands_type_ == TRBinaryOpIC::BOTH_STRING); 1134 ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
1139 ASSERT(op_ == Token::ADD); 1135 ASSERT(op_ == Token::ADD);
1140 // If both arguments are strings, call the string add stub. 1136 // If both arguments are strings, call the string add stub.
1141 // Otherwise, do a transition. 1137 // Otherwise, do a transition.
1142 1138
1143 // Registers containing left and right operands respectively. 1139 // Registers containing left and right operands respectively.
1144 Register left = rdx; 1140 Register left = rdx;
1145 Register right = rax; 1141 Register right = rax;
1146 1142
1147 // Test if left operand is a string. 1143 // Test if left operand is a string.
1148 __ JumpIfSmi(left, &call_runtime); 1144 __ JumpIfSmi(left, &call_runtime);
1149 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx); 1145 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx);
1150 __ j(above_equal, &call_runtime); 1146 __ j(above_equal, &call_runtime);
1151 1147
1152 // Test if right operand is a string. 1148 // Test if right operand is a string.
1153 __ JumpIfSmi(right, &call_runtime); 1149 __ JumpIfSmi(right, &call_runtime);
1154 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx); 1150 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx);
1155 __ j(above_equal, &call_runtime); 1151 __ j(above_equal, &call_runtime);
1156 1152
1157 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); 1153 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
1158 GenerateRegisterArgsPush(masm); 1154 GenerateRegisterArgsPush(masm);
1159 __ TailCallStub(&string_add_stub); 1155 __ TailCallStub(&string_add_stub);
1160 1156
1161 __ bind(&call_runtime); 1157 __ bind(&call_runtime);
1162 GenerateTypeTransition(masm); 1158 GenerateTypeTransition(masm);
1163 } 1159 }
1164 1160
1165 1161
1166 void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { 1162 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
1167 Label call_runtime; 1163 Label call_runtime;
1168 1164
1169 if (op_ == Token::ADD) { 1165 if (op_ == Token::ADD) {
1170 // Handle string addition here, because it is the only operation 1166 // Handle string addition here, because it is the only operation
1171 // that does not do a ToNumber conversion on the operands. 1167 // that does not do a ToNumber conversion on the operands.
1172 GenerateStringAddCode(masm); 1168 GenerateStringAddCode(masm);
1173 } 1169 }
1174 1170
1175 // Convert oddball arguments to numbers. 1171 // Convert oddball arguments to numbers.
1176 Label check, done; 1172 Label check, done;
(...skipping 12 matching lines...) Expand all
1189 __ xor_(rax, rax); 1185 __ xor_(rax, rax);
1190 } else { 1186 } else {
1191 __ LoadRoot(rax, Heap::kNanValueRootIndex); 1187 __ LoadRoot(rax, Heap::kNanValueRootIndex);
1192 } 1188 }
1193 __ bind(&done); 1189 __ bind(&done);
1194 1190
1195 GenerateHeapNumberStub(masm); 1191 GenerateHeapNumberStub(masm);
1196 } 1192 }
1197 1193
1198 1194
1199 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { 1195 void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
1200 Label gc_required, not_number; 1196 Label gc_required, not_number;
1201 GenerateFloatingPointCode(masm, &gc_required, &not_number); 1197 GenerateFloatingPointCode(masm, &gc_required, &not_number);
1202 1198
1203 __ bind(&not_number); 1199 __ bind(&not_number);
1204 GenerateTypeTransition(masm); 1200 GenerateTypeTransition(masm);
1205 1201
1206 __ bind(&gc_required); 1202 __ bind(&gc_required);
1207 GenerateCallRuntimeCode(masm); 1203 GenerateCallRuntimeCode(masm);
1208 } 1204 }
1209 1205
1210 1206
1211 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { 1207 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
1212 Label call_runtime, call_string_add_or_runtime; 1208 Label call_runtime, call_string_add_or_runtime;
1213 1209
1214 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); 1210 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
1215 1211
1216 GenerateFloatingPointCode(masm, &call_runtime, &call_string_add_or_runtime); 1212 GenerateFloatingPointCode(masm, &call_runtime, &call_string_add_or_runtime);
1217 1213
1218 __ bind(&call_string_add_or_runtime); 1214 __ bind(&call_string_add_or_runtime);
1219 if (op_ == Token::ADD) { 1215 if (op_ == Token::ADD) {
1220 GenerateStringAddCode(masm); 1216 GenerateStringAddCode(masm);
1221 } 1217 }
1222 1218
1223 __ bind(&call_runtime); 1219 __ bind(&call_runtime);
1224 GenerateCallRuntimeCode(masm); 1220 GenerateCallRuntimeCode(masm);
1225 } 1221 }
1226 1222
1227 1223
1228 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( 1224 void BinaryOpStub::GenerateHeapResultAllocation(MacroAssembler* masm,
1229 MacroAssembler* masm, 1225 Label* alloc_failure) {
1230 Label* alloc_failure) {
1231 Label skip_allocation; 1226 Label skip_allocation;
1232 OverwriteMode mode = mode_; 1227 OverwriteMode mode = mode_;
1233 switch (mode) { 1228 switch (mode) {
1234 case OVERWRITE_LEFT: { 1229 case OVERWRITE_LEFT: {
1235 // If the argument in rdx is already an object, we skip the 1230 // If the argument in rdx is already an object, we skip the
1236 // allocation of a heap number. 1231 // allocation of a heap number.
1237 __ JumpIfNotSmi(rdx, &skip_allocation); 1232 __ JumpIfNotSmi(rdx, &skip_allocation);
1238 // Allocate a heap number for the result. Keep eax and edx intact 1233 // Allocate a heap number for the result. Keep eax and edx intact
1239 // for the possible runtime call. 1234 // for the possible runtime call.
1240 __ AllocateHeapNumber(rbx, rcx, alloc_failure); 1235 __ AllocateHeapNumber(rbx, rcx, alloc_failure);
(...skipping 17 matching lines...) Expand all
1258 // Now rax can be overwritten losing one of the arguments as we are 1253 // Now rax can be overwritten losing one of the arguments as we are
1259 // now done and will not need it any more. 1254 // now done and will not need it any more.
1260 __ movq(rax, rbx); 1255 __ movq(rax, rbx);
1261 __ bind(&skip_allocation); 1256 __ bind(&skip_allocation);
1262 break; 1257 break;
1263 default: UNREACHABLE(); 1258 default: UNREACHABLE();
1264 } 1259 }
1265 } 1260 }
1266 1261
1267 1262
1268 void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { 1263 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
1269 __ pop(rcx); 1264 __ pop(rcx);
1270 __ push(rdx); 1265 __ push(rdx);
1271 __ push(rax); 1266 __ push(rax);
1272 __ push(rcx); 1267 __ push(rcx);
1273 } 1268 }
1274 1269
1275 1270
1276 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { 1271 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
1277 // TAGGED case: 1272 // TAGGED case:
1278 // Input: 1273 // Input:
(...skipping 3845 matching lines...) Expand 10 before | Expand all | Expand 10 after
5124 __ Drop(1); 5119 __ Drop(1);
5125 __ ret(2 * kPointerSize); 5120 __ ret(2 * kPointerSize);
5126 } 5121 }
5127 5122
5128 5123
5129 #undef __ 5124 #undef __
5130 5125
5131 } } // namespace v8::internal 5126 } } // namespace v8::internal
5132 5127
5133 #endif // V8_TARGET_ARCH_X64 5128 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698