OLD | NEW |
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 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 } | 586 } |
587 } | 587 } |
588 | 588 |
589 | 589 |
590 void LCodeGen::DoParameter(LParameter* instr) { | 590 void LCodeGen::DoParameter(LParameter* instr) { |
591 // Nothing to do. | 591 // Nothing to do. |
592 } | 592 } |
593 | 593 |
594 | 594 |
595 void LCodeGen::DoCallStub(LCallStub* instr) { | 595 void LCodeGen::DoCallStub(LCallStub* instr) { |
596 Abort("Unimplemented: %s", "DoCallStub"); | 596 ASSERT(ToRegister(instr->result()).is(rax)); |
| 597 switch (instr->hydrogen()->major_key()) { |
| 598 case CodeStub::RegExpConstructResult: { |
| 599 RegExpConstructResultStub stub; |
| 600 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 601 break; |
| 602 } |
| 603 case CodeStub::RegExpExec: { |
| 604 RegExpExecStub stub; |
| 605 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 606 break; |
| 607 } |
| 608 case CodeStub::SubString: { |
| 609 SubStringStub stub; |
| 610 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 611 break; |
| 612 } |
| 613 case CodeStub::StringCharAt: { |
| 614 // TODO(1116): Add StringCharAt stub to x64. |
| 615 Abort("Unimplemented: %s", "StringCharAt Stub"); |
| 616 break; |
| 617 } |
| 618 case CodeStub::MathPow: { |
| 619 // TODO(1115): Add MathPow stub to x64. |
| 620 Abort("Unimplemented: %s", "MathPow Stub"); |
| 621 break; |
| 622 } |
| 623 case CodeStub::NumberToString: { |
| 624 NumberToStringStub stub; |
| 625 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 626 break; |
| 627 } |
| 628 case CodeStub::StringAdd: { |
| 629 StringAddStub stub(NO_STRING_ADD_FLAGS); |
| 630 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 631 break; |
| 632 } |
| 633 case CodeStub::StringCompare: { |
| 634 StringCompareStub stub; |
| 635 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 636 break; |
| 637 } |
| 638 case CodeStub::TranscendentalCache: { |
| 639 TranscendentalCacheStub stub(instr->transcendental_type()); |
| 640 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 641 break; |
| 642 } |
| 643 default: |
| 644 UNREACHABLE(); |
| 645 } |
597 } | 646 } |
598 | 647 |
599 | 648 |
600 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 649 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
601 // Nothing to do. | 650 // Nothing to do. |
602 } | 651 } |
603 | 652 |
604 | 653 |
605 void LCodeGen::DoModI(LModI* instr) { | 654 void LCodeGen::DoModI(LModI* instr) { |
606 Abort("Unimplemented: %s", "DoModI"); | 655 Abort("Unimplemented: %s", "DoModI"); |
607 } | 656 } |
608 | 657 |
609 | 658 |
610 void LCodeGen::DoDivI(LDivI* instr) { | 659 void LCodeGen::DoDivI(LDivI* instr) { |
611 Abort("Unimplemented: %s", "DoDivI");} | 660 LOperand* right = instr->InputAt(1); |
| 661 ASSERT(ToRegister(instr->result()).is(rax)); |
| 662 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); |
| 663 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); |
| 664 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); |
| 665 |
| 666 Register left_reg = rax; |
| 667 |
| 668 // Check for x / 0. |
| 669 Register right_reg = ToRegister(right); |
| 670 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 671 __ testl(right_reg, right_reg); |
| 672 DeoptimizeIf(zero, instr->environment()); |
| 673 } |
| 674 |
| 675 // Check for (0 / -x) that will produce negative zero. |
| 676 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 677 NearLabel left_not_zero; |
| 678 __ testl(left_reg, left_reg); |
| 679 __ j(not_zero, &left_not_zero); |
| 680 __ testl(right_reg, right_reg); |
| 681 DeoptimizeIf(sign, instr->environment()); |
| 682 __ bind(&left_not_zero); |
| 683 } |
| 684 |
| 685 // Check for (-kMinInt / -1). |
| 686 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 687 NearLabel left_not_min_int; |
| 688 __ cmpl(left_reg, Immediate(kMinInt)); |
| 689 __ j(not_zero, &left_not_min_int); |
| 690 __ cmpl(right_reg, Immediate(-1)); |
| 691 DeoptimizeIf(zero, instr->environment()); |
| 692 __ bind(&left_not_min_int); |
| 693 } |
| 694 |
| 695 // Sign extend to rdx. |
| 696 __ cdq(); |
| 697 __ idivl(right_reg); |
| 698 |
| 699 // Deoptimize if remainder is not 0. |
| 700 __ testl(rdx, rdx); |
| 701 DeoptimizeIf(not_zero, instr->environment()); |
| 702 } |
612 | 703 |
613 | 704 |
614 void LCodeGen::DoMulI(LMulI* instr) { | 705 void LCodeGen::DoMulI(LMulI* instr) { |
615 Abort("Unimplemented: %s", "DoMultI");} | 706 Register left = ToRegister(instr->InputAt(0)); |
| 707 LOperand* right = instr->InputAt(1); |
| 708 |
| 709 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 710 __ movl(kScratchRegister, left); |
| 711 } |
| 712 |
| 713 if (right->IsConstantOperand()) { |
| 714 int right_value = ToInteger32(LConstantOperand::cast(right)); |
| 715 __ imull(left, left, Immediate(right_value)); |
| 716 } else if (right->IsStackSlot()) { |
| 717 __ imull(left, ToOperand(right)); |
| 718 } else { |
| 719 __ imull(left, ToRegister(right)); |
| 720 } |
| 721 |
| 722 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 723 DeoptimizeIf(overflow, instr->environment()); |
| 724 } |
| 725 |
| 726 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 727 // Bail out if the result is supposed to be negative zero. |
| 728 NearLabel done; |
| 729 __ testl(left, left); |
| 730 __ j(not_zero, &done); |
| 731 if (right->IsConstantOperand()) { |
| 732 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { |
| 733 DeoptimizeIf(no_condition, instr->environment()); |
| 734 } |
| 735 } else if (right->IsStackSlot()) { |
| 736 __ or_(kScratchRegister, ToOperand(right)); |
| 737 DeoptimizeIf(sign, instr->environment()); |
| 738 } else { |
| 739 // Test the non-zero operand for negative sign. |
| 740 __ or_(kScratchRegister, ToRegister(right)); |
| 741 DeoptimizeIf(sign, instr->environment()); |
| 742 } |
| 743 __ bind(&done); |
| 744 } |
| 745 } |
616 | 746 |
617 | 747 |
618 void LCodeGen::DoBitI(LBitI* instr) { | 748 void LCodeGen::DoBitI(LBitI* instr) { |
619 LOperand* left = instr->InputAt(0); | 749 LOperand* left = instr->InputAt(0); |
620 LOperand* right = instr->InputAt(1); | 750 LOperand* right = instr->InputAt(1); |
621 ASSERT(left->Equals(instr->result())); | 751 ASSERT(left->Equals(instr->result())); |
622 ASSERT(left->IsRegister()); | 752 ASSERT(left->IsRegister()); |
623 | 753 |
624 if (right->IsConstantOperand()) { | 754 if (right->IsConstantOperand()) { |
625 int right_operand = ToInteger32(LConstantOperand::cast(right)); | 755 int right_operand = ToInteger32(LConstantOperand::cast(right)); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 | 933 |
804 | 934 |
805 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 935 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
806 LOperand* input = instr->InputAt(0); | 936 LOperand* input = instr->InputAt(0); |
807 ASSERT(input->Equals(instr->result())); | 937 ASSERT(input->Equals(instr->result())); |
808 __ not_(ToRegister(input)); | 938 __ not_(ToRegister(input)); |
809 } | 939 } |
810 | 940 |
811 | 941 |
812 void LCodeGen::DoThrow(LThrow* instr) { | 942 void LCodeGen::DoThrow(LThrow* instr) { |
813 Abort("Unimplemented: %s", "DoThrow"); | 943 __ push(ToRegister(instr->InputAt(0))); |
| 944 CallRuntime(Runtime::kThrow, 1, instr); |
| 945 |
| 946 if (FLAG_debug_code) { |
| 947 Comment("Unreachable code."); |
| 948 __ int3(); |
| 949 } |
814 } | 950 } |
815 | 951 |
816 | 952 |
817 void LCodeGen::DoAddI(LAddI* instr) { | 953 void LCodeGen::DoAddI(LAddI* instr) { |
818 LOperand* left = instr->InputAt(0); | 954 LOperand* left = instr->InputAt(0); |
819 LOperand* right = instr->InputAt(1); | 955 LOperand* right = instr->InputAt(1); |
820 ASSERT(left->Equals(instr->result())); | 956 ASSERT(left->Equals(instr->result())); |
821 | 957 |
822 if (right->IsConstantOperand()) { | 958 if (right->IsConstantOperand()) { |
823 __ addl(ToRegister(left), | 959 __ addl(ToRegister(left), |
(...skipping 13 matching lines...) Expand all Loading... |
837 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 973 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
838 Abort("Unimplemented: %s", "DoArithmeticD"); | 974 Abort("Unimplemented: %s", "DoArithmeticD"); |
839 } | 975 } |
840 | 976 |
841 | 977 |
842 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 978 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
843 ASSERT(ToRegister(instr->InputAt(0)).is(rdx)); | 979 ASSERT(ToRegister(instr->InputAt(0)).is(rdx)); |
844 ASSERT(ToRegister(instr->InputAt(1)).is(rax)); | 980 ASSERT(ToRegister(instr->InputAt(1)).is(rax)); |
845 ASSERT(ToRegister(instr->result()).is(rax)); | 981 ASSERT(ToRegister(instr->result()).is(rax)); |
846 | 982 |
847 GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, NO_GENERIC_BINARY_FLAGS); | 983 TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); |
848 stub.SetArgsInRegisters(); | |
849 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 984 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
850 } | 985 } |
851 | 986 |
852 | 987 |
853 int LCodeGen::GetNextEmittedBlock(int block) { | 988 int LCodeGen::GetNextEmittedBlock(int block) { |
854 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 989 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
855 LLabel* label = chunk_->GetLabel(i); | 990 LLabel* label = chunk_->GetLabel(i); |
856 if (!label->HasReplacement()) return i; | 991 if (!label->HasReplacement()) return i; |
857 } | 992 } |
858 return -1; | 993 return -1; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
956 __ jmp(deferred_stack_check->entry()); | 1091 __ jmp(deferred_stack_check->entry()); |
957 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block)); | 1092 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block)); |
958 } else { | 1093 } else { |
959 __ jmp(chunk_->GetAssemblyLabel(block)); | 1094 __ jmp(chunk_->GetAssemblyLabel(block)); |
960 } | 1095 } |
961 } | 1096 } |
962 } | 1097 } |
963 | 1098 |
964 | 1099 |
965 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { | 1100 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { |
966 Abort("Unimplemented: %s", "DoDeferredStackCheck"); | 1101 __ Pushad(); |
| 1102 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| 1103 RecordSafepointWithRegisters( |
| 1104 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 1105 __ Popad(); |
967 } | 1106 } |
968 | 1107 |
969 | 1108 |
970 void LCodeGen::DoGoto(LGoto* instr) { | 1109 void LCodeGen::DoGoto(LGoto* instr) { |
971 class DeferredStackCheck: public LDeferredCode { | 1110 class DeferredStackCheck: public LDeferredCode { |
972 public: | 1111 public: |
973 DeferredStackCheck(LCodeGen* codegen, LGoto* instr) | 1112 DeferredStackCheck(LCodeGen* codegen, LGoto* instr) |
974 : LDeferredCode(codegen), instr_(instr) { } | 1113 : LDeferredCode(codegen), instr_(instr) { } |
975 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 1114 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } |
976 private: | 1115 private: |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 | 1154 |
1016 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { | 1155 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { |
1017 if (right->IsConstantOperand()) { | 1156 if (right->IsConstantOperand()) { |
1018 int32_t value = ToInteger32(LConstantOperand::cast(right)); | 1157 int32_t value = ToInteger32(LConstantOperand::cast(right)); |
1019 if (left->IsRegister()) { | 1158 if (left->IsRegister()) { |
1020 __ cmpl(ToRegister(left), Immediate(value)); | 1159 __ cmpl(ToRegister(left), Immediate(value)); |
1021 } else { | 1160 } else { |
1022 __ cmpl(ToOperand(left), Immediate(value)); | 1161 __ cmpl(ToOperand(left), Immediate(value)); |
1023 } | 1162 } |
1024 } else if (right->IsRegister()) { | 1163 } else if (right->IsRegister()) { |
1025 __ cmpq(ToRegister(left), ToRegister(right)); | 1164 __ cmpl(ToRegister(left), ToRegister(right)); |
1026 } else { | 1165 } else { |
1027 __ cmpq(ToRegister(left), ToOperand(right)); | 1166 __ cmpl(ToRegister(left), ToOperand(right)); |
1028 } | 1167 } |
1029 } | 1168 } |
1030 | 1169 |
1031 | 1170 |
1032 void LCodeGen::DoCmpID(LCmpID* instr) { | 1171 void LCodeGen::DoCmpID(LCmpID* instr) { |
1033 LOperand* left = instr->InputAt(0); | 1172 LOperand* left = instr->InputAt(0); |
1034 LOperand* right = instr->InputAt(1); | 1173 LOperand* right = instr->InputAt(1); |
1035 LOperand* result = instr->result(); | 1174 LOperand* result = instr->result(); |
1036 | 1175 |
1037 NearLabel unordered; | 1176 NearLabel unordered; |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1504 | 1643 |
1505 void LCodeGen::DoReturn(LReturn* instr) { | 1644 void LCodeGen::DoReturn(LReturn* instr) { |
1506 if (FLAG_trace) { | 1645 if (FLAG_trace) { |
1507 // Preserve the return value on the stack and rely on the runtime | 1646 // Preserve the return value on the stack and rely on the runtime |
1508 // call to return the value in the same register. | 1647 // call to return the value in the same register. |
1509 __ push(rax); | 1648 __ push(rax); |
1510 __ CallRuntime(Runtime::kTraceExit, 1); | 1649 __ CallRuntime(Runtime::kTraceExit, 1); |
1511 } | 1650 } |
1512 __ movq(rsp, rbp); | 1651 __ movq(rsp, rbp); |
1513 __ pop(rbp); | 1652 __ pop(rbp); |
1514 __ ret((ParameterCount() + 1) * kPointerSize); | 1653 __ Ret((ParameterCount() + 1) * kPointerSize, rcx); |
1515 } | 1654 } |
1516 | 1655 |
1517 | 1656 |
1518 void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) { | 1657 void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) { |
1519 Abort("Unimplemented: %s", "DoLoadGlobal"); | 1658 Register result = ToRegister(instr->result()); |
| 1659 if (result.is(rax)) { |
| 1660 __ load_rax(instr->hydrogen()->cell().location(), |
| 1661 RelocInfo::GLOBAL_PROPERTY_CELL); |
| 1662 } else { |
| 1663 __ movq(result, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL); |
| 1664 __ movq(result, Operand(result, 0)); |
| 1665 } |
| 1666 if (instr->hydrogen()->check_hole_value()) { |
| 1667 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 1668 DeoptimizeIf(equal, instr->environment()); |
| 1669 } |
1520 } | 1670 } |
1521 | 1671 |
1522 | 1672 |
1523 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { | 1673 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { |
1524 Register value = ToRegister(instr->InputAt(0)); | 1674 Register value = ToRegister(instr->InputAt(0)); |
1525 Register temp = ToRegister(instr->TempAt(0)); | 1675 Register temp = ToRegister(instr->TempAt(0)); |
1526 ASSERT(!value.is(temp)); | 1676 ASSERT(!value.is(temp)); |
1527 bool check_hole = instr->hydrogen()->check_hole_value(); | 1677 bool check_hole = instr->hydrogen()->check_hole_value(); |
1528 if (!check_hole && value.is(rax)) { | 1678 if (!check_hole && value.is(rax)) { |
1529 __ store_rax(instr->hydrogen()->cell().location(), | 1679 __ store_rax(instr->hydrogen()->cell().location(), |
1530 RelocInfo::GLOBAL_PROPERTY_CELL); | 1680 RelocInfo::GLOBAL_PROPERTY_CELL); |
1531 return; | 1681 return; |
1532 } | 1682 } |
1533 // If the cell we are storing to contains the hole it could have | 1683 // If the cell we are storing to contains the hole it could have |
1534 // been deleted from the property dictionary. In that case, we need | 1684 // been deleted from the property dictionary. In that case, we need |
1535 // to update the property details in the property dictionary to mark | 1685 // to update the property details in the property dictionary to mark |
1536 // it as no longer deleted. We deoptimize in that case. | 1686 // it as no longer deleted. We deoptimize in that case. |
1537 __ movq(temp, | 1687 __ movq(temp, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL); |
1538 Handle<Object>::cast(instr->hydrogen()->cell()), | |
1539 RelocInfo::GLOBAL_PROPERTY_CELL); | |
1540 if (check_hole) { | 1688 if (check_hole) { |
1541 __ CompareRoot(Operand(temp, 0), Heap::kTheHoleValueRootIndex); | 1689 __ CompareRoot(Operand(temp, 0), Heap::kTheHoleValueRootIndex); |
1542 DeoptimizeIf(equal, instr->environment()); | 1690 DeoptimizeIf(equal, instr->environment()); |
1543 } | 1691 } |
1544 __ movq(Operand(temp, 0), value); | 1692 __ movq(Operand(temp, 0), value); |
1545 } | 1693 } |
1546 | 1694 |
1547 | 1695 |
1548 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 1696 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
1549 Abort("Unimplemented: %s", "DoLoadContextSlot"); | 1697 Abort("Unimplemented: %s", "DoLoadContextSlot"); |
1550 } | 1698 } |
1551 | 1699 |
1552 | 1700 |
1553 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 1701 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
1554 Register object = ToRegister(instr->InputAt(0)); | 1702 Register object = ToRegister(instr->InputAt(0)); |
1555 Register result = ToRegister(instr->result()); | 1703 Register result = ToRegister(instr->result()); |
1556 if (instr->hydrogen()->is_in_object()) { | 1704 if (instr->hydrogen()->is_in_object()) { |
1557 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); | 1705 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); |
1558 } else { | 1706 } else { |
1559 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 1707 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
1560 __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); | 1708 __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); |
1561 } | 1709 } |
1562 } | 1710 } |
1563 | 1711 |
1564 | 1712 |
1565 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 1713 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
1566 Abort("Unimplemented: %s", "DoLoadNamedGeneric"); | 1714 ASSERT(ToRegister(instr->object()).is(rax)); |
| 1715 ASSERT(ToRegister(instr->result()).is(rax)); |
| 1716 |
| 1717 __ Move(rcx, instr->name()); |
| 1718 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1719 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
1567 } | 1720 } |
1568 | 1721 |
1569 | 1722 |
1570 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 1723 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
1571 Abort("Unimplemented: %s", "DoLoadFunctionPrototype"); | 1724 Abort("Unimplemented: %s", "DoLoadFunctionPrototype"); |
1572 } | 1725 } |
1573 | 1726 |
1574 | 1727 |
1575 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 1728 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
1576 ASSERT(instr->result()->Equals(instr->InputAt(0))); | 1729 ASSERT(instr->result()->Equals(instr->InputAt(0))); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1848 if (instr->length()->IsRegister()) { | 2001 if (instr->length()->IsRegister()) { |
1849 __ cmpq(ToRegister(instr->index()), ToRegister(instr->length())); | 2002 __ cmpq(ToRegister(instr->index()), ToRegister(instr->length())); |
1850 } else { | 2003 } else { |
1851 __ cmpq(ToRegister(instr->index()), ToOperand(instr->length())); | 2004 __ cmpq(ToRegister(instr->index()), ToOperand(instr->length())); |
1852 } | 2005 } |
1853 DeoptimizeIf(above_equal, instr->environment()); | 2006 DeoptimizeIf(above_equal, instr->environment()); |
1854 } | 2007 } |
1855 | 2008 |
1856 | 2009 |
1857 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 2010 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
1858 Abort("Unimplemented: %s", "DoStoreKeyedFastElement"); | 2011 Register value = ToRegister(instr->value()); |
| 2012 Register elements = ToRegister(instr->object()); |
| 2013 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; |
| 2014 |
| 2015 // Do the store. |
| 2016 if (instr->key()->IsConstantOperand()) { |
| 2017 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 2018 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| 2019 int offset = |
| 2020 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; |
| 2021 __ movq(FieldOperand(elements, offset), value); |
| 2022 } else { |
| 2023 __ movq(FieldOperand(elements, |
| 2024 key, |
| 2025 times_pointer_size, |
| 2026 FixedArray::kHeaderSize), |
| 2027 value); |
| 2028 } |
| 2029 |
| 2030 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 2031 // Compute address of modified element and store it into key register. |
| 2032 __ lea(key, FieldOperand(elements, |
| 2033 key, |
| 2034 times_pointer_size, |
| 2035 FixedArray::kHeaderSize)); |
| 2036 __ RecordWrite(elements, key, value); |
| 2037 } |
1859 } | 2038 } |
1860 | 2039 |
1861 | 2040 |
1862 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 2041 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
1863 Abort("Unimplemented: %s", "DoStoreKeyedGeneric"); | 2042 Abort("Unimplemented: %s", "DoStoreKeyedGeneric"); |
1864 } | 2043 } |
1865 | 2044 |
1866 | 2045 |
1867 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 2046 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
1868 LOperand* input = instr->InputAt(0); | 2047 LOperand* input = instr->InputAt(0); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1919 RecordSafepointWithRegisters( | 2098 RecordSafepointWithRegisters( |
1920 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | 2099 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
1921 // Ensure that value in rax survives popping registers. | 2100 // Ensure that value in rax survives popping registers. |
1922 __ movq(kScratchRegister, rax); | 2101 __ movq(kScratchRegister, rax); |
1923 __ PopSafepointRegisters(); | 2102 __ PopSafepointRegisters(); |
1924 __ movq(reg, kScratchRegister); | 2103 __ movq(reg, kScratchRegister); |
1925 } | 2104 } |
1926 | 2105 |
1927 | 2106 |
1928 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 2107 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
1929 Abort("Unimplemented: %s", "DoSmiTag"); | 2108 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 2109 Register input = ToRegister(instr->InputAt(0)); |
| 2110 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 2111 __ Integer32ToSmi(input, input); |
1930 } | 2112 } |
1931 | 2113 |
1932 | 2114 |
1933 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 2115 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
1934 Abort("Unimplemented: %s", "DoSmiUntag"); | 2116 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 2117 Register input = ToRegister(instr->InputAt(0)); |
| 2118 if (instr->needs_check()) { |
| 2119 Condition is_smi = __ CheckSmi(input); |
| 2120 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |
| 2121 } |
| 2122 __ SmiToInteger32(input, input); |
1935 } | 2123 } |
1936 | 2124 |
1937 | 2125 |
1938 void LCodeGen::EmitNumberUntagD(Register input_reg, | 2126 void LCodeGen::EmitNumberUntagD(Register input_reg, |
1939 XMMRegister result_reg, | 2127 XMMRegister result_reg, |
1940 LEnvironment* env) { | 2128 LEnvironment* env) { |
1941 NearLabel load_smi, heap_number, done; | 2129 NearLabel load_smi, heap_number, done; |
1942 | 2130 |
1943 // Smi check. | 2131 // Smi check. |
1944 __ JumpIfSmi(input_reg, &load_smi); | 2132 __ JumpIfSmi(input_reg, &load_smi); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2103 LOperand* input = instr->InputAt(0); | 2291 LOperand* input = instr->InputAt(0); |
2104 ASSERT(input->IsRegister()); | 2292 ASSERT(input->IsRegister()); |
2105 Register reg = ToRegister(input); | 2293 Register reg = ToRegister(input); |
2106 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), | 2294 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), |
2107 instr->hydrogen()->map()); | 2295 instr->hydrogen()->map()); |
2108 DeoptimizeIf(not_equal, instr->environment()); | 2296 DeoptimizeIf(not_equal, instr->environment()); |
2109 } | 2297 } |
2110 | 2298 |
2111 | 2299 |
2112 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { | 2300 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { |
2113 Abort("Unimplemented: %s", "LoadHeapObject"); | 2301 if (Heap::InNewSpace(*object)) { |
| 2302 Handle<JSGlobalPropertyCell> cell = |
| 2303 Factory::NewJSGlobalPropertyCell(object); |
| 2304 __ movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL); |
| 2305 __ movq(result, Operand(result, 0)); |
| 2306 } else { |
| 2307 __ Move(result, object); |
| 2308 } |
2114 } | 2309 } |
2115 | 2310 |
2116 | 2311 |
2117 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 2312 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
2118 Register reg = ToRegister(instr->TempAt(0)); | 2313 Register reg = ToRegister(instr->TempAt(0)); |
2119 | 2314 |
2120 Handle<JSObject> holder = instr->holder(); | 2315 Handle<JSObject> holder = instr->holder(); |
2121 Handle<JSObject> current_prototype = instr->prototype(); | 2316 Handle<JSObject> current_prototype = instr->prototype(); |
2122 | 2317 |
2123 // Load prototype object. | 2318 // Load prototype object. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2212 void LCodeGen::DoTypeof(LTypeof* instr) { | 2407 void LCodeGen::DoTypeof(LTypeof* instr) { |
2213 Abort("Unimplemented: %s", "DoTypeof"); | 2408 Abort("Unimplemented: %s", "DoTypeof"); |
2214 } | 2409 } |
2215 | 2410 |
2216 | 2411 |
2217 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 2412 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
2218 Abort("Unimplemented: %s", "DoTypeofIs"); | 2413 Abort("Unimplemented: %s", "DoTypeofIs"); |
2219 } | 2414 } |
2220 | 2415 |
2221 | 2416 |
| 2417 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { |
| 2418 Register result = ToRegister(instr->result()); |
| 2419 NearLabel true_label; |
| 2420 NearLabel false_label; |
| 2421 NearLabel done; |
| 2422 |
| 2423 EmitIsConstructCall(result); |
| 2424 __ j(equal, &true_label); |
| 2425 |
| 2426 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 2427 __ jmp(&done); |
| 2428 |
| 2429 __ bind(&true_label); |
| 2430 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 2431 |
| 2432 |
| 2433 __ bind(&done); |
| 2434 } |
| 2435 |
| 2436 |
| 2437 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 2438 Register temp = ToRegister(instr->TempAt(0)); |
| 2439 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2440 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2441 |
| 2442 EmitIsConstructCall(temp); |
| 2443 EmitBranch(true_block, false_block, equal); |
| 2444 } |
| 2445 |
| 2446 |
| 2447 void LCodeGen::EmitIsConstructCall(Register temp) { |
| 2448 // Get the frame pointer for the calling frame. |
| 2449 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2450 |
| 2451 // Skip the arguments adaptor frame if it exists. |
| 2452 NearLabel check_frame_marker; |
| 2453 __ SmiCompare(Operand(temp, StandardFrameConstants::kContextOffset), |
| 2454 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 2455 __ j(not_equal, &check_frame_marker); |
| 2456 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); |
| 2457 |
| 2458 // Check the marker in the calling frame. |
| 2459 __ bind(&check_frame_marker); |
| 2460 __ SmiCompare(Operand(temp, StandardFrameConstants::kMarkerOffset), |
| 2461 Smi::FromInt(StackFrame::CONSTRUCT)); |
| 2462 } |
| 2463 |
| 2464 |
2222 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 2465 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
2223 Register input = ToRegister(instr->InputAt(0)); | 2466 Register input = ToRegister(instr->InputAt(0)); |
2224 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2467 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2225 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2468 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2226 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2469 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
2227 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2470 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2228 | 2471 |
2229 Condition final_branch_condition = EmitTypeofIs(true_label, | 2472 Condition final_branch_condition = EmitTypeofIs(true_label, |
2230 false_label, | 2473 false_label, |
2231 input, | 2474 input, |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2329 | 2572 |
2330 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 2573 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
2331 Abort("Unimplemented: %s", "DoOsrEntry"); | 2574 Abort("Unimplemented: %s", "DoOsrEntry"); |
2332 } | 2575 } |
2333 | 2576 |
2334 #undef __ | 2577 #undef __ |
2335 | 2578 |
2336 } } // namespace v8::internal | 2579 } } // namespace v8::internal |
2337 | 2580 |
2338 #endif // V8_TARGET_ARCH_X64 | 2581 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |