OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 } | 811 } |
812 | 812 |
813 | 813 |
814 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 814 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
815 // Nothing to do. | 815 // Nothing to do. |
816 } | 816 } |
817 | 817 |
818 | 818 |
819 void LCodeGen::DoModI(LModI* instr) { | 819 void LCodeGen::DoModI(LModI* instr) { |
820 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 820 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
821 Register dividend = ToRegister(instr->InputAt(0)); | 821 Register dividend = ToRegister(instr->left()); |
822 | 822 |
823 int32_t divisor = | 823 int32_t divisor = |
824 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 824 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
825 | 825 |
826 if (divisor < 0) divisor = -divisor; | 826 if (divisor < 0) divisor = -divisor; |
827 | 827 |
828 Label positive_dividend, done; | 828 Label positive_dividend, done; |
829 __ testl(dividend, dividend); | 829 __ testl(dividend, dividend); |
830 __ j(not_sign, &positive_dividend, Label::kNear); | 830 __ j(not_sign, &positive_dividend, Label::kNear); |
831 __ negl(dividend); | 831 __ negl(dividend); |
832 __ andl(dividend, Immediate(divisor - 1)); | 832 __ andl(dividend, Immediate(divisor - 1)); |
833 __ negl(dividend); | 833 __ negl(dividend); |
834 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 834 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
835 __ j(not_zero, &done, Label::kNear); | 835 __ j(not_zero, &done, Label::kNear); |
836 DeoptimizeIf(no_condition, instr->environment()); | 836 DeoptimizeIf(no_condition, instr->environment()); |
837 } else { | 837 } else { |
838 __ jmp(&done, Label::kNear); | 838 __ jmp(&done, Label::kNear); |
839 } | 839 } |
840 __ bind(&positive_dividend); | 840 __ bind(&positive_dividend); |
841 __ andl(dividend, Immediate(divisor - 1)); | 841 __ andl(dividend, Immediate(divisor - 1)); |
842 __ bind(&done); | 842 __ bind(&done); |
843 } else { | 843 } else { |
844 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; | 844 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; |
845 Register left_reg = ToRegister(instr->InputAt(0)); | 845 Register left_reg = ToRegister(instr->left()); |
846 Register right_reg = ToRegister(instr->InputAt(1)); | 846 Register right_reg = ToRegister(instr->right()); |
847 Register result_reg = ToRegister(instr->result()); | 847 Register result_reg = ToRegister(instr->result()); |
848 | 848 |
849 ASSERT(left_reg.is(rax)); | 849 ASSERT(left_reg.is(rax)); |
850 ASSERT(result_reg.is(rdx)); | 850 ASSERT(result_reg.is(rdx)); |
851 ASSERT(!right_reg.is(rax)); | 851 ASSERT(!right_reg.is(rax)); |
852 ASSERT(!right_reg.is(rdx)); | 852 ASSERT(!right_reg.is(rdx)); |
853 | 853 |
854 // Check for x % 0. | 854 // Check for x % 0. |
855 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 855 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
856 __ testl(right_reg, right_reg); | 856 __ testl(right_reg, right_reg); |
857 DeoptimizeIf(zero, instr->environment()); | 857 DeoptimizeIf(zero, instr->environment()); |
858 } | 858 } |
859 | 859 |
860 __ testl(left_reg, left_reg); | 860 __ testl(left_reg, left_reg); |
861 __ j(zero, &remainder_eq_dividend, Label::kNear); | 861 __ j(zero, &remainder_eq_dividend, Label::kNear); |
862 __ j(sign, &slow, Label::kNear); | 862 __ j(sign, &slow, Label::kNear); |
863 | 863 |
864 __ testl(right_reg, right_reg); | 864 __ testl(right_reg, right_reg); |
865 __ j(not_sign, &both_positive, Label::kNear); | 865 __ j(not_sign, &both_positive, Label::kNear); |
866 // The sign of the divisor doesn't matter. | 866 // The sign of the divisor doesn't matter. |
867 __ neg(right_reg); | 867 __ neg(right_reg); |
868 | 868 |
869 __ bind(&both_positive); | 869 __ bind(&both_positive); |
870 // If the dividend is smaller than the nonnegative | 870 // If the dividend is smaller than the nonnegative |
871 // divisor, the dividend is the result. | 871 // divisor, the dividend is the result. |
872 __ cmpl(left_reg, right_reg); | 872 __ cmpl(left_reg, right_reg); |
873 __ j(less, &remainder_eq_dividend, Label::kNear); | 873 __ j(less, &remainder_eq_dividend, Label::kNear); |
874 | 874 |
875 // Check if the divisor is a PowerOfTwo integer. | 875 // Check if the divisor is a PowerOfTwo integer. |
876 Register scratch = ToRegister(instr->TempAt(0)); | 876 Register scratch = ToRegister(instr->temp()); |
877 __ movl(scratch, right_reg); | 877 __ movl(scratch, right_reg); |
878 __ subl(scratch, Immediate(1)); | 878 __ subl(scratch, Immediate(1)); |
879 __ testl(scratch, right_reg); | 879 __ testl(scratch, right_reg); |
880 __ j(not_zero, &do_subtraction, Label::kNear); | 880 __ j(not_zero, &do_subtraction, Label::kNear); |
881 __ andl(left_reg, scratch); | 881 __ andl(left_reg, scratch); |
882 __ jmp(&remainder_eq_dividend, Label::kNear); | 882 __ jmp(&remainder_eq_dividend, Label::kNear); |
883 | 883 |
884 __ bind(&do_subtraction); | 884 __ bind(&do_subtraction); |
885 const int kUnfolds = 3; | 885 const int kUnfolds = 3; |
886 // Try a few subtractions of the dividend. | 886 // Try a few subtractions of the dividend. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 | 923 |
924 __ bind(&remainder_eq_dividend); | 924 __ bind(&remainder_eq_dividend); |
925 __ movl(result_reg, left_reg); | 925 __ movl(result_reg, left_reg); |
926 | 926 |
927 __ bind(&done); | 927 __ bind(&done); |
928 } | 928 } |
929 } | 929 } |
930 | 930 |
931 | 931 |
932 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { | 932 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { |
933 ASSERT(instr->InputAt(1)->IsConstantOperand()); | 933 ASSERT(instr->right()->IsConstantOperand()); |
934 | 934 |
935 const Register dividend = ToRegister(instr->InputAt(0)); | 935 const Register dividend = ToRegister(instr->left()); |
936 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->InputAt(1))); | 936 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); |
937 const Register result = ToRegister(instr->result()); | 937 const Register result = ToRegister(instr->result()); |
938 | 938 |
939 switch (divisor) { | 939 switch (divisor) { |
940 case 0: | 940 case 0: |
941 DeoptimizeIf(no_condition, instr->environment()); | 941 DeoptimizeIf(no_condition, instr->environment()); |
942 return; | 942 return; |
943 | 943 |
944 case 1: | 944 case 1: |
945 if (!result.is(dividend)) { | 945 if (!result.is(dividend)) { |
946 __ movl(result, dividend); | 946 __ movl(result, dividend); |
(...skipping 24 matching lines...) Expand all Loading... |
971 DeoptimizeIf(zero, instr->environment()); | 971 DeoptimizeIf(zero, instr->environment()); |
972 } | 972 } |
973 __ sar(result, Immediate(power)); | 973 __ sar(result, Immediate(power)); |
974 } else { | 974 } else { |
975 if (!result.is(dividend)) { | 975 if (!result.is(dividend)) { |
976 __ movl(result, dividend); | 976 __ movl(result, dividend); |
977 } | 977 } |
978 __ sarl(result, Immediate(power)); | 978 __ sarl(result, Immediate(power)); |
979 } | 979 } |
980 } else { | 980 } else { |
981 Register reg1 = ToRegister(instr->TempAt(0)); | 981 Register reg1 = ToRegister(instr->temp()); |
982 Register reg2 = ToRegister(instr->result()); | 982 Register reg2 = ToRegister(instr->result()); |
983 | 983 |
984 // Find b which: 2^b < divisor_abs < 2^(b+1). | 984 // Find b which: 2^b < divisor_abs < 2^(b+1). |
985 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); | 985 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); |
986 unsigned shift = 32 + b; // Precision +1bit (effectively). | 986 unsigned shift = 32 + b; // Precision +1bit (effectively). |
987 double multiplier_f = | 987 double multiplier_f = |
988 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; | 988 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; |
989 int64_t multiplier; | 989 int64_t multiplier; |
990 if (multiplier_f - floor(multiplier_f) < 0.5) { | 990 if (multiplier_f - floor(multiplier_f) < 0.5) { |
991 multiplier = static_cast<int64_t>(floor(multiplier_f)); | 991 multiplier = static_cast<int64_t>(floor(multiplier_f)); |
(...skipping 14 matching lines...) Expand all Loading... |
1006 // Result just fit in r64, because it's int32 * uint32. | 1006 // Result just fit in r64, because it's int32 * uint32. |
1007 __ imul(reg2, reg1); | 1007 __ imul(reg2, reg1); |
1008 | 1008 |
1009 __ addq(reg2, Immediate(1 << 30)); | 1009 __ addq(reg2, Immediate(1 << 30)); |
1010 __ sar(reg2, Immediate(shift)); | 1010 __ sar(reg2, Immediate(shift)); |
1011 } | 1011 } |
1012 } | 1012 } |
1013 | 1013 |
1014 | 1014 |
1015 void LCodeGen::DoDivI(LDivI* instr) { | 1015 void LCodeGen::DoDivI(LDivI* instr) { |
1016 LOperand* right = instr->InputAt(1); | 1016 LOperand* right = instr->right(); |
1017 ASSERT(ToRegister(instr->result()).is(rax)); | 1017 ASSERT(ToRegister(instr->result()).is(rax)); |
1018 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); | 1018 ASSERT(ToRegister(instr->left()).is(rax)); |
1019 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); | 1019 ASSERT(!ToRegister(instr->right()).is(rax)); |
1020 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); | 1020 ASSERT(!ToRegister(instr->right()).is(rdx)); |
1021 | 1021 |
1022 Register left_reg = rax; | 1022 Register left_reg = rax; |
1023 | 1023 |
1024 // Check for x / 0. | 1024 // Check for x / 0. |
1025 Register right_reg = ToRegister(right); | 1025 Register right_reg = ToRegister(right); |
1026 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1026 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
1027 __ testl(right_reg, right_reg); | 1027 __ testl(right_reg, right_reg); |
1028 DeoptimizeIf(zero, instr->environment()); | 1028 DeoptimizeIf(zero, instr->environment()); |
1029 } | 1029 } |
1030 | 1030 |
(...skipping 21 matching lines...) Expand all Loading... |
1052 __ cdq(); | 1052 __ cdq(); |
1053 __ idivl(right_reg); | 1053 __ idivl(right_reg); |
1054 | 1054 |
1055 // Deoptimize if remainder is not 0. | 1055 // Deoptimize if remainder is not 0. |
1056 __ testl(rdx, rdx); | 1056 __ testl(rdx, rdx); |
1057 DeoptimizeIf(not_zero, instr->environment()); | 1057 DeoptimizeIf(not_zero, instr->environment()); |
1058 } | 1058 } |
1059 | 1059 |
1060 | 1060 |
1061 void LCodeGen::DoMulI(LMulI* instr) { | 1061 void LCodeGen::DoMulI(LMulI* instr) { |
1062 Register left = ToRegister(instr->InputAt(0)); | 1062 Register left = ToRegister(instr->left()); |
1063 LOperand* right = instr->InputAt(1); | 1063 LOperand* right = instr->right(); |
1064 | 1064 |
1065 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1065 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1066 __ movl(kScratchRegister, left); | 1066 __ movl(kScratchRegister, left); |
1067 } | 1067 } |
1068 | 1068 |
1069 bool can_overflow = | 1069 bool can_overflow = |
1070 instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1070 instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1071 if (right->IsConstantOperand()) { | 1071 if (right->IsConstantOperand()) { |
1072 int right_value = ToInteger32(LConstantOperand::cast(right)); | 1072 int right_value = ToInteger32(LConstantOperand::cast(right)); |
1073 if (right_value == -1) { | 1073 if (right_value == -1) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 // Test the non-zero operand for negative sign. | 1135 // Test the non-zero operand for negative sign. |
1136 __ orl(kScratchRegister, ToRegister(right)); | 1136 __ orl(kScratchRegister, ToRegister(right)); |
1137 DeoptimizeIf(sign, instr->environment()); | 1137 DeoptimizeIf(sign, instr->environment()); |
1138 } | 1138 } |
1139 __ bind(&done); | 1139 __ bind(&done); |
1140 } | 1140 } |
1141 } | 1141 } |
1142 | 1142 |
1143 | 1143 |
1144 void LCodeGen::DoBitI(LBitI* instr) { | 1144 void LCodeGen::DoBitI(LBitI* instr) { |
1145 LOperand* left = instr->InputAt(0); | 1145 LOperand* left = instr->left(); |
1146 LOperand* right = instr->InputAt(1); | 1146 LOperand* right = instr->right(); |
1147 ASSERT(left->Equals(instr->result())); | 1147 ASSERT(left->Equals(instr->result())); |
1148 ASSERT(left->IsRegister()); | 1148 ASSERT(left->IsRegister()); |
1149 | 1149 |
1150 if (right->IsConstantOperand()) { | 1150 if (right->IsConstantOperand()) { |
1151 int right_operand = ToInteger32(LConstantOperand::cast(right)); | 1151 int right_operand = ToInteger32(LConstantOperand::cast(right)); |
1152 switch (instr->op()) { | 1152 switch (instr->op()) { |
1153 case Token::BIT_AND: | 1153 case Token::BIT_AND: |
1154 __ andl(ToRegister(left), Immediate(right_operand)); | 1154 __ andl(ToRegister(left), Immediate(right_operand)); |
1155 break; | 1155 break; |
1156 case Token::BIT_OR: | 1156 case Token::BIT_OR: |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1192 break; | 1192 break; |
1193 default: | 1193 default: |
1194 UNREACHABLE(); | 1194 UNREACHABLE(); |
1195 break; | 1195 break; |
1196 } | 1196 } |
1197 } | 1197 } |
1198 } | 1198 } |
1199 | 1199 |
1200 | 1200 |
1201 void LCodeGen::DoShiftI(LShiftI* instr) { | 1201 void LCodeGen::DoShiftI(LShiftI* instr) { |
1202 LOperand* left = instr->InputAt(0); | 1202 LOperand* left = instr->left(); |
1203 LOperand* right = instr->InputAt(1); | 1203 LOperand* right = instr->right(); |
1204 ASSERT(left->Equals(instr->result())); | 1204 ASSERT(left->Equals(instr->result())); |
1205 ASSERT(left->IsRegister()); | 1205 ASSERT(left->IsRegister()); |
1206 if (right->IsRegister()) { | 1206 if (right->IsRegister()) { |
1207 ASSERT(ToRegister(right).is(rcx)); | 1207 ASSERT(ToRegister(right).is(rcx)); |
1208 | 1208 |
1209 switch (instr->op()) { | 1209 switch (instr->op()) { |
1210 case Token::SAR: | 1210 case Token::SAR: |
1211 __ sarl_cl(ToRegister(left)); | 1211 __ sarl_cl(ToRegister(left)); |
1212 break; | 1212 break; |
1213 case Token::SHR: | 1213 case Token::SHR: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 break; | 1248 break; |
1249 default: | 1249 default: |
1250 UNREACHABLE(); | 1250 UNREACHABLE(); |
1251 break; | 1251 break; |
1252 } | 1252 } |
1253 } | 1253 } |
1254 } | 1254 } |
1255 | 1255 |
1256 | 1256 |
1257 void LCodeGen::DoSubI(LSubI* instr) { | 1257 void LCodeGen::DoSubI(LSubI* instr) { |
1258 LOperand* left = instr->InputAt(0); | 1258 LOperand* left = instr->left(); |
1259 LOperand* right = instr->InputAt(1); | 1259 LOperand* right = instr->right(); |
1260 ASSERT(left->Equals(instr->result())); | 1260 ASSERT(left->Equals(instr->result())); |
1261 | 1261 |
1262 if (right->IsConstantOperand()) { | 1262 if (right->IsConstantOperand()) { |
1263 __ subl(ToRegister(left), | 1263 __ subl(ToRegister(left), |
1264 Immediate(ToInteger32(LConstantOperand::cast(right)))); | 1264 Immediate(ToInteger32(LConstantOperand::cast(right)))); |
1265 } else if (right->IsRegister()) { | 1265 } else if (right->IsRegister()) { |
1266 __ subl(ToRegister(left), ToRegister(right)); | 1266 __ subl(ToRegister(left), ToRegister(right)); |
1267 } else { | 1267 } else { |
1268 __ subl(ToRegister(left), ToOperand(right)); | 1268 __ subl(ToRegister(left), ToOperand(right)); |
1269 } | 1269 } |
(...skipping 13 matching lines...) Expand all Loading... |
1283 void LCodeGen::DoConstantD(LConstantD* instr) { | 1283 void LCodeGen::DoConstantD(LConstantD* instr) { |
1284 ASSERT(instr->result()->IsDoubleRegister()); | 1284 ASSERT(instr->result()->IsDoubleRegister()); |
1285 XMMRegister res = ToDoubleRegister(instr->result()); | 1285 XMMRegister res = ToDoubleRegister(instr->result()); |
1286 double v = instr->value(); | 1286 double v = instr->value(); |
1287 uint64_t int_val = BitCast<uint64_t, double>(v); | 1287 uint64_t int_val = BitCast<uint64_t, double>(v); |
1288 // Use xor to produce +0.0 in a fast and compact way, but avoid to | 1288 // Use xor to produce +0.0 in a fast and compact way, but avoid to |
1289 // do so if the constant is -0.0. | 1289 // do so if the constant is -0.0. |
1290 if (int_val == 0) { | 1290 if (int_val == 0) { |
1291 __ xorps(res, res); | 1291 __ xorps(res, res); |
1292 } else { | 1292 } else { |
1293 Register tmp = ToRegister(instr->TempAt(0)); | 1293 Register tmp = ToRegister(instr->temp()); |
1294 __ Set(tmp, int_val); | 1294 __ Set(tmp, int_val); |
1295 __ movq(res, tmp); | 1295 __ movq(res, tmp); |
1296 } | 1296 } |
1297 } | 1297 } |
1298 | 1298 |
1299 | 1299 |
1300 void LCodeGen::DoConstantT(LConstantT* instr) { | 1300 void LCodeGen::DoConstantT(LConstantT* instr) { |
1301 Handle<Object> value = instr->value(); | 1301 Handle<Object> value = instr->value(); |
1302 if (value->IsSmi()) { | 1302 if (value->IsSmi()) { |
1303 __ Move(ToRegister(instr->result()), value); | 1303 __ Move(ToRegister(instr->result()), value); |
1304 } else { | 1304 } else { |
1305 __ LoadHeapObject(ToRegister(instr->result()), | 1305 __ LoadHeapObject(ToRegister(instr->result()), |
1306 Handle<HeapObject>::cast(value)); | 1306 Handle<HeapObject>::cast(value)); |
1307 } | 1307 } |
1308 } | 1308 } |
1309 | 1309 |
1310 | 1310 |
1311 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1311 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
1312 Register result = ToRegister(instr->result()); | 1312 Register result = ToRegister(instr->result()); |
1313 Register array = ToRegister(instr->InputAt(0)); | 1313 Register array = ToRegister(instr->value()); |
1314 __ movq(result, FieldOperand(array, JSArray::kLengthOffset)); | 1314 __ movq(result, FieldOperand(array, JSArray::kLengthOffset)); |
1315 } | 1315 } |
1316 | 1316 |
1317 | 1317 |
1318 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { | 1318 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { |
1319 Register result = ToRegister(instr->result()); | 1319 Register result = ToRegister(instr->result()); |
1320 Register array = ToRegister(instr->InputAt(0)); | 1320 Register array = ToRegister(instr->value()); |
1321 __ movq(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); | 1321 __ movq(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); |
1322 } | 1322 } |
1323 | 1323 |
1324 | 1324 |
1325 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1325 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
1326 Register result = ToRegister(instr->result()); | 1326 Register result = ToRegister(instr->result()); |
1327 Register map = ToRegister(instr->InputAt(0)); | 1327 Register map = ToRegister(instr->value()); |
1328 __ EnumLength(result, map); | 1328 __ EnumLength(result, map); |
1329 } | 1329 } |
1330 | 1330 |
1331 | 1331 |
1332 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1332 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
1333 Register result = ToRegister(instr->result()); | 1333 Register result = ToRegister(instr->result()); |
1334 Register input = ToRegister(instr->InputAt(0)); | 1334 Register input = ToRegister(instr->value()); |
1335 | 1335 |
1336 // Load map into |result|. | 1336 // Load map into |result|. |
1337 __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); | 1337 __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); |
1338 // Load the map's "bit field 2" into |result|. We only need the first byte. | 1338 // Load the map's "bit field 2" into |result|. We only need the first byte. |
1339 __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset)); | 1339 __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset)); |
1340 // Retrieve elements_kind from bit field 2. | 1340 // Retrieve elements_kind from bit field 2. |
1341 __ and_(result, Immediate(Map::kElementsKindMask)); | 1341 __ and_(result, Immediate(Map::kElementsKindMask)); |
1342 __ shr(result, Immediate(Map::kElementsKindShift)); | 1342 __ shr(result, Immediate(Map::kElementsKindShift)); |
1343 } | 1343 } |
1344 | 1344 |
1345 | 1345 |
1346 void LCodeGen::DoValueOf(LValueOf* instr) { | 1346 void LCodeGen::DoValueOf(LValueOf* instr) { |
1347 Register input = ToRegister(instr->InputAt(0)); | 1347 Register input = ToRegister(instr->value()); |
1348 Register result = ToRegister(instr->result()); | 1348 Register result = ToRegister(instr->result()); |
1349 ASSERT(input.is(result)); | 1349 ASSERT(input.is(result)); |
1350 Label done; | 1350 Label done; |
1351 // If the object is a smi return the object. | 1351 // If the object is a smi return the object. |
1352 __ JumpIfSmi(input, &done, Label::kNear); | 1352 __ JumpIfSmi(input, &done, Label::kNear); |
1353 | 1353 |
1354 // If the object is not a value type, return the object. | 1354 // If the object is not a value type, return the object. |
1355 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); | 1355 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); |
1356 __ j(not_equal, &done, Label::kNear); | 1356 __ j(not_equal, &done, Label::kNear); |
1357 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); | 1357 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); |
1358 | 1358 |
1359 __ bind(&done); | 1359 __ bind(&done); |
1360 } | 1360 } |
1361 | 1361 |
1362 | 1362 |
1363 void LCodeGen::DoDateField(LDateField* instr) { | 1363 void LCodeGen::DoDateField(LDateField* instr) { |
1364 Register object = ToRegister(instr->InputAt(0)); | 1364 Register object = ToRegister(instr->date()); |
1365 Register result = ToRegister(instr->result()); | 1365 Register result = ToRegister(instr->result()); |
1366 Smi* index = instr->index(); | 1366 Smi* index = instr->index(); |
1367 Label runtime, done, not_date_object; | 1367 Label runtime, done, not_date_object; |
1368 ASSERT(object.is(result)); | 1368 ASSERT(object.is(result)); |
1369 ASSERT(object.is(rax)); | 1369 ASSERT(object.is(rax)); |
1370 | 1370 |
1371 Condition cc = masm()->CheckSmi(object); | 1371 Condition cc = masm()->CheckSmi(object); |
1372 DeoptimizeIf(cc, instr->environment()); | 1372 DeoptimizeIf(cc, instr->environment()); |
1373 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); | 1373 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); |
1374 DeoptimizeIf(not_equal, instr->environment()); | 1374 DeoptimizeIf(not_equal, instr->environment()); |
(...skipping 21 matching lines...) Expand all Loading... |
1396 __ movq(rsi, index, RelocInfo::NONE); | 1396 __ movq(rsi, index, RelocInfo::NONE); |
1397 #endif | 1397 #endif |
1398 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 1398 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
1399 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1399 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1400 __ bind(&done); | 1400 __ bind(&done); |
1401 } | 1401 } |
1402 } | 1402 } |
1403 | 1403 |
1404 | 1404 |
1405 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1405 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1406 LOperand* input = instr->InputAt(0); | 1406 LOperand* input = instr->value(); |
1407 ASSERT(input->Equals(instr->result())); | 1407 ASSERT(input->Equals(instr->result())); |
1408 __ not_(ToRegister(input)); | 1408 __ not_(ToRegister(input)); |
1409 } | 1409 } |
1410 | 1410 |
1411 | 1411 |
1412 void LCodeGen::DoThrow(LThrow* instr) { | 1412 void LCodeGen::DoThrow(LThrow* instr) { |
1413 __ push(ToRegister(instr->InputAt(0))); | 1413 __ push(ToRegister(instr->value())); |
1414 CallRuntime(Runtime::kThrow, 1, instr); | 1414 CallRuntime(Runtime::kThrow, 1, instr); |
1415 | 1415 |
1416 if (FLAG_debug_code) { | 1416 if (FLAG_debug_code) { |
1417 Comment("Unreachable code."); | 1417 Comment("Unreachable code."); |
1418 __ int3(); | 1418 __ int3(); |
1419 } | 1419 } |
1420 } | 1420 } |
1421 | 1421 |
1422 | 1422 |
1423 void LCodeGen::DoAddI(LAddI* instr) { | 1423 void LCodeGen::DoAddI(LAddI* instr) { |
1424 LOperand* left = instr->InputAt(0); | 1424 LOperand* left = instr->left(); |
1425 LOperand* right = instr->InputAt(1); | 1425 LOperand* right = instr->right(); |
1426 ASSERT(left->Equals(instr->result())); | 1426 ASSERT(left->Equals(instr->result())); |
1427 | 1427 |
1428 if (right->IsConstantOperand()) { | 1428 if (right->IsConstantOperand()) { |
1429 __ addl(ToRegister(left), | 1429 __ addl(ToRegister(left), |
1430 Immediate(ToInteger32(LConstantOperand::cast(right)))); | 1430 Immediate(ToInteger32(LConstantOperand::cast(right)))); |
1431 } else if (right->IsRegister()) { | 1431 } else if (right->IsRegister()) { |
1432 __ addl(ToRegister(left), ToRegister(right)); | 1432 __ addl(ToRegister(left), ToRegister(right)); |
1433 } else { | 1433 } else { |
1434 __ addl(ToRegister(left), ToOperand(right)); | 1434 __ addl(ToRegister(left), ToOperand(right)); |
1435 } | 1435 } |
1436 | 1436 |
1437 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1437 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1438 DeoptimizeIf(overflow, instr->environment()); | 1438 DeoptimizeIf(overflow, instr->environment()); |
1439 } | 1439 } |
1440 } | 1440 } |
1441 | 1441 |
1442 | 1442 |
1443 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1443 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
1444 LOperand* left = instr->InputAt(0); | 1444 LOperand* left = instr->left(); |
1445 LOperand* right = instr->InputAt(1); | 1445 LOperand* right = instr->right(); |
1446 ASSERT(left->Equals(instr->result())); | 1446 ASSERT(left->Equals(instr->result())); |
1447 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1447 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
1448 if (instr->hydrogen()->representation().IsInteger32()) { | 1448 if (instr->hydrogen()->representation().IsInteger32()) { |
1449 Label return_left; | 1449 Label return_left; |
1450 Condition condition = (operation == HMathMinMax::kMathMin) | 1450 Condition condition = (operation == HMathMinMax::kMathMin) |
1451 ? less_equal | 1451 ? less_equal |
1452 : greater_equal; | 1452 : greater_equal; |
1453 Register left_reg = ToRegister(left); | 1453 Register left_reg = ToRegister(left); |
1454 if (right->IsConstantOperand()) { | 1454 if (right->IsConstantOperand()) { |
1455 Immediate right_imm = | 1455 Immediate right_imm = |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1500 __ j(parity_even, &return_left, Label::kNear); | 1500 __ j(parity_even, &return_left, Label::kNear); |
1501 __ bind(&return_right); | 1501 __ bind(&return_right); |
1502 __ movsd(left_reg, right_reg); | 1502 __ movsd(left_reg, right_reg); |
1503 | 1503 |
1504 __ bind(&return_left); | 1504 __ bind(&return_left); |
1505 } | 1505 } |
1506 } | 1506 } |
1507 | 1507 |
1508 | 1508 |
1509 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1509 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
1510 XMMRegister left = ToDoubleRegister(instr->InputAt(0)); | 1510 XMMRegister left = ToDoubleRegister(instr->left()); |
1511 XMMRegister right = ToDoubleRegister(instr->InputAt(1)); | 1511 XMMRegister right = ToDoubleRegister(instr->right()); |
1512 XMMRegister result = ToDoubleRegister(instr->result()); | 1512 XMMRegister result = ToDoubleRegister(instr->result()); |
1513 // All operations except MOD are computed in-place. | 1513 // All operations except MOD are computed in-place. |
1514 ASSERT(instr->op() == Token::MOD || left.is(result)); | 1514 ASSERT(instr->op() == Token::MOD || left.is(result)); |
1515 switch (instr->op()) { | 1515 switch (instr->op()) { |
1516 case Token::ADD: | 1516 case Token::ADD: |
1517 __ addsd(left, right); | 1517 __ addsd(left, right); |
1518 break; | 1518 break; |
1519 case Token::SUB: | 1519 case Token::SUB: |
1520 __ subsd(left, right); | 1520 __ subsd(left, right); |
1521 break; | 1521 break; |
(...skipping 13 matching lines...) Expand all Loading... |
1535 __ movaps(result, xmm0); | 1535 __ movaps(result, xmm0); |
1536 break; | 1536 break; |
1537 default: | 1537 default: |
1538 UNREACHABLE(); | 1538 UNREACHABLE(); |
1539 break; | 1539 break; |
1540 } | 1540 } |
1541 } | 1541 } |
1542 | 1542 |
1543 | 1543 |
1544 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1544 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
1545 ASSERT(ToRegister(instr->InputAt(0)).is(rdx)); | 1545 ASSERT(ToRegister(instr->left()).is(rdx)); |
1546 ASSERT(ToRegister(instr->InputAt(1)).is(rax)); | 1546 ASSERT(ToRegister(instr->right()).is(rax)); |
1547 ASSERT(ToRegister(instr->result()).is(rax)); | 1547 ASSERT(ToRegister(instr->result()).is(rax)); |
1548 | 1548 |
1549 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1549 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
1550 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1550 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1551 __ nop(); // Signals no inlined code. | 1551 __ nop(); // Signals no inlined code. |
1552 } | 1552 } |
1553 | 1553 |
1554 | 1554 |
1555 int LCodeGen::GetNextEmittedBlock(int block) { | 1555 int LCodeGen::GetNextEmittedBlock(int block) { |
1556 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 1556 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
(...skipping 23 matching lines...) Expand all Loading... |
1580 } | 1580 } |
1581 } | 1581 } |
1582 | 1582 |
1583 | 1583 |
1584 void LCodeGen::DoBranch(LBranch* instr) { | 1584 void LCodeGen::DoBranch(LBranch* instr) { |
1585 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1585 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1586 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1586 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1587 | 1587 |
1588 Representation r = instr->hydrogen()->value()->representation(); | 1588 Representation r = instr->hydrogen()->value()->representation(); |
1589 if (r.IsInteger32()) { | 1589 if (r.IsInteger32()) { |
1590 Register reg = ToRegister(instr->InputAt(0)); | 1590 Register reg = ToRegister(instr->value()); |
1591 __ testl(reg, reg); | 1591 __ testl(reg, reg); |
1592 EmitBranch(true_block, false_block, not_zero); | 1592 EmitBranch(true_block, false_block, not_zero); |
1593 } else if (r.IsDouble()) { | 1593 } else if (r.IsDouble()) { |
1594 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1594 XMMRegister reg = ToDoubleRegister(instr->value()); |
1595 __ xorps(xmm0, xmm0); | 1595 __ xorps(xmm0, xmm0); |
1596 __ ucomisd(reg, xmm0); | 1596 __ ucomisd(reg, xmm0); |
1597 EmitBranch(true_block, false_block, not_equal); | 1597 EmitBranch(true_block, false_block, not_equal); |
1598 } else { | 1598 } else { |
1599 ASSERT(r.IsTagged()); | 1599 ASSERT(r.IsTagged()); |
1600 Register reg = ToRegister(instr->InputAt(0)); | 1600 Register reg = ToRegister(instr->value()); |
1601 HType type = instr->hydrogen()->value()->type(); | 1601 HType type = instr->hydrogen()->value()->type(); |
1602 if (type.IsBoolean()) { | 1602 if (type.IsBoolean()) { |
1603 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1603 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
1604 EmitBranch(true_block, false_block, equal); | 1604 EmitBranch(true_block, false_block, equal); |
1605 } else if (type.IsSmi()) { | 1605 } else if (type.IsSmi()) { |
1606 __ SmiCompare(reg, Smi::FromInt(0)); | 1606 __ SmiCompare(reg, Smi::FromInt(0)); |
1607 EmitBranch(true_block, false_block, not_equal); | 1607 EmitBranch(true_block, false_block, not_equal); |
1608 } else { | 1608 } else { |
1609 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1609 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1610 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1610 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1727 case Token::IN: | 1727 case Token::IN: |
1728 case Token::INSTANCEOF: | 1728 case Token::INSTANCEOF: |
1729 default: | 1729 default: |
1730 UNREACHABLE(); | 1730 UNREACHABLE(); |
1731 } | 1731 } |
1732 return cond; | 1732 return cond; |
1733 } | 1733 } |
1734 | 1734 |
1735 | 1735 |
1736 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1736 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
1737 LOperand* left = instr->InputAt(0); | 1737 LOperand* left = instr->left(); |
1738 LOperand* right = instr->InputAt(1); | 1738 LOperand* right = instr->right(); |
1739 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1739 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1740 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1740 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1741 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1741 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1742 | 1742 |
1743 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 1743 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
1744 // We can statically evaluate the comparison. | 1744 // We can statically evaluate the comparison. |
1745 double left_val = ToDouble(LConstantOperand::cast(left)); | 1745 double left_val = ToDouble(LConstantOperand::cast(left)); |
1746 double right_val = ToDouble(LConstantOperand::cast(right)); | 1746 double right_val = ToDouble(LConstantOperand::cast(right)); |
1747 int next_block = | 1747 int next_block = |
1748 EvalComparison(instr->op(), left_val, right_val) ? true_block | 1748 EvalComparison(instr->op(), left_val, right_val) ? true_block |
(...skipping 26 matching lines...) Expand all Loading... |
1775 __ cmpl(ToRegister(left), ToOperand(right)); | 1775 __ cmpl(ToRegister(left), ToOperand(right)); |
1776 } | 1776 } |
1777 } | 1777 } |
1778 } | 1778 } |
1779 EmitBranch(true_block, false_block, cc); | 1779 EmitBranch(true_block, false_block, cc); |
1780 } | 1780 } |
1781 } | 1781 } |
1782 | 1782 |
1783 | 1783 |
1784 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 1784 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
1785 Register left = ToRegister(instr->InputAt(0)); | 1785 Register left = ToRegister(instr->left()); |
1786 Register right = ToRegister(instr->InputAt(1)); | 1786 Register right = ToRegister(instr->right()); |
1787 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1787 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1788 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1788 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1789 | 1789 |
1790 __ cmpq(left, right); | 1790 __ cmpq(left, right); |
1791 EmitBranch(true_block, false_block, equal); | 1791 EmitBranch(true_block, false_block, equal); |
1792 } | 1792 } |
1793 | 1793 |
1794 | 1794 |
1795 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 1795 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
1796 Register left = ToRegister(instr->InputAt(0)); | 1796 Register left = ToRegister(instr->left()); |
1797 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1797 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1798 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1798 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1799 | 1799 |
1800 __ cmpq(left, Immediate(instr->hydrogen()->right())); | 1800 __ cmpq(left, Immediate(instr->hydrogen()->right())); |
1801 EmitBranch(true_block, false_block, equal); | 1801 EmitBranch(true_block, false_block, equal); |
1802 } | 1802 } |
1803 | 1803 |
1804 | 1804 |
1805 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { | 1805 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { |
1806 Register reg = ToRegister(instr->InputAt(0)); | 1806 Register reg = ToRegister(instr->value()); |
1807 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1807 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1808 | 1808 |
1809 // If the expression is known to be untagged or a smi, then it's definitely | 1809 // If the expression is known to be untagged or a smi, then it's definitely |
1810 // not null, and it can't be a an undetectable object. | 1810 // not null, and it can't be a an undetectable object. |
1811 if (instr->hydrogen()->representation().IsSpecialization() || | 1811 if (instr->hydrogen()->representation().IsSpecialization() || |
1812 instr->hydrogen()->type().IsSmi()) { | 1812 instr->hydrogen()->type().IsSmi()) { |
1813 EmitGoto(false_block); | 1813 EmitGoto(false_block); |
1814 return; | 1814 return; |
1815 } | 1815 } |
1816 | 1816 |
1817 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1817 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1818 Heap::RootListIndex nil_value = instr->nil() == kNullValue ? | 1818 Heap::RootListIndex nil_value = instr->nil() == kNullValue ? |
1819 Heap::kNullValueRootIndex : | 1819 Heap::kNullValueRootIndex : |
1820 Heap::kUndefinedValueRootIndex; | 1820 Heap::kUndefinedValueRootIndex; |
1821 __ CompareRoot(reg, nil_value); | 1821 __ CompareRoot(reg, nil_value); |
1822 if (instr->kind() == kStrictEquality) { | 1822 if (instr->kind() == kStrictEquality) { |
1823 EmitBranch(true_block, false_block, equal); | 1823 EmitBranch(true_block, false_block, equal); |
1824 } else { | 1824 } else { |
1825 Heap::RootListIndex other_nil_value = instr->nil() == kNullValue ? | 1825 Heap::RootListIndex other_nil_value = instr->nil() == kNullValue ? |
1826 Heap::kUndefinedValueRootIndex : | 1826 Heap::kUndefinedValueRootIndex : |
1827 Heap::kNullValueRootIndex; | 1827 Heap::kNullValueRootIndex; |
1828 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1828 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1829 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1829 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1830 __ j(equal, true_label); | 1830 __ j(equal, true_label); |
1831 __ CompareRoot(reg, other_nil_value); | 1831 __ CompareRoot(reg, other_nil_value); |
1832 __ j(equal, true_label); | 1832 __ j(equal, true_label); |
1833 __ JumpIfSmi(reg, false_label); | 1833 __ JumpIfSmi(reg, false_label); |
1834 // Check for undetectable objects by looking in the bit field in | 1834 // Check for undetectable objects by looking in the bit field in |
1835 // the map. The object has already been smi checked. | 1835 // the map. The object has already been smi checked. |
1836 Register scratch = ToRegister(instr->TempAt(0)); | 1836 Register scratch = ToRegister(instr->temp()); |
1837 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1837 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
1838 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | 1838 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
1839 Immediate(1 << Map::kIsUndetectable)); | 1839 Immediate(1 << Map::kIsUndetectable)); |
1840 EmitBranch(true_block, false_block, not_zero); | 1840 EmitBranch(true_block, false_block, not_zero); |
1841 } | 1841 } |
1842 } | 1842 } |
1843 | 1843 |
1844 | 1844 |
1845 Condition LCodeGen::EmitIsObject(Register input, | 1845 Condition LCodeGen::EmitIsObject(Register input, |
1846 Label* is_not_object, | 1846 Label* is_not_object, |
(...skipping 14 matching lines...) Expand all Loading... |
1861 __ movzxbl(kScratchRegister, | 1861 __ movzxbl(kScratchRegister, |
1862 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); | 1862 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
1863 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1863 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1864 __ j(below, is_not_object); | 1864 __ j(below, is_not_object); |
1865 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1865 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1866 return below_equal; | 1866 return below_equal; |
1867 } | 1867 } |
1868 | 1868 |
1869 | 1869 |
1870 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1870 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1871 Register reg = ToRegister(instr->InputAt(0)); | 1871 Register reg = ToRegister(instr->value()); |
1872 | 1872 |
1873 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1873 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1874 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1874 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1875 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1875 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1876 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1876 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1877 | 1877 |
1878 Condition true_cond = EmitIsObject(reg, false_label, true_label); | 1878 Condition true_cond = EmitIsObject(reg, false_label, true_label); |
1879 | 1879 |
1880 EmitBranch(true_block, false_block, true_cond); | 1880 EmitBranch(true_block, false_block, true_cond); |
1881 } | 1881 } |
1882 | 1882 |
1883 | 1883 |
1884 Condition LCodeGen::EmitIsString(Register input, | 1884 Condition LCodeGen::EmitIsString(Register input, |
1885 Register temp1, | 1885 Register temp1, |
1886 Label* is_not_string) { | 1886 Label* is_not_string) { |
1887 __ JumpIfSmi(input, is_not_string); | 1887 __ JumpIfSmi(input, is_not_string); |
1888 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); | 1888 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); |
1889 | 1889 |
1890 return cond; | 1890 return cond; |
1891 } | 1891 } |
1892 | 1892 |
1893 | 1893 |
1894 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 1894 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
1895 Register reg = ToRegister(instr->InputAt(0)); | 1895 Register reg = ToRegister(instr->value()); |
1896 Register temp = ToRegister(instr->TempAt(0)); | 1896 Register temp = ToRegister(instr->temp()); |
1897 | 1897 |
1898 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1898 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1899 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1899 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1900 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1900 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1901 | 1901 |
1902 Condition true_cond = EmitIsString(reg, temp, false_label); | 1902 Condition true_cond = EmitIsString(reg, temp, false_label); |
1903 | 1903 |
1904 EmitBranch(true_block, false_block, true_cond); | 1904 EmitBranch(true_block, false_block, true_cond); |
1905 } | 1905 } |
1906 | 1906 |
1907 | 1907 |
1908 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1908 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
1909 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1909 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1910 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1910 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1911 | 1911 |
1912 Condition is_smi; | 1912 Condition is_smi; |
1913 if (instr->InputAt(0)->IsRegister()) { | 1913 if (instr->value()->IsRegister()) { |
1914 Register input = ToRegister(instr->InputAt(0)); | 1914 Register input = ToRegister(instr->value()); |
1915 is_smi = masm()->CheckSmi(input); | 1915 is_smi = masm()->CheckSmi(input); |
1916 } else { | 1916 } else { |
1917 Operand input = ToOperand(instr->InputAt(0)); | 1917 Operand input = ToOperand(instr->value()); |
1918 is_smi = masm()->CheckSmi(input); | 1918 is_smi = masm()->CheckSmi(input); |
1919 } | 1919 } |
1920 EmitBranch(true_block, false_block, is_smi); | 1920 EmitBranch(true_block, false_block, is_smi); |
1921 } | 1921 } |
1922 | 1922 |
1923 | 1923 |
1924 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 1924 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
1925 Register input = ToRegister(instr->InputAt(0)); | 1925 Register input = ToRegister(instr->value()); |
1926 Register temp = ToRegister(instr->TempAt(0)); | 1926 Register temp = ToRegister(instr->temp()); |
1927 | 1927 |
1928 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1928 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1929 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1929 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1930 | 1930 |
1931 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 1931 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
1932 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); | 1932 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); |
1933 __ testb(FieldOperand(temp, Map::kBitFieldOffset), | 1933 __ testb(FieldOperand(temp, Map::kBitFieldOffset), |
1934 Immediate(1 << Map::kIsUndetectable)); | 1934 Immediate(1 << Map::kIsUndetectable)); |
1935 EmitBranch(true_block, false_block, not_zero); | 1935 EmitBranch(true_block, false_block, not_zero); |
1936 } | 1936 } |
(...skipping 28 matching lines...) Expand all Loading... |
1965 InstanceType to = instr->to(); | 1965 InstanceType to = instr->to(); |
1966 if (from == to) return equal; | 1966 if (from == to) return equal; |
1967 if (to == LAST_TYPE) return above_equal; | 1967 if (to == LAST_TYPE) return above_equal; |
1968 if (from == FIRST_TYPE) return below_equal; | 1968 if (from == FIRST_TYPE) return below_equal; |
1969 UNREACHABLE(); | 1969 UNREACHABLE(); |
1970 return equal; | 1970 return equal; |
1971 } | 1971 } |
1972 | 1972 |
1973 | 1973 |
1974 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1974 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
1975 Register input = ToRegister(instr->InputAt(0)); | 1975 Register input = ToRegister(instr->value()); |
1976 | 1976 |
1977 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1977 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1978 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1978 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1979 | 1979 |
1980 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1980 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1981 | 1981 |
1982 __ JumpIfSmi(input, false_label); | 1982 __ JumpIfSmi(input, false_label); |
1983 | 1983 |
1984 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); | 1984 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); |
1985 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 1985 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
1986 } | 1986 } |
1987 | 1987 |
1988 | 1988 |
1989 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 1989 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
1990 Register input = ToRegister(instr->InputAt(0)); | 1990 Register input = ToRegister(instr->value()); |
1991 Register result = ToRegister(instr->result()); | 1991 Register result = ToRegister(instr->result()); |
1992 | 1992 |
1993 __ AbortIfNotString(input); | 1993 __ AbortIfNotString(input); |
1994 | 1994 |
1995 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); | 1995 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); |
1996 ASSERT(String::kHashShift >= kSmiTagSize); | 1996 ASSERT(String::kHashShift >= kSmiTagSize); |
1997 __ IndexFromHash(result, result); | 1997 __ IndexFromHash(result, result); |
1998 } | 1998 } |
1999 | 1999 |
2000 | 2000 |
2001 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2001 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2002 LHasCachedArrayIndexAndBranch* instr) { | 2002 LHasCachedArrayIndexAndBranch* instr) { |
2003 Register input = ToRegister(instr->InputAt(0)); | 2003 Register input = ToRegister(instr->value()); |
2004 | 2004 |
2005 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2005 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2006 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2006 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2007 | 2007 |
2008 __ testl(FieldOperand(input, String::kHashFieldOffset), | 2008 __ testl(FieldOperand(input, String::kHashFieldOffset), |
2009 Immediate(String::kContainsCachedArrayIndexMask)); | 2009 Immediate(String::kContainsCachedArrayIndexMask)); |
2010 EmitBranch(true_block, false_block, equal); | 2010 EmitBranch(true_block, false_block, equal); |
2011 } | 2011 } |
2012 | 2012 |
2013 | 2013 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2073 // classes and it doesn't have to because you can't access it with natives | 2073 // classes and it doesn't have to because you can't access it with natives |
2074 // syntax. Since both sides are symbols it is sufficient to use an identity | 2074 // syntax. Since both sides are symbols it is sufficient to use an identity |
2075 // comparison. | 2075 // comparison. |
2076 ASSERT(class_name->IsSymbol()); | 2076 ASSERT(class_name->IsSymbol()); |
2077 __ Cmp(temp, class_name); | 2077 __ Cmp(temp, class_name); |
2078 // End with the answer in the z flag. | 2078 // End with the answer in the z flag. |
2079 } | 2079 } |
2080 | 2080 |
2081 | 2081 |
2082 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2082 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2083 Register input = ToRegister(instr->InputAt(0)); | 2083 Register input = ToRegister(instr->value()); |
2084 Register temp = ToRegister(instr->TempAt(0)); | 2084 Register temp = ToRegister(instr->temp()); |
2085 Register temp2 = ToRegister(instr->TempAt(1)); | 2085 Register temp2 = ToRegister(instr->temp2()); |
2086 Handle<String> class_name = instr->hydrogen()->class_name(); | 2086 Handle<String> class_name = instr->hydrogen()->class_name(); |
2087 | 2087 |
2088 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2088 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2089 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2089 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2090 | 2090 |
2091 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2091 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
2092 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2092 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2093 | 2093 |
2094 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 2094 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
2095 | 2095 |
2096 EmitBranch(true_block, false_block, equal); | 2096 EmitBranch(true_block, false_block, equal); |
2097 } | 2097 } |
2098 | 2098 |
2099 | 2099 |
2100 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2100 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2101 Register reg = ToRegister(instr->InputAt(0)); | 2101 Register reg = ToRegister(instr->value()); |
2102 int true_block = instr->true_block_id(); | 2102 int true_block = instr->true_block_id(); |
2103 int false_block = instr->false_block_id(); | 2103 int false_block = instr->false_block_id(); |
2104 | 2104 |
2105 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2105 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
2106 EmitBranch(true_block, false_block, equal); | 2106 EmitBranch(true_block, false_block, equal); |
2107 } | 2107 } |
2108 | 2108 |
2109 | 2109 |
2110 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2110 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2111 InstanceofStub stub(InstanceofStub::kNoFlags); | 2111 InstanceofStub stub(InstanceofStub::kNoFlags); |
2112 __ push(ToRegister(instr->InputAt(0))); | 2112 __ push(ToRegister(instr->left())); |
2113 __ push(ToRegister(instr->InputAt(1))); | 2113 __ push(ToRegister(instr->right())); |
2114 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2114 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2115 Label true_value, done; | 2115 Label true_value, done; |
2116 __ testq(rax, rax); | 2116 __ testq(rax, rax); |
2117 __ j(zero, &true_value, Label::kNear); | 2117 __ j(zero, &true_value, Label::kNear); |
2118 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2118 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
2119 __ jmp(&done, Label::kNear); | 2119 __ jmp(&done, Label::kNear); |
2120 __ bind(&true_value); | 2120 __ bind(&true_value); |
2121 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 2121 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
2122 __ bind(&done); | 2122 __ bind(&done); |
2123 } | 2123 } |
(...skipping 13 matching lines...) Expand all Loading... |
2137 private: | 2137 private: |
2138 LInstanceOfKnownGlobal* instr_; | 2138 LInstanceOfKnownGlobal* instr_; |
2139 Label map_check_; | 2139 Label map_check_; |
2140 }; | 2140 }; |
2141 | 2141 |
2142 | 2142 |
2143 DeferredInstanceOfKnownGlobal* deferred; | 2143 DeferredInstanceOfKnownGlobal* deferred; |
2144 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2144 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
2145 | 2145 |
2146 Label done, false_result; | 2146 Label done, false_result; |
2147 Register object = ToRegister(instr->InputAt(0)); | 2147 Register object = ToRegister(instr->value()); |
2148 | 2148 |
2149 // A Smi is not an instance of anything. | 2149 // A Smi is not an instance of anything. |
2150 __ JumpIfSmi(object, &false_result); | 2150 __ JumpIfSmi(object, &false_result); |
2151 | 2151 |
2152 // This is the inlined call site instanceof cache. The two occurences of the | 2152 // This is the inlined call site instanceof cache. The two occurences of the |
2153 // hole value will be patched to the last map/result pair generated by the | 2153 // hole value will be patched to the last map/result pair generated by the |
2154 // instanceof stub. | 2154 // instanceof stub. |
2155 Label cache_miss; | 2155 Label cache_miss; |
2156 // Use a temp register to avoid memory operands with variable lengths. | 2156 // Use a temp register to avoid memory operands with variable lengths. |
2157 Register map = ToRegister(instr->TempAt(0)); | 2157 Register map = ToRegister(instr->temp()); |
2158 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); | 2158 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); |
2159 __ bind(deferred->map_check()); // Label for calculating code patching. | 2159 __ bind(deferred->map_check()); // Label for calculating code patching. |
2160 Handle<JSGlobalPropertyCell> cache_cell = | 2160 Handle<JSGlobalPropertyCell> cache_cell = |
2161 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); | 2161 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); |
2162 __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL); | 2162 __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL); |
2163 __ cmpq(map, Operand(kScratchRegister, 0)); | 2163 __ cmpq(map, Operand(kScratchRegister, 0)); |
2164 __ j(not_equal, &cache_miss, Label::kNear); | 2164 __ j(not_equal, &cache_miss, Label::kNear); |
2165 // Patched to load either true or false. | 2165 // Patched to load either true or false. |
2166 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 2166 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
2167 #ifdef DEBUG | 2167 #ifdef DEBUG |
(...skipping 22 matching lines...) Expand all Loading... |
2190 | 2190 |
2191 | 2191 |
2192 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, | 2192 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
2193 Label* map_check) { | 2193 Label* map_check) { |
2194 { | 2194 { |
2195 PushSafepointRegistersScope scope(this); | 2195 PushSafepointRegistersScope scope(this); |
2196 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( | 2196 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( |
2197 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); | 2197 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); |
2198 InstanceofStub stub(flags); | 2198 InstanceofStub stub(flags); |
2199 | 2199 |
2200 __ push(ToRegister(instr->InputAt(0))); | 2200 __ push(ToRegister(instr->value())); |
2201 __ PushHeapObject(instr->function()); | 2201 __ PushHeapObject(instr->function()); |
2202 | 2202 |
2203 static const int kAdditionalDelta = 10; | 2203 static const int kAdditionalDelta = 10; |
2204 int delta = | 2204 int delta = |
2205 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 2205 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
2206 ASSERT(delta >= 0); | 2206 ASSERT(delta >= 0); |
2207 __ push_imm32(delta); | 2207 __ push_imm32(delta); |
2208 | 2208 |
2209 // We are pushing three values on the stack but recording a | 2209 // We are pushing three values on the stack but recording a |
2210 // safepoint with two arguments because stub is going to | 2210 // safepoint with two arguments because stub is going to |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2290 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2290 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
2291 Register value = ToRegister(instr->value()); | 2291 Register value = ToRegister(instr->value()); |
2292 Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell(); | 2292 Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell(); |
2293 | 2293 |
2294 // If the cell we are storing to contains the hole it could have | 2294 // If the cell we are storing to contains the hole it could have |
2295 // been deleted from the property dictionary. In that case, we need | 2295 // been deleted from the property dictionary. In that case, we need |
2296 // to update the property details in the property dictionary to mark | 2296 // to update the property details in the property dictionary to mark |
2297 // it as no longer deleted. We deoptimize in that case. | 2297 // it as no longer deleted. We deoptimize in that case. |
2298 if (instr->hydrogen()->RequiresHoleCheck()) { | 2298 if (instr->hydrogen()->RequiresHoleCheck()) { |
2299 // We have a temp because CompareRoot might clobber kScratchRegister. | 2299 // We have a temp because CompareRoot might clobber kScratchRegister. |
2300 Register cell = ToRegister(instr->TempAt(0)); | 2300 Register cell = ToRegister(instr->temp()); |
2301 ASSERT(!value.is(cell)); | 2301 ASSERT(!value.is(cell)); |
2302 __ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); | 2302 __ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); |
2303 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); | 2303 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); |
2304 DeoptimizeIf(equal, instr->environment()); | 2304 DeoptimizeIf(equal, instr->environment()); |
2305 // Store the value. | 2305 // Store the value. |
2306 __ movq(Operand(cell, 0), value); | 2306 __ movq(Operand(cell, 0), value); |
2307 } else { | 2307 } else { |
2308 // Store the value. | 2308 // Store the value. |
2309 __ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); | 2309 __ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); |
2310 __ movq(Operand(kScratchRegister, 0), value); | 2310 __ movq(Operand(kScratchRegister, 0), value); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2358 __ j(not_equal, &skip_assignment); | 2358 __ j(not_equal, &skip_assignment); |
2359 } | 2359 } |
2360 } | 2360 } |
2361 __ movq(target, value); | 2361 __ movq(target, value); |
2362 | 2362 |
2363 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2363 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2364 HType type = instr->hydrogen()->value()->type(); | 2364 HType type = instr->hydrogen()->value()->type(); |
2365 SmiCheck check_needed = | 2365 SmiCheck check_needed = |
2366 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2366 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
2367 int offset = Context::SlotOffset(instr->slot_index()); | 2367 int offset = Context::SlotOffset(instr->slot_index()); |
2368 Register scratch = ToRegister(instr->TempAt(0)); | 2368 Register scratch = ToRegister(instr->temp()); |
2369 __ RecordWriteContextSlot(context, | 2369 __ RecordWriteContextSlot(context, |
2370 offset, | 2370 offset, |
2371 value, | 2371 value, |
2372 scratch, | 2372 scratch, |
2373 kSaveFPRegs, | 2373 kSaveFPRegs, |
2374 EMIT_REMEMBERED_SET, | 2374 EMIT_REMEMBERED_SET, |
2375 check_needed); | 2375 check_needed); |
2376 } | 2376 } |
2377 | 2377 |
2378 __ bind(&skip_assignment); | 2378 __ bind(&skip_assignment); |
2379 } | 2379 } |
2380 | 2380 |
2381 | 2381 |
2382 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2382 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
2383 Register object = ToRegister(instr->InputAt(0)); | 2383 Register object = ToRegister(instr->object()); |
2384 Register result = ToRegister(instr->result()); | 2384 Register result = ToRegister(instr->result()); |
2385 if (instr->hydrogen()->is_in_object()) { | 2385 if (instr->hydrogen()->is_in_object()) { |
2386 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); | 2386 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); |
2387 } else { | 2387 } else { |
2388 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2388 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
2389 __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); | 2389 __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); |
2390 } | 2390 } |
2391 } | 2391 } |
2392 | 2392 |
2393 | 2393 |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2545 __ bind(&non_instance); | 2545 __ bind(&non_instance); |
2546 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); | 2546 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); |
2547 | 2547 |
2548 // All done. | 2548 // All done. |
2549 __ bind(&done); | 2549 __ bind(&done); |
2550 } | 2550 } |
2551 | 2551 |
2552 | 2552 |
2553 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2553 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
2554 Register result = ToRegister(instr->result()); | 2554 Register result = ToRegister(instr->result()); |
2555 Register input = ToRegister(instr->InputAt(0)); | 2555 Register input = ToRegister(instr->object()); |
2556 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); | 2556 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); |
2557 if (FLAG_debug_code) { | 2557 if (FLAG_debug_code) { |
2558 Label done, ok, fail; | 2558 Label done, ok, fail; |
2559 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2559 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
2560 Heap::kFixedArrayMapRootIndex); | 2560 Heap::kFixedArrayMapRootIndex); |
2561 __ j(equal, &done, Label::kNear); | 2561 __ j(equal, &done, Label::kNear); |
2562 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2562 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
2563 Heap::kFixedCOWArrayMapRootIndex); | 2563 Heap::kFixedCOWArrayMapRootIndex); |
2564 __ j(equal, &done, Label::kNear); | 2564 __ j(equal, &done, Label::kNear); |
2565 Register temp((result.is(rax)) ? rbx : rax); | 2565 Register temp((result.is(rax)) ? rbx : rax); |
(...skipping 15 matching lines...) Expand all Loading... |
2581 __ bind(&ok); | 2581 __ bind(&ok); |
2582 __ pop(temp); | 2582 __ pop(temp); |
2583 __ bind(&done); | 2583 __ bind(&done); |
2584 } | 2584 } |
2585 } | 2585 } |
2586 | 2586 |
2587 | 2587 |
2588 void LCodeGen::DoLoadExternalArrayPointer( | 2588 void LCodeGen::DoLoadExternalArrayPointer( |
2589 LLoadExternalArrayPointer* instr) { | 2589 LLoadExternalArrayPointer* instr) { |
2590 Register result = ToRegister(instr->result()); | 2590 Register result = ToRegister(instr->result()); |
2591 Register input = ToRegister(instr->InputAt(0)); | 2591 Register input = ToRegister(instr->object()); |
2592 __ movq(result, FieldOperand(input, | 2592 __ movq(result, FieldOperand(input, |
2593 ExternalPixelArray::kExternalPointerOffset)); | 2593 ExternalPixelArray::kExternalPointerOffset)); |
2594 } | 2594 } |
2595 | 2595 |
2596 | 2596 |
2597 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2597 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
2598 Register arguments = ToRegister(instr->arguments()); | 2598 Register arguments = ToRegister(instr->arguments()); |
2599 Register length = ToRegister(instr->length()); | 2599 Register length = ToRegister(instr->length()); |
2600 Register result = ToRegister(instr->result()); | 2600 Register result = ToRegister(instr->result()); |
2601 | 2601 |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2829 } | 2829 } |
2830 } | 2830 } |
2831 | 2831 |
2832 | 2832 |
2833 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2833 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
2834 Register result = ToRegister(instr->result()); | 2834 Register result = ToRegister(instr->result()); |
2835 | 2835 |
2836 Label done; | 2836 Label done; |
2837 | 2837 |
2838 // If no arguments adaptor frame the number of arguments is fixed. | 2838 // If no arguments adaptor frame the number of arguments is fixed. |
2839 if (instr->InputAt(0)->IsRegister()) { | 2839 if (instr->elements()->IsRegister()) { |
2840 __ cmpq(rbp, ToRegister(instr->InputAt(0))); | 2840 __ cmpq(rbp, ToRegister(instr->elements())); |
2841 } else { | 2841 } else { |
2842 __ cmpq(rbp, ToOperand(instr->InputAt(0))); | 2842 __ cmpq(rbp, ToOperand(instr->elements())); |
2843 } | 2843 } |
2844 __ movl(result, Immediate(scope()->num_parameters())); | 2844 __ movl(result, Immediate(scope()->num_parameters())); |
2845 __ j(equal, &done, Label::kNear); | 2845 __ j(equal, &done, Label::kNear); |
2846 | 2846 |
2847 // Arguments adaptor frame present. Get argument length from there. | 2847 // Arguments adaptor frame present. Get argument length from there. |
2848 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2848 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
2849 __ SmiToInteger32(result, | 2849 __ SmiToInteger32(result, |
2850 Operand(result, | 2850 Operand(result, |
2851 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2851 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2852 | 2852 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2940 SafepointGenerator safepoint_generator( | 2940 SafepointGenerator safepoint_generator( |
2941 this, pointers, Safepoint::kLazyDeopt); | 2941 this, pointers, Safepoint::kLazyDeopt); |
2942 ParameterCount actual(rax); | 2942 ParameterCount actual(rax); |
2943 __ InvokeFunction(function, actual, CALL_FUNCTION, | 2943 __ InvokeFunction(function, actual, CALL_FUNCTION, |
2944 safepoint_generator, CALL_AS_METHOD); | 2944 safepoint_generator, CALL_AS_METHOD); |
2945 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2945 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2946 } | 2946 } |
2947 | 2947 |
2948 | 2948 |
2949 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2949 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
2950 LOperand* argument = instr->InputAt(0); | 2950 LOperand* argument = instr->value(); |
2951 EmitPushTaggedOperand(argument); | 2951 EmitPushTaggedOperand(argument); |
2952 } | 2952 } |
2953 | 2953 |
2954 | 2954 |
2955 void LCodeGen::DoDrop(LDrop* instr) { | 2955 void LCodeGen::DoDrop(LDrop* instr) { |
2956 __ Drop(instr->count()); | 2956 __ Drop(instr->count()); |
2957 } | 2957 } |
2958 | 2958 |
2959 | 2959 |
2960 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 2960 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3050 ASSERT(ToRegister(instr->result()).is(rax)); | 3050 ASSERT(ToRegister(instr->result()).is(rax)); |
3051 CallKnownFunction(instr->function(), | 3051 CallKnownFunction(instr->function(), |
3052 instr->arity(), | 3052 instr->arity(), |
3053 instr, | 3053 instr, |
3054 CALL_AS_METHOD, | 3054 CALL_AS_METHOD, |
3055 RDI_UNINITIALIZED); | 3055 RDI_UNINITIALIZED); |
3056 } | 3056 } |
3057 | 3057 |
3058 | 3058 |
3059 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 3059 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
3060 Register input_reg = ToRegister(instr->InputAt(0)); | 3060 Register input_reg = ToRegister(instr->value()); |
3061 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3061 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
3062 Heap::kHeapNumberMapRootIndex); | 3062 Heap::kHeapNumberMapRootIndex); |
3063 DeoptimizeIf(not_equal, instr->environment()); | 3063 DeoptimizeIf(not_equal, instr->environment()); |
3064 | 3064 |
3065 Label done; | 3065 Label done; |
3066 Register tmp = input_reg.is(rax) ? rcx : rax; | 3066 Register tmp = input_reg.is(rax) ? rcx : rax; |
3067 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; | 3067 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; |
3068 | 3068 |
3069 // Preserve the value of all registers. | 3069 // Preserve the value of all registers. |
3070 PushSafepointRegistersScope scope(this); | 3070 PushSafepointRegistersScope scope(this); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3102 __ shl(tmp2, Immediate(1)); | 3102 __ shl(tmp2, Immediate(1)); |
3103 __ shr(tmp2, Immediate(1)); | 3103 __ shr(tmp2, Immediate(1)); |
3104 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); | 3104 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); |
3105 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 3105 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
3106 | 3106 |
3107 __ bind(&done); | 3107 __ bind(&done); |
3108 } | 3108 } |
3109 | 3109 |
3110 | 3110 |
3111 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 3111 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
3112 Register input_reg = ToRegister(instr->InputAt(0)); | 3112 Register input_reg = ToRegister(instr->value()); |
3113 __ testl(input_reg, input_reg); | 3113 __ testl(input_reg, input_reg); |
3114 Label is_positive; | 3114 Label is_positive; |
3115 __ j(not_sign, &is_positive); | 3115 __ j(not_sign, &is_positive); |
3116 __ negl(input_reg); // Sets flags. | 3116 __ negl(input_reg); // Sets flags. |
3117 DeoptimizeIf(negative, instr->environment()); | 3117 DeoptimizeIf(negative, instr->environment()); |
3118 __ bind(&is_positive); | 3118 __ bind(&is_positive); |
3119 } | 3119 } |
3120 | 3120 |
3121 | 3121 |
3122 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 3122 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
3123 // Class for deferred case. | 3123 // Class for deferred case. |
3124 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3124 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
3125 public: | 3125 public: |
3126 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3126 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
3127 LUnaryMathOperation* instr) | 3127 LUnaryMathOperation* instr) |
3128 : LDeferredCode(codegen), instr_(instr) { } | 3128 : LDeferredCode(codegen), instr_(instr) { } |
3129 virtual void Generate() { | 3129 virtual void Generate() { |
3130 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3130 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
3131 } | 3131 } |
3132 virtual LInstruction* instr() { return instr_; } | 3132 virtual LInstruction* instr() { return instr_; } |
3133 private: | 3133 private: |
3134 LUnaryMathOperation* instr_; | 3134 LUnaryMathOperation* instr_; |
3135 }; | 3135 }; |
3136 | 3136 |
3137 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 3137 ASSERT(instr->value()->Equals(instr->result())); |
3138 Representation r = instr->hydrogen()->value()->representation(); | 3138 Representation r = instr->hydrogen()->value()->representation(); |
3139 | 3139 |
3140 if (r.IsDouble()) { | 3140 if (r.IsDouble()) { |
3141 XMMRegister scratch = xmm0; | 3141 XMMRegister scratch = xmm0; |
3142 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 3142 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3143 __ xorps(scratch, scratch); | 3143 __ xorps(scratch, scratch); |
3144 __ subsd(scratch, input_reg); | 3144 __ subsd(scratch, input_reg); |
3145 __ andpd(input_reg, scratch); | 3145 __ andpd(input_reg, scratch); |
3146 } else if (r.IsInteger32()) { | 3146 } else if (r.IsInteger32()) { |
3147 EmitIntegerMathAbs(instr); | 3147 EmitIntegerMathAbs(instr); |
3148 } else { // Tagged case. | 3148 } else { // Tagged case. |
3149 DeferredMathAbsTaggedHeapNumber* deferred = | 3149 DeferredMathAbsTaggedHeapNumber* deferred = |
3150 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3150 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
3151 Register input_reg = ToRegister(instr->InputAt(0)); | 3151 Register input_reg = ToRegister(instr->value()); |
3152 // Smi check. | 3152 // Smi check. |
3153 __ JumpIfNotSmi(input_reg, deferred->entry()); | 3153 __ JumpIfNotSmi(input_reg, deferred->entry()); |
3154 __ SmiToInteger32(input_reg, input_reg); | 3154 __ SmiToInteger32(input_reg, input_reg); |
3155 EmitIntegerMathAbs(instr); | 3155 EmitIntegerMathAbs(instr); |
3156 __ Integer32ToSmi(input_reg, input_reg); | 3156 __ Integer32ToSmi(input_reg, input_reg); |
3157 __ bind(deferred->exit()); | 3157 __ bind(deferred->exit()); |
3158 } | 3158 } |
3159 } | 3159 } |
3160 | 3160 |
3161 | 3161 |
3162 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 3162 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
3163 XMMRegister xmm_scratch = xmm0; | 3163 XMMRegister xmm_scratch = xmm0; |
3164 Register output_reg = ToRegister(instr->result()); | 3164 Register output_reg = ToRegister(instr->result()); |
3165 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 3165 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3166 | 3166 |
3167 if (CpuFeatures::IsSupported(SSE4_1)) { | 3167 if (CpuFeatures::IsSupported(SSE4_1)) { |
3168 CpuFeatures::Scope scope(SSE4_1); | 3168 CpuFeatures::Scope scope(SSE4_1); |
3169 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3169 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3170 // Deoptimize if minus zero. | 3170 // Deoptimize if minus zero. |
3171 __ movq(output_reg, input_reg); | 3171 __ movq(output_reg, input_reg); |
3172 __ subq(output_reg, Immediate(1)); | 3172 __ subq(output_reg, Immediate(1)); |
3173 DeoptimizeIf(overflow, instr->environment()); | 3173 DeoptimizeIf(overflow, instr->environment()); |
3174 } | 3174 } |
3175 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); | 3175 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3214 DeoptimizeIf(overflow, instr->environment()); | 3214 DeoptimizeIf(overflow, instr->environment()); |
3215 | 3215 |
3216 __ bind(&done); | 3216 __ bind(&done); |
3217 } | 3217 } |
3218 } | 3218 } |
3219 | 3219 |
3220 | 3220 |
3221 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 3221 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
3222 const XMMRegister xmm_scratch = xmm0; | 3222 const XMMRegister xmm_scratch = xmm0; |
3223 Register output_reg = ToRegister(instr->result()); | 3223 Register output_reg = ToRegister(instr->result()); |
3224 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 3224 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3225 | 3225 |
3226 Label done; | 3226 Label done; |
3227 // xmm_scratch = 0.5 | 3227 // xmm_scratch = 0.5 |
3228 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); | 3228 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); |
3229 __ movq(xmm_scratch, kScratchRegister); | 3229 __ movq(xmm_scratch, kScratchRegister); |
3230 Label below_half; | 3230 Label below_half; |
3231 __ ucomisd(xmm_scratch, input_reg); | 3231 __ ucomisd(xmm_scratch, input_reg); |
3232 // If input_reg is NaN, this doesn't jump. | 3232 // If input_reg is NaN, this doesn't jump. |
3233 __ j(above, &below_half, Label::kNear); | 3233 __ j(above, &below_half, Label::kNear); |
3234 // input = input + 0.5 | 3234 // input = input + 0.5 |
(...skipping 24 matching lines...) Expand all Loading... |
3259 __ ucomisd(input_reg, xmm_scratch); | 3259 __ ucomisd(input_reg, xmm_scratch); |
3260 DeoptimizeIf(below, instr->environment()); | 3260 DeoptimizeIf(below, instr->environment()); |
3261 } | 3261 } |
3262 __ xorl(output_reg, output_reg); | 3262 __ xorl(output_reg, output_reg); |
3263 | 3263 |
3264 __ bind(&done); | 3264 __ bind(&done); |
3265 } | 3265 } |
3266 | 3266 |
3267 | 3267 |
3268 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3268 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
3269 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 3269 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3270 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3270 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
3271 __ sqrtsd(input_reg, input_reg); | 3271 __ sqrtsd(input_reg, input_reg); |
3272 } | 3272 } |
3273 | 3273 |
3274 | 3274 |
3275 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3275 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
3276 XMMRegister xmm_scratch = xmm0; | 3276 XMMRegister xmm_scratch = xmm0; |
3277 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 3277 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3278 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3278 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
3279 | 3279 |
3280 // Note that according to ECMA-262 15.8.2.13: | 3280 // Note that according to ECMA-262 15.8.2.13: |
3281 // Math.pow(-Infinity, 0.5) == Infinity | 3281 // Math.pow(-Infinity, 0.5) == Infinity |
3282 // Math.sqrt(-Infinity) == NaN | 3282 // Math.sqrt(-Infinity) == NaN |
3283 Label done, sqrt; | 3283 Label done, sqrt; |
3284 // Check base for -Infinity. According to IEEE-754, double-precision | 3284 // Check base for -Infinity. According to IEEE-754, double-precision |
3285 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. | 3285 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. |
3286 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000), RelocInfo::NONE); | 3286 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000), RelocInfo::NONE); |
3287 __ movq(xmm_scratch, kScratchRegister); | 3287 __ movq(xmm_scratch, kScratchRegister); |
(...skipping 20 matching lines...) Expand all Loading... |
3308 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3308 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3309 // Having marked this as a call, we can use any registers. | 3309 // Having marked this as a call, we can use any registers. |
3310 // Just make sure that the input/output registers are the expected ones. | 3310 // Just make sure that the input/output registers are the expected ones. |
3311 | 3311 |
3312 // Choose register conforming to calling convention (when bailing out). | 3312 // Choose register conforming to calling convention (when bailing out). |
3313 #ifdef _WIN64 | 3313 #ifdef _WIN64 |
3314 Register exponent = rdx; | 3314 Register exponent = rdx; |
3315 #else | 3315 #else |
3316 Register exponent = rdi; | 3316 Register exponent = rdi; |
3317 #endif | 3317 #endif |
3318 ASSERT(!instr->InputAt(1)->IsRegister() || | 3318 ASSERT(!instr->right()->IsRegister() || |
3319 ToRegister(instr->InputAt(1)).is(exponent)); | 3319 ToRegister(instr->right()).is(exponent)); |
3320 ASSERT(!instr->InputAt(1)->IsDoubleRegister() || | 3320 ASSERT(!instr->right()->IsDoubleRegister() || |
3321 ToDoubleRegister(instr->InputAt(1)).is(xmm1)); | 3321 ToDoubleRegister(instr->right()).is(xmm1)); |
3322 ASSERT(ToDoubleRegister(instr->InputAt(0)).is(xmm2)); | 3322 ASSERT(ToDoubleRegister(instr->left()).is(xmm2)); |
3323 ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); | 3323 ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); |
3324 | 3324 |
3325 if (exponent_type.IsTagged()) { | 3325 if (exponent_type.IsTagged()) { |
3326 Label no_deopt; | 3326 Label no_deopt; |
3327 __ JumpIfSmi(exponent, &no_deopt); | 3327 __ JumpIfSmi(exponent, &no_deopt); |
3328 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, rcx); | 3328 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, rcx); |
3329 DeoptimizeIf(not_equal, instr->environment()); | 3329 DeoptimizeIf(not_equal, instr->environment()); |
3330 __ bind(&no_deopt); | 3330 __ bind(&no_deopt); |
3331 MathPowStub stub(MathPowStub::TAGGED); | 3331 MathPowStub stub(MathPowStub::TAGGED); |
3332 __ CallStub(&stub); | 3332 __ CallStub(&stub); |
(...skipping 21 matching lines...) Expand all Loading... |
3354 | 3354 |
3355 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); | 3355 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); |
3356 | 3356 |
3357 // Having marked this instruction as a call we can use any | 3357 // Having marked this instruction as a call we can use any |
3358 // registers. | 3358 // registers. |
3359 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3359 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
3360 | 3360 |
3361 // Choose the right register for the first argument depending on | 3361 // Choose the right register for the first argument depending on |
3362 // calling convention. | 3362 // calling convention. |
3363 #ifdef _WIN64 | 3363 #ifdef _WIN64 |
3364 ASSERT(ToRegister(instr->InputAt(0)).is(rcx)); | 3364 ASSERT(ToRegister(instr->global_object()).is(rcx)); |
3365 Register global_object = rcx; | 3365 Register global_object = rcx; |
3366 #else | 3366 #else |
3367 ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); | 3367 ASSERT(ToRegister(instr->global_object()).is(rdi)); |
3368 Register global_object = rdi; | 3368 Register global_object = rdi; |
3369 #endif | 3369 #endif |
3370 | 3370 |
3371 static const int kSeedSize = sizeof(uint32_t); | 3371 static const int kSeedSize = sizeof(uint32_t); |
3372 STATIC_ASSERT(kPointerSize == 2 * kSeedSize); | 3372 STATIC_ASSERT(kPointerSize == 2 * kSeedSize); |
3373 | 3373 |
3374 __ movq(global_object, | 3374 __ movq(global_object, |
3375 FieldOperand(global_object, GlobalObject::kNativeContextOffset)); | 3375 FieldOperand(global_object, GlobalObject::kNativeContextOffset)); |
3376 static const int kRandomSeedOffset = | 3376 static const int kRandomSeedOffset = |
3377 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; | 3377 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3572 ASSERT(ToRegister(instr->result()).is(rax)); | 3572 ASSERT(ToRegister(instr->result()).is(rax)); |
3573 CallKnownFunction(instr->target(), | 3573 CallKnownFunction(instr->target(), |
3574 instr->arity(), | 3574 instr->arity(), |
3575 instr, | 3575 instr, |
3576 CALL_AS_FUNCTION, | 3576 CALL_AS_FUNCTION, |
3577 RDI_UNINITIALIZED); | 3577 RDI_UNINITIALIZED); |
3578 } | 3578 } |
3579 | 3579 |
3580 | 3580 |
3581 void LCodeGen::DoCallNew(LCallNew* instr) { | 3581 void LCodeGen::DoCallNew(LCallNew* instr) { |
3582 ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); | 3582 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
3583 ASSERT(ToRegister(instr->result()).is(rax)); | 3583 ASSERT(ToRegister(instr->result()).is(rax)); |
3584 | 3584 |
3585 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3585 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
3586 __ Set(rax, instr->arity()); | 3586 __ Set(rax, instr->arity()); |
3587 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 3587 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
3588 } | 3588 } |
3589 | 3589 |
3590 | 3590 |
3591 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3591 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
3592 CallRuntime(instr->function(), instr->arity(), instr); | 3592 CallRuntime(instr->function(), instr->arity(), instr); |
3593 } | 3593 } |
3594 | 3594 |
3595 | 3595 |
3596 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3596 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
3597 Register object = ToRegister(instr->object()); | 3597 Register object = ToRegister(instr->object()); |
3598 Register value = ToRegister(instr->value()); | 3598 Register value = ToRegister(instr->value()); |
3599 int offset = instr->offset(); | 3599 int offset = instr->offset(); |
3600 | 3600 |
3601 if (!instr->transition().is_null()) { | 3601 if (!instr->transition().is_null()) { |
3602 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3602 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { |
3603 __ Move(FieldOperand(object, HeapObject::kMapOffset), | 3603 __ Move(FieldOperand(object, HeapObject::kMapOffset), |
3604 instr->transition()); | 3604 instr->transition()); |
3605 } else { | 3605 } else { |
3606 Register temp = ToRegister(instr->TempAt(0)); | 3606 Register temp = ToRegister(instr->temp()); |
3607 __ Move(kScratchRegister, instr->transition()); | 3607 __ Move(kScratchRegister, instr->transition()); |
3608 __ movq(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); | 3608 __ movq(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); |
3609 // Update the write barrier for the map field. | 3609 // Update the write barrier for the map field. |
3610 __ RecordWriteField(object, | 3610 __ RecordWriteField(object, |
3611 HeapObject::kMapOffset, | 3611 HeapObject::kMapOffset, |
3612 kScratchRegister, | 3612 kScratchRegister, |
3613 temp, | 3613 temp, |
3614 kSaveFPRegs, | 3614 kSaveFPRegs, |
3615 OMIT_REMEMBERED_SET, | 3615 OMIT_REMEMBERED_SET, |
3616 OMIT_SMI_CHECK); | 3616 OMIT_SMI_CHECK); |
3617 } | 3617 } |
3618 } | 3618 } |
3619 | 3619 |
3620 // Do the store. | 3620 // Do the store. |
3621 HType type = instr->hydrogen()->value()->type(); | 3621 HType type = instr->hydrogen()->value()->type(); |
3622 SmiCheck check_needed = | 3622 SmiCheck check_needed = |
3623 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 3623 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3624 if (instr->is_in_object()) { | 3624 if (instr->is_in_object()) { |
3625 __ movq(FieldOperand(object, offset), value); | 3625 __ movq(FieldOperand(object, offset), value); |
3626 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3626 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3627 Register temp = ToRegister(instr->TempAt(0)); | 3627 Register temp = ToRegister(instr->temp()); |
3628 // Update the write barrier for the object for in-object properties. | 3628 // Update the write barrier for the object for in-object properties. |
3629 __ RecordWriteField(object, | 3629 __ RecordWriteField(object, |
3630 offset, | 3630 offset, |
3631 value, | 3631 value, |
3632 temp, | 3632 temp, |
3633 kSaveFPRegs, | 3633 kSaveFPRegs, |
3634 EMIT_REMEMBERED_SET, | 3634 EMIT_REMEMBERED_SET, |
3635 check_needed); | 3635 check_needed); |
3636 } | 3636 } |
3637 } else { | 3637 } else { |
3638 Register temp = ToRegister(instr->TempAt(0)); | 3638 Register temp = ToRegister(instr->temp()); |
3639 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 3639 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
3640 __ movq(FieldOperand(temp, offset), value); | 3640 __ movq(FieldOperand(temp, offset), value); |
3641 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3641 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3642 // Update the write barrier for the properties array. | 3642 // Update the write barrier for the properties array. |
3643 // object is used as a scratch register. | 3643 // object is used as a scratch register. |
3644 __ RecordWriteField(temp, | 3644 __ RecordWriteField(temp, |
3645 offset, | 3645 offset, |
3646 value, | 3646 value, |
3647 object, | 3647 object, |
3648 kSaveFPRegs, | 3648 kSaveFPRegs, |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3881 | 3881 |
3882 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3882 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3883 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3883 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3884 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3884 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3885 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3885 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3886 } | 3886 } |
3887 | 3887 |
3888 | 3888 |
3889 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 3889 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
3890 Register object_reg = ToRegister(instr->object()); | 3890 Register object_reg = ToRegister(instr->object()); |
3891 Register new_map_reg = ToRegister(instr->new_map_reg()); | 3891 Register new_map_reg = ToRegister(instr->new_map_temp()); |
3892 | 3892 |
3893 Handle<Map> from_map = instr->original_map(); | 3893 Handle<Map> from_map = instr->original_map(); |
3894 Handle<Map> to_map = instr->transitioned_map(); | 3894 Handle<Map> to_map = instr->transitioned_map(); |
3895 ElementsKind from_kind = from_map->elements_kind(); | 3895 ElementsKind from_kind = from_map->elements_kind(); |
3896 ElementsKind to_kind = to_map->elements_kind(); | 3896 ElementsKind to_kind = to_map->elements_kind(); |
3897 | 3897 |
3898 Label not_applicable; | 3898 Label not_applicable; |
3899 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 3899 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
3900 __ j(not_equal, ¬_applicable); | 3900 __ j(not_equal, ¬_applicable); |
3901 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); | 3901 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); |
3902 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 3902 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
3903 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 3903 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
3904 // Write barrier. | 3904 // Write barrier. |
3905 ASSERT_NE(instr->temp_reg(), NULL); | 3905 ASSERT_NE(instr->temp(), NULL); |
3906 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 3906 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
3907 ToRegister(instr->temp_reg()), kDontSaveFPRegs); | 3907 ToRegister(instr->temp()), kDontSaveFPRegs); |
3908 } else if (IsFastSmiElementsKind(from_kind) && | 3908 } else if (IsFastSmiElementsKind(from_kind) && |
3909 IsFastDoubleElementsKind(to_kind)) { | 3909 IsFastDoubleElementsKind(to_kind)) { |
3910 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3910 Register fixed_object_reg = ToRegister(instr->temp()); |
3911 ASSERT(fixed_object_reg.is(rdx)); | 3911 ASSERT(fixed_object_reg.is(rdx)); |
3912 ASSERT(new_map_reg.is(rbx)); | 3912 ASSERT(new_map_reg.is(rbx)); |
3913 __ movq(fixed_object_reg, object_reg); | 3913 __ movq(fixed_object_reg, object_reg); |
3914 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3914 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
3915 RelocInfo::CODE_TARGET, instr); | 3915 RelocInfo::CODE_TARGET, instr); |
3916 } else if (IsFastDoubleElementsKind(from_kind) && | 3916 } else if (IsFastDoubleElementsKind(from_kind) && |
3917 IsFastObjectElementsKind(to_kind)) { | 3917 IsFastObjectElementsKind(to_kind)) { |
3918 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3918 Register fixed_object_reg = ToRegister(instr->temp()); |
3919 ASSERT(fixed_object_reg.is(rdx)); | 3919 ASSERT(fixed_object_reg.is(rdx)); |
3920 ASSERT(new_map_reg.is(rbx)); | 3920 ASSERT(new_map_reg.is(rbx)); |
3921 __ movq(fixed_object_reg, object_reg); | 3921 __ movq(fixed_object_reg, object_reg); |
3922 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3922 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
3923 RelocInfo::CODE_TARGET, instr); | 3923 RelocInfo::CODE_TARGET, instr); |
3924 } else { | 3924 } else { |
3925 UNREACHABLE(); | 3925 UNREACHABLE(); |
3926 } | 3926 } |
3927 __ bind(¬_applicable); | 3927 __ bind(¬_applicable); |
3928 } | 3928 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4039 | 4039 |
4040 | 4040 |
4041 void LCodeGen::DoStringLength(LStringLength* instr) { | 4041 void LCodeGen::DoStringLength(LStringLength* instr) { |
4042 Register string = ToRegister(instr->string()); | 4042 Register string = ToRegister(instr->string()); |
4043 Register result = ToRegister(instr->result()); | 4043 Register result = ToRegister(instr->result()); |
4044 __ movq(result, FieldOperand(string, String::kLengthOffset)); | 4044 __ movq(result, FieldOperand(string, String::kLengthOffset)); |
4045 } | 4045 } |
4046 | 4046 |
4047 | 4047 |
4048 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4048 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4049 LOperand* input = instr->InputAt(0); | 4049 LOperand* input = instr->value(); |
4050 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4050 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4051 LOperand* output = instr->result(); | 4051 LOperand* output = instr->result(); |
4052 ASSERT(output->IsDoubleRegister()); | 4052 ASSERT(output->IsDoubleRegister()); |
4053 if (input->IsRegister()) { | 4053 if (input->IsRegister()) { |
4054 __ cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); | 4054 __ cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); |
4055 } else { | 4055 } else { |
4056 __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); | 4056 __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); |
4057 } | 4057 } |
4058 } | 4058 } |
4059 | 4059 |
4060 | 4060 |
4061 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4061 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
4062 LOperand* input = instr->InputAt(0); | 4062 LOperand* input = instr->value(); |
4063 LOperand* output = instr->result(); | 4063 LOperand* output = instr->result(); |
4064 LOperand* temp = instr->TempAt(0); | 4064 LOperand* temp = instr->temp(); |
4065 | 4065 |
4066 __ LoadUint32(ToDoubleRegister(output), | 4066 __ LoadUint32(ToDoubleRegister(output), |
4067 ToRegister(input), | 4067 ToRegister(input), |
4068 ToDoubleRegister(temp)); | 4068 ToDoubleRegister(temp)); |
4069 } | 4069 } |
4070 | 4070 |
4071 | 4071 |
4072 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4072 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
4073 LOperand* input = instr->InputAt(0); | 4073 LOperand* input = instr->value(); |
4074 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4074 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4075 Register reg = ToRegister(input); | 4075 Register reg = ToRegister(input); |
4076 | 4076 |
4077 __ Integer32ToSmi(reg, reg); | 4077 __ Integer32ToSmi(reg, reg); |
4078 } | 4078 } |
4079 | 4079 |
4080 | 4080 |
4081 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4081 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
4082 class DeferredNumberTagU: public LDeferredCode { | 4082 class DeferredNumberTagU: public LDeferredCode { |
4083 public: | 4083 public: |
4084 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4084 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
4085 : LDeferredCode(codegen), instr_(instr) { } | 4085 : LDeferredCode(codegen), instr_(instr) { } |
4086 virtual void Generate() { | 4086 virtual void Generate() { |
4087 codegen()->DoDeferredNumberTagU(instr_); | 4087 codegen()->DoDeferredNumberTagU(instr_); |
4088 } | 4088 } |
4089 virtual LInstruction* instr() { return instr_; } | 4089 virtual LInstruction* instr() { return instr_; } |
4090 private: | 4090 private: |
4091 LNumberTagU* instr_; | 4091 LNumberTagU* instr_; |
4092 }; | 4092 }; |
4093 | 4093 |
4094 LOperand* input = instr->InputAt(0); | 4094 LOperand* input = instr->value(); |
4095 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4095 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4096 Register reg = ToRegister(input); | 4096 Register reg = ToRegister(input); |
4097 | 4097 |
4098 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4098 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
4099 __ cmpl(reg, Immediate(Smi::kMaxValue)); | 4099 __ cmpl(reg, Immediate(Smi::kMaxValue)); |
4100 __ j(above, deferred->entry()); | 4100 __ j(above, deferred->entry()); |
4101 __ Integer32ToSmi(reg, reg); | 4101 __ Integer32ToSmi(reg, reg); |
4102 __ bind(deferred->exit()); | 4102 __ bind(deferred->exit()); |
4103 } | 4103 } |
4104 | 4104 |
4105 | 4105 |
4106 void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { | 4106 void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { |
4107 Label slow; | 4107 Label slow; |
4108 Register reg = ToRegister(instr->InputAt(0)); | 4108 Register reg = ToRegister(instr->value()); |
4109 Register tmp = reg.is(rax) ? rcx : rax; | 4109 Register tmp = reg.is(rax) ? rcx : rax; |
4110 | 4110 |
4111 // Preserve the value of all registers. | 4111 // Preserve the value of all registers. |
4112 PushSafepointRegistersScope scope(this); | 4112 PushSafepointRegistersScope scope(this); |
4113 | 4113 |
4114 Label done; | 4114 Label done; |
4115 // Load value into xmm1 which will be preserved across potential call to | 4115 // Load value into xmm1 which will be preserved across potential call to |
4116 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable | 4116 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable |
4117 // XMM registers on x64). | 4117 // XMM registers on x64). |
4118 __ LoadUint32(xmm1, reg, xmm0); | 4118 __ LoadUint32(xmm1, reg, xmm0); |
(...skipping 26 matching lines...) Expand all Loading... |
4145 class DeferredNumberTagD: public LDeferredCode { | 4145 class DeferredNumberTagD: public LDeferredCode { |
4146 public: | 4146 public: |
4147 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4147 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
4148 : LDeferredCode(codegen), instr_(instr) { } | 4148 : LDeferredCode(codegen), instr_(instr) { } |
4149 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4149 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
4150 virtual LInstruction* instr() { return instr_; } | 4150 virtual LInstruction* instr() { return instr_; } |
4151 private: | 4151 private: |
4152 LNumberTagD* instr_; | 4152 LNumberTagD* instr_; |
4153 }; | 4153 }; |
4154 | 4154 |
4155 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 4155 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
4156 Register reg = ToRegister(instr->result()); | 4156 Register reg = ToRegister(instr->result()); |
4157 Register tmp = ToRegister(instr->TempAt(0)); | 4157 Register tmp = ToRegister(instr->temp()); |
4158 | 4158 |
4159 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4159 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
4160 if (FLAG_inline_new) { | 4160 if (FLAG_inline_new) { |
4161 __ AllocateHeapNumber(reg, tmp, deferred->entry()); | 4161 __ AllocateHeapNumber(reg, tmp, deferred->entry()); |
4162 } else { | 4162 } else { |
4163 __ jmp(deferred->entry()); | 4163 __ jmp(deferred->entry()); |
4164 } | 4164 } |
4165 __ bind(deferred->exit()); | 4165 __ bind(deferred->exit()); |
4166 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 4166 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
4167 } | 4167 } |
(...skipping 10 matching lines...) Expand all Loading... |
4178 PushSafepointRegistersScope scope(this); | 4178 PushSafepointRegistersScope scope(this); |
4179 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4179 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
4180 // Ensure that value in rax survives popping registers. | 4180 // Ensure that value in rax survives popping registers. |
4181 __ movq(kScratchRegister, rax); | 4181 __ movq(kScratchRegister, rax); |
4182 } | 4182 } |
4183 __ movq(reg, kScratchRegister); | 4183 __ movq(reg, kScratchRegister); |
4184 } | 4184 } |
4185 | 4185 |
4186 | 4186 |
4187 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4187 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4188 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 4188 ASSERT(instr->value()->Equals(instr->result())); |
4189 Register input = ToRegister(instr->InputAt(0)); | 4189 Register input = ToRegister(instr->value()); |
4190 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4190 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
4191 __ Integer32ToSmi(input, input); | 4191 __ Integer32ToSmi(input, input); |
4192 } | 4192 } |
4193 | 4193 |
4194 | 4194 |
4195 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4195 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
4196 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 4196 ASSERT(instr->value()->Equals(instr->result())); |
4197 Register input = ToRegister(instr->InputAt(0)); | 4197 Register input = ToRegister(instr->value()); |
4198 if (instr->needs_check()) { | 4198 if (instr->needs_check()) { |
4199 Condition is_smi = __ CheckSmi(input); | 4199 Condition is_smi = __ CheckSmi(input); |
4200 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); | 4200 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |
4201 } else { | 4201 } else { |
4202 if (FLAG_debug_code) { | 4202 if (FLAG_debug_code) { |
4203 __ AbortIfNotSmi(input); | 4203 __ AbortIfNotSmi(input); |
4204 } | 4204 } |
4205 } | 4205 } |
4206 __ SmiToInteger32(input, input); | 4206 __ SmiToInteger32(input, input); |
4207 } | 4207 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4252 // Smi to XMM conversion | 4252 // Smi to XMM conversion |
4253 __ bind(&load_smi); | 4253 __ bind(&load_smi); |
4254 __ SmiToInteger32(kScratchRegister, input_reg); | 4254 __ SmiToInteger32(kScratchRegister, input_reg); |
4255 __ cvtlsi2sd(result_reg, kScratchRegister); | 4255 __ cvtlsi2sd(result_reg, kScratchRegister); |
4256 __ bind(&done); | 4256 __ bind(&done); |
4257 } | 4257 } |
4258 | 4258 |
4259 | 4259 |
4260 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 4260 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
4261 Label done, heap_number; | 4261 Label done, heap_number; |
4262 Register input_reg = ToRegister(instr->InputAt(0)); | 4262 Register input_reg = ToRegister(instr->value()); |
4263 | 4263 |
4264 // Heap number map check. | 4264 // Heap number map check. |
4265 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 4265 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
4266 Heap::kHeapNumberMapRootIndex); | 4266 Heap::kHeapNumberMapRootIndex); |
4267 | 4267 |
4268 if (instr->truncating()) { | 4268 if (instr->truncating()) { |
4269 __ j(equal, &heap_number, Label::kNear); | 4269 __ j(equal, &heap_number, Label::kNear); |
4270 // Check for undefined. Undefined is converted to zero for truncating | 4270 // Check for undefined. Undefined is converted to zero for truncating |
4271 // conversions. | 4271 // conversions. |
4272 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 4272 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
4273 DeoptimizeIf(not_equal, instr->environment()); | 4273 DeoptimizeIf(not_equal, instr->environment()); |
4274 __ Set(input_reg, 0); | 4274 __ Set(input_reg, 0); |
4275 __ jmp(&done, Label::kNear); | 4275 __ jmp(&done, Label::kNear); |
4276 | 4276 |
4277 __ bind(&heap_number); | 4277 __ bind(&heap_number); |
4278 | 4278 |
4279 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4279 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4280 __ cvttsd2siq(input_reg, xmm0); | 4280 __ cvttsd2siq(input_reg, xmm0); |
4281 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); | 4281 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); |
4282 __ cmpq(input_reg, kScratchRegister); | 4282 __ cmpq(input_reg, kScratchRegister); |
4283 DeoptimizeIf(equal, instr->environment()); | 4283 DeoptimizeIf(equal, instr->environment()); |
4284 } else { | 4284 } else { |
4285 // Deoptimize if we don't have a heap number. | 4285 // Deoptimize if we don't have a heap number. |
4286 DeoptimizeIf(not_equal, instr->environment()); | 4286 DeoptimizeIf(not_equal, instr->environment()); |
4287 | 4287 |
4288 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); | 4288 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); |
4289 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4289 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4290 __ cvttsd2si(input_reg, xmm0); | 4290 __ cvttsd2si(input_reg, xmm0); |
4291 __ cvtlsi2sd(xmm_temp, input_reg); | 4291 __ cvtlsi2sd(xmm_temp, input_reg); |
4292 __ ucomisd(xmm0, xmm_temp); | 4292 __ ucomisd(xmm0, xmm_temp); |
4293 DeoptimizeIf(not_equal, instr->environment()); | 4293 DeoptimizeIf(not_equal, instr->environment()); |
4294 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 4294 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
4295 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4295 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
4296 __ testl(input_reg, input_reg); | 4296 __ testl(input_reg, input_reg); |
4297 __ j(not_zero, &done); | 4297 __ j(not_zero, &done); |
4298 __ movmskpd(input_reg, xmm0); | 4298 __ movmskpd(input_reg, xmm0); |
4299 __ andl(input_reg, Immediate(1)); | 4299 __ andl(input_reg, Immediate(1)); |
4300 DeoptimizeIf(not_zero, instr->environment()); | 4300 DeoptimizeIf(not_zero, instr->environment()); |
4301 } | 4301 } |
4302 } | 4302 } |
4303 __ bind(&done); | 4303 __ bind(&done); |
4304 } | 4304 } |
4305 | 4305 |
4306 | 4306 |
4307 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4307 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
4308 class DeferredTaggedToI: public LDeferredCode { | 4308 class DeferredTaggedToI: public LDeferredCode { |
4309 public: | 4309 public: |
4310 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4310 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
4311 : LDeferredCode(codegen), instr_(instr) { } | 4311 : LDeferredCode(codegen), instr_(instr) { } |
4312 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 4312 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
4313 virtual LInstruction* instr() { return instr_; } | 4313 virtual LInstruction* instr() { return instr_; } |
4314 private: | 4314 private: |
4315 LTaggedToI* instr_; | 4315 LTaggedToI* instr_; |
4316 }; | 4316 }; |
4317 | 4317 |
4318 LOperand* input = instr->InputAt(0); | 4318 LOperand* input = instr->value(); |
4319 ASSERT(input->IsRegister()); | 4319 ASSERT(input->IsRegister()); |
4320 ASSERT(input->Equals(instr->result())); | 4320 ASSERT(input->Equals(instr->result())); |
4321 | 4321 |
4322 Register input_reg = ToRegister(input); | 4322 Register input_reg = ToRegister(input); |
4323 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 4323 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
4324 __ JumpIfNotSmi(input_reg, deferred->entry()); | 4324 __ JumpIfNotSmi(input_reg, deferred->entry()); |
4325 __ SmiToInteger32(input_reg, input_reg); | 4325 __ SmiToInteger32(input_reg, input_reg); |
4326 __ bind(deferred->exit()); | 4326 __ bind(deferred->exit()); |
4327 } | 4327 } |
4328 | 4328 |
4329 | 4329 |
4330 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4330 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
4331 LOperand* input = instr->InputAt(0); | 4331 LOperand* input = instr->value(); |
4332 ASSERT(input->IsRegister()); | 4332 ASSERT(input->IsRegister()); |
4333 LOperand* result = instr->result(); | 4333 LOperand* result = instr->result(); |
4334 ASSERT(result->IsDoubleRegister()); | 4334 ASSERT(result->IsDoubleRegister()); |
4335 | 4335 |
4336 Register input_reg = ToRegister(input); | 4336 Register input_reg = ToRegister(input); |
4337 XMMRegister result_reg = ToDoubleRegister(result); | 4337 XMMRegister result_reg = ToDoubleRegister(result); |
4338 | 4338 |
4339 EmitNumberUntagD(input_reg, result_reg, | 4339 EmitNumberUntagD(input_reg, result_reg, |
4340 instr->hydrogen()->deoptimize_on_undefined(), | 4340 instr->hydrogen()->deoptimize_on_undefined(), |
4341 instr->hydrogen()->deoptimize_on_minus_zero(), | 4341 instr->hydrogen()->deoptimize_on_minus_zero(), |
4342 instr->environment()); | 4342 instr->environment()); |
4343 } | 4343 } |
4344 | 4344 |
4345 | 4345 |
4346 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4346 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
4347 LOperand* input = instr->InputAt(0); | 4347 LOperand* input = instr->value(); |
4348 ASSERT(input->IsDoubleRegister()); | 4348 ASSERT(input->IsDoubleRegister()); |
4349 LOperand* result = instr->result(); | 4349 LOperand* result = instr->result(); |
4350 ASSERT(result->IsRegister()); | 4350 ASSERT(result->IsRegister()); |
4351 | 4351 |
4352 XMMRegister input_reg = ToDoubleRegister(input); | 4352 XMMRegister input_reg = ToDoubleRegister(input); |
4353 Register result_reg = ToRegister(result); | 4353 Register result_reg = ToRegister(result); |
4354 | 4354 |
4355 if (instr->truncating()) { | 4355 if (instr->truncating()) { |
4356 // Performs a truncating conversion of a floating point number as used by | 4356 // Performs a truncating conversion of a floating point number as used by |
4357 // the JS bitwise operations. | 4357 // the JS bitwise operations. |
(...skipping 19 matching lines...) Expand all Loading... |
4377 // deoptimize. | 4377 // deoptimize. |
4378 __ andl(result_reg, Immediate(1)); | 4378 __ andl(result_reg, Immediate(1)); |
4379 DeoptimizeIf(not_zero, instr->environment()); | 4379 DeoptimizeIf(not_zero, instr->environment()); |
4380 __ bind(&done); | 4380 __ bind(&done); |
4381 } | 4381 } |
4382 } | 4382 } |
4383 } | 4383 } |
4384 | 4384 |
4385 | 4385 |
4386 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4386 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
4387 LOperand* input = instr->InputAt(0); | 4387 LOperand* input = instr->value(); |
4388 Condition cc = masm()->CheckSmi(ToRegister(input)); | 4388 Condition cc = masm()->CheckSmi(ToRegister(input)); |
4389 DeoptimizeIf(NegateCondition(cc), instr->environment()); | 4389 DeoptimizeIf(NegateCondition(cc), instr->environment()); |
4390 } | 4390 } |
4391 | 4391 |
4392 | 4392 |
4393 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4393 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
4394 LOperand* input = instr->InputAt(0); | 4394 LOperand* input = instr->value(); |
4395 Condition cc = masm()->CheckSmi(ToRegister(input)); | 4395 Condition cc = masm()->CheckSmi(ToRegister(input)); |
4396 DeoptimizeIf(cc, instr->environment()); | 4396 DeoptimizeIf(cc, instr->environment()); |
4397 } | 4397 } |
4398 | 4398 |
4399 | 4399 |
4400 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4400 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
4401 Register input = ToRegister(instr->InputAt(0)); | 4401 Register input = ToRegister(instr->value()); |
4402 | 4402 |
4403 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); | 4403 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); |
4404 | 4404 |
4405 if (instr->hydrogen()->is_interval_check()) { | 4405 if (instr->hydrogen()->is_interval_check()) { |
4406 InstanceType first; | 4406 InstanceType first; |
4407 InstanceType last; | 4407 InstanceType last; |
4408 instr->hydrogen()->GetCheckInterval(&first, &last); | 4408 instr->hydrogen()->GetCheckInterval(&first, &last); |
4409 | 4409 |
4410 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 4410 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), |
4411 Immediate(static_cast<int8_t>(first))); | 4411 Immediate(static_cast<int8_t>(first))); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4463 CompareMapMode mode, | 4463 CompareMapMode mode, |
4464 LEnvironment* env) { | 4464 LEnvironment* env) { |
4465 Label success; | 4465 Label success; |
4466 __ CompareMap(reg, map, &success, mode); | 4466 __ CompareMap(reg, map, &success, mode); |
4467 DeoptimizeIf(not_equal, env); | 4467 DeoptimizeIf(not_equal, env); |
4468 __ bind(&success); | 4468 __ bind(&success); |
4469 } | 4469 } |
4470 | 4470 |
4471 | 4471 |
4472 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4472 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
4473 LOperand* input = instr->InputAt(0); | 4473 LOperand* input = instr->value(); |
4474 ASSERT(input->IsRegister()); | 4474 ASSERT(input->IsRegister()); |
4475 Register reg = ToRegister(input); | 4475 Register reg = ToRegister(input); |
4476 | 4476 |
4477 Label success; | 4477 Label success; |
4478 SmallMapList* map_set = instr->hydrogen()->map_set(); | 4478 SmallMapList* map_set = instr->hydrogen()->map_set(); |
4479 for (int i = 0; i < map_set->length() - 1; i++) { | 4479 for (int i = 0; i < map_set->length() - 1; i++) { |
4480 Handle<Map> map = map_set->at(i); | 4480 Handle<Map> map = map_set->at(i); |
4481 __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP); | 4481 __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP); |
4482 __ j(equal, &success); | 4482 __ j(equal, &success); |
4483 } | 4483 } |
4484 Handle<Map> map = map_set->last(); | 4484 Handle<Map> map = map_set->last(); |
4485 DoCheckMapCommon(reg, map, REQUIRE_EXACT_MAP, instr->environment()); | 4485 DoCheckMapCommon(reg, map, REQUIRE_EXACT_MAP, instr->environment()); |
4486 __ bind(&success); | 4486 __ bind(&success); |
4487 } | 4487 } |
4488 | 4488 |
4489 | 4489 |
4490 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 4490 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
4491 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 4491 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
4492 Register result_reg = ToRegister(instr->result()); | 4492 Register result_reg = ToRegister(instr->result()); |
4493 Register temp_reg = ToRegister(instr->TempAt(0)); | 4493 Register temp_reg = ToRegister(instr->temp()); |
4494 __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); | 4494 __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); |
4495 } | 4495 } |
4496 | 4496 |
4497 | 4497 |
4498 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 4498 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
4499 ASSERT(instr->unclamped()->Equals(instr->result())); | 4499 ASSERT(instr->unclamped()->Equals(instr->result())); |
4500 Register value_reg = ToRegister(instr->result()); | 4500 Register value_reg = ToRegister(instr->result()); |
4501 __ ClampUint8(value_reg); | 4501 __ ClampUint8(value_reg); |
4502 } | 4502 } |
4503 | 4503 |
4504 | 4504 |
4505 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 4505 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
4506 ASSERT(instr->unclamped()->Equals(instr->result())); | 4506 ASSERT(instr->unclamped()->Equals(instr->result())); |
4507 Register input_reg = ToRegister(instr->unclamped()); | 4507 Register input_reg = ToRegister(instr->unclamped()); |
4508 Register temp_reg = ToRegister(instr->TempAt(0)); | 4508 Register temp_reg = ToRegister(instr->temp()); |
4509 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->TempAt(1)); | 4509 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp2()); |
4510 Label is_smi, done, heap_number; | 4510 Label is_smi, done, heap_number; |
4511 | 4511 |
4512 __ JumpIfSmi(input_reg, &is_smi); | 4512 __ JumpIfSmi(input_reg, &is_smi); |
4513 | 4513 |
4514 // Check for heap number | 4514 // Check for heap number |
4515 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 4515 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
4516 factory()->heap_number_map()); | 4516 factory()->heap_number_map()); |
4517 __ j(equal, &heap_number, Label::kNear); | 4517 __ j(equal, &heap_number, Label::kNear); |
4518 | 4518 |
4519 // Check for undefined. Undefined is converted to zero for clamping | 4519 // Check for undefined. Undefined is converted to zero for clamping |
(...skipping 12 matching lines...) Expand all Loading... |
4532 // smi | 4532 // smi |
4533 __ bind(&is_smi); | 4533 __ bind(&is_smi); |
4534 __ SmiToInteger32(input_reg, input_reg); | 4534 __ SmiToInteger32(input_reg, input_reg); |
4535 __ ClampUint8(input_reg); | 4535 __ ClampUint8(input_reg); |
4536 | 4536 |
4537 __ bind(&done); | 4537 __ bind(&done); |
4538 } | 4538 } |
4539 | 4539 |
4540 | 4540 |
4541 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 4541 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
4542 Register reg = ToRegister(instr->TempAt(0)); | 4542 Register reg = ToRegister(instr->temp()); |
4543 | 4543 |
4544 Handle<JSObject> holder = instr->holder(); | 4544 Handle<JSObject> holder = instr->holder(); |
4545 Handle<JSObject> current_prototype = instr->prototype(); | 4545 Handle<JSObject> current_prototype = instr->prototype(); |
4546 | 4546 |
4547 // Load prototype object. | 4547 // Load prototype object. |
4548 __ LoadHeapObject(reg, current_prototype); | 4548 __ LoadHeapObject(reg, current_prototype); |
4549 | 4549 |
4550 // Check prototype maps up to the holder. | 4550 // Check prototype maps up to the holder. |
4551 while (!current_prototype.is_identical_to(holder)) { | 4551 while (!current_prototype.is_identical_to(holder)) { |
4552 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), | 4552 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), |
(...skipping 18 matching lines...) Expand all Loading... |
4571 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } | 4571 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } |
4572 virtual LInstruction* instr() { return instr_; } | 4572 virtual LInstruction* instr() { return instr_; } |
4573 private: | 4573 private: |
4574 LAllocateObject* instr_; | 4574 LAllocateObject* instr_; |
4575 }; | 4575 }; |
4576 | 4576 |
4577 DeferredAllocateObject* deferred = | 4577 DeferredAllocateObject* deferred = |
4578 new(zone()) DeferredAllocateObject(this, instr); | 4578 new(zone()) DeferredAllocateObject(this, instr); |
4579 | 4579 |
4580 Register result = ToRegister(instr->result()); | 4580 Register result = ToRegister(instr->result()); |
4581 Register scratch = ToRegister(instr->TempAt(0)); | 4581 Register scratch = ToRegister(instr->temp()); |
4582 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); | 4582 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); |
4583 Handle<Map> initial_map(constructor->initial_map()); | 4583 Handle<Map> initial_map(constructor->initial_map()); |
4584 int instance_size = initial_map->instance_size(); | 4584 int instance_size = initial_map->instance_size(); |
4585 ASSERT(initial_map->pre_allocated_property_fields() + | 4585 ASSERT(initial_map->pre_allocated_property_fields() + |
4586 initial_map->unused_property_fields() - | 4586 initial_map->unused_property_fields() - |
4587 initial_map->inobject_properties() == 0); | 4587 initial_map->inobject_properties() == 0); |
4588 | 4588 |
4589 // Allocate memory for the object. The initial map might change when | 4589 // Allocate memory for the object. The initial map might change when |
4590 // the constructor's prototype changes, but instance size and property | 4590 // the constructor's prototype changes, but instance size and property |
4591 // counts remain unchanged (if slack tracking finished). | 4591 // counts remain unchanged (if slack tracking finished). |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4873 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 4873 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
4874 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); | 4874 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); |
4875 } else { | 4875 } else { |
4876 FastCloneShallowObjectStub stub(properties_count); | 4876 FastCloneShallowObjectStub stub(properties_count); |
4877 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4877 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
4878 } | 4878 } |
4879 } | 4879 } |
4880 | 4880 |
4881 | 4881 |
4882 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 4882 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
4883 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); | 4883 ASSERT(ToRegister(instr->value()).is(rax)); |
4884 __ push(rax); | 4884 __ push(rax); |
4885 CallRuntime(Runtime::kToFastProperties, 1, instr); | 4885 CallRuntime(Runtime::kToFastProperties, 1, instr); |
4886 } | 4886 } |
4887 | 4887 |
4888 | 4888 |
4889 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 4889 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
4890 Label materialized; | 4890 Label materialized; |
4891 // Registers will be used as follows: | 4891 // Registers will be used as follows: |
4892 // rcx = literals array. | 4892 // rcx = literals array. |
4893 // rbx = regexp literal. | 4893 // rbx = regexp literal. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4950 __ Push(shared_info); | 4950 __ Push(shared_info); |
4951 __ PushRoot(pretenure ? | 4951 __ PushRoot(pretenure ? |
4952 Heap::kTrueValueRootIndex : | 4952 Heap::kTrueValueRootIndex : |
4953 Heap::kFalseValueRootIndex); | 4953 Heap::kFalseValueRootIndex); |
4954 CallRuntime(Runtime::kNewClosure, 3, instr); | 4954 CallRuntime(Runtime::kNewClosure, 3, instr); |
4955 } | 4955 } |
4956 } | 4956 } |
4957 | 4957 |
4958 | 4958 |
4959 void LCodeGen::DoTypeof(LTypeof* instr) { | 4959 void LCodeGen::DoTypeof(LTypeof* instr) { |
4960 LOperand* input = instr->InputAt(0); | 4960 LOperand* input = instr->value(); |
4961 EmitPushTaggedOperand(input); | 4961 EmitPushTaggedOperand(input); |
4962 CallRuntime(Runtime::kTypeof, 1, instr); | 4962 CallRuntime(Runtime::kTypeof, 1, instr); |
4963 } | 4963 } |
4964 | 4964 |
4965 | 4965 |
4966 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 4966 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
4967 ASSERT(!operand->IsDoubleRegister()); | 4967 ASSERT(!operand->IsDoubleRegister()); |
4968 if (operand->IsConstantOperand()) { | 4968 if (operand->IsConstantOperand()) { |
4969 Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); | 4969 Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); |
4970 if (object->IsSmi()) { | 4970 if (object->IsSmi()) { |
4971 __ Push(Handle<Smi>::cast(object)); | 4971 __ Push(Handle<Smi>::cast(object)); |
4972 } else { | 4972 } else { |
4973 __ PushHeapObject(Handle<HeapObject>::cast(object)); | 4973 __ PushHeapObject(Handle<HeapObject>::cast(object)); |
4974 } | 4974 } |
4975 } else if (operand->IsRegister()) { | 4975 } else if (operand->IsRegister()) { |
4976 __ push(ToRegister(operand)); | 4976 __ push(ToRegister(operand)); |
4977 } else { | 4977 } else { |
4978 __ push(ToOperand(operand)); | 4978 __ push(ToOperand(operand)); |
4979 } | 4979 } |
4980 } | 4980 } |
4981 | 4981 |
4982 | 4982 |
4983 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4983 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
4984 Register input = ToRegister(instr->InputAt(0)); | 4984 Register input = ToRegister(instr->value()); |
4985 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4985 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4986 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4986 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4987 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 4987 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
4988 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 4988 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
4989 | 4989 |
4990 Condition final_branch_condition = | 4990 Condition final_branch_condition = |
4991 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); | 4991 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); |
4992 if (final_branch_condition != no_condition) { | 4992 if (final_branch_condition != no_condition) { |
4993 EmitBranch(true_block, false_block, final_branch_condition); | 4993 EmitBranch(true_block, false_block, final_branch_condition); |
4994 } | 4994 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5060 | 5060 |
5061 } else { | 5061 } else { |
5062 __ jmp(false_label); | 5062 __ jmp(false_label); |
5063 } | 5063 } |
5064 | 5064 |
5065 return final_branch_condition; | 5065 return final_branch_condition; |
5066 } | 5066 } |
5067 | 5067 |
5068 | 5068 |
5069 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5069 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
5070 Register temp = ToRegister(instr->TempAt(0)); | 5070 Register temp = ToRegister(instr->temp()); |
5071 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5071 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
5072 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5072 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
5073 | 5073 |
5074 EmitIsConstructCall(temp); | 5074 EmitIsConstructCall(temp); |
5075 EmitBranch(true_block, false_block, equal); | 5075 EmitBranch(true_block, false_block, equal); |
5076 } | 5076 } |
5077 | 5077 |
5078 | 5078 |
5079 void LCodeGen::EmitIsConstructCall(Register temp) { | 5079 void LCodeGen::EmitIsConstructCall(Register temp) { |
5080 // Get the frame pointer for the calling frame. | 5080 // Get the frame pointer for the calling frame. |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5313 FixedArray::kHeaderSize - kPointerSize)); | 5313 FixedArray::kHeaderSize - kPointerSize)); |
5314 __ bind(&done); | 5314 __ bind(&done); |
5315 } | 5315 } |
5316 | 5316 |
5317 | 5317 |
5318 #undef __ | 5318 #undef __ |
5319 | 5319 |
5320 } } // namespace v8::internal | 5320 } } // namespace v8::internal |
5321 | 5321 |
5322 #endif // V8_TARGET_ARCH_X64 | 5322 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |