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 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 } | 739 } |
740 } | 740 } |
741 | 741 |
742 | 742 |
743 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 743 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
744 // Nothing to do. | 744 // Nothing to do. |
745 } | 745 } |
746 | 746 |
747 | 747 |
748 void LCodeGen::DoModI(LModI* instr) { | 748 void LCodeGen::DoModI(LModI* instr) { |
749 LOperand* right = instr->right(); | 749 LOperand* right = instr->InputAt(1); |
750 ASSERT(ToRegister(instr->result()).is(edx)); | 750 ASSERT(ToRegister(instr->result()).is(edx)); |
751 ASSERT(ToRegister(instr->left()).is(eax)); | 751 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
752 ASSERT(!ToRegister(instr->right()).is(eax)); | 752 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); |
753 ASSERT(!ToRegister(instr->right()).is(edx)); | 753 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); |
754 | 754 |
755 Register right_reg = ToRegister(right); | 755 Register right_reg = ToRegister(right); |
756 | 756 |
757 // Check for x % 0. | 757 // Check for x % 0. |
758 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 758 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
759 __ test(right_reg, ToOperand(right)); | 759 __ test(right_reg, ToOperand(right)); |
760 DeoptimizeIf(zero, instr->environment()); | 760 DeoptimizeIf(zero, instr->environment()); |
761 } | 761 } |
762 | 762 |
763 // Sign extend to edx. | 763 // Sign extend to edx. |
(...skipping 15 matching lines...) Expand all Loading... |
779 __ bind(&positive_left); | 779 __ bind(&positive_left); |
780 __ idiv(right_reg); | 780 __ idiv(right_reg); |
781 __ bind(&done); | 781 __ bind(&done); |
782 } else { | 782 } else { |
783 __ idiv(right_reg); | 783 __ idiv(right_reg); |
784 } | 784 } |
785 } | 785 } |
786 | 786 |
787 | 787 |
788 void LCodeGen::DoDivI(LDivI* instr) { | 788 void LCodeGen::DoDivI(LDivI* instr) { |
789 LOperand* right = instr->right(); | 789 LOperand* right = instr->InputAt(1); |
790 ASSERT(ToRegister(instr->result()).is(eax)); | 790 ASSERT(ToRegister(instr->result()).is(eax)); |
791 ASSERT(ToRegister(instr->left()).is(eax)); | 791 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
792 ASSERT(!ToRegister(instr->right()).is(eax)); | 792 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); |
793 ASSERT(!ToRegister(instr->right()).is(edx)); | 793 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); |
794 | 794 |
795 Register left_reg = eax; | 795 Register left_reg = eax; |
796 | 796 |
797 // Check for x / 0. | 797 // Check for x / 0. |
798 Register right_reg = ToRegister(right); | 798 Register right_reg = ToRegister(right); |
799 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 799 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
800 __ test(right_reg, ToOperand(right)); | 800 __ test(right_reg, ToOperand(right)); |
801 DeoptimizeIf(zero, instr->environment()); | 801 DeoptimizeIf(zero, instr->environment()); |
802 } | 802 } |
803 | 803 |
(...skipping 21 matching lines...) Expand all Loading... |
825 __ cdq(); | 825 __ cdq(); |
826 __ idiv(right_reg); | 826 __ idiv(right_reg); |
827 | 827 |
828 // Deoptimize if remainder is not 0. | 828 // Deoptimize if remainder is not 0. |
829 __ test(edx, Operand(edx)); | 829 __ test(edx, Operand(edx)); |
830 DeoptimizeIf(not_zero, instr->environment()); | 830 DeoptimizeIf(not_zero, instr->environment()); |
831 } | 831 } |
832 | 832 |
833 | 833 |
834 void LCodeGen::DoMulI(LMulI* instr) { | 834 void LCodeGen::DoMulI(LMulI* instr) { |
835 Register left = ToRegister(instr->left()); | 835 Register left = ToRegister(instr->InputAt(0)); |
836 LOperand* right = instr->right(); | 836 LOperand* right = instr->InputAt(1); |
837 | 837 |
838 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 838 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
839 __ mov(ToRegister(instr->temp()), left); | 839 __ mov(ToRegister(instr->TempAt(0)), left); |
840 } | 840 } |
841 | 841 |
842 if (right->IsConstantOperand()) { | 842 if (right->IsConstantOperand()) { |
843 __ imul(left, left, ToInteger32(LConstantOperand::cast(right))); | 843 __ imul(left, left, ToInteger32(LConstantOperand::cast(right))); |
844 } else { | 844 } else { |
845 __ imul(left, ToOperand(right)); | 845 __ imul(left, ToOperand(right)); |
846 } | 846 } |
847 | 847 |
848 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 848 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
849 DeoptimizeIf(overflow, instr->environment()); | 849 DeoptimizeIf(overflow, instr->environment()); |
850 } | 850 } |
851 | 851 |
852 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 852 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
853 // Bail out if the result is supposed to be negative zero. | 853 // Bail out if the result is supposed to be negative zero. |
854 NearLabel done; | 854 NearLabel done; |
855 __ test(left, Operand(left)); | 855 __ test(left, Operand(left)); |
856 __ j(not_zero, &done); | 856 __ j(not_zero, &done); |
857 if (right->IsConstantOperand()) { | 857 if (right->IsConstantOperand()) { |
858 if (ToInteger32(LConstantOperand::cast(right)) < 0) { | 858 if (ToInteger32(LConstantOperand::cast(right)) < 0) { |
859 DeoptimizeIf(no_condition, instr->environment()); | 859 DeoptimizeIf(no_condition, instr->environment()); |
860 } | 860 } |
861 } else { | 861 } else { |
862 // Test the non-zero operand for negative sign. | 862 // Test the non-zero operand for negative sign. |
863 __ or_(ToRegister(instr->temp()), ToOperand(right)); | 863 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); |
864 DeoptimizeIf(sign, instr->environment()); | 864 DeoptimizeIf(sign, instr->environment()); |
865 } | 865 } |
866 __ bind(&done); | 866 __ bind(&done); |
867 } | 867 } |
868 } | 868 } |
869 | 869 |
870 | 870 |
871 void LCodeGen::DoBitI(LBitI* instr) { | 871 void LCodeGen::DoBitI(LBitI* instr) { |
872 LOperand* left = instr->left(); | 872 LOperand* left = instr->InputAt(0); |
873 LOperand* right = instr->right(); | 873 LOperand* right = instr->InputAt(1); |
874 ASSERT(left->Equals(instr->result())); | 874 ASSERT(left->Equals(instr->result())); |
875 ASSERT(left->IsRegister()); | 875 ASSERT(left->IsRegister()); |
876 | 876 |
877 if (right->IsConstantOperand()) { | 877 if (right->IsConstantOperand()) { |
878 int right_operand = ToInteger32(LConstantOperand::cast(right)); | 878 int right_operand = ToInteger32(LConstantOperand::cast(right)); |
879 switch (instr->op()) { | 879 switch (instr->op()) { |
880 case Token::BIT_AND: | 880 case Token::BIT_AND: |
881 __ and_(ToRegister(left), right_operand); | 881 __ and_(ToRegister(left), right_operand); |
882 break; | 882 break; |
883 case Token::BIT_OR: | 883 case Token::BIT_OR: |
(...skipping 19 matching lines...) Expand all Loading... |
903 break; | 903 break; |
904 default: | 904 default: |
905 UNREACHABLE(); | 905 UNREACHABLE(); |
906 break; | 906 break; |
907 } | 907 } |
908 } | 908 } |
909 } | 909 } |
910 | 910 |
911 | 911 |
912 void LCodeGen::DoShiftI(LShiftI* instr) { | 912 void LCodeGen::DoShiftI(LShiftI* instr) { |
913 LOperand* left = instr->left(); | 913 LOperand* left = instr->InputAt(0); |
914 LOperand* right = instr->right(); | 914 LOperand* right = instr->InputAt(1); |
915 ASSERT(left->Equals(instr->result())); | 915 ASSERT(left->Equals(instr->result())); |
916 ASSERT(left->IsRegister()); | 916 ASSERT(left->IsRegister()); |
917 if (right->IsRegister()) { | 917 if (right->IsRegister()) { |
918 ASSERT(ToRegister(right).is(ecx)); | 918 ASSERT(ToRegister(right).is(ecx)); |
919 | 919 |
920 switch (instr->op()) { | 920 switch (instr->op()) { |
921 case Token::SAR: | 921 case Token::SAR: |
922 __ sar_cl(ToRegister(left)); | 922 __ sar_cl(ToRegister(left)); |
923 break; | 923 break; |
924 case Token::SHR: | 924 case Token::SHR: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 break; | 959 break; |
960 default: | 960 default: |
961 UNREACHABLE(); | 961 UNREACHABLE(); |
962 break; | 962 break; |
963 } | 963 } |
964 } | 964 } |
965 } | 965 } |
966 | 966 |
967 | 967 |
968 void LCodeGen::DoSubI(LSubI* instr) { | 968 void LCodeGen::DoSubI(LSubI* instr) { |
969 LOperand* left = instr->left(); | 969 LOperand* left = instr->InputAt(0); |
970 LOperand* right = instr->right(); | 970 LOperand* right = instr->InputAt(1); |
971 ASSERT(left->Equals(instr->result())); | 971 ASSERT(left->Equals(instr->result())); |
972 | 972 |
973 if (right->IsConstantOperand()) { | 973 if (right->IsConstantOperand()) { |
974 __ sub(ToOperand(left), ToImmediate(right)); | 974 __ sub(ToOperand(left), ToImmediate(right)); |
975 } else { | 975 } else { |
976 __ sub(ToRegister(left), ToOperand(right)); | 976 __ sub(ToRegister(left), ToOperand(right)); |
977 } | 977 } |
978 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 978 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
979 DeoptimizeIf(overflow, instr->environment()); | 979 DeoptimizeIf(overflow, instr->environment()); |
980 } | 980 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 | 1015 |
1016 | 1016 |
1017 void LCodeGen::DoConstantT(LConstantT* instr) { | 1017 void LCodeGen::DoConstantT(LConstantT* instr) { |
1018 ASSERT(instr->result()->IsRegister()); | 1018 ASSERT(instr->result()->IsRegister()); |
1019 __ Set(ToRegister(instr->result()), Immediate(instr->value())); | 1019 __ Set(ToRegister(instr->result()), Immediate(instr->value())); |
1020 } | 1020 } |
1021 | 1021 |
1022 | 1022 |
1023 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1023 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
1024 Register result = ToRegister(instr->result()); | 1024 Register result = ToRegister(instr->result()); |
1025 Register array = ToRegister(instr->input()); | 1025 Register array = ToRegister(instr->InputAt(0)); |
1026 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); | 1026 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); |
1027 } | 1027 } |
1028 | 1028 |
1029 | 1029 |
1030 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | 1030 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { |
1031 Register result = ToRegister(instr->result()); | 1031 Register result = ToRegister(instr->result()); |
1032 Register array = ToRegister(instr->input()); | 1032 Register array = ToRegister(instr->InputAt(0)); |
1033 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset)); | 1033 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset)); |
1034 } | 1034 } |
1035 | 1035 |
1036 | 1036 |
1037 void LCodeGen::DoValueOf(LValueOf* instr) { | 1037 void LCodeGen::DoValueOf(LValueOf* instr) { |
1038 Register input = ToRegister(instr->input()); | 1038 Register input = ToRegister(instr->InputAt(0)); |
1039 Register result = ToRegister(instr->result()); | 1039 Register result = ToRegister(instr->result()); |
1040 Register map = ToRegister(instr->temporary()); | 1040 Register map = ToRegister(instr->TempAt(0)); |
1041 ASSERT(input.is(result)); | 1041 ASSERT(input.is(result)); |
1042 NearLabel done; | 1042 NearLabel done; |
1043 // If the object is a smi return the object. | 1043 // If the object is a smi return the object. |
1044 __ test(input, Immediate(kSmiTagMask)); | 1044 __ test(input, Immediate(kSmiTagMask)); |
1045 __ j(zero, &done); | 1045 __ j(zero, &done); |
1046 | 1046 |
1047 // If the object is not a value type, return the object. | 1047 // If the object is not a value type, return the object. |
1048 __ CmpObjectType(input, JS_VALUE_TYPE, map); | 1048 __ CmpObjectType(input, JS_VALUE_TYPE, map); |
1049 __ j(not_equal, &done); | 1049 __ j(not_equal, &done); |
1050 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); | 1050 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); |
1051 | 1051 |
1052 __ bind(&done); | 1052 __ bind(&done); |
1053 } | 1053 } |
1054 | 1054 |
1055 | 1055 |
1056 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1056 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1057 LOperand* input = instr->input(); | 1057 LOperand* input = instr->InputAt(0); |
1058 ASSERT(input->Equals(instr->result())); | 1058 ASSERT(input->Equals(instr->result())); |
1059 __ not_(ToRegister(input)); | 1059 __ not_(ToRegister(input)); |
1060 } | 1060 } |
1061 | 1061 |
1062 | 1062 |
1063 void LCodeGen::DoThrow(LThrow* instr) { | 1063 void LCodeGen::DoThrow(LThrow* instr) { |
1064 __ push(ToOperand(instr->input())); | 1064 __ push(ToOperand(instr->InputAt(0))); |
1065 CallRuntime(Runtime::kThrow, 1, instr); | 1065 CallRuntime(Runtime::kThrow, 1, instr); |
1066 | 1066 |
1067 if (FLAG_debug_code) { | 1067 if (FLAG_debug_code) { |
1068 Comment("Unreachable code."); | 1068 Comment("Unreachable code."); |
1069 __ int3(); | 1069 __ int3(); |
1070 } | 1070 } |
1071 } | 1071 } |
1072 | 1072 |
1073 | 1073 |
1074 void LCodeGen::DoAddI(LAddI* instr) { | 1074 void LCodeGen::DoAddI(LAddI* instr) { |
1075 LOperand* left = instr->left(); | 1075 LOperand* left = instr->InputAt(0); |
1076 LOperand* right = instr->right(); | 1076 LOperand* right = instr->InputAt(1); |
1077 ASSERT(left->Equals(instr->result())); | 1077 ASSERT(left->Equals(instr->result())); |
1078 | 1078 |
1079 if (right->IsConstantOperand()) { | 1079 if (right->IsConstantOperand()) { |
1080 __ add(ToOperand(left), ToImmediate(right)); | 1080 __ add(ToOperand(left), ToImmediate(right)); |
1081 } else { | 1081 } else { |
1082 __ add(ToRegister(left), ToOperand(right)); | 1082 __ add(ToRegister(left), ToOperand(right)); |
1083 } | 1083 } |
1084 | 1084 |
1085 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1085 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1086 DeoptimizeIf(overflow, instr->environment()); | 1086 DeoptimizeIf(overflow, instr->environment()); |
1087 } | 1087 } |
1088 } | 1088 } |
1089 | 1089 |
1090 | 1090 |
1091 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1091 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
1092 LOperand* left = instr->left(); | 1092 LOperand* left = instr->InputAt(0); |
1093 LOperand* right = instr->right(); | 1093 LOperand* right = instr->InputAt(1); |
1094 // Modulo uses a fixed result register. | 1094 // Modulo uses a fixed result register. |
1095 ASSERT(instr->op() == Token::MOD || left->Equals(instr->result())); | 1095 ASSERT(instr->op() == Token::MOD || left->Equals(instr->result())); |
1096 switch (instr->op()) { | 1096 switch (instr->op()) { |
1097 case Token::ADD: | 1097 case Token::ADD: |
1098 __ addsd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1098 __ addsd(ToDoubleRegister(left), ToDoubleRegister(right)); |
1099 break; | 1099 break; |
1100 case Token::SUB: | 1100 case Token::SUB: |
1101 __ subsd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1101 __ subsd(ToDoubleRegister(left), ToDoubleRegister(right)); |
1102 break; | 1102 break; |
1103 case Token::MUL: | 1103 case Token::MUL: |
(...skipping 18 matching lines...) Expand all Loading... |
1122 break; | 1122 break; |
1123 } | 1123 } |
1124 default: | 1124 default: |
1125 UNREACHABLE(); | 1125 UNREACHABLE(); |
1126 break; | 1126 break; |
1127 } | 1127 } |
1128 } | 1128 } |
1129 | 1129 |
1130 | 1130 |
1131 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1131 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
1132 ASSERT(ToRegister(instr->left()).is(edx)); | 1132 ASSERT(ToRegister(instr->InputAt(0)).is(edx)); |
1133 ASSERT(ToRegister(instr->right()).is(eax)); | 1133 ASSERT(ToRegister(instr->InputAt(1)).is(eax)); |
1134 ASSERT(ToRegister(instr->result()).is(eax)); | 1134 ASSERT(ToRegister(instr->result()).is(eax)); |
1135 | 1135 |
1136 TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1136 TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); |
1137 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1137 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1138 } | 1138 } |
1139 | 1139 |
1140 | 1140 |
1141 int LCodeGen::GetNextEmittedBlock(int block) { | 1141 int LCodeGen::GetNextEmittedBlock(int block) { |
1142 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 1142 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
1143 LLabel* label = chunk_->GetLabel(i); | 1143 LLabel* label = chunk_->GetLabel(i); |
(...skipping 20 matching lines...) Expand all Loading... |
1164 } | 1164 } |
1165 } | 1165 } |
1166 | 1166 |
1167 | 1167 |
1168 void LCodeGen::DoBranch(LBranch* instr) { | 1168 void LCodeGen::DoBranch(LBranch* instr) { |
1169 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1169 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1170 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1170 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1171 | 1171 |
1172 Representation r = instr->hydrogen()->representation(); | 1172 Representation r = instr->hydrogen()->representation(); |
1173 if (r.IsInteger32()) { | 1173 if (r.IsInteger32()) { |
1174 Register reg = ToRegister(instr->input()); | 1174 Register reg = ToRegister(instr->InputAt(0)); |
1175 __ test(reg, Operand(reg)); | 1175 __ test(reg, Operand(reg)); |
1176 EmitBranch(true_block, false_block, not_zero); | 1176 EmitBranch(true_block, false_block, not_zero); |
1177 } else if (r.IsDouble()) { | 1177 } else if (r.IsDouble()) { |
1178 XMMRegister reg = ToDoubleRegister(instr->input()); | 1178 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); |
1179 __ xorpd(xmm0, xmm0); | 1179 __ xorpd(xmm0, xmm0); |
1180 __ ucomisd(reg, xmm0); | 1180 __ ucomisd(reg, xmm0); |
1181 EmitBranch(true_block, false_block, not_equal); | 1181 EmitBranch(true_block, false_block, not_equal); |
1182 } else { | 1182 } else { |
1183 ASSERT(r.IsTagged()); | 1183 ASSERT(r.IsTagged()); |
1184 Register reg = ToRegister(instr->input()); | 1184 Register reg = ToRegister(instr->InputAt(0)); |
1185 if (instr->hydrogen()->type().IsBoolean()) { | 1185 if (instr->hydrogen()->type().IsBoolean()) { |
1186 __ cmp(reg, Factory::true_value()); | 1186 __ cmp(reg, Factory::true_value()); |
1187 EmitBranch(true_block, false_block, equal); | 1187 EmitBranch(true_block, false_block, equal); |
1188 } else { | 1188 } else { |
1189 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1189 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1190 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1190 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1191 | 1191 |
1192 __ cmp(reg, Factory::undefined_value()); | 1192 __ cmp(reg, Factory::undefined_value()); |
1193 __ j(equal, false_label); | 1193 __ j(equal, false_label); |
1194 __ cmp(reg, Factory::true_value()); | 1194 __ cmp(reg, Factory::true_value()); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1302 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { | 1302 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { |
1303 if (right->IsConstantOperand()) { | 1303 if (right->IsConstantOperand()) { |
1304 __ cmp(ToOperand(left), ToImmediate(right)); | 1304 __ cmp(ToOperand(left), ToImmediate(right)); |
1305 } else { | 1305 } else { |
1306 __ cmp(ToRegister(left), ToOperand(right)); | 1306 __ cmp(ToRegister(left), ToOperand(right)); |
1307 } | 1307 } |
1308 } | 1308 } |
1309 | 1309 |
1310 | 1310 |
1311 void LCodeGen::DoCmpID(LCmpID* instr) { | 1311 void LCodeGen::DoCmpID(LCmpID* instr) { |
1312 LOperand* left = instr->left(); | 1312 LOperand* left = instr->InputAt(0); |
1313 LOperand* right = instr->right(); | 1313 LOperand* right = instr->InputAt(1); |
1314 LOperand* result = instr->result(); | 1314 LOperand* result = instr->result(); |
1315 | 1315 |
1316 NearLabel unordered; | 1316 NearLabel unordered; |
1317 if (instr->is_double()) { | 1317 if (instr->is_double()) { |
1318 // Don't base result on EFLAGS when a NaN is involved. Instead | 1318 // Don't base result on EFLAGS when a NaN is involved. Instead |
1319 // jump to the unordered case, which produces a false value. | 1319 // jump to the unordered case, which produces a false value. |
1320 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1320 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
1321 __ j(parity_even, &unordered, not_taken); | 1321 __ j(parity_even, &unordered, not_taken); |
1322 } else { | 1322 } else { |
1323 EmitCmpI(left, right); | 1323 EmitCmpI(left, right); |
1324 } | 1324 } |
1325 | 1325 |
1326 NearLabel done; | 1326 NearLabel done; |
1327 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1327 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1328 __ mov(ToRegister(result), Handle<Object>(Heap::true_value())); | 1328 __ mov(ToRegister(result), Handle<Object>(Heap::true_value())); |
1329 __ j(cc, &done); | 1329 __ j(cc, &done); |
1330 | 1330 |
1331 __ bind(&unordered); | 1331 __ bind(&unordered); |
1332 __ mov(ToRegister(result), Handle<Object>(Heap::false_value())); | 1332 __ mov(ToRegister(result), Handle<Object>(Heap::false_value())); |
1333 __ bind(&done); | 1333 __ bind(&done); |
1334 } | 1334 } |
1335 | 1335 |
1336 | 1336 |
1337 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1337 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
1338 LOperand* left = instr->left(); | 1338 LOperand* left = instr->InputAt(0); |
1339 LOperand* right = instr->right(); | 1339 LOperand* right = instr->InputAt(1); |
1340 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1340 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1341 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1341 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1342 | 1342 |
1343 if (instr->is_double()) { | 1343 if (instr->is_double()) { |
1344 // Don't base result on EFLAGS when a NaN is involved. Instead | 1344 // Don't base result on EFLAGS when a NaN is involved. Instead |
1345 // jump to the false block. | 1345 // jump to the false block. |
1346 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1346 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
1347 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); | 1347 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); |
1348 } else { | 1348 } else { |
1349 EmitCmpI(left, right); | 1349 EmitCmpI(left, right); |
1350 } | 1350 } |
1351 | 1351 |
1352 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1352 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1353 EmitBranch(true_block, false_block, cc); | 1353 EmitBranch(true_block, false_block, cc); |
1354 } | 1354 } |
1355 | 1355 |
1356 | 1356 |
1357 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1357 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
1358 Register left = ToRegister(instr->left()); | 1358 Register left = ToRegister(instr->InputAt(0)); |
1359 Register right = ToRegister(instr->right()); | 1359 Register right = ToRegister(instr->InputAt(1)); |
1360 Register result = ToRegister(instr->result()); | 1360 Register result = ToRegister(instr->result()); |
1361 | 1361 |
1362 __ cmp(left, Operand(right)); | 1362 __ cmp(left, Operand(right)); |
1363 __ mov(result, Handle<Object>(Heap::true_value())); | 1363 __ mov(result, Handle<Object>(Heap::true_value())); |
1364 NearLabel done; | 1364 NearLabel done; |
1365 __ j(equal, &done); | 1365 __ j(equal, &done); |
1366 __ mov(result, Handle<Object>(Heap::false_value())); | 1366 __ mov(result, Handle<Object>(Heap::false_value())); |
1367 __ bind(&done); | 1367 __ bind(&done); |
1368 } | 1368 } |
1369 | 1369 |
1370 | 1370 |
1371 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1371 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
1372 Register left = ToRegister(instr->left()); | 1372 Register left = ToRegister(instr->InputAt(0)); |
1373 Register right = ToRegister(instr->right()); | 1373 Register right = ToRegister(instr->InputAt(1)); |
1374 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1374 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1375 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1375 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1376 | 1376 |
1377 __ cmp(left, Operand(right)); | 1377 __ cmp(left, Operand(right)); |
1378 EmitBranch(true_block, false_block, equal); | 1378 EmitBranch(true_block, false_block, equal); |
1379 } | 1379 } |
1380 | 1380 |
1381 | 1381 |
1382 void LCodeGen::DoIsNull(LIsNull* instr) { | 1382 void LCodeGen::DoIsNull(LIsNull* instr) { |
1383 Register reg = ToRegister(instr->input()); | 1383 Register reg = ToRegister(instr->InputAt(0)); |
1384 Register result = ToRegister(instr->result()); | 1384 Register result = ToRegister(instr->result()); |
1385 | 1385 |
1386 // TODO(fsc): If the expression is known to be a smi, then it's | 1386 // TODO(fsc): If the expression is known to be a smi, then it's |
1387 // definitely not null. Materialize false. | 1387 // definitely not null. Materialize false. |
1388 | 1388 |
1389 __ cmp(reg, Factory::null_value()); | 1389 __ cmp(reg, Factory::null_value()); |
1390 if (instr->is_strict()) { | 1390 if (instr->is_strict()) { |
1391 __ mov(result, Handle<Object>(Heap::true_value())); | 1391 __ mov(result, Handle<Object>(Heap::true_value())); |
1392 NearLabel done; | 1392 NearLabel done; |
1393 __ j(equal, &done); | 1393 __ j(equal, &done); |
(...skipping 17 matching lines...) Expand all Loading... |
1411 __ mov(result, Handle<Object>(Heap::false_value())); | 1411 __ mov(result, Handle<Object>(Heap::false_value())); |
1412 __ jmp(&done); | 1412 __ jmp(&done); |
1413 __ bind(&true_value); | 1413 __ bind(&true_value); |
1414 __ mov(result, Handle<Object>(Heap::true_value())); | 1414 __ mov(result, Handle<Object>(Heap::true_value())); |
1415 __ bind(&done); | 1415 __ bind(&done); |
1416 } | 1416 } |
1417 } | 1417 } |
1418 | 1418 |
1419 | 1419 |
1420 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1420 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
1421 Register reg = ToRegister(instr->input()); | 1421 Register reg = ToRegister(instr->InputAt(0)); |
1422 | 1422 |
1423 // TODO(fsc): If the expression is known to be a smi, then it's | 1423 // TODO(fsc): If the expression is known to be a smi, then it's |
1424 // definitely not null. Jump to the false block. | 1424 // definitely not null. Jump to the false block. |
1425 | 1425 |
1426 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1426 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1427 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1427 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1428 | 1428 |
1429 __ cmp(reg, Factory::null_value()); | 1429 __ cmp(reg, Factory::null_value()); |
1430 if (instr->is_strict()) { | 1430 if (instr->is_strict()) { |
1431 EmitBranch(true_block, false_block, equal); | 1431 EmitBranch(true_block, false_block, equal); |
1432 } else { | 1432 } else { |
1433 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1433 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1434 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1434 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1435 __ j(equal, true_label); | 1435 __ j(equal, true_label); |
1436 __ cmp(reg, Factory::undefined_value()); | 1436 __ cmp(reg, Factory::undefined_value()); |
1437 __ j(equal, true_label); | 1437 __ j(equal, true_label); |
1438 __ test(reg, Immediate(kSmiTagMask)); | 1438 __ test(reg, Immediate(kSmiTagMask)); |
1439 __ j(zero, false_label); | 1439 __ j(zero, false_label); |
1440 // Check for undetectable objects by looking in the bit field in | 1440 // Check for undetectable objects by looking in the bit field in |
1441 // the map. The object has already been smi checked. | 1441 // the map. The object has already been smi checked. |
1442 Register scratch = ToRegister(instr->temp()); | 1442 Register scratch = ToRegister(instr->TempAt(0)); |
1443 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1443 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
1444 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1444 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
1445 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1445 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
1446 EmitBranch(true_block, false_block, not_zero); | 1446 EmitBranch(true_block, false_block, not_zero); |
1447 } | 1447 } |
1448 } | 1448 } |
1449 | 1449 |
1450 | 1450 |
1451 Condition LCodeGen::EmitIsObject(Register input, | 1451 Condition LCodeGen::EmitIsObject(Register input, |
1452 Register temp1, | 1452 Register temp1, |
(...skipping 18 matching lines...) Expand all Loading... |
1471 | 1471 |
1472 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); | 1472 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); |
1473 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); | 1473 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); |
1474 __ j(below, is_not_object); | 1474 __ j(below, is_not_object); |
1475 __ cmp(temp2, LAST_JS_OBJECT_TYPE); | 1475 __ cmp(temp2, LAST_JS_OBJECT_TYPE); |
1476 return below_equal; | 1476 return below_equal; |
1477 } | 1477 } |
1478 | 1478 |
1479 | 1479 |
1480 void LCodeGen::DoIsObject(LIsObject* instr) { | 1480 void LCodeGen::DoIsObject(LIsObject* instr) { |
1481 Register reg = ToRegister(instr->input()); | 1481 Register reg = ToRegister(instr->InputAt(0)); |
1482 Register result = ToRegister(instr->result()); | 1482 Register result = ToRegister(instr->result()); |
1483 Register temp = ToRegister(instr->temp()); | 1483 Register temp = ToRegister(instr->TempAt(0)); |
1484 Label is_false, is_true, done; | 1484 Label is_false, is_true, done; |
1485 | 1485 |
1486 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); | 1486 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); |
1487 __ j(true_cond, &is_true); | 1487 __ j(true_cond, &is_true); |
1488 | 1488 |
1489 __ bind(&is_false); | 1489 __ bind(&is_false); |
1490 __ mov(result, Handle<Object>(Heap::false_value())); | 1490 __ mov(result, Handle<Object>(Heap::false_value())); |
1491 __ jmp(&done); | 1491 __ jmp(&done); |
1492 | 1492 |
1493 __ bind(&is_true); | 1493 __ bind(&is_true); |
1494 __ mov(result, Handle<Object>(Heap::true_value())); | 1494 __ mov(result, Handle<Object>(Heap::true_value())); |
1495 | 1495 |
1496 __ bind(&done); | 1496 __ bind(&done); |
1497 } | 1497 } |
1498 | 1498 |
1499 | 1499 |
1500 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1500 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1501 Register reg = ToRegister(instr->input()); | 1501 Register reg = ToRegister(instr->InputAt(0)); |
1502 Register temp = ToRegister(instr->temp()); | 1502 Register temp = ToRegister(instr->TempAt(0)); |
1503 Register temp2 = ToRegister(instr->temp2()); | 1503 Register temp2 = ToRegister(instr->TempAt(1)); |
1504 | 1504 |
1505 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1505 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1506 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1506 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1507 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1507 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1508 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1508 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1509 | 1509 |
1510 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); | 1510 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); |
1511 | 1511 |
1512 EmitBranch(true_block, false_block, true_cond); | 1512 EmitBranch(true_block, false_block, true_cond); |
1513 } | 1513 } |
1514 | 1514 |
1515 | 1515 |
1516 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1516 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
1517 Operand input = ToOperand(instr->input()); | 1517 Operand input = ToOperand(instr->InputAt(0)); |
1518 Register result = ToRegister(instr->result()); | 1518 Register result = ToRegister(instr->result()); |
1519 | 1519 |
1520 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1520 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1521 __ test(input, Immediate(kSmiTagMask)); | 1521 __ test(input, Immediate(kSmiTagMask)); |
1522 __ mov(result, Handle<Object>(Heap::true_value())); | 1522 __ mov(result, Handle<Object>(Heap::true_value())); |
1523 NearLabel done; | 1523 NearLabel done; |
1524 __ j(zero, &done); | 1524 __ j(zero, &done); |
1525 __ mov(result, Handle<Object>(Heap::false_value())); | 1525 __ mov(result, Handle<Object>(Heap::false_value())); |
1526 __ bind(&done); | 1526 __ bind(&done); |
1527 } | 1527 } |
1528 | 1528 |
1529 | 1529 |
1530 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1530 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
1531 Operand input = ToOperand(instr->input()); | 1531 Operand input = ToOperand(instr->InputAt(0)); |
1532 | 1532 |
1533 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1533 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1534 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1534 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1535 | 1535 |
1536 __ test(input, Immediate(kSmiTagMask)); | 1536 __ test(input, Immediate(kSmiTagMask)); |
1537 EmitBranch(true_block, false_block, zero); | 1537 EmitBranch(true_block, false_block, zero); |
1538 } | 1538 } |
1539 | 1539 |
1540 | 1540 |
1541 InstanceType LHasInstanceType::TestType() { | 1541 static InstanceType TestType(HHasInstanceType* instr) { |
1542 InstanceType from = hydrogen()->from(); | 1542 InstanceType from = instr->from(); |
1543 InstanceType to = hydrogen()->to(); | 1543 InstanceType to = instr->to(); |
1544 if (from == FIRST_TYPE) return to; | 1544 if (from == FIRST_TYPE) return to; |
1545 ASSERT(from == to || to == LAST_TYPE); | 1545 ASSERT(from == to || to == LAST_TYPE); |
1546 return from; | 1546 return from; |
1547 } | 1547 } |
1548 | 1548 |
1549 | 1549 |
1550 | 1550 |
1551 Condition LHasInstanceType::BranchCondition() { | 1551 static Condition BranchCondition(HHasInstanceType* instr) { |
1552 InstanceType from = hydrogen()->from(); | 1552 InstanceType from = instr->from(); |
1553 InstanceType to = hydrogen()->to(); | 1553 InstanceType to = instr->to(); |
1554 if (from == to) return equal; | 1554 if (from == to) return equal; |
1555 if (to == LAST_TYPE) return above_equal; | 1555 if (to == LAST_TYPE) return above_equal; |
1556 if (from == FIRST_TYPE) return below_equal; | 1556 if (from == FIRST_TYPE) return below_equal; |
1557 UNREACHABLE(); | 1557 UNREACHABLE(); |
1558 return equal; | 1558 return equal; |
1559 } | 1559 } |
1560 | 1560 |
1561 | 1561 |
1562 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1562 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
1563 Register input = ToRegister(instr->input()); | 1563 Register input = ToRegister(instr->InputAt(0)); |
1564 Register result = ToRegister(instr->result()); | 1564 Register result = ToRegister(instr->result()); |
1565 | 1565 |
1566 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1566 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1567 __ test(input, Immediate(kSmiTagMask)); | 1567 __ test(input, Immediate(kSmiTagMask)); |
1568 NearLabel done, is_false; | 1568 NearLabel done, is_false; |
1569 __ j(zero, &is_false); | 1569 __ j(zero, &is_false); |
1570 __ CmpObjectType(input, instr->TestType(), result); | 1570 __ CmpObjectType(input, TestType(instr->hydrogen()), result); |
1571 __ j(NegateCondition(instr->BranchCondition()), &is_false); | 1571 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); |
1572 __ mov(result, Handle<Object>(Heap::true_value())); | 1572 __ mov(result, Handle<Object>(Heap::true_value())); |
1573 __ jmp(&done); | 1573 __ jmp(&done); |
1574 __ bind(&is_false); | 1574 __ bind(&is_false); |
1575 __ mov(result, Handle<Object>(Heap::false_value())); | 1575 __ mov(result, Handle<Object>(Heap::false_value())); |
1576 __ bind(&done); | 1576 __ bind(&done); |
1577 } | 1577 } |
1578 | 1578 |
1579 | 1579 |
1580 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1580 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
1581 Register input = ToRegister(instr->input()); | 1581 Register input = ToRegister(instr->InputAt(0)); |
1582 Register temp = ToRegister(instr->temp()); | 1582 Register temp = ToRegister(instr->TempAt(0)); |
1583 | 1583 |
1584 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1584 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1585 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1585 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1586 | 1586 |
1587 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1587 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1588 | 1588 |
1589 __ test(input, Immediate(kSmiTagMask)); | 1589 __ test(input, Immediate(kSmiTagMask)); |
1590 __ j(zero, false_label); | 1590 __ j(zero, false_label); |
1591 | 1591 |
1592 __ CmpObjectType(input, instr->TestType(), temp); | 1592 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); |
1593 EmitBranch(true_block, false_block, instr->BranchCondition()); | 1593 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
1594 } | 1594 } |
1595 | 1595 |
1596 | 1596 |
1597 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1597 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
1598 Register input = ToRegister(instr->input()); | 1598 Register input = ToRegister(instr->InputAt(0)); |
1599 Register result = ToRegister(instr->result()); | 1599 Register result = ToRegister(instr->result()); |
1600 | 1600 |
1601 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1601 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1602 __ mov(result, Handle<Object>(Heap::true_value())); | 1602 __ mov(result, Handle<Object>(Heap::true_value())); |
1603 __ test(FieldOperand(input, String::kHashFieldOffset), | 1603 __ test(FieldOperand(input, String::kHashFieldOffset), |
1604 Immediate(String::kContainsCachedArrayIndexMask)); | 1604 Immediate(String::kContainsCachedArrayIndexMask)); |
1605 NearLabel done; | 1605 NearLabel done; |
1606 __ j(not_zero, &done); | 1606 __ j(not_zero, &done); |
1607 __ mov(result, Handle<Object>(Heap::false_value())); | 1607 __ mov(result, Handle<Object>(Heap::false_value())); |
1608 __ bind(&done); | 1608 __ bind(&done); |
1609 } | 1609 } |
1610 | 1610 |
1611 | 1611 |
1612 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1612 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
1613 LHasCachedArrayIndexAndBranch* instr) { | 1613 LHasCachedArrayIndexAndBranch* instr) { |
1614 Register input = ToRegister(instr->input()); | 1614 Register input = ToRegister(instr->InputAt(0)); |
1615 | 1615 |
1616 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1616 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1617 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1617 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1618 | 1618 |
1619 __ test(FieldOperand(input, String::kHashFieldOffset), | 1619 __ test(FieldOperand(input, String::kHashFieldOffset), |
1620 Immediate(String::kContainsCachedArrayIndexMask)); | 1620 Immediate(String::kContainsCachedArrayIndexMask)); |
1621 EmitBranch(true_block, false_block, not_equal); | 1621 EmitBranch(true_block, false_block, not_equal); |
1622 } | 1622 } |
1623 | 1623 |
1624 | 1624 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1673 // booted. This routine isn't expected to work for random API-created | 1673 // booted. This routine isn't expected to work for random API-created |
1674 // classes and it doesn't have to because you can't access it with natives | 1674 // classes and it doesn't have to because you can't access it with natives |
1675 // syntax. Since both sides are symbols it is sufficient to use an identity | 1675 // syntax. Since both sides are symbols it is sufficient to use an identity |
1676 // comparison. | 1676 // comparison. |
1677 __ cmp(temp, class_name); | 1677 __ cmp(temp, class_name); |
1678 // End with the answer in the z flag. | 1678 // End with the answer in the z flag. |
1679 } | 1679 } |
1680 | 1680 |
1681 | 1681 |
1682 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1682 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
1683 Register input = ToRegister(instr->input()); | 1683 Register input = ToRegister(instr->InputAt(0)); |
1684 Register result = ToRegister(instr->result()); | 1684 Register result = ToRegister(instr->result()); |
1685 ASSERT(input.is(result)); | 1685 ASSERT(input.is(result)); |
1686 Register temp = ToRegister(instr->temporary()); | 1686 Register temp = ToRegister(instr->TempAt(0)); |
1687 Handle<String> class_name = instr->hydrogen()->class_name(); | 1687 Handle<String> class_name = instr->hydrogen()->class_name(); |
1688 NearLabel done; | 1688 NearLabel done; |
1689 Label is_true, is_false; | 1689 Label is_true, is_false; |
1690 | 1690 |
1691 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); | 1691 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); |
1692 | 1692 |
1693 __ j(not_equal, &is_false); | 1693 __ j(not_equal, &is_false); |
1694 | 1694 |
1695 __ bind(&is_true); | 1695 __ bind(&is_true); |
1696 __ mov(result, Handle<Object>(Heap::true_value())); | 1696 __ mov(result, Handle<Object>(Heap::true_value())); |
1697 __ jmp(&done); | 1697 __ jmp(&done); |
1698 | 1698 |
1699 __ bind(&is_false); | 1699 __ bind(&is_false); |
1700 __ mov(result, Handle<Object>(Heap::false_value())); | 1700 __ mov(result, Handle<Object>(Heap::false_value())); |
1701 __ bind(&done); | 1701 __ bind(&done); |
1702 } | 1702 } |
1703 | 1703 |
1704 | 1704 |
1705 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1705 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1706 Register input = ToRegister(instr->input()); | 1706 Register input = ToRegister(instr->InputAt(0)); |
1707 Register temp = ToRegister(instr->temporary()); | 1707 Register temp = ToRegister(instr->TempAt(0)); |
1708 Register temp2 = ToRegister(instr->temporary2()); | 1708 Register temp2 = ToRegister(instr->TempAt(1)); |
1709 if (input.is(temp)) { | 1709 if (input.is(temp)) { |
1710 // Swap. | 1710 // Swap. |
1711 Register swapper = temp; | 1711 Register swapper = temp; |
1712 temp = temp2; | 1712 temp = temp2; |
1713 temp2 = swapper; | 1713 temp2 = swapper; |
1714 } | 1714 } |
1715 Handle<String> class_name = instr->hydrogen()->class_name(); | 1715 Handle<String> class_name = instr->hydrogen()->class_name(); |
1716 | 1716 |
1717 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1717 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1718 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1718 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1719 | 1719 |
1720 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1720 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1721 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1721 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1722 | 1722 |
1723 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 1723 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
1724 | 1724 |
1725 EmitBranch(true_block, false_block, equal); | 1725 EmitBranch(true_block, false_block, equal); |
1726 } | 1726 } |
1727 | 1727 |
1728 | 1728 |
1729 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1729 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
1730 Register reg = ToRegister(instr->input()); | 1730 Register reg = ToRegister(instr->InputAt(0)); |
1731 int true_block = instr->true_block_id(); | 1731 int true_block = instr->true_block_id(); |
1732 int false_block = instr->false_block_id(); | 1732 int false_block = instr->false_block_id(); |
1733 | 1733 |
1734 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 1734 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
1735 EmitBranch(true_block, false_block, equal); | 1735 EmitBranch(true_block, false_block, equal); |
1736 } | 1736 } |
1737 | 1737 |
1738 | 1738 |
1739 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1739 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
1740 // Object and function are in fixed registers defined by the stub. | 1740 // Object and function are in fixed registers defined by the stub. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1777 | 1777 |
1778 private: | 1778 private: |
1779 LInstanceOfKnownGlobal* instr_; | 1779 LInstanceOfKnownGlobal* instr_; |
1780 Label map_check_; | 1780 Label map_check_; |
1781 }; | 1781 }; |
1782 | 1782 |
1783 DeferredInstanceOfKnownGlobal* deferred; | 1783 DeferredInstanceOfKnownGlobal* deferred; |
1784 deferred = new DeferredInstanceOfKnownGlobal(this, instr); | 1784 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
1785 | 1785 |
1786 Label done, false_result; | 1786 Label done, false_result; |
1787 Register object = ToRegister(instr->input()); | 1787 Register object = ToRegister(instr->InputAt(0)); |
1788 Register temp = ToRegister(instr->temp()); | 1788 Register temp = ToRegister(instr->TempAt(0)); |
1789 | 1789 |
1790 // A Smi is not instance of anything. | 1790 // A Smi is not instance of anything. |
1791 __ test(object, Immediate(kSmiTagMask)); | 1791 __ test(object, Immediate(kSmiTagMask)); |
1792 __ j(zero, &false_result, not_taken); | 1792 __ j(zero, &false_result, not_taken); |
1793 | 1793 |
1794 // This is the inlined call site instanceof cache. The two occourences of the | 1794 // This is the inlined call site instanceof cache. The two occourences of the |
1795 // hole value will be patched to the last map/result pair generated by the | 1795 // hole value will be patched to the last map/result pair generated by the |
1796 // instanceof stub. | 1796 // instanceof stub. |
1797 NearLabel cache_miss; | 1797 NearLabel cache_miss; |
1798 Register map = ToRegister(instr->temp()); | 1798 Register map = ToRegister(instr->TempAt(0)); |
1799 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); | 1799 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
1800 __ bind(deferred->map_check()); // Label for calculating code patching. | 1800 __ bind(deferred->map_check()); // Label for calculating code patching. |
1801 __ cmp(map, Factory::the_hole_value()); // Patched to cached map. | 1801 __ cmp(map, Factory::the_hole_value()); // Patched to cached map. |
1802 __ j(not_equal, &cache_miss, not_taken); | 1802 __ j(not_equal, &cache_miss, not_taken); |
1803 __ mov(eax, Factory::the_hole_value()); // Patched to either true or false. | 1803 __ mov(eax, Factory::the_hole_value()); // Patched to either true or false. |
1804 __ jmp(&done); | 1804 __ jmp(&done); |
1805 | 1805 |
1806 // The inlined call site cache did not match. Check null and string before | 1806 // The inlined call site cache did not match. Check null and string before |
1807 // calling the deferred code. | 1807 // calling the deferred code. |
1808 __ bind(&cache_miss); | 1808 __ bind(&cache_miss); |
(...skipping 27 matching lines...) Expand all Loading... |
1836 flags | InstanceofStub::kArgsInRegisters); | 1836 flags | InstanceofStub::kArgsInRegisters); |
1837 flags = static_cast<InstanceofStub::Flags>( | 1837 flags = static_cast<InstanceofStub::Flags>( |
1838 flags | InstanceofStub::kCallSiteInlineCheck); | 1838 flags | InstanceofStub::kCallSiteInlineCheck); |
1839 flags = static_cast<InstanceofStub::Flags>( | 1839 flags = static_cast<InstanceofStub::Flags>( |
1840 flags | InstanceofStub::kReturnTrueFalseObject); | 1840 flags | InstanceofStub::kReturnTrueFalseObject); |
1841 InstanceofStub stub(flags); | 1841 InstanceofStub stub(flags); |
1842 | 1842 |
1843 // Get the temp register reserved by the instruction. This needs to be edi as | 1843 // Get the temp register reserved by the instruction. This needs to be edi as |
1844 // its slot of the pushing of safepoint registers is used to communicate the | 1844 // its slot of the pushing of safepoint registers is used to communicate the |
1845 // offset to the location of the map check. | 1845 // offset to the location of the map check. |
1846 Register temp = ToRegister(instr->temp()); | 1846 Register temp = ToRegister(instr->TempAt(0)); |
1847 ASSERT(temp.is(edi)); | 1847 ASSERT(temp.is(edi)); |
1848 __ mov(InstanceofStub::right(), Immediate(instr->function())); | 1848 __ mov(InstanceofStub::right(), Immediate(instr->function())); |
1849 static const int kAdditionalDelta = 13; | 1849 static const int kAdditionalDelta = 13; |
1850 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 1850 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
1851 Label before_push_delta; | 1851 Label before_push_delta; |
1852 __ bind(&before_push_delta); | 1852 __ bind(&before_push_delta); |
1853 __ mov(temp, Immediate(delta)); | 1853 __ mov(temp, Immediate(delta)); |
1854 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); | 1854 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); |
1855 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); | 1855 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
1856 ASSERT_EQ(kAdditionalDelta, | 1856 ASSERT_EQ(kAdditionalDelta, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1941 Register result = ToRegister(instr->result()); | 1941 Register result = ToRegister(instr->result()); |
1942 __ mov(result, Operand::Cell(instr->hydrogen()->cell())); | 1942 __ mov(result, Operand::Cell(instr->hydrogen()->cell())); |
1943 if (instr->hydrogen()->check_hole_value()) { | 1943 if (instr->hydrogen()->check_hole_value()) { |
1944 __ cmp(result, Factory::the_hole_value()); | 1944 __ cmp(result, Factory::the_hole_value()); |
1945 DeoptimizeIf(equal, instr->environment()); | 1945 DeoptimizeIf(equal, instr->environment()); |
1946 } | 1946 } |
1947 } | 1947 } |
1948 | 1948 |
1949 | 1949 |
1950 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { | 1950 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { |
1951 Register value = ToRegister(instr->input()); | 1951 Register value = ToRegister(instr->InputAt(0)); |
1952 __ mov(Operand::Cell(instr->hydrogen()->cell()), value); | 1952 __ mov(Operand::Cell(instr->hydrogen()->cell()), value); |
1953 } | 1953 } |
1954 | 1954 |
1955 | 1955 |
1956 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 1956 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
1957 Register object = ToRegister(instr->input()); | 1957 Register object = ToRegister(instr->InputAt(0)); |
1958 Register result = ToRegister(instr->result()); | 1958 Register result = ToRegister(instr->result()); |
1959 if (instr->hydrogen()->is_in_object()) { | 1959 if (instr->hydrogen()->is_in_object()) { |
1960 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); | 1960 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); |
1961 } else { | 1961 } else { |
1962 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 1962 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
1963 __ mov(result, FieldOperand(result, instr->hydrogen()->offset())); | 1963 __ mov(result, FieldOperand(result, instr->hydrogen()->offset())); |
1964 } | 1964 } |
1965 } | 1965 } |
1966 | 1966 |
1967 | 1967 |
1968 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 1968 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
1969 ASSERT(ToRegister(instr->object()).is(eax)); | 1969 ASSERT(ToRegister(instr->object()).is(eax)); |
1970 ASSERT(ToRegister(instr->result()).is(eax)); | 1970 ASSERT(ToRegister(instr->result()).is(eax)); |
1971 | 1971 |
1972 __ mov(ecx, instr->name()); | 1972 __ mov(ecx, instr->name()); |
1973 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1973 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1974 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 1974 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
1975 } | 1975 } |
1976 | 1976 |
1977 | 1977 |
1978 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 1978 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
1979 Register function = ToRegister(instr->function()); | 1979 Register function = ToRegister(instr->function()); |
1980 Register temp = ToRegister(instr->temporary()); | 1980 Register temp = ToRegister(instr->TempAt(0)); |
1981 Register result = ToRegister(instr->result()); | 1981 Register result = ToRegister(instr->result()); |
1982 | 1982 |
1983 // Check that the function really is a function. | 1983 // Check that the function really is a function. |
1984 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 1984 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
1985 DeoptimizeIf(not_equal, instr->environment()); | 1985 DeoptimizeIf(not_equal, instr->environment()); |
1986 | 1986 |
1987 // Check whether the function has an instance prototype. | 1987 // Check whether the function has an instance prototype. |
1988 NearLabel non_instance; | 1988 NearLabel non_instance; |
1989 __ test_b(FieldOperand(result, Map::kBitFieldOffset), | 1989 __ test_b(FieldOperand(result, Map::kBitFieldOffset), |
1990 1 << Map::kHasNonInstancePrototype); | 1990 1 << Map::kHasNonInstancePrototype); |
(...skipping 20 matching lines...) Expand all Loading... |
2011 // in the function's map. | 2011 // in the function's map. |
2012 __ bind(&non_instance); | 2012 __ bind(&non_instance); |
2013 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); | 2013 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); |
2014 | 2014 |
2015 // All done. | 2015 // All done. |
2016 __ bind(&done); | 2016 __ bind(&done); |
2017 } | 2017 } |
2018 | 2018 |
2019 | 2019 |
2020 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2020 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
2021 ASSERT(instr->result()->Equals(instr->input())); | 2021 ASSERT(instr->result()->Equals(instr->InputAt(0))); |
2022 Register reg = ToRegister(instr->input()); | 2022 Register reg = ToRegister(instr->InputAt(0)); |
2023 __ mov(reg, FieldOperand(reg, JSObject::kElementsOffset)); | 2023 __ mov(reg, FieldOperand(reg, JSObject::kElementsOffset)); |
2024 if (FLAG_debug_code) { | 2024 if (FLAG_debug_code) { |
2025 NearLabel done; | 2025 NearLabel done; |
2026 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 2026 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
2027 Immediate(Factory::fixed_array_map())); | 2027 Immediate(Factory::fixed_array_map())); |
2028 __ j(equal, &done); | 2028 __ j(equal, &done); |
2029 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 2029 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
2030 Immediate(Factory::fixed_cow_array_map())); | 2030 Immediate(Factory::fixed_cow_array_map())); |
2031 __ Check(equal, "Check for fast elements failed."); | 2031 __ Check(equal, "Check for fast elements failed."); |
2032 __ bind(&done); | 2032 __ bind(&done); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2092 __ bind(&adapted); | 2092 __ bind(&adapted); |
2093 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2093 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2094 | 2094 |
2095 // Result is the frame pointer for the frame if not adapted and for the real | 2095 // Result is the frame pointer for the frame if not adapted and for the real |
2096 // frame below the adaptor frame if adapted. | 2096 // frame below the adaptor frame if adapted. |
2097 __ bind(&done); | 2097 __ bind(&done); |
2098 } | 2098 } |
2099 | 2099 |
2100 | 2100 |
2101 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2101 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
2102 Operand elem = ToOperand(instr->input()); | 2102 Operand elem = ToOperand(instr->InputAt(0)); |
2103 Register result = ToRegister(instr->result()); | 2103 Register result = ToRegister(instr->result()); |
2104 | 2104 |
2105 NearLabel done; | 2105 NearLabel done; |
2106 | 2106 |
2107 // If no arguments adaptor frame the number of arguments is fixed. | 2107 // If no arguments adaptor frame the number of arguments is fixed. |
2108 __ cmp(ebp, elem); | 2108 __ cmp(ebp, elem); |
2109 __ mov(result, Immediate(scope()->num_parameters())); | 2109 __ mov(result, Immediate(scope()->num_parameters())); |
2110 __ j(equal, &done); | 2110 __ j(equal, &done); |
2111 | 2111 |
2112 // Arguments adaptor frame present. Get argument length from there. | 2112 // Arguments adaptor frame present. Get argument length from there. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2166 ASSERT(receiver.is(eax)); | 2166 ASSERT(receiver.is(eax)); |
2167 v8::internal::ParameterCount actual(eax); | 2167 v8::internal::ParameterCount actual(eax); |
2168 SafepointGenerator safepoint_generator(this, | 2168 SafepointGenerator safepoint_generator(this, |
2169 instr->pointer_map(), | 2169 instr->pointer_map(), |
2170 Safepoint::kNoDeoptimizationIndex); | 2170 Safepoint::kNoDeoptimizationIndex); |
2171 __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator); | 2171 __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator); |
2172 } | 2172 } |
2173 | 2173 |
2174 | 2174 |
2175 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2175 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
2176 LOperand* argument = instr->input(); | 2176 LOperand* argument = instr->InputAt(0); |
2177 if (argument->IsConstantOperand()) { | 2177 if (argument->IsConstantOperand()) { |
2178 __ push(ToImmediate(argument)); | 2178 __ push(ToImmediate(argument)); |
2179 } else { | 2179 } else { |
2180 __ push(ToOperand(argument)); | 2180 __ push(ToOperand(argument)); |
2181 } | 2181 } |
2182 } | 2182 } |
2183 | 2183 |
2184 | 2184 |
2185 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 2185 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
2186 Register result = ToRegister(instr->result()); | 2186 Register result = ToRegister(instr->result()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 | 2232 |
2233 | 2233 |
2234 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2234 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
2235 ASSERT(ToRegister(instr->result()).is(eax)); | 2235 ASSERT(ToRegister(instr->result()).is(eax)); |
2236 __ mov(edi, instr->function()); | 2236 __ mov(edi, instr->function()); |
2237 CallKnownFunction(instr->function(), instr->arity(), instr); | 2237 CallKnownFunction(instr->function(), instr->arity(), instr); |
2238 } | 2238 } |
2239 | 2239 |
2240 | 2240 |
2241 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2241 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
2242 Register input_reg = ToRegister(instr->input()); | 2242 Register input_reg = ToRegister(instr->InputAt(0)); |
2243 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 2243 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
2244 Factory::heap_number_map()); | 2244 Factory::heap_number_map()); |
2245 DeoptimizeIf(not_equal, instr->environment()); | 2245 DeoptimizeIf(not_equal, instr->environment()); |
2246 | 2246 |
2247 Label done; | 2247 Label done; |
2248 Register tmp = input_reg.is(eax) ? ecx : eax; | 2248 Register tmp = input_reg.is(eax) ? ecx : eax; |
2249 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; | 2249 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; |
2250 | 2250 |
2251 // Preserve the value of all registers. | 2251 // Preserve the value of all registers. |
2252 __ PushSafepointRegisters(); | 2252 __ PushSafepointRegisters(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2299 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2299 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
2300 LUnaryMathOperation* instr) | 2300 LUnaryMathOperation* instr) |
2301 : LDeferredCode(codegen), instr_(instr) { } | 2301 : LDeferredCode(codegen), instr_(instr) { } |
2302 virtual void Generate() { | 2302 virtual void Generate() { |
2303 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 2303 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
2304 } | 2304 } |
2305 private: | 2305 private: |
2306 LUnaryMathOperation* instr_; | 2306 LUnaryMathOperation* instr_; |
2307 }; | 2307 }; |
2308 | 2308 |
2309 ASSERT(instr->input()->Equals(instr->result())); | 2309 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
2310 Representation r = instr->hydrogen()->value()->representation(); | 2310 Representation r = instr->hydrogen()->value()->representation(); |
2311 | 2311 |
2312 if (r.IsDouble()) { | 2312 if (r.IsDouble()) { |
2313 XMMRegister scratch = xmm0; | 2313 XMMRegister scratch = xmm0; |
2314 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2314 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
2315 __ pxor(scratch, scratch); | 2315 __ pxor(scratch, scratch); |
2316 __ subsd(scratch, input_reg); | 2316 __ subsd(scratch, input_reg); |
2317 __ pand(input_reg, scratch); | 2317 __ pand(input_reg, scratch); |
2318 } else if (r.IsInteger32()) { | 2318 } else if (r.IsInteger32()) { |
2319 Register input_reg = ToRegister(instr->input()); | 2319 Register input_reg = ToRegister(instr->InputAt(0)); |
2320 __ test(input_reg, Operand(input_reg)); | 2320 __ test(input_reg, Operand(input_reg)); |
2321 Label is_positive; | 2321 Label is_positive; |
2322 __ j(not_sign, &is_positive); | 2322 __ j(not_sign, &is_positive); |
2323 __ neg(input_reg); | 2323 __ neg(input_reg); |
2324 __ test(input_reg, Operand(input_reg)); | 2324 __ test(input_reg, Operand(input_reg)); |
2325 DeoptimizeIf(negative, instr->environment()); | 2325 DeoptimizeIf(negative, instr->environment()); |
2326 __ bind(&is_positive); | 2326 __ bind(&is_positive); |
2327 } else { // Tagged case. | 2327 } else { // Tagged case. |
2328 DeferredMathAbsTaggedHeapNumber* deferred = | 2328 DeferredMathAbsTaggedHeapNumber* deferred = |
2329 new DeferredMathAbsTaggedHeapNumber(this, instr); | 2329 new DeferredMathAbsTaggedHeapNumber(this, instr); |
2330 Label not_smi; | 2330 Label not_smi; |
2331 Register input_reg = ToRegister(instr->input()); | 2331 Register input_reg = ToRegister(instr->InputAt(0)); |
2332 // Smi check. | 2332 // Smi check. |
2333 __ test(input_reg, Immediate(kSmiTagMask)); | 2333 __ test(input_reg, Immediate(kSmiTagMask)); |
2334 __ j(not_zero, deferred->entry()); | 2334 __ j(not_zero, deferred->entry()); |
2335 __ test(input_reg, Operand(input_reg)); | 2335 __ test(input_reg, Operand(input_reg)); |
2336 Label is_positive; | 2336 Label is_positive; |
2337 __ j(not_sign, &is_positive); | 2337 __ j(not_sign, &is_positive); |
2338 __ neg(input_reg); | 2338 __ neg(input_reg); |
2339 | 2339 |
2340 __ test(input_reg, Operand(input_reg)); | 2340 __ test(input_reg, Operand(input_reg)); |
2341 DeoptimizeIf(negative, instr->environment()); | 2341 DeoptimizeIf(negative, instr->environment()); |
2342 | 2342 |
2343 __ bind(&is_positive); | 2343 __ bind(&is_positive); |
2344 __ bind(deferred->exit()); | 2344 __ bind(deferred->exit()); |
2345 } | 2345 } |
2346 } | 2346 } |
2347 | 2347 |
2348 | 2348 |
2349 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 2349 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
2350 XMMRegister xmm_scratch = xmm0; | 2350 XMMRegister xmm_scratch = xmm0; |
2351 Register output_reg = ToRegister(instr->result()); | 2351 Register output_reg = ToRegister(instr->result()); |
2352 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2352 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
2353 __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. | 2353 __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. |
2354 __ ucomisd(input_reg, xmm_scratch); | 2354 __ ucomisd(input_reg, xmm_scratch); |
2355 | 2355 |
2356 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2356 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
2357 DeoptimizeIf(below_equal, instr->environment()); | 2357 DeoptimizeIf(below_equal, instr->environment()); |
2358 } else { | 2358 } else { |
2359 DeoptimizeIf(below, instr->environment()); | 2359 DeoptimizeIf(below, instr->environment()); |
2360 } | 2360 } |
2361 | 2361 |
2362 // Use truncating instruction (OK because input is positive). | 2362 // Use truncating instruction (OK because input is positive). |
2363 __ cvttsd2si(output_reg, Operand(input_reg)); | 2363 __ cvttsd2si(output_reg, Operand(input_reg)); |
2364 | 2364 |
2365 // Overflow is signalled with minint. | 2365 // Overflow is signalled with minint. |
2366 __ cmp(output_reg, 0x80000000u); | 2366 __ cmp(output_reg, 0x80000000u); |
2367 DeoptimizeIf(equal, instr->environment()); | 2367 DeoptimizeIf(equal, instr->environment()); |
2368 } | 2368 } |
2369 | 2369 |
2370 | 2370 |
2371 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2371 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
2372 XMMRegister xmm_scratch = xmm0; | 2372 XMMRegister xmm_scratch = xmm0; |
2373 Register output_reg = ToRegister(instr->result()); | 2373 Register output_reg = ToRegister(instr->result()); |
2374 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2374 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
2375 | 2375 |
2376 // xmm_scratch = 0.5 | 2376 // xmm_scratch = 0.5 |
2377 ExternalReference one_half = ExternalReference::address_of_one_half(); | 2377 ExternalReference one_half = ExternalReference::address_of_one_half(); |
2378 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); | 2378 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); |
2379 | 2379 |
2380 // input = input + 0.5 | 2380 // input = input + 0.5 |
2381 __ addsd(input_reg, xmm_scratch); | 2381 __ addsd(input_reg, xmm_scratch); |
2382 | 2382 |
2383 // We need to return -0 for the input range [-0.5, 0[, otherwise | 2383 // We need to return -0 for the input range [-0.5, 0[, otherwise |
2384 // compute Math.floor(value + 0.5). | 2384 // compute Math.floor(value + 0.5). |
(...skipping 12 matching lines...) Expand all Loading... |
2397 // Use truncating instruction (OK because input is positive). | 2397 // Use truncating instruction (OK because input is positive). |
2398 __ cvttsd2si(output_reg, Operand(input_reg)); | 2398 __ cvttsd2si(output_reg, Operand(input_reg)); |
2399 | 2399 |
2400 // Overflow is signalled with minint. | 2400 // Overflow is signalled with minint. |
2401 __ cmp(output_reg, 0x80000000u); | 2401 __ cmp(output_reg, 0x80000000u); |
2402 DeoptimizeIf(equal, instr->environment()); | 2402 DeoptimizeIf(equal, instr->environment()); |
2403 } | 2403 } |
2404 | 2404 |
2405 | 2405 |
2406 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 2406 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
2407 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2407 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
2408 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2408 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
2409 __ sqrtsd(input_reg, input_reg); | 2409 __ sqrtsd(input_reg, input_reg); |
2410 } | 2410 } |
2411 | 2411 |
2412 | 2412 |
2413 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 2413 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
2414 XMMRegister xmm_scratch = xmm0; | 2414 XMMRegister xmm_scratch = xmm0; |
2415 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2415 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
2416 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2416 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
2417 ExternalReference negative_infinity = | 2417 ExternalReference negative_infinity = |
2418 ExternalReference::address_of_negative_infinity(); | 2418 ExternalReference::address_of_negative_infinity(); |
2419 __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); | 2419 __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); |
2420 __ ucomisd(xmm_scratch, input_reg); | 2420 __ ucomisd(xmm_scratch, input_reg); |
2421 DeoptimizeIf(equal, instr->environment()); | 2421 DeoptimizeIf(equal, instr->environment()); |
2422 __ sqrtsd(input_reg, input_reg); | 2422 __ sqrtsd(input_reg, input_reg); |
2423 } | 2423 } |
2424 | 2424 |
2425 | 2425 |
2426 void LCodeGen::DoPower(LPower* instr) { | 2426 void LCodeGen::DoPower(LPower* instr) { |
2427 LOperand* left = instr->left(); | 2427 LOperand* left = instr->InputAt(0); |
2428 LOperand* right = instr->right(); | 2428 LOperand* right = instr->InputAt(1); |
2429 DoubleRegister result_reg = ToDoubleRegister(instr->result()); | 2429 DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
2430 Representation exponent_type = instr->hydrogen()->right()->representation(); | 2430 Representation exponent_type = instr->hydrogen()->right()->representation(); |
2431 if (exponent_type.IsDouble()) { | 2431 if (exponent_type.IsDouble()) { |
2432 // It is safe to use ebx directly since the instruction is marked | 2432 // It is safe to use ebx directly since the instruction is marked |
2433 // as a call. | 2433 // as a call. |
2434 __ PrepareCallCFunction(4, ebx); | 2434 __ PrepareCallCFunction(4, ebx); |
2435 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); | 2435 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
2436 __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); | 2436 __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); |
2437 __ CallCFunction(ExternalReference::power_double_double_function(), 4); | 2437 __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
2438 } else if (exponent_type.IsInteger32()) { | 2438 } else if (exponent_type.IsInteger32()) { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2580 | 2580 |
2581 | 2581 |
2582 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 2582 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
2583 ASSERT(ToRegister(instr->result()).is(eax)); | 2583 ASSERT(ToRegister(instr->result()).is(eax)); |
2584 __ mov(edi, instr->target()); | 2584 __ mov(edi, instr->target()); |
2585 CallKnownFunction(instr->target(), instr->arity(), instr); | 2585 CallKnownFunction(instr->target(), instr->arity(), instr); |
2586 } | 2586 } |
2587 | 2587 |
2588 | 2588 |
2589 void LCodeGen::DoCallNew(LCallNew* instr) { | 2589 void LCodeGen::DoCallNew(LCallNew* instr) { |
2590 ASSERT(ToRegister(instr->input()).is(edi)); | 2590 ASSERT(ToRegister(instr->InputAt(0)).is(edi)); |
2591 ASSERT(ToRegister(instr->result()).is(eax)); | 2591 ASSERT(ToRegister(instr->result()).is(eax)); |
2592 | 2592 |
2593 Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); | 2593 Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); |
2594 __ Set(eax, Immediate(instr->arity())); | 2594 __ Set(eax, Immediate(instr->arity())); |
2595 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); | 2595 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); |
2596 } | 2596 } |
2597 | 2597 |
2598 | 2598 |
2599 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 2599 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
2600 CallRuntime(instr->function(), instr->arity(), instr); | 2600 CallRuntime(instr->function(), instr->arity(), instr); |
2601 } | 2601 } |
2602 | 2602 |
2603 | 2603 |
2604 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 2604 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
2605 Register object = ToRegister(instr->object()); | 2605 Register object = ToRegister(instr->object()); |
2606 Register value = ToRegister(instr->value()); | 2606 Register value = ToRegister(instr->value()); |
2607 int offset = instr->offset(); | 2607 int offset = instr->offset(); |
2608 | 2608 |
2609 if (!instr->transition().is_null()) { | 2609 if (!instr->transition().is_null()) { |
2610 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 2610 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
2611 } | 2611 } |
2612 | 2612 |
2613 // Do the store. | 2613 // Do the store. |
2614 if (instr->is_in_object()) { | 2614 if (instr->is_in_object()) { |
2615 __ mov(FieldOperand(object, offset), value); | 2615 __ mov(FieldOperand(object, offset), value); |
2616 if (instr->needs_write_barrier()) { | 2616 if (instr->needs_write_barrier()) { |
2617 Register temp = ToRegister(instr->temp()); | 2617 Register temp = ToRegister(instr->TempAt(0)); |
2618 // Update the write barrier for the object for in-object properties. | 2618 // Update the write barrier for the object for in-object properties. |
2619 __ RecordWrite(object, offset, value, temp); | 2619 __ RecordWrite(object, offset, value, temp); |
2620 } | 2620 } |
2621 } else { | 2621 } else { |
2622 Register temp = ToRegister(instr->temp()); | 2622 Register temp = ToRegister(instr->TempAt(0)); |
2623 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 2623 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
2624 __ mov(FieldOperand(temp, offset), value); | 2624 __ mov(FieldOperand(temp, offset), value); |
2625 if (instr->needs_write_barrier()) { | 2625 if (instr->needs_write_barrier()) { |
2626 // Update the write barrier for the properties array. | 2626 // Update the write barrier for the properties array. |
2627 // object is used as a scratch register. | 2627 // object is used as a scratch register. |
2628 __ RecordWrite(temp, offset, value, object); | 2628 __ RecordWrite(temp, offset, value, object); |
2629 } | 2629 } |
2630 } | 2630 } |
2631 } | 2631 } |
2632 | 2632 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2676 ASSERT(ToRegister(instr->object()).is(edx)); | 2676 ASSERT(ToRegister(instr->object()).is(edx)); |
2677 ASSERT(ToRegister(instr->key()).is(ecx)); | 2677 ASSERT(ToRegister(instr->key()).is(ecx)); |
2678 ASSERT(ToRegister(instr->value()).is(eax)); | 2678 ASSERT(ToRegister(instr->value()).is(eax)); |
2679 | 2679 |
2680 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 2680 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
2681 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2681 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2682 } | 2682 } |
2683 | 2683 |
2684 | 2684 |
2685 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 2685 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
2686 LOperand* input = instr->input(); | 2686 LOperand* input = instr->InputAt(0); |
2687 ASSERT(input->IsRegister() || input->IsStackSlot()); | 2687 ASSERT(input->IsRegister() || input->IsStackSlot()); |
2688 LOperand* output = instr->result(); | 2688 LOperand* output = instr->result(); |
2689 ASSERT(output->IsDoubleRegister()); | 2689 ASSERT(output->IsDoubleRegister()); |
2690 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); | 2690 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); |
2691 } | 2691 } |
2692 | 2692 |
2693 | 2693 |
2694 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 2694 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
2695 class DeferredNumberTagI: public LDeferredCode { | 2695 class DeferredNumberTagI: public LDeferredCode { |
2696 public: | 2696 public: |
2697 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 2697 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
2698 : LDeferredCode(codegen), instr_(instr) { } | 2698 : LDeferredCode(codegen), instr_(instr) { } |
2699 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } | 2699 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } |
2700 private: | 2700 private: |
2701 LNumberTagI* instr_; | 2701 LNumberTagI* instr_; |
2702 }; | 2702 }; |
2703 | 2703 |
2704 LOperand* input = instr->input(); | 2704 LOperand* input = instr->InputAt(0); |
2705 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 2705 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
2706 Register reg = ToRegister(input); | 2706 Register reg = ToRegister(input); |
2707 | 2707 |
2708 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); | 2708 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); |
2709 __ SmiTag(reg); | 2709 __ SmiTag(reg); |
2710 __ j(overflow, deferred->entry()); | 2710 __ j(overflow, deferred->entry()); |
2711 __ bind(deferred->exit()); | 2711 __ bind(deferred->exit()); |
2712 } | 2712 } |
2713 | 2713 |
2714 | 2714 |
2715 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 2715 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
2716 Label slow; | 2716 Label slow; |
2717 Register reg = ToRegister(instr->input()); | 2717 Register reg = ToRegister(instr->InputAt(0)); |
2718 Register tmp = reg.is(eax) ? ecx : eax; | 2718 Register tmp = reg.is(eax) ? ecx : eax; |
2719 | 2719 |
2720 // Preserve the value of all registers. | 2720 // Preserve the value of all registers. |
2721 __ PushSafepointRegisters(); | 2721 __ PushSafepointRegisters(); |
2722 | 2722 |
2723 // There was overflow, so bits 30 and 31 of the original integer | 2723 // There was overflow, so bits 30 and 31 of the original integer |
2724 // disagree. Try to allocate a heap number in new space and store | 2724 // disagree. Try to allocate a heap number in new space and store |
2725 // the value in there. If that fails, call the runtime system. | 2725 // the value in there. If that fails, call the runtime system. |
2726 NearLabel done; | 2726 NearLabel done; |
2727 __ SmiUntag(reg); | 2727 __ SmiUntag(reg); |
(...skipping 29 matching lines...) Expand all Loading... |
2757 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 2757 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
2758 class DeferredNumberTagD: public LDeferredCode { | 2758 class DeferredNumberTagD: public LDeferredCode { |
2759 public: | 2759 public: |
2760 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 2760 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
2761 : LDeferredCode(codegen), instr_(instr) { } | 2761 : LDeferredCode(codegen), instr_(instr) { } |
2762 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 2762 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
2763 private: | 2763 private: |
2764 LNumberTagD* instr_; | 2764 LNumberTagD* instr_; |
2765 }; | 2765 }; |
2766 | 2766 |
2767 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2767 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
2768 Register reg = ToRegister(instr->result()); | 2768 Register reg = ToRegister(instr->result()); |
2769 Register tmp = ToRegister(instr->temp()); | 2769 Register tmp = ToRegister(instr->TempAt(0)); |
2770 | 2770 |
2771 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); | 2771 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); |
2772 if (FLAG_inline_new) { | 2772 if (FLAG_inline_new) { |
2773 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); | 2773 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); |
2774 } else { | 2774 } else { |
2775 __ jmp(deferred->entry()); | 2775 __ jmp(deferred->entry()); |
2776 } | 2776 } |
2777 __ bind(deferred->exit()); | 2777 __ bind(deferred->exit()); |
2778 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 2778 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
2779 } | 2779 } |
2780 | 2780 |
2781 | 2781 |
2782 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 2782 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
2783 // TODO(3095996): Get rid of this. For now, we need to make the | 2783 // TODO(3095996): Get rid of this. For now, we need to make the |
2784 // result register contain a valid pointer because it is already | 2784 // result register contain a valid pointer because it is already |
2785 // contained in the register pointer map. | 2785 // contained in the register pointer map. |
2786 Register reg = ToRegister(instr->result()); | 2786 Register reg = ToRegister(instr->result()); |
2787 __ Set(reg, Immediate(0)); | 2787 __ Set(reg, Immediate(0)); |
2788 | 2788 |
2789 __ PushSafepointRegisters(); | 2789 __ PushSafepointRegisters(); |
2790 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 2790 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
2791 RecordSafepointWithRegisters( | 2791 RecordSafepointWithRegisters( |
2792 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | 2792 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
2793 __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), eax); | 2793 __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), eax); |
2794 __ PopSafepointRegisters(); | 2794 __ PopSafepointRegisters(); |
2795 } | 2795 } |
2796 | 2796 |
2797 | 2797 |
2798 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 2798 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
2799 LOperand* input = instr->input(); | 2799 LOperand* input = instr->InputAt(0); |
2800 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 2800 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
2801 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 2801 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
2802 __ SmiTag(ToRegister(input)); | 2802 __ SmiTag(ToRegister(input)); |
2803 } | 2803 } |
2804 | 2804 |
2805 | 2805 |
2806 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 2806 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
2807 LOperand* input = instr->input(); | 2807 LOperand* input = instr->InputAt(0); |
2808 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 2808 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
2809 if (instr->needs_check()) { | 2809 if (instr->needs_check()) { |
2810 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 2810 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
2811 DeoptimizeIf(not_zero, instr->environment()); | 2811 DeoptimizeIf(not_zero, instr->environment()); |
2812 } | 2812 } |
2813 __ SmiUntag(ToRegister(input)); | 2813 __ SmiUntag(ToRegister(input)); |
2814 } | 2814 } |
2815 | 2815 |
2816 | 2816 |
2817 void LCodeGen::EmitNumberUntagD(Register input_reg, | 2817 void LCodeGen::EmitNumberUntagD(Register input_reg, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2857 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 2857 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
2858 : LDeferredCode(codegen), instr_(instr) { } | 2858 : LDeferredCode(codegen), instr_(instr) { } |
2859 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 2859 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
2860 private: | 2860 private: |
2861 LTaggedToI* instr_; | 2861 LTaggedToI* instr_; |
2862 }; | 2862 }; |
2863 | 2863 |
2864 | 2864 |
2865 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 2865 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
2866 NearLabel done, heap_number; | 2866 NearLabel done, heap_number; |
2867 Register input_reg = ToRegister(instr->input()); | 2867 Register input_reg = ToRegister(instr->InputAt(0)); |
2868 | 2868 |
2869 // Heap number map check. | 2869 // Heap number map check. |
2870 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 2870 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
2871 Factory::heap_number_map()); | 2871 Factory::heap_number_map()); |
2872 | 2872 |
2873 if (instr->truncating()) { | 2873 if (instr->truncating()) { |
2874 __ j(equal, &heap_number); | 2874 __ j(equal, &heap_number); |
2875 // Check for undefined. Undefined is converted to zero for truncating | 2875 // Check for undefined. Undefined is converted to zero for truncating |
2876 // conversions. | 2876 // conversions. |
2877 __ cmp(input_reg, Factory::undefined_value()); | 2877 __ cmp(input_reg, Factory::undefined_value()); |
(...skipping 22 matching lines...) Expand all Loading... |
2900 | 2900 |
2901 // Reserve space for 64 bit answer. | 2901 // Reserve space for 64 bit answer. |
2902 __ bind(&convert); | 2902 __ bind(&convert); |
2903 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2903 __ sub(Operand(esp), Immediate(kDoubleSize)); |
2904 // Do conversion, which cannot fail because we checked the exponent. | 2904 // Do conversion, which cannot fail because we checked the exponent. |
2905 __ fisttp_d(Operand(esp, 0)); | 2905 __ fisttp_d(Operand(esp, 0)); |
2906 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. | 2906 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. |
2907 __ add(Operand(esp), Immediate(kDoubleSize)); | 2907 __ add(Operand(esp), Immediate(kDoubleSize)); |
2908 } else { | 2908 } else { |
2909 NearLabel deopt; | 2909 NearLabel deopt; |
2910 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | 2910 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
2911 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 2911 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
2912 __ cvttsd2si(input_reg, Operand(xmm0)); | 2912 __ cvttsd2si(input_reg, Operand(xmm0)); |
2913 __ cmp(input_reg, 0x80000000u); | 2913 __ cmp(input_reg, 0x80000000u); |
2914 __ j(not_equal, &done); | 2914 __ j(not_equal, &done); |
2915 // Check if the input was 0x8000000 (kMinInt). | 2915 // Check if the input was 0x8000000 (kMinInt). |
2916 // If no, then we got an overflow and we deoptimize. | 2916 // If no, then we got an overflow and we deoptimize. |
2917 ExternalReference min_int = ExternalReference::address_of_min_int(); | 2917 ExternalReference min_int = ExternalReference::address_of_min_int(); |
2918 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); | 2918 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); |
2919 __ ucomisd(xmm_temp, xmm0); | 2919 __ ucomisd(xmm_temp, xmm0); |
2920 DeoptimizeIf(not_equal, instr->environment()); | 2920 DeoptimizeIf(not_equal, instr->environment()); |
2921 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 2921 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
2922 } | 2922 } |
2923 } else { | 2923 } else { |
2924 // Deoptimize if we don't have a heap number. | 2924 // Deoptimize if we don't have a heap number. |
2925 DeoptimizeIf(not_equal, instr->environment()); | 2925 DeoptimizeIf(not_equal, instr->environment()); |
2926 | 2926 |
2927 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | 2927 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
2928 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 2928 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
2929 __ cvttsd2si(input_reg, Operand(xmm0)); | 2929 __ cvttsd2si(input_reg, Operand(xmm0)); |
2930 __ cvtsi2sd(xmm_temp, Operand(input_reg)); | 2930 __ cvtsi2sd(xmm_temp, Operand(input_reg)); |
2931 __ ucomisd(xmm0, xmm_temp); | 2931 __ ucomisd(xmm0, xmm_temp); |
2932 DeoptimizeIf(not_equal, instr->environment()); | 2932 DeoptimizeIf(not_equal, instr->environment()); |
2933 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 2933 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
2934 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2934 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
2935 __ test(input_reg, Operand(input_reg)); | 2935 __ test(input_reg, Operand(input_reg)); |
2936 __ j(not_zero, &done); | 2936 __ j(not_zero, &done); |
2937 __ movmskpd(input_reg, xmm0); | 2937 __ movmskpd(input_reg, xmm0); |
2938 __ and_(input_reg, 1); | 2938 __ and_(input_reg, 1); |
2939 DeoptimizeIf(not_zero, instr->environment()); | 2939 DeoptimizeIf(not_zero, instr->environment()); |
2940 } | 2940 } |
2941 } | 2941 } |
2942 __ bind(&done); | 2942 __ bind(&done); |
2943 } | 2943 } |
2944 | 2944 |
2945 | 2945 |
2946 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 2946 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
2947 LOperand* input = instr->input(); | 2947 LOperand* input = instr->InputAt(0); |
2948 ASSERT(input->IsRegister()); | 2948 ASSERT(input->IsRegister()); |
2949 ASSERT(input->Equals(instr->result())); | 2949 ASSERT(input->Equals(instr->result())); |
2950 | 2950 |
2951 Register input_reg = ToRegister(input); | 2951 Register input_reg = ToRegister(input); |
2952 | 2952 |
2953 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); | 2953 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); |
2954 | 2954 |
2955 // Smi check. | 2955 // Smi check. |
2956 __ test(input_reg, Immediate(kSmiTagMask)); | 2956 __ test(input_reg, Immediate(kSmiTagMask)); |
2957 __ j(not_zero, deferred->entry()); | 2957 __ j(not_zero, deferred->entry()); |
2958 | 2958 |
2959 // Smi to int32 conversion | 2959 // Smi to int32 conversion |
2960 __ SmiUntag(input_reg); // Untag smi. | 2960 __ SmiUntag(input_reg); // Untag smi. |
2961 | 2961 |
2962 __ bind(deferred->exit()); | 2962 __ bind(deferred->exit()); |
2963 } | 2963 } |
2964 | 2964 |
2965 | 2965 |
2966 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 2966 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
2967 LOperand* input = instr->input(); | 2967 LOperand* input = instr->InputAt(0); |
2968 ASSERT(input->IsRegister()); | 2968 ASSERT(input->IsRegister()); |
2969 LOperand* result = instr->result(); | 2969 LOperand* result = instr->result(); |
2970 ASSERT(result->IsDoubleRegister()); | 2970 ASSERT(result->IsDoubleRegister()); |
2971 | 2971 |
2972 Register input_reg = ToRegister(input); | 2972 Register input_reg = ToRegister(input); |
2973 XMMRegister result_reg = ToDoubleRegister(result); | 2973 XMMRegister result_reg = ToDoubleRegister(result); |
2974 | 2974 |
2975 EmitNumberUntagD(input_reg, result_reg, instr->environment()); | 2975 EmitNumberUntagD(input_reg, result_reg, instr->environment()); |
2976 } | 2976 } |
2977 | 2977 |
2978 | 2978 |
2979 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 2979 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
2980 LOperand* input = instr->input(); | 2980 LOperand* input = instr->InputAt(0); |
2981 ASSERT(input->IsDoubleRegister()); | 2981 ASSERT(input->IsDoubleRegister()); |
2982 LOperand* result = instr->result(); | 2982 LOperand* result = instr->result(); |
2983 ASSERT(result->IsRegister()); | 2983 ASSERT(result->IsRegister()); |
2984 | 2984 |
2985 XMMRegister input_reg = ToDoubleRegister(input); | 2985 XMMRegister input_reg = ToDoubleRegister(input); |
2986 Register result_reg = ToRegister(result); | 2986 Register result_reg = ToRegister(result); |
2987 | 2987 |
2988 if (instr->truncating()) { | 2988 if (instr->truncating()) { |
2989 // Performs a truncating conversion of a floating point number as used by | 2989 // Performs a truncating conversion of a floating point number as used by |
2990 // the JS bitwise operations. | 2990 // the JS bitwise operations. |
(...skipping 17 matching lines...) Expand all Loading... |
3008 DeoptimizeIf(no_condition, instr->environment()); | 3008 DeoptimizeIf(no_condition, instr->environment()); |
3009 __ bind(&convert); | 3009 __ bind(&convert); |
3010 // Do conversion, which cannot fail because we checked the exponent. | 3010 // Do conversion, which cannot fail because we checked the exponent. |
3011 __ fld_d(Operand(esp, 0)); | 3011 __ fld_d(Operand(esp, 0)); |
3012 __ fisttp_d(Operand(esp, 0)); | 3012 __ fisttp_d(Operand(esp, 0)); |
3013 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | 3013 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. |
3014 __ add(Operand(esp), Immediate(kDoubleSize)); | 3014 __ add(Operand(esp), Immediate(kDoubleSize)); |
3015 __ bind(&done); | 3015 __ bind(&done); |
3016 } else { | 3016 } else { |
3017 NearLabel done; | 3017 NearLabel done; |
3018 Register temp_reg = ToRegister(instr->temporary()); | 3018 Register temp_reg = ToRegister(instr->TempAt(0)); |
3019 XMMRegister xmm_scratch = xmm0; | 3019 XMMRegister xmm_scratch = xmm0; |
3020 | 3020 |
3021 // If cvttsd2si succeeded, we're done. Otherwise, we attempt | 3021 // If cvttsd2si succeeded, we're done. Otherwise, we attempt |
3022 // manual conversion. | 3022 // manual conversion. |
3023 __ j(not_equal, &done); | 3023 __ j(not_equal, &done); |
3024 | 3024 |
3025 // Get high 32 bits of the input in result_reg and temp_reg. | 3025 // Get high 32 bits of the input in result_reg and temp_reg. |
3026 __ pshufd(xmm_scratch, input_reg, 1); | 3026 __ pshufd(xmm_scratch, input_reg, 1); |
3027 __ movd(Operand(temp_reg), xmm_scratch); | 3027 __ movd(Operand(temp_reg), xmm_scratch); |
3028 __ mov(result_reg, temp_reg); | 3028 __ mov(result_reg, temp_reg); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3087 // deoptimize. | 3087 // deoptimize. |
3088 __ and_(result_reg, 1); | 3088 __ and_(result_reg, 1); |
3089 DeoptimizeIf(not_zero, instr->environment()); | 3089 DeoptimizeIf(not_zero, instr->environment()); |
3090 } | 3090 } |
3091 __ bind(&done); | 3091 __ bind(&done); |
3092 } | 3092 } |
3093 } | 3093 } |
3094 | 3094 |
3095 | 3095 |
3096 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 3096 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
3097 LOperand* input = instr->input(); | 3097 LOperand* input = instr->InputAt(0); |
3098 ASSERT(input->IsRegister()); | 3098 ASSERT(input->IsRegister()); |
3099 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 3099 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
3100 DeoptimizeIf(instr->condition(), instr->environment()); | 3100 DeoptimizeIf(instr->condition(), instr->environment()); |
3101 } | 3101 } |
3102 | 3102 |
3103 | 3103 |
3104 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 3104 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
3105 Register input = ToRegister(instr->input()); | 3105 Register input = ToRegister(instr->InputAt(0)); |
3106 Register temp = ToRegister(instr->temp()); | 3106 Register temp = ToRegister(instr->TempAt(0)); |
3107 InstanceType first = instr->hydrogen()->first(); | 3107 InstanceType first = instr->hydrogen()->first(); |
3108 InstanceType last = instr->hydrogen()->last(); | 3108 InstanceType last = instr->hydrogen()->last(); |
3109 | 3109 |
3110 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 3110 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
3111 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 3111 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
3112 static_cast<int8_t>(first)); | 3112 static_cast<int8_t>(first)); |
3113 | 3113 |
3114 // If there is only one type in the interval check for equality. | 3114 // If there is only one type in the interval check for equality. |
3115 if (first == last) { | 3115 if (first == last) { |
3116 DeoptimizeIf(not_equal, instr->environment()); | 3116 DeoptimizeIf(not_equal, instr->environment()); |
3117 } else { | 3117 } else { |
3118 DeoptimizeIf(below, instr->environment()); | 3118 DeoptimizeIf(below, instr->environment()); |
3119 // Omit check for the last type. | 3119 // Omit check for the last type. |
3120 if (last != LAST_TYPE) { | 3120 if (last != LAST_TYPE) { |
3121 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 3121 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
3122 static_cast<int8_t>(last)); | 3122 static_cast<int8_t>(last)); |
3123 DeoptimizeIf(above, instr->environment()); | 3123 DeoptimizeIf(above, instr->environment()); |
3124 } | 3124 } |
3125 } | 3125 } |
3126 } | 3126 } |
3127 | 3127 |
3128 | 3128 |
3129 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 3129 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
3130 ASSERT(instr->input()->IsRegister()); | 3130 ASSERT(instr->InputAt(0)->IsRegister()); |
3131 Register reg = ToRegister(instr->input()); | 3131 Register reg = ToRegister(instr->InputAt(0)); |
3132 __ cmp(reg, instr->hydrogen()->target()); | 3132 __ cmp(reg, instr->hydrogen()->target()); |
3133 DeoptimizeIf(not_equal, instr->environment()); | 3133 DeoptimizeIf(not_equal, instr->environment()); |
3134 } | 3134 } |
3135 | 3135 |
3136 | 3136 |
3137 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 3137 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
3138 LOperand* input = instr->input(); | 3138 LOperand* input = instr->InputAt(0); |
3139 ASSERT(input->IsRegister()); | 3139 ASSERT(input->IsRegister()); |
3140 Register reg = ToRegister(input); | 3140 Register reg = ToRegister(input); |
3141 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3141 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
3142 instr->hydrogen()->map()); | 3142 instr->hydrogen()->map()); |
3143 DeoptimizeIf(not_equal, instr->environment()); | 3143 DeoptimizeIf(not_equal, instr->environment()); |
3144 } | 3144 } |
3145 | 3145 |
3146 | 3146 |
3147 void LCodeGen::LoadPrototype(Register result, Handle<JSObject> prototype) { | 3147 void LCodeGen::LoadPrototype(Register result, Handle<JSObject> prototype) { |
3148 if (Heap::InNewSpace(*prototype)) { | 3148 if (Heap::InNewSpace(*prototype)) { |
3149 Handle<JSGlobalPropertyCell> cell = | 3149 Handle<JSGlobalPropertyCell> cell = |
3150 Factory::NewJSGlobalPropertyCell(prototype); | 3150 Factory::NewJSGlobalPropertyCell(prototype); |
3151 __ mov(result, Operand::Cell(cell)); | 3151 __ mov(result, Operand::Cell(cell)); |
3152 } else { | 3152 } else { |
3153 __ mov(result, prototype); | 3153 __ mov(result, prototype); |
3154 } | 3154 } |
3155 } | 3155 } |
3156 | 3156 |
3157 | 3157 |
3158 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 3158 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
3159 Register reg = ToRegister(instr->temp()); | 3159 Register reg = ToRegister(instr->TempAt(0)); |
3160 | 3160 |
3161 Handle<JSObject> holder = instr->holder(); | 3161 Handle<JSObject> holder = instr->holder(); |
3162 Handle<JSObject> current_prototype = instr->prototype(); | 3162 Handle<JSObject> current_prototype = instr->prototype(); |
3163 | 3163 |
3164 // Load prototype object. | 3164 // Load prototype object. |
3165 LoadPrototype(reg, current_prototype); | 3165 LoadPrototype(reg, current_prototype); |
3166 | 3166 |
3167 // Check prototype maps up to the holder. | 3167 // Check prototype maps up to the holder. |
3168 while (!current_prototype.is_identical_to(holder)) { | 3168 while (!current_prototype.is_identical_to(holder)) { |
3169 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3169 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3293 __ push(Immediate(shared_info)); | 3293 __ push(Immediate(shared_info)); |
3294 __ push(Immediate(pretenure | 3294 __ push(Immediate(pretenure |
3295 ? Factory::true_value() | 3295 ? Factory::true_value() |
3296 : Factory::false_value())); | 3296 : Factory::false_value())); |
3297 CallRuntime(Runtime::kNewClosure, 3, instr); | 3297 CallRuntime(Runtime::kNewClosure, 3, instr); |
3298 } | 3298 } |
3299 } | 3299 } |
3300 | 3300 |
3301 | 3301 |
3302 void LCodeGen::DoTypeof(LTypeof* instr) { | 3302 void LCodeGen::DoTypeof(LTypeof* instr) { |
3303 LOperand* input = instr->input(); | 3303 LOperand* input = instr->InputAt(0); |
3304 if (input->IsConstantOperand()) { | 3304 if (input->IsConstantOperand()) { |
3305 __ push(ToImmediate(input)); | 3305 __ push(ToImmediate(input)); |
3306 } else { | 3306 } else { |
3307 __ push(ToOperand(input)); | 3307 __ push(ToOperand(input)); |
3308 } | 3308 } |
3309 CallRuntime(Runtime::kTypeof, 1, instr); | 3309 CallRuntime(Runtime::kTypeof, 1, instr); |
3310 } | 3310 } |
3311 | 3311 |
3312 | 3312 |
3313 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 3313 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
3314 Register input = ToRegister(instr->input()); | 3314 Register input = ToRegister(instr->InputAt(0)); |
3315 Register result = ToRegister(instr->result()); | 3315 Register result = ToRegister(instr->result()); |
3316 Label true_label; | 3316 Label true_label; |
3317 Label false_label; | 3317 Label false_label; |
3318 NearLabel done; | 3318 NearLabel done; |
3319 | 3319 |
3320 Condition final_branch_condition = EmitTypeofIs(&true_label, | 3320 Condition final_branch_condition = EmitTypeofIs(&true_label, |
3321 &false_label, | 3321 &false_label, |
3322 input, | 3322 input, |
3323 instr->type_literal()); | 3323 instr->type_literal()); |
3324 __ j(final_branch_condition, &true_label); | 3324 __ j(final_branch_condition, &true_label); |
3325 __ bind(&false_label); | 3325 __ bind(&false_label); |
3326 __ mov(result, Handle<Object>(Heap::false_value())); | 3326 __ mov(result, Handle<Object>(Heap::false_value())); |
3327 __ jmp(&done); | 3327 __ jmp(&done); |
3328 | 3328 |
3329 __ bind(&true_label); | 3329 __ bind(&true_label); |
3330 __ mov(result, Handle<Object>(Heap::true_value())); | 3330 __ mov(result, Handle<Object>(Heap::true_value())); |
3331 | 3331 |
3332 __ bind(&done); | 3332 __ bind(&done); |
3333 } | 3333 } |
3334 | 3334 |
3335 | 3335 |
3336 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 3336 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
3337 Register input = ToRegister(instr->input()); | 3337 Register input = ToRegister(instr->InputAt(0)); |
3338 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 3338 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
3339 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 3339 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
3340 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 3340 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
3341 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 3341 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
3342 | 3342 |
3343 Condition final_branch_condition = EmitTypeofIs(true_label, | 3343 Condition final_branch_condition = EmitTypeofIs(true_label, |
3344 false_label, | 3344 false_label, |
3345 input, | 3345 input, |
3346 instr->type_literal()); | 3346 instr->type_literal()); |
3347 | 3347 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3481 ASSERT(osr_pc_offset_ == -1); | 3481 ASSERT(osr_pc_offset_ == -1); |
3482 osr_pc_offset_ = masm()->pc_offset(); | 3482 osr_pc_offset_ = masm()->pc_offset(); |
3483 } | 3483 } |
3484 | 3484 |
3485 | 3485 |
3486 #undef __ | 3486 #undef __ |
3487 | 3487 |
3488 } } // namespace v8::internal | 3488 } } // namespace v8::internal |
3489 | 3489 |
3490 #endif // V8_TARGET_ARCH_IA32 | 3490 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |