| 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 |