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 891 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 } | 902 } |
903 | 903 |
904 | 904 |
905 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 905 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
906 // Nothing to do. | 906 // Nothing to do. |
907 } | 907 } |
908 | 908 |
909 | 909 |
910 void LCodeGen::DoModI(LModI* instr) { | 910 void LCodeGen::DoModI(LModI* instr) { |
911 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 911 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
912 Register dividend = ToRegister(instr->InputAt(0)); | 912 Register dividend = ToRegister(instr->left()); |
913 | 913 |
914 int32_t divisor = | 914 int32_t divisor = |
915 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 915 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
916 | 916 |
917 if (divisor < 0) divisor = -divisor; | 917 if (divisor < 0) divisor = -divisor; |
918 | 918 |
919 Label positive_dividend, done; | 919 Label positive_dividend, done; |
920 __ test(dividend, Operand(dividend)); | 920 __ test(dividend, Operand(dividend)); |
921 __ j(not_sign, &positive_dividend, Label::kNear); | 921 __ j(not_sign, &positive_dividend, Label::kNear); |
922 __ neg(dividend); | 922 __ neg(dividend); |
923 __ and_(dividend, divisor - 1); | 923 __ and_(dividend, divisor - 1); |
924 __ neg(dividend); | 924 __ neg(dividend); |
925 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 925 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
926 __ j(not_zero, &done, Label::kNear); | 926 __ j(not_zero, &done, Label::kNear); |
927 DeoptimizeIf(no_condition, instr->environment()); | 927 DeoptimizeIf(no_condition, instr->environment()); |
928 } else { | 928 } else { |
929 __ jmp(&done, Label::kNear); | 929 __ jmp(&done, Label::kNear); |
930 } | 930 } |
931 __ bind(&positive_dividend); | 931 __ bind(&positive_dividend); |
932 __ and_(dividend, divisor - 1); | 932 __ and_(dividend, divisor - 1); |
933 __ bind(&done); | 933 __ bind(&done); |
934 } else { | 934 } else { |
935 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; | 935 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; |
936 Register left_reg = ToRegister(instr->InputAt(0)); | 936 Register left_reg = ToRegister(instr->left()); |
937 Register right_reg = ToRegister(instr->InputAt(1)); | 937 Register right_reg = ToRegister(instr->right()); |
938 Register result_reg = ToRegister(instr->result()); | 938 Register result_reg = ToRegister(instr->result()); |
939 | 939 |
940 ASSERT(left_reg.is(eax)); | 940 ASSERT(left_reg.is(eax)); |
941 ASSERT(result_reg.is(edx)); | 941 ASSERT(result_reg.is(edx)); |
942 ASSERT(!right_reg.is(eax)); | 942 ASSERT(!right_reg.is(eax)); |
943 ASSERT(!right_reg.is(edx)); | 943 ASSERT(!right_reg.is(edx)); |
944 | 944 |
945 // Check for x % 0. | 945 // Check for x % 0. |
946 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 946 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
947 __ test(right_reg, Operand(right_reg)); | 947 __ test(right_reg, Operand(right_reg)); |
948 DeoptimizeIf(zero, instr->environment()); | 948 DeoptimizeIf(zero, instr->environment()); |
949 } | 949 } |
950 | 950 |
951 __ test(left_reg, Operand(left_reg)); | 951 __ test(left_reg, Operand(left_reg)); |
952 __ j(zero, &remainder_eq_dividend, Label::kNear); | 952 __ j(zero, &remainder_eq_dividend, Label::kNear); |
953 __ j(sign, &slow, Label::kNear); | 953 __ j(sign, &slow, Label::kNear); |
954 | 954 |
955 __ test(right_reg, Operand(right_reg)); | 955 __ test(right_reg, Operand(right_reg)); |
956 __ j(not_sign, &both_positive, Label::kNear); | 956 __ j(not_sign, &both_positive, Label::kNear); |
957 // The sign of the divisor doesn't matter. | 957 // The sign of the divisor doesn't matter. |
958 __ neg(right_reg); | 958 __ neg(right_reg); |
959 | 959 |
960 __ bind(&both_positive); | 960 __ bind(&both_positive); |
961 // If the dividend is smaller than the nonnegative | 961 // If the dividend is smaller than the nonnegative |
962 // divisor, the dividend is the result. | 962 // divisor, the dividend is the result. |
963 __ cmp(left_reg, Operand(right_reg)); | 963 __ cmp(left_reg, Operand(right_reg)); |
964 __ j(less, &remainder_eq_dividend, Label::kNear); | 964 __ j(less, &remainder_eq_dividend, Label::kNear); |
965 | 965 |
966 // Check if the divisor is a PowerOfTwo integer. | 966 // Check if the divisor is a PowerOfTwo integer. |
967 Register scratch = ToRegister(instr->TempAt(0)); | 967 Register scratch = ToRegister(instr->temp()); |
968 __ mov(scratch, right_reg); | 968 __ mov(scratch, right_reg); |
969 __ sub(Operand(scratch), Immediate(1)); | 969 __ sub(Operand(scratch), Immediate(1)); |
970 __ test(scratch, Operand(right_reg)); | 970 __ test(scratch, Operand(right_reg)); |
971 __ j(not_zero, &do_subtraction, Label::kNear); | 971 __ j(not_zero, &do_subtraction, Label::kNear); |
972 __ and_(left_reg, Operand(scratch)); | 972 __ and_(left_reg, Operand(scratch)); |
973 __ jmp(&remainder_eq_dividend, Label::kNear); | 973 __ jmp(&remainder_eq_dividend, Label::kNear); |
974 | 974 |
975 __ bind(&do_subtraction); | 975 __ bind(&do_subtraction); |
976 const int kUnfolds = 3; | 976 const int kUnfolds = 3; |
977 // Try a few subtractions of the dividend. | 977 // Try a few subtractions of the dividend. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 | 1013 |
1014 __ bind(&remainder_eq_dividend); | 1014 __ bind(&remainder_eq_dividend); |
1015 __ mov(result_reg, left_reg); | 1015 __ mov(result_reg, left_reg); |
1016 | 1016 |
1017 __ bind(&done); | 1017 __ bind(&done); |
1018 } | 1018 } |
1019 } | 1019 } |
1020 | 1020 |
1021 | 1021 |
1022 void LCodeGen::DoDivI(LDivI* instr) { | 1022 void LCodeGen::DoDivI(LDivI* instr) { |
1023 LOperand* right = instr->InputAt(1); | 1023 LOperand* right = instr->right(); |
1024 ASSERT(ToRegister(instr->result()).is(eax)); | 1024 ASSERT(ToRegister(instr->result()).is(eax)); |
1025 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 1025 ASSERT(ToRegister(instr->left()).is(eax)); |
1026 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); | 1026 ASSERT(!ToRegister(instr->right()).is(eax)); |
1027 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); | 1027 ASSERT(!ToRegister(instr->right()).is(edx)); |
1028 | 1028 |
1029 Register left_reg = eax; | 1029 Register left_reg = eax; |
1030 | 1030 |
1031 // Check for x / 0. | 1031 // Check for x / 0. |
1032 Register right_reg = ToRegister(right); | 1032 Register right_reg = ToRegister(right); |
1033 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1033 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
1034 __ test(right_reg, ToOperand(right)); | 1034 __ test(right_reg, ToOperand(right)); |
1035 DeoptimizeIf(zero, instr->environment()); | 1035 DeoptimizeIf(zero, instr->environment()); |
1036 } | 1036 } |
1037 | 1037 |
(...skipping 21 matching lines...) Expand all Loading... |
1059 __ cdq(); | 1059 __ cdq(); |
1060 __ idiv(right_reg); | 1060 __ idiv(right_reg); |
1061 | 1061 |
1062 // Deoptimize if remainder is not 0. | 1062 // Deoptimize if remainder is not 0. |
1063 __ test(edx, Operand(edx)); | 1063 __ test(edx, Operand(edx)); |
1064 DeoptimizeIf(not_zero, instr->environment()); | 1064 DeoptimizeIf(not_zero, instr->environment()); |
1065 } | 1065 } |
1066 | 1066 |
1067 | 1067 |
1068 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { | 1068 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { |
1069 ASSERT(instr->InputAt(1)->IsConstantOperand()); | 1069 ASSERT(instr->right()->IsConstantOperand()); |
1070 | 1070 |
1071 Register dividend = ToRegister(instr->InputAt(0)); | 1071 Register dividend = ToRegister(instr->left()); |
1072 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->InputAt(1))); | 1072 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); |
1073 Register result = ToRegister(instr->result()); | 1073 Register result = ToRegister(instr->result()); |
1074 | 1074 |
1075 switch (divisor) { | 1075 switch (divisor) { |
1076 case 0: | 1076 case 0: |
1077 DeoptimizeIf(no_condition, instr->environment()); | 1077 DeoptimizeIf(no_condition, instr->environment()); |
1078 return; | 1078 return; |
1079 | 1079 |
1080 case 1: | 1080 case 1: |
1081 __ Move(result, dividend); | 1081 __ Move(result, dividend); |
1082 return; | 1082 return; |
(...skipping 25 matching lines...) Expand all Loading... |
1108 __ shl(dividend, 32 - power); | 1108 __ shl(dividend, 32 - power); |
1109 __ sar(result, power); | 1109 __ sar(result, power); |
1110 __ not_(dividend); | 1110 __ not_(dividend); |
1111 // Clear result.sign if dividend.sign is set. | 1111 // Clear result.sign if dividend.sign is set. |
1112 __ and_(result, dividend); | 1112 __ and_(result, dividend); |
1113 } else { | 1113 } else { |
1114 __ Move(result, dividend); | 1114 __ Move(result, dividend); |
1115 __ sar(result, power); | 1115 __ sar(result, power); |
1116 } | 1116 } |
1117 } else { | 1117 } else { |
1118 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 1118 ASSERT(ToRegister(instr->left()).is(eax)); |
1119 ASSERT(ToRegister(instr->result()).is(edx)); | 1119 ASSERT(ToRegister(instr->result()).is(edx)); |
1120 Register scratch = ToRegister(instr->TempAt(0)); | 1120 Register scratch = ToRegister(instr->temp()); |
1121 | 1121 |
1122 // Find b which: 2^b < divisor_abs < 2^(b+1). | 1122 // Find b which: 2^b < divisor_abs < 2^(b+1). |
1123 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); | 1123 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); |
1124 unsigned shift = 32 + b; // Precision +1bit (effectively). | 1124 unsigned shift = 32 + b; // Precision +1bit (effectively). |
1125 double multiplier_f = | 1125 double multiplier_f = |
1126 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; | 1126 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; |
1127 int64_t multiplier; | 1127 int64_t multiplier; |
1128 if (multiplier_f - floor(multiplier_f) < 0.5) { | 1128 if (multiplier_f - floor(multiplier_f) < 0.5) { |
1129 multiplier = static_cast<int64_t>(floor(multiplier_f)); | 1129 multiplier = static_cast<int64_t>(floor(multiplier_f)); |
1130 } else { | 1130 } else { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 __ cmp(reg_lo, 0xC0000000); | 1162 __ cmp(reg_lo, 0xC0000000); |
1163 __ setcc(above_equal, reg_byte_scratch); | 1163 __ setcc(above_equal, reg_byte_scratch); |
1164 __ add(edx, reg_byte_scratch); | 1164 __ add(edx, reg_byte_scratch); |
1165 } | 1165 } |
1166 __ sar(edx, shift - 32); | 1166 __ sar(edx, shift - 32); |
1167 } | 1167 } |
1168 } | 1168 } |
1169 | 1169 |
1170 | 1170 |
1171 void LCodeGen::DoMulI(LMulI* instr) { | 1171 void LCodeGen::DoMulI(LMulI* instr) { |
1172 Register left = ToRegister(instr->InputAt(0)); | 1172 Register left = ToRegister(instr->left()); |
1173 LOperand* right = instr->InputAt(1); | 1173 LOperand* right = instr->right(); |
1174 | 1174 |
1175 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1175 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1176 __ mov(ToRegister(instr->TempAt(0)), left); | 1176 __ mov(ToRegister(instr->temp()), left); |
1177 } | 1177 } |
1178 | 1178 |
1179 if (right->IsConstantOperand()) { | 1179 if (right->IsConstantOperand()) { |
1180 // Try strength reductions on the multiplication. | 1180 // Try strength reductions on the multiplication. |
1181 // All replacement instructions are at most as long as the imul | 1181 // All replacement instructions are at most as long as the imul |
1182 // and have better latency. | 1182 // and have better latency. |
1183 int constant = ToInteger32(LConstantOperand::cast(right)); | 1183 int constant = ToInteger32(LConstantOperand::cast(right)); |
1184 if (constant == -1) { | 1184 if (constant == -1) { |
1185 __ neg(left); | 1185 __ neg(left); |
1186 } else if (constant == 0) { | 1186 } else if (constant == 0) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1232 // Bail out if the result is supposed to be negative zero. | 1232 // Bail out if the result is supposed to be negative zero. |
1233 Label done; | 1233 Label done; |
1234 __ test(left, Operand(left)); | 1234 __ test(left, Operand(left)); |
1235 __ j(not_zero, &done, Label::kNear); | 1235 __ j(not_zero, &done, Label::kNear); |
1236 if (right->IsConstantOperand()) { | 1236 if (right->IsConstantOperand()) { |
1237 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { | 1237 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { |
1238 DeoptimizeIf(no_condition, instr->environment()); | 1238 DeoptimizeIf(no_condition, instr->environment()); |
1239 } | 1239 } |
1240 } else { | 1240 } else { |
1241 // Test the non-zero operand for negative sign. | 1241 // Test the non-zero operand for negative sign. |
1242 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); | 1242 __ or_(ToRegister(instr->temp()), ToOperand(right)); |
1243 DeoptimizeIf(sign, instr->environment()); | 1243 DeoptimizeIf(sign, instr->environment()); |
1244 } | 1244 } |
1245 __ bind(&done); | 1245 __ bind(&done); |
1246 } | 1246 } |
1247 } | 1247 } |
1248 | 1248 |
1249 | 1249 |
1250 void LCodeGen::DoBitI(LBitI* instr) { | 1250 void LCodeGen::DoBitI(LBitI* instr) { |
1251 LOperand* left = instr->InputAt(0); | 1251 LOperand* left = instr->left(); |
1252 LOperand* right = instr->InputAt(1); | 1252 LOperand* right = instr->right(); |
1253 ASSERT(left->Equals(instr->result())); | 1253 ASSERT(left->Equals(instr->result())); |
1254 ASSERT(left->IsRegister()); | 1254 ASSERT(left->IsRegister()); |
1255 | 1255 |
1256 if (right->IsConstantOperand()) { | 1256 if (right->IsConstantOperand()) { |
1257 int right_operand = ToInteger32(LConstantOperand::cast(right)); | 1257 int right_operand = ToInteger32(LConstantOperand::cast(right)); |
1258 switch (instr->op()) { | 1258 switch (instr->op()) { |
1259 case Token::BIT_AND: | 1259 case Token::BIT_AND: |
1260 __ and_(ToRegister(left), right_operand); | 1260 __ and_(ToRegister(left), right_operand); |
1261 break; | 1261 break; |
1262 case Token::BIT_OR: | 1262 case Token::BIT_OR: |
(...skipping 19 matching lines...) Expand all Loading... |
1282 break; | 1282 break; |
1283 default: | 1283 default: |
1284 UNREACHABLE(); | 1284 UNREACHABLE(); |
1285 break; | 1285 break; |
1286 } | 1286 } |
1287 } | 1287 } |
1288 } | 1288 } |
1289 | 1289 |
1290 | 1290 |
1291 void LCodeGen::DoShiftI(LShiftI* instr) { | 1291 void LCodeGen::DoShiftI(LShiftI* instr) { |
1292 LOperand* left = instr->InputAt(0); | 1292 LOperand* left = instr->left(); |
1293 LOperand* right = instr->InputAt(1); | 1293 LOperand* right = instr->right(); |
1294 ASSERT(left->Equals(instr->result())); | 1294 ASSERT(left->Equals(instr->result())); |
1295 ASSERT(left->IsRegister()); | 1295 ASSERT(left->IsRegister()); |
1296 if (right->IsRegister()) { | 1296 if (right->IsRegister()) { |
1297 ASSERT(ToRegister(right).is(ecx)); | 1297 ASSERT(ToRegister(right).is(ecx)); |
1298 | 1298 |
1299 switch (instr->op()) { | 1299 switch (instr->op()) { |
1300 case Token::SAR: | 1300 case Token::SAR: |
1301 __ sar_cl(ToRegister(left)); | 1301 __ sar_cl(ToRegister(left)); |
1302 break; | 1302 break; |
1303 case Token::SHR: | 1303 case Token::SHR: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1338 break; | 1338 break; |
1339 default: | 1339 default: |
1340 UNREACHABLE(); | 1340 UNREACHABLE(); |
1341 break; | 1341 break; |
1342 } | 1342 } |
1343 } | 1343 } |
1344 } | 1344 } |
1345 | 1345 |
1346 | 1346 |
1347 void LCodeGen::DoSubI(LSubI* instr) { | 1347 void LCodeGen::DoSubI(LSubI* instr) { |
1348 LOperand* left = instr->InputAt(0); | 1348 LOperand* left = instr->left(); |
1349 LOperand* right = instr->InputAt(1); | 1349 LOperand* right = instr->right(); |
1350 ASSERT(left->Equals(instr->result())); | 1350 ASSERT(left->Equals(instr->result())); |
1351 | 1351 |
1352 if (right->IsConstantOperand()) { | 1352 if (right->IsConstantOperand()) { |
1353 __ sub(ToOperand(left), ToInteger32Immediate(right)); | 1353 __ sub(ToOperand(left), ToInteger32Immediate(right)); |
1354 } else { | 1354 } else { |
1355 __ sub(ToRegister(left), ToOperand(right)); | 1355 __ sub(ToRegister(left), ToOperand(right)); |
1356 } | 1356 } |
1357 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1357 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1358 DeoptimizeIf(overflow, instr->environment()); | 1358 DeoptimizeIf(overflow, instr->environment()); |
1359 } | 1359 } |
1360 } | 1360 } |
1361 | 1361 |
1362 | 1362 |
1363 void LCodeGen::DoConstantI(LConstantI* instr) { | 1363 void LCodeGen::DoConstantI(LConstantI* instr) { |
1364 ASSERT(instr->result()->IsRegister()); | 1364 ASSERT(instr->result()->IsRegister()); |
1365 __ Set(ToRegister(instr->result()), Immediate(instr->value())); | 1365 __ Set(ToRegister(instr->result()), Immediate(instr->value())); |
1366 } | 1366 } |
1367 | 1367 |
1368 | 1368 |
1369 void LCodeGen::DoConstantD(LConstantD* instr) { | 1369 void LCodeGen::DoConstantD(LConstantD* instr) { |
1370 ASSERT(instr->result()->IsDoubleRegister()); | 1370 ASSERT(instr->result()->IsDoubleRegister()); |
1371 XMMRegister res = ToDoubleRegister(instr->result()); | 1371 XMMRegister res = ToDoubleRegister(instr->result()); |
1372 double v = instr->value(); | 1372 double v = instr->value(); |
1373 // Use xor to produce +0.0 in a fast and compact way, but avoid to | 1373 // Use xor to produce +0.0 in a fast and compact way, but avoid to |
1374 // do so if the constant is -0.0. | 1374 // do so if the constant is -0.0. |
1375 if (BitCast<uint64_t, double>(v) == 0) { | 1375 if (BitCast<uint64_t, double>(v) == 0) { |
1376 __ xorps(res, res); | 1376 __ xorps(res, res); |
1377 } else { | 1377 } else { |
1378 Register temp = ToRegister(instr->TempAt(0)); | 1378 Register temp = ToRegister(instr->temp()); |
1379 uint64_t int_val = BitCast<uint64_t, double>(v); | 1379 uint64_t int_val = BitCast<uint64_t, double>(v); |
1380 int32_t lower = static_cast<int32_t>(int_val); | 1380 int32_t lower = static_cast<int32_t>(int_val); |
1381 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | 1381 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); |
1382 if (CpuFeatures::IsSupported(SSE4_1)) { | 1382 if (CpuFeatures::IsSupported(SSE4_1)) { |
1383 CpuFeatures::Scope scope(SSE4_1); | 1383 CpuFeatures::Scope scope(SSE4_1); |
1384 if (lower != 0) { | 1384 if (lower != 0) { |
1385 __ Set(temp, Immediate(lower)); | 1385 __ Set(temp, Immediate(lower)); |
1386 __ movd(res, Operand(temp)); | 1386 __ movd(res, Operand(temp)); |
1387 __ Set(temp, Immediate(upper)); | 1387 __ Set(temp, Immediate(upper)); |
1388 __ pinsrd(res, Operand(temp), 1); | 1388 __ pinsrd(res, Operand(temp), 1); |
(...skipping 22 matching lines...) Expand all Loading... |
1411 if (handle->IsHeapObject()) { | 1411 if (handle->IsHeapObject()) { |
1412 __ LoadHeapObject(reg, Handle<HeapObject>::cast(handle)); | 1412 __ LoadHeapObject(reg, Handle<HeapObject>::cast(handle)); |
1413 } else { | 1413 } else { |
1414 __ Set(reg, Immediate(handle)); | 1414 __ Set(reg, Immediate(handle)); |
1415 } | 1415 } |
1416 } | 1416 } |
1417 | 1417 |
1418 | 1418 |
1419 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1419 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
1420 Register result = ToRegister(instr->result()); | 1420 Register result = ToRegister(instr->result()); |
1421 Register array = ToRegister(instr->InputAt(0)); | 1421 Register array = ToRegister(instr->value()); |
1422 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); | 1422 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); |
1423 } | 1423 } |
1424 | 1424 |
1425 | 1425 |
1426 void LCodeGen::DoFixedArrayBaseLength( | 1426 void LCodeGen::DoFixedArrayBaseLength( |
1427 LFixedArrayBaseLength* instr) { | 1427 LFixedArrayBaseLength* instr) { |
1428 Register result = ToRegister(instr->result()); | 1428 Register result = ToRegister(instr->result()); |
1429 Register array = ToRegister(instr->InputAt(0)); | 1429 Register array = ToRegister(instr->value()); |
1430 __ mov(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); | 1430 __ mov(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); |
1431 } | 1431 } |
1432 | 1432 |
1433 | 1433 |
1434 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1434 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
1435 Register result = ToRegister(instr->result()); | 1435 Register result = ToRegister(instr->result()); |
1436 Register map = ToRegister(instr->InputAt(0)); | 1436 Register map = ToRegister(instr->value()); |
1437 __ EnumLength(result, map); | 1437 __ EnumLength(result, map); |
1438 } | 1438 } |
1439 | 1439 |
1440 | 1440 |
1441 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1441 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
1442 Register result = ToRegister(instr->result()); | 1442 Register result = ToRegister(instr->result()); |
1443 Register input = ToRegister(instr->InputAt(0)); | 1443 Register input = ToRegister(instr->value()); |
1444 | 1444 |
1445 // Load map into |result|. | 1445 // Load map into |result|. |
1446 __ mov(result, FieldOperand(input, HeapObject::kMapOffset)); | 1446 __ mov(result, FieldOperand(input, HeapObject::kMapOffset)); |
1447 // Load the map's "bit field 2" into |result|. We only need the first byte, | 1447 // Load the map's "bit field 2" into |result|. We only need the first byte, |
1448 // but the following masking takes care of that anyway. | 1448 // but the following masking takes care of that anyway. |
1449 __ mov(result, FieldOperand(result, Map::kBitField2Offset)); | 1449 __ mov(result, FieldOperand(result, Map::kBitField2Offset)); |
1450 // Retrieve elements_kind from bit field 2. | 1450 // Retrieve elements_kind from bit field 2. |
1451 __ and_(result, Map::kElementsKindMask); | 1451 __ and_(result, Map::kElementsKindMask); |
1452 __ shr(result, Map::kElementsKindShift); | 1452 __ shr(result, Map::kElementsKindShift); |
1453 } | 1453 } |
1454 | 1454 |
1455 | 1455 |
1456 void LCodeGen::DoValueOf(LValueOf* instr) { | 1456 void LCodeGen::DoValueOf(LValueOf* instr) { |
1457 Register input = ToRegister(instr->InputAt(0)); | 1457 Register input = ToRegister(instr->value()); |
1458 Register result = ToRegister(instr->result()); | 1458 Register result = ToRegister(instr->result()); |
1459 Register map = ToRegister(instr->TempAt(0)); | 1459 Register map = ToRegister(instr->temp()); |
1460 ASSERT(input.is(result)); | 1460 ASSERT(input.is(result)); |
1461 | 1461 |
1462 Label done; | 1462 Label done; |
1463 // If the object is a smi return the object. | 1463 // If the object is a smi return the object. |
1464 __ JumpIfSmi(input, &done, Label::kNear); | 1464 __ JumpIfSmi(input, &done, Label::kNear); |
1465 | 1465 |
1466 // If the object is not a value type, return the object. | 1466 // If the object is not a value type, return the object. |
1467 __ CmpObjectType(input, JS_VALUE_TYPE, map); | 1467 __ CmpObjectType(input, JS_VALUE_TYPE, map); |
1468 __ j(not_equal, &done, Label::kNear); | 1468 __ j(not_equal, &done, Label::kNear); |
1469 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); | 1469 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); |
1470 | 1470 |
1471 __ bind(&done); | 1471 __ bind(&done); |
1472 } | 1472 } |
1473 | 1473 |
1474 | 1474 |
1475 void LCodeGen::DoDateField(LDateField* instr) { | 1475 void LCodeGen::DoDateField(LDateField* instr) { |
1476 Register object = ToRegister(instr->InputAt(0)); | 1476 Register object = ToRegister(instr->date()); |
1477 Register result = ToRegister(instr->result()); | 1477 Register result = ToRegister(instr->result()); |
1478 Register scratch = ToRegister(instr->TempAt(0)); | 1478 Register scratch = ToRegister(instr->temp()); |
1479 Smi* index = instr->index(); | 1479 Smi* index = instr->index(); |
1480 Label runtime, done; | 1480 Label runtime, done; |
1481 ASSERT(object.is(result)); | 1481 ASSERT(object.is(result)); |
1482 ASSERT(object.is(eax)); | 1482 ASSERT(object.is(eax)); |
1483 | 1483 |
1484 __ test(object, Immediate(kSmiTagMask)); | 1484 __ test(object, Immediate(kSmiTagMask)); |
1485 DeoptimizeIf(zero, instr->environment()); | 1485 DeoptimizeIf(zero, instr->environment()); |
1486 __ CmpObjectType(object, JS_DATE_TYPE, scratch); | 1486 __ CmpObjectType(object, JS_DATE_TYPE, scratch); |
1487 DeoptimizeIf(not_equal, instr->environment()); | 1487 DeoptimizeIf(not_equal, instr->environment()); |
1488 | 1488 |
(...skipping 13 matching lines...) Expand all Loading... |
1502 __ PrepareCallCFunction(2, scratch); | 1502 __ PrepareCallCFunction(2, scratch); |
1503 __ mov(Operand(esp, 0), object); | 1503 __ mov(Operand(esp, 0), object); |
1504 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); | 1504 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); |
1505 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 1505 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
1506 __ bind(&done); | 1506 __ bind(&done); |
1507 } | 1507 } |
1508 } | 1508 } |
1509 | 1509 |
1510 | 1510 |
1511 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1511 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1512 LOperand* input = instr->InputAt(0); | 1512 LOperand* input = instr->value(); |
1513 ASSERT(input->Equals(instr->result())); | 1513 ASSERT(input->Equals(instr->result())); |
1514 __ not_(ToRegister(input)); | 1514 __ not_(ToRegister(input)); |
1515 } | 1515 } |
1516 | 1516 |
1517 | 1517 |
1518 void LCodeGen::DoThrow(LThrow* instr) { | 1518 void LCodeGen::DoThrow(LThrow* instr) { |
1519 __ push(ToOperand(instr->value())); | 1519 __ push(ToOperand(instr->value())); |
1520 ASSERT(ToRegister(instr->context()).is(esi)); | 1520 ASSERT(ToRegister(instr->context()).is(esi)); |
1521 CallRuntime(Runtime::kThrow, 1, instr); | 1521 CallRuntime(Runtime::kThrow, 1, instr); |
1522 | 1522 |
1523 if (FLAG_debug_code) { | 1523 if (FLAG_debug_code) { |
1524 Comment("Unreachable code."); | 1524 Comment("Unreachable code."); |
1525 __ int3(); | 1525 __ int3(); |
1526 } | 1526 } |
1527 } | 1527 } |
1528 | 1528 |
1529 | 1529 |
1530 void LCodeGen::DoAddI(LAddI* instr) { | 1530 void LCodeGen::DoAddI(LAddI* instr) { |
1531 LOperand* left = instr->InputAt(0); | 1531 LOperand* left = instr->left(); |
1532 LOperand* right = instr->InputAt(1); | 1532 LOperand* right = instr->right(); |
1533 ASSERT(left->Equals(instr->result())); | 1533 ASSERT(left->Equals(instr->result())); |
1534 | 1534 |
1535 if (right->IsConstantOperand()) { | 1535 if (right->IsConstantOperand()) { |
1536 __ add(ToOperand(left), ToInteger32Immediate(right)); | 1536 __ add(ToOperand(left), ToInteger32Immediate(right)); |
1537 } else { | 1537 } else { |
1538 __ add(ToRegister(left), ToOperand(right)); | 1538 __ add(ToRegister(left), ToOperand(right)); |
1539 } | 1539 } |
1540 | 1540 |
1541 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1541 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1542 DeoptimizeIf(overflow, instr->environment()); | 1542 DeoptimizeIf(overflow, instr->environment()); |
1543 } | 1543 } |
1544 } | 1544 } |
1545 | 1545 |
1546 | 1546 |
1547 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1547 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
1548 LOperand* left = instr->InputAt(0); | 1548 LOperand* left = instr->left(); |
1549 LOperand* right = instr->InputAt(1); | 1549 LOperand* right = instr->right(); |
1550 ASSERT(left->Equals(instr->result())); | 1550 ASSERT(left->Equals(instr->result())); |
1551 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1551 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
1552 if (instr->hydrogen()->representation().IsInteger32()) { | 1552 if (instr->hydrogen()->representation().IsInteger32()) { |
1553 Label return_left; | 1553 Label return_left; |
1554 Condition condition = (operation == HMathMinMax::kMathMin) | 1554 Condition condition = (operation == HMathMinMax::kMathMin) |
1555 ? less_equal | 1555 ? less_equal |
1556 : greater_equal; | 1556 : greater_equal; |
1557 if (right->IsConstantOperand()) { | 1557 if (right->IsConstantOperand()) { |
1558 Operand left_op = ToOperand(left); | 1558 Operand left_op = ToOperand(left); |
1559 Immediate right_imm = ToInteger32Immediate(right); | 1559 Immediate right_imm = ToInteger32Immediate(right); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1599 __ j(parity_even, &return_left, Label::kNear); // left == NaN. | 1599 __ j(parity_even, &return_left, Label::kNear); // left == NaN. |
1600 __ bind(&return_right); | 1600 __ bind(&return_right); |
1601 __ movsd(left_reg, right_reg); | 1601 __ movsd(left_reg, right_reg); |
1602 | 1602 |
1603 __ bind(&return_left); | 1603 __ bind(&return_left); |
1604 } | 1604 } |
1605 } | 1605 } |
1606 | 1606 |
1607 | 1607 |
1608 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1608 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
1609 XMMRegister left = ToDoubleRegister(instr->InputAt(0)); | 1609 XMMRegister left = ToDoubleRegister(instr->left()); |
1610 XMMRegister right = ToDoubleRegister(instr->InputAt(1)); | 1610 XMMRegister right = ToDoubleRegister(instr->right()); |
1611 XMMRegister result = ToDoubleRegister(instr->result()); | 1611 XMMRegister result = ToDoubleRegister(instr->result()); |
1612 // Modulo uses a fixed result register. | 1612 // Modulo uses a fixed result register. |
1613 ASSERT(instr->op() == Token::MOD || left.is(result)); | 1613 ASSERT(instr->op() == Token::MOD || left.is(result)); |
1614 switch (instr->op()) { | 1614 switch (instr->op()) { |
1615 case Token::ADD: | 1615 case Token::ADD: |
1616 __ addsd(left, right); | 1616 __ addsd(left, right); |
1617 break; | 1617 break; |
1618 case Token::SUB: | 1618 case Token::SUB: |
1619 __ subsd(left, right); | 1619 __ subsd(left, right); |
1620 break; | 1620 break; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1686 } | 1686 } |
1687 } | 1687 } |
1688 | 1688 |
1689 | 1689 |
1690 void LCodeGen::DoBranch(LBranch* instr) { | 1690 void LCodeGen::DoBranch(LBranch* instr) { |
1691 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1691 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1692 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1692 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1693 | 1693 |
1694 Representation r = instr->hydrogen()->value()->representation(); | 1694 Representation r = instr->hydrogen()->value()->representation(); |
1695 if (r.IsInteger32()) { | 1695 if (r.IsInteger32()) { |
1696 Register reg = ToRegister(instr->InputAt(0)); | 1696 Register reg = ToRegister(instr->value()); |
1697 __ test(reg, Operand(reg)); | 1697 __ test(reg, Operand(reg)); |
1698 EmitBranch(true_block, false_block, not_zero); | 1698 EmitBranch(true_block, false_block, not_zero); |
1699 } else if (r.IsDouble()) { | 1699 } else if (r.IsDouble()) { |
1700 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1700 XMMRegister reg = ToDoubleRegister(instr->value()); |
1701 __ xorps(xmm0, xmm0); | 1701 __ xorps(xmm0, xmm0); |
1702 __ ucomisd(reg, xmm0); | 1702 __ ucomisd(reg, xmm0); |
1703 EmitBranch(true_block, false_block, not_equal); | 1703 EmitBranch(true_block, false_block, not_equal); |
1704 } else { | 1704 } else { |
1705 ASSERT(r.IsTagged()); | 1705 ASSERT(r.IsTagged()); |
1706 Register reg = ToRegister(instr->InputAt(0)); | 1706 Register reg = ToRegister(instr->value()); |
1707 HType type = instr->hydrogen()->value()->type(); | 1707 HType type = instr->hydrogen()->value()->type(); |
1708 if (type.IsBoolean()) { | 1708 if (type.IsBoolean()) { |
1709 __ cmp(reg, factory()->true_value()); | 1709 __ cmp(reg, factory()->true_value()); |
1710 EmitBranch(true_block, false_block, equal); | 1710 EmitBranch(true_block, false_block, equal); |
1711 } else if (type.IsSmi()) { | 1711 } else if (type.IsSmi()) { |
1712 __ test(reg, Operand(reg)); | 1712 __ test(reg, Operand(reg)); |
1713 EmitBranch(true_block, false_block, not_equal); | 1713 EmitBranch(true_block, false_block, not_equal); |
1714 } else { | 1714 } else { |
1715 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1715 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1716 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1716 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
(...skipping 27 matching lines...) Expand all Loading... |
1744 __ j(equal, false_label); | 1744 __ j(equal, false_label); |
1745 __ JumpIfSmi(reg, true_label); | 1745 __ JumpIfSmi(reg, true_label); |
1746 } else if (expected.NeedsMap()) { | 1746 } else if (expected.NeedsMap()) { |
1747 // If we need a map later and have a Smi -> deopt. | 1747 // If we need a map later and have a Smi -> deopt. |
1748 __ test(reg, Immediate(kSmiTagMask)); | 1748 __ test(reg, Immediate(kSmiTagMask)); |
1749 DeoptimizeIf(zero, instr->environment()); | 1749 DeoptimizeIf(zero, instr->environment()); |
1750 } | 1750 } |
1751 | 1751 |
1752 Register map = no_reg; // Keep the compiler happy. | 1752 Register map = no_reg; // Keep the compiler happy. |
1753 if (expected.NeedsMap()) { | 1753 if (expected.NeedsMap()) { |
1754 map = ToRegister(instr->TempAt(0)); | 1754 map = ToRegister(instr->temp()); |
1755 ASSERT(!map.is(reg)); | 1755 ASSERT(!map.is(reg)); |
1756 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | 1756 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
1757 | 1757 |
1758 if (expected.CanBeUndetectable()) { | 1758 if (expected.CanBeUndetectable()) { |
1759 // Undetectable -> false. | 1759 // Undetectable -> false. |
1760 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | 1760 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
1761 1 << Map::kIsUndetectable); | 1761 1 << Map::kIsUndetectable); |
1762 __ j(not_zero, false_label); | 1762 __ j(not_zero, false_label); |
1763 } | 1763 } |
1764 } | 1764 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1837 case Token::IN: | 1837 case Token::IN: |
1838 case Token::INSTANCEOF: | 1838 case Token::INSTANCEOF: |
1839 default: | 1839 default: |
1840 UNREACHABLE(); | 1840 UNREACHABLE(); |
1841 } | 1841 } |
1842 return cond; | 1842 return cond; |
1843 } | 1843 } |
1844 | 1844 |
1845 | 1845 |
1846 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1846 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
1847 LOperand* left = instr->InputAt(0); | 1847 LOperand* left = instr->left(); |
1848 LOperand* right = instr->InputAt(1); | 1848 LOperand* right = instr->right(); |
1849 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1849 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1850 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1850 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1851 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1851 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1852 | 1852 |
1853 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 1853 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
1854 // We can statically evaluate the comparison. | 1854 // We can statically evaluate the comparison. |
1855 double left_val = ToDouble(LConstantOperand::cast(left)); | 1855 double left_val = ToDouble(LConstantOperand::cast(left)); |
1856 double right_val = ToDouble(LConstantOperand::cast(right)); | 1856 double right_val = ToDouble(LConstantOperand::cast(right)); |
1857 int next_block = | 1857 int next_block = |
1858 EvalComparison(instr->op(), left_val, right_val) ? true_block | 1858 EvalComparison(instr->op(), left_val, right_val) ? true_block |
(...skipping 15 matching lines...) Expand all Loading... |
1874 } else { | 1874 } else { |
1875 __ cmp(ToRegister(left), ToOperand(right)); | 1875 __ cmp(ToRegister(left), ToOperand(right)); |
1876 } | 1876 } |
1877 } | 1877 } |
1878 EmitBranch(true_block, false_block, cc); | 1878 EmitBranch(true_block, false_block, cc); |
1879 } | 1879 } |
1880 } | 1880 } |
1881 | 1881 |
1882 | 1882 |
1883 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 1883 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
1884 Register left = ToRegister(instr->InputAt(0)); | 1884 Register left = ToRegister(instr->left()); |
1885 Operand right = ToOperand(instr->InputAt(1)); | 1885 Operand right = ToOperand(instr->right()); |
1886 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1886 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1887 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1887 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1888 | 1888 |
1889 __ cmp(left, Operand(right)); | 1889 __ cmp(left, Operand(right)); |
1890 EmitBranch(true_block, false_block, equal); | 1890 EmitBranch(true_block, false_block, equal); |
1891 } | 1891 } |
1892 | 1892 |
1893 | 1893 |
1894 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 1894 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
1895 Register left = ToRegister(instr->InputAt(0)); | 1895 Register left = ToRegister(instr->left()); |
1896 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1896 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1897 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1897 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1898 | 1898 |
1899 __ cmp(left, instr->hydrogen()->right()); | 1899 __ cmp(left, instr->hydrogen()->right()); |
1900 EmitBranch(true_block, false_block, equal); | 1900 EmitBranch(true_block, false_block, equal); |
1901 } | 1901 } |
1902 | 1902 |
1903 | 1903 |
1904 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { | 1904 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { |
1905 Register reg = ToRegister(instr->InputAt(0)); | 1905 Register reg = ToRegister(instr->value()); |
1906 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1906 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1907 | 1907 |
1908 // If the expression is known to be untagged or a smi, then it's definitely | 1908 // If the expression is known to be untagged or a smi, then it's definitely |
1909 // not null, and it can't be a an undetectable object. | 1909 // not null, and it can't be a an undetectable object. |
1910 if (instr->hydrogen()->representation().IsSpecialization() || | 1910 if (instr->hydrogen()->representation().IsSpecialization() || |
1911 instr->hydrogen()->type().IsSmi()) { | 1911 instr->hydrogen()->type().IsSmi()) { |
1912 EmitGoto(false_block); | 1912 EmitGoto(false_block); |
1913 return; | 1913 return; |
1914 } | 1914 } |
1915 | 1915 |
1916 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1916 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1917 Handle<Object> nil_value = instr->nil() == kNullValue ? | 1917 Handle<Object> nil_value = instr->nil() == kNullValue ? |
1918 factory()->null_value() : | 1918 factory()->null_value() : |
1919 factory()->undefined_value(); | 1919 factory()->undefined_value(); |
1920 __ cmp(reg, nil_value); | 1920 __ cmp(reg, nil_value); |
1921 if (instr->kind() == kStrictEquality) { | 1921 if (instr->kind() == kStrictEquality) { |
1922 EmitBranch(true_block, false_block, equal); | 1922 EmitBranch(true_block, false_block, equal); |
1923 } else { | 1923 } else { |
1924 Handle<Object> other_nil_value = instr->nil() == kNullValue ? | 1924 Handle<Object> other_nil_value = instr->nil() == kNullValue ? |
1925 factory()->undefined_value() : | 1925 factory()->undefined_value() : |
1926 factory()->null_value(); | 1926 factory()->null_value(); |
1927 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1927 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1928 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1928 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1929 __ j(equal, true_label); | 1929 __ j(equal, true_label); |
1930 __ cmp(reg, other_nil_value); | 1930 __ cmp(reg, other_nil_value); |
1931 __ j(equal, true_label); | 1931 __ j(equal, true_label); |
1932 __ JumpIfSmi(reg, false_label); | 1932 __ JumpIfSmi(reg, false_label); |
1933 // Check for undetectable objects by looking in the bit field in | 1933 // Check for undetectable objects by looking in the bit field in |
1934 // the map. The object has already been smi checked. | 1934 // the map. The object has already been smi checked. |
1935 Register scratch = ToRegister(instr->TempAt(0)); | 1935 Register scratch = ToRegister(instr->temp()); |
1936 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1936 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
1937 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1937 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
1938 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1938 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
1939 EmitBranch(true_block, false_block, not_zero); | 1939 EmitBranch(true_block, false_block, not_zero); |
1940 } | 1940 } |
1941 } | 1941 } |
1942 | 1942 |
1943 | 1943 |
1944 Condition LCodeGen::EmitIsObject(Register input, | 1944 Condition LCodeGen::EmitIsObject(Register input, |
1945 Register temp1, | 1945 Register temp1, |
(...skipping 12 matching lines...) Expand all Loading... |
1958 | 1958 |
1959 __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset)); | 1959 __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset)); |
1960 __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); | 1960 __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); |
1961 __ j(below, is_not_object); | 1961 __ j(below, is_not_object); |
1962 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 1962 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
1963 return below_equal; | 1963 return below_equal; |
1964 } | 1964 } |
1965 | 1965 |
1966 | 1966 |
1967 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1967 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1968 Register reg = ToRegister(instr->InputAt(0)); | 1968 Register reg = ToRegister(instr->value()); |
1969 Register temp = ToRegister(instr->TempAt(0)); | 1969 Register temp = ToRegister(instr->temp()); |
1970 | 1970 |
1971 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1971 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1972 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1972 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1973 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1973 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1974 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1974 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1975 | 1975 |
1976 Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); | 1976 Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); |
1977 | 1977 |
1978 EmitBranch(true_block, false_block, true_cond); | 1978 EmitBranch(true_block, false_block, true_cond); |
1979 } | 1979 } |
1980 | 1980 |
1981 | 1981 |
1982 Condition LCodeGen::EmitIsString(Register input, | 1982 Condition LCodeGen::EmitIsString(Register input, |
1983 Register temp1, | 1983 Register temp1, |
1984 Label* is_not_string) { | 1984 Label* is_not_string) { |
1985 __ JumpIfSmi(input, is_not_string); | 1985 __ JumpIfSmi(input, is_not_string); |
1986 | 1986 |
1987 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); | 1987 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); |
1988 | 1988 |
1989 return cond; | 1989 return cond; |
1990 } | 1990 } |
1991 | 1991 |
1992 | 1992 |
1993 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 1993 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
1994 Register reg = ToRegister(instr->InputAt(0)); | 1994 Register reg = ToRegister(instr->value()); |
1995 Register temp = ToRegister(instr->TempAt(0)); | 1995 Register temp = ToRegister(instr->temp()); |
1996 | 1996 |
1997 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1997 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1998 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1998 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1999 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1999 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2000 | 2000 |
2001 Condition true_cond = EmitIsString(reg, temp, false_label); | 2001 Condition true_cond = EmitIsString(reg, temp, false_label); |
2002 | 2002 |
2003 EmitBranch(true_block, false_block, true_cond); | 2003 EmitBranch(true_block, false_block, true_cond); |
2004 } | 2004 } |
2005 | 2005 |
2006 | 2006 |
2007 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 2007 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
2008 Operand input = ToOperand(instr->InputAt(0)); | 2008 Operand input = ToOperand(instr->value()); |
2009 | 2009 |
2010 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2010 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2011 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2011 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2012 | 2012 |
2013 __ test(input, Immediate(kSmiTagMask)); | 2013 __ test(input, Immediate(kSmiTagMask)); |
2014 EmitBranch(true_block, false_block, zero); | 2014 EmitBranch(true_block, false_block, zero); |
2015 } | 2015 } |
2016 | 2016 |
2017 | 2017 |
2018 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2018 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
2019 Register input = ToRegister(instr->InputAt(0)); | 2019 Register input = ToRegister(instr->value()); |
2020 Register temp = ToRegister(instr->TempAt(0)); | 2020 Register temp = ToRegister(instr->temp()); |
2021 | 2021 |
2022 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2022 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2023 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2023 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2024 | 2024 |
2025 STATIC_ASSERT(kSmiTag == 0); | 2025 STATIC_ASSERT(kSmiTag == 0); |
2026 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 2026 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
2027 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 2027 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
2028 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), | 2028 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), |
2029 1 << Map::kIsUndetectable); | 2029 1 << Map::kIsUndetectable); |
2030 EmitBranch(true_block, false_block, not_zero); | 2030 EmitBranch(true_block, false_block, not_zero); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2080 InstanceType to = instr->to(); | 2080 InstanceType to = instr->to(); |
2081 if (from == to) return equal; | 2081 if (from == to) return equal; |
2082 if (to == LAST_TYPE) return above_equal; | 2082 if (to == LAST_TYPE) return above_equal; |
2083 if (from == FIRST_TYPE) return below_equal; | 2083 if (from == FIRST_TYPE) return below_equal; |
2084 UNREACHABLE(); | 2084 UNREACHABLE(); |
2085 return equal; | 2085 return equal; |
2086 } | 2086 } |
2087 | 2087 |
2088 | 2088 |
2089 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 2089 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
2090 Register input = ToRegister(instr->InputAt(0)); | 2090 Register input = ToRegister(instr->value()); |
2091 Register temp = ToRegister(instr->TempAt(0)); | 2091 Register temp = ToRegister(instr->temp()); |
2092 | 2092 |
2093 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2093 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2094 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2094 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2095 | 2095 |
2096 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2096 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2097 | 2097 |
2098 __ JumpIfSmi(input, false_label); | 2098 __ JumpIfSmi(input, false_label); |
2099 | 2099 |
2100 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); | 2100 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); |
2101 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 2101 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
2102 } | 2102 } |
2103 | 2103 |
2104 | 2104 |
2105 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2105 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
2106 Register input = ToRegister(instr->InputAt(0)); | 2106 Register input = ToRegister(instr->value()); |
2107 Register result = ToRegister(instr->result()); | 2107 Register result = ToRegister(instr->result()); |
2108 | 2108 |
2109 __ AbortIfNotString(input); | 2109 __ AbortIfNotString(input); |
2110 | 2110 |
2111 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); | 2111 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); |
2112 __ IndexFromHash(result, result); | 2112 __ IndexFromHash(result, result); |
2113 } | 2113 } |
2114 | 2114 |
2115 | 2115 |
2116 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2116 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2117 LHasCachedArrayIndexAndBranch* instr) { | 2117 LHasCachedArrayIndexAndBranch* instr) { |
2118 Register input = ToRegister(instr->InputAt(0)); | 2118 Register input = ToRegister(instr->value()); |
2119 | 2119 |
2120 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2120 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2121 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2121 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2122 | 2122 |
2123 __ test(FieldOperand(input, String::kHashFieldOffset), | 2123 __ test(FieldOperand(input, String::kHashFieldOffset), |
2124 Immediate(String::kContainsCachedArrayIndexMask)); | 2124 Immediate(String::kContainsCachedArrayIndexMask)); |
2125 EmitBranch(true_block, false_block, equal); | 2125 EmitBranch(true_block, false_block, equal); |
2126 } | 2126 } |
2127 | 2127 |
2128 | 2128 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2185 // booted. This routine isn't expected to work for random API-created | 2185 // booted. This routine isn't expected to work for random API-created |
2186 // classes and it doesn't have to because you can't access it with natives | 2186 // classes and it doesn't have to because you can't access it with natives |
2187 // syntax. Since both sides are symbols it is sufficient to use an identity | 2187 // syntax. Since both sides are symbols it is sufficient to use an identity |
2188 // comparison. | 2188 // comparison. |
2189 __ cmp(temp, class_name); | 2189 __ cmp(temp, class_name); |
2190 // End with the answer in the z flag. | 2190 // End with the answer in the z flag. |
2191 } | 2191 } |
2192 | 2192 |
2193 | 2193 |
2194 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2194 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2195 Register input = ToRegister(instr->InputAt(0)); | 2195 Register input = ToRegister(instr->value()); |
2196 Register temp = ToRegister(instr->TempAt(0)); | 2196 Register temp = ToRegister(instr->temp()); |
2197 Register temp2 = ToRegister(instr->TempAt(1)); | 2197 Register temp2 = ToRegister(instr->temp2()); |
2198 | 2198 |
2199 Handle<String> class_name = instr->hydrogen()->class_name(); | 2199 Handle<String> class_name = instr->hydrogen()->class_name(); |
2200 | 2200 |
2201 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2201 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2202 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2202 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2203 | 2203 |
2204 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2204 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
2205 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2205 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2206 | 2206 |
2207 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 2207 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
2208 | 2208 |
2209 EmitBranch(true_block, false_block, equal); | 2209 EmitBranch(true_block, false_block, equal); |
2210 } | 2210 } |
2211 | 2211 |
2212 | 2212 |
2213 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2213 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2214 Register reg = ToRegister(instr->InputAt(0)); | 2214 Register reg = ToRegister(instr->value()); |
2215 int true_block = instr->true_block_id(); | 2215 int true_block = instr->true_block_id(); |
2216 int false_block = instr->false_block_id(); | 2216 int false_block = instr->false_block_id(); |
2217 | 2217 |
2218 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2218 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
2219 EmitBranch(true_block, false_block, equal); | 2219 EmitBranch(true_block, false_block, equal); |
2220 } | 2220 } |
2221 | 2221 |
2222 | 2222 |
2223 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2223 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2224 // Object and function are in fixed registers defined by the stub. | 2224 // Object and function are in fixed registers defined by the stub. |
(...skipping 25 matching lines...) Expand all Loading... |
2250 Label* map_check() { return &map_check_; } | 2250 Label* map_check() { return &map_check_; } |
2251 private: | 2251 private: |
2252 LInstanceOfKnownGlobal* instr_; | 2252 LInstanceOfKnownGlobal* instr_; |
2253 Label map_check_; | 2253 Label map_check_; |
2254 }; | 2254 }; |
2255 | 2255 |
2256 DeferredInstanceOfKnownGlobal* deferred; | 2256 DeferredInstanceOfKnownGlobal* deferred; |
2257 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2257 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
2258 | 2258 |
2259 Label done, false_result; | 2259 Label done, false_result; |
2260 Register object = ToRegister(instr->InputAt(1)); | 2260 Register object = ToRegister(instr->value()); |
2261 Register temp = ToRegister(instr->TempAt(0)); | 2261 Register temp = ToRegister(instr->temp()); |
2262 | 2262 |
2263 // A Smi is not an instance of anything. | 2263 // A Smi is not an instance of anything. |
2264 __ JumpIfSmi(object, &false_result); | 2264 __ JumpIfSmi(object, &false_result); |
2265 | 2265 |
2266 // This is the inlined call site instanceof cache. The two occurences of the | 2266 // This is the inlined call site instanceof cache. The two occurences of the |
2267 // hole value will be patched to the last map/result pair generated by the | 2267 // hole value will be patched to the last map/result pair generated by the |
2268 // instanceof stub. | 2268 // instanceof stub. |
2269 Label cache_miss; | 2269 Label cache_miss; |
2270 Register map = ToRegister(instr->TempAt(0)); | 2270 Register map = ToRegister(instr->temp()); |
2271 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); | 2271 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
2272 __ bind(deferred->map_check()); // Label for calculating code patching. | 2272 __ bind(deferred->map_check()); // Label for calculating code patching. |
2273 Handle<JSGlobalPropertyCell> cache_cell = | 2273 Handle<JSGlobalPropertyCell> cache_cell = |
2274 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); | 2274 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); |
2275 __ cmp(map, Operand::Cell(cache_cell)); // Patched to cached map. | 2275 __ cmp(map, Operand::Cell(cache_cell)); // Patched to cached map. |
2276 __ j(not_equal, &cache_miss, Label::kNear); | 2276 __ j(not_equal, &cache_miss, Label::kNear); |
2277 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. | 2277 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. |
2278 __ jmp(&done); | 2278 __ jmp(&done); |
2279 | 2279 |
2280 // The inlined call site cache did not match. Check for null and string | 2280 // The inlined call site cache did not match. Check for null and string |
(...skipping 30 matching lines...) Expand all Loading... |
2311 flags = static_cast<InstanceofStub::Flags>( | 2311 flags = static_cast<InstanceofStub::Flags>( |
2312 flags | InstanceofStub::kCallSiteInlineCheck); | 2312 flags | InstanceofStub::kCallSiteInlineCheck); |
2313 flags = static_cast<InstanceofStub::Flags>( | 2313 flags = static_cast<InstanceofStub::Flags>( |
2314 flags | InstanceofStub::kReturnTrueFalseObject); | 2314 flags | InstanceofStub::kReturnTrueFalseObject); |
2315 InstanceofStub stub(flags); | 2315 InstanceofStub stub(flags); |
2316 | 2316 |
2317 // Get the temp register reserved by the instruction. This needs to be a | 2317 // Get the temp register reserved by the instruction. This needs to be a |
2318 // register which is pushed last by PushSafepointRegisters as top of the | 2318 // register which is pushed last by PushSafepointRegisters as top of the |
2319 // stack is used to pass the offset to the location of the map check to | 2319 // stack is used to pass the offset to the location of the map check to |
2320 // the stub. | 2320 // the stub. |
2321 Register temp = ToRegister(instr->TempAt(0)); | 2321 Register temp = ToRegister(instr->temp()); |
2322 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); | 2322 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); |
2323 __ LoadHeapObject(InstanceofStub::right(), instr->function()); | 2323 __ LoadHeapObject(InstanceofStub::right(), instr->function()); |
2324 static const int kAdditionalDelta = 13; | 2324 static const int kAdditionalDelta = 13; |
2325 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 2325 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
2326 __ mov(temp, Immediate(delta)); | 2326 __ mov(temp, Immediate(delta)); |
2327 __ StoreToSafepointRegisterSlot(temp, temp); | 2327 __ StoreToSafepointRegisterSlot(temp, temp); |
2328 CallCodeGeneric(stub.GetCode(), | 2328 CallCodeGeneric(stub.GetCode(), |
2329 RelocInfo::CODE_TARGET, | 2329 RelocInfo::CODE_TARGET, |
2330 instr, | 2330 instr, |
2331 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 2331 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2478 } else { | 2478 } else { |
2479 __ j(not_equal, &skip_assignment, Label::kNear); | 2479 __ j(not_equal, &skip_assignment, Label::kNear); |
2480 } | 2480 } |
2481 } | 2481 } |
2482 | 2482 |
2483 __ mov(target, value); | 2483 __ mov(target, value); |
2484 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2484 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2485 HType type = instr->hydrogen()->value()->type(); | 2485 HType type = instr->hydrogen()->value()->type(); |
2486 SmiCheck check_needed = | 2486 SmiCheck check_needed = |
2487 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2487 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
2488 Register temp = ToRegister(instr->TempAt(0)); | 2488 Register temp = ToRegister(instr->temp()); |
2489 int offset = Context::SlotOffset(instr->slot_index()); | 2489 int offset = Context::SlotOffset(instr->slot_index()); |
2490 __ RecordWriteContextSlot(context, | 2490 __ RecordWriteContextSlot(context, |
2491 offset, | 2491 offset, |
2492 value, | 2492 value, |
2493 temp, | 2493 temp, |
2494 kSaveFPRegs, | 2494 kSaveFPRegs, |
2495 EMIT_REMEMBERED_SET, | 2495 EMIT_REMEMBERED_SET, |
2496 check_needed); | 2496 check_needed); |
2497 } | 2497 } |
2498 | 2498 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2643 ASSERT(ToRegister(instr->result()).is(eax)); | 2643 ASSERT(ToRegister(instr->result()).is(eax)); |
2644 | 2644 |
2645 __ mov(ecx, instr->name()); | 2645 __ mov(ecx, instr->name()); |
2646 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2646 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2647 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2647 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2648 } | 2648 } |
2649 | 2649 |
2650 | 2650 |
2651 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2651 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
2652 Register function = ToRegister(instr->function()); | 2652 Register function = ToRegister(instr->function()); |
2653 Register temp = ToRegister(instr->TempAt(0)); | 2653 Register temp = ToRegister(instr->temp()); |
2654 Register result = ToRegister(instr->result()); | 2654 Register result = ToRegister(instr->result()); |
2655 | 2655 |
2656 // Check that the function really is a function. | 2656 // Check that the function really is a function. |
2657 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 2657 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
2658 DeoptimizeIf(not_equal, instr->environment()); | 2658 DeoptimizeIf(not_equal, instr->environment()); |
2659 | 2659 |
2660 // Check whether the function has an instance prototype. | 2660 // Check whether the function has an instance prototype. |
2661 Label non_instance; | 2661 Label non_instance; |
2662 __ test_b(FieldOperand(result, Map::kBitFieldOffset), | 2662 __ test_b(FieldOperand(result, Map::kBitFieldOffset), |
2663 1 << Map::kHasNonInstancePrototype); | 2663 1 << Map::kHasNonInstancePrototype); |
(...skipping 21 matching lines...) Expand all Loading... |
2685 __ bind(&non_instance); | 2685 __ bind(&non_instance); |
2686 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); | 2686 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); |
2687 | 2687 |
2688 // All done. | 2688 // All done. |
2689 __ bind(&done); | 2689 __ bind(&done); |
2690 } | 2690 } |
2691 | 2691 |
2692 | 2692 |
2693 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2693 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
2694 Register result = ToRegister(instr->result()); | 2694 Register result = ToRegister(instr->result()); |
2695 Register input = ToRegister(instr->InputAt(0)); | 2695 Register input = ToRegister(instr->object()); |
2696 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); | 2696 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); |
2697 if (FLAG_debug_code) { | 2697 if (FLAG_debug_code) { |
2698 Label done, ok, fail; | 2698 Label done, ok, fail; |
2699 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 2699 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
2700 Immediate(factory()->fixed_array_map())); | 2700 Immediate(factory()->fixed_array_map())); |
2701 __ j(equal, &done, Label::kNear); | 2701 __ j(equal, &done, Label::kNear); |
2702 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 2702 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
2703 Immediate(factory()->fixed_cow_array_map())); | 2703 Immediate(factory()->fixed_cow_array_map())); |
2704 __ j(equal, &done, Label::kNear); | 2704 __ j(equal, &done, Label::kNear); |
2705 Register temp((result.is(eax)) ? ebx : eax); | 2705 Register temp((result.is(eax)) ? ebx : eax); |
(...skipping 15 matching lines...) Expand all Loading... |
2721 __ bind(&ok); | 2721 __ bind(&ok); |
2722 __ pop(temp); | 2722 __ pop(temp); |
2723 __ bind(&done); | 2723 __ bind(&done); |
2724 } | 2724 } |
2725 } | 2725 } |
2726 | 2726 |
2727 | 2727 |
2728 void LCodeGen::DoLoadExternalArrayPointer( | 2728 void LCodeGen::DoLoadExternalArrayPointer( |
2729 LLoadExternalArrayPointer* instr) { | 2729 LLoadExternalArrayPointer* instr) { |
2730 Register result = ToRegister(instr->result()); | 2730 Register result = ToRegister(instr->result()); |
2731 Register input = ToRegister(instr->InputAt(0)); | 2731 Register input = ToRegister(instr->object()); |
2732 __ mov(result, FieldOperand(input, | 2732 __ mov(result, FieldOperand(input, |
2733 ExternalArray::kExternalPointerOffset)); | 2733 ExternalArray::kExternalPointerOffset)); |
2734 } | 2734 } |
2735 | 2735 |
2736 | 2736 |
2737 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2737 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
2738 Register arguments = ToRegister(instr->arguments()); | 2738 Register arguments = ToRegister(instr->arguments()); |
2739 Register length = ToRegister(instr->length()); | 2739 Register length = ToRegister(instr->length()); |
2740 Operand index = ToOperand(instr->index()); | 2740 Operand index = ToOperand(instr->index()); |
2741 Register result = ToRegister(instr->result()); | 2741 Register result = ToRegister(instr->result()); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2934 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2934 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2935 | 2935 |
2936 // Result is the frame pointer for the frame if not adapted and for the real | 2936 // Result is the frame pointer for the frame if not adapted and for the real |
2937 // frame below the adaptor frame if adapted. | 2937 // frame below the adaptor frame if adapted. |
2938 __ bind(&done); | 2938 __ bind(&done); |
2939 } | 2939 } |
2940 } | 2940 } |
2941 | 2941 |
2942 | 2942 |
2943 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2943 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
2944 Operand elem = ToOperand(instr->InputAt(0)); | 2944 Operand elem = ToOperand(instr->elements()); |
2945 Register result = ToRegister(instr->result()); | 2945 Register result = ToRegister(instr->result()); |
2946 | 2946 |
2947 Label done; | 2947 Label done; |
2948 | 2948 |
2949 // If no arguments adaptor frame the number of arguments is fixed. | 2949 // If no arguments adaptor frame the number of arguments is fixed. |
2950 __ cmp(ebp, elem); | 2950 __ cmp(ebp, elem); |
2951 __ mov(result, Immediate(scope()->num_parameters())); | 2951 __ mov(result, Immediate(scope()->num_parameters())); |
2952 __ j(equal, &done, Label::kNear); | 2952 __ j(equal, &done, Label::kNear); |
2953 | 2953 |
2954 // Arguments adaptor frame present. Get argument length from there. | 2954 // Arguments adaptor frame present. Get argument length from there. |
2955 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2955 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2956 __ mov(result, Operand(result, | 2956 __ mov(result, Operand(result, |
2957 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2957 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2958 __ SmiUntag(result); | 2958 __ SmiUntag(result); |
2959 | 2959 |
2960 // Argument length is in result register. | 2960 // Argument length is in result register. |
2961 __ bind(&done); | 2961 __ bind(&done); |
2962 } | 2962 } |
2963 | 2963 |
2964 | 2964 |
2965 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 2965 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
2966 Register receiver = ToRegister(instr->receiver()); | 2966 Register receiver = ToRegister(instr->receiver()); |
2967 Register function = ToRegister(instr->function()); | 2967 Register function = ToRegister(instr->function()); |
2968 Register scratch = ToRegister(instr->TempAt(0)); | 2968 Register scratch = ToRegister(instr->temp()); |
2969 | 2969 |
2970 // If the receiver is null or undefined, we have to pass the global | 2970 // If the receiver is null or undefined, we have to pass the global |
2971 // object as a receiver to normal functions. Values have to be | 2971 // object as a receiver to normal functions. Values have to be |
2972 // passed unchanged to builtins and strict-mode functions. | 2972 // passed unchanged to builtins and strict-mode functions. |
2973 Label global_object, receiver_ok; | 2973 Label global_object, receiver_ok; |
2974 | 2974 |
2975 // Do not transform the receiver to object for strict mode | 2975 // Do not transform the receiver to object for strict mode |
2976 // functions. | 2976 // functions. |
2977 __ mov(scratch, | 2977 __ mov(scratch, |
2978 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 2978 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3046 RecordPosition(pointers->position()); | 3046 RecordPosition(pointers->position()); |
3047 SafepointGenerator safepoint_generator( | 3047 SafepointGenerator safepoint_generator( |
3048 this, pointers, Safepoint::kLazyDeopt); | 3048 this, pointers, Safepoint::kLazyDeopt); |
3049 ParameterCount actual(eax); | 3049 ParameterCount actual(eax); |
3050 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3050 __ InvokeFunction(function, actual, CALL_FUNCTION, |
3051 safepoint_generator, CALL_AS_METHOD); | 3051 safepoint_generator, CALL_AS_METHOD); |
3052 } | 3052 } |
3053 | 3053 |
3054 | 3054 |
3055 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3055 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3056 LOperand* argument = instr->InputAt(0); | 3056 LOperand* argument = instr->value(); |
3057 EmitPushTaggedOperand(argument); | 3057 EmitPushTaggedOperand(argument); |
3058 } | 3058 } |
3059 | 3059 |
3060 | 3060 |
3061 void LCodeGen::DoDrop(LDrop* instr) { | 3061 void LCodeGen::DoDrop(LDrop* instr) { |
3062 __ Drop(instr->count()); | 3062 __ Drop(instr->count()); |
3063 } | 3063 } |
3064 | 3064 |
3065 | 3065 |
3066 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 3066 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
(...skipping 10 matching lines...) Expand all Loading... |
3077 | 3077 |
3078 void LCodeGen::DoOuterContext(LOuterContext* instr) { | 3078 void LCodeGen::DoOuterContext(LOuterContext* instr) { |
3079 Register context = ToRegister(instr->context()); | 3079 Register context = ToRegister(instr->context()); |
3080 Register result = ToRegister(instr->result()); | 3080 Register result = ToRegister(instr->result()); |
3081 __ mov(result, | 3081 __ mov(result, |
3082 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 3082 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
3083 } | 3083 } |
3084 | 3084 |
3085 | 3085 |
3086 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3086 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
3087 ASSERT(ToRegister(instr->InputAt(0)).is(esi)); | 3087 ASSERT(ToRegister(instr->context()).is(esi)); |
3088 __ push(esi); // The context is the first argument. | 3088 __ push(esi); // The context is the first argument. |
3089 __ push(Immediate(instr->hydrogen()->pairs())); | 3089 __ push(Immediate(instr->hydrogen()->pairs())); |
3090 __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); | 3090 __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); |
3091 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3091 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
3092 } | 3092 } |
3093 | 3093 |
3094 | 3094 |
3095 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 3095 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
3096 Register context = ToRegister(instr->context()); | 3096 Register context = ToRegister(instr->context()); |
3097 Register result = ToRegister(instr->result()); | 3097 Register result = ToRegister(instr->result()); |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3410 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. | 3410 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. |
3411 __ sqrtsd(input_reg, input_reg); | 3411 __ sqrtsd(input_reg, input_reg); |
3412 __ bind(&done); | 3412 __ bind(&done); |
3413 } | 3413 } |
3414 | 3414 |
3415 | 3415 |
3416 void LCodeGen::DoPower(LPower* instr) { | 3416 void LCodeGen::DoPower(LPower* instr) { |
3417 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3417 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3418 // Having marked this as a call, we can use any registers. | 3418 // Having marked this as a call, we can use any registers. |
3419 // Just make sure that the input/output registers are the expected ones. | 3419 // Just make sure that the input/output registers are the expected ones. |
3420 ASSERT(!instr->InputAt(1)->IsDoubleRegister() || | 3420 ASSERT(!instr->right()->IsDoubleRegister() || |
3421 ToDoubleRegister(instr->InputAt(1)).is(xmm1)); | 3421 ToDoubleRegister(instr->right()).is(xmm1)); |
3422 ASSERT(!instr->InputAt(1)->IsRegister() || | 3422 ASSERT(!instr->right()->IsRegister() || |
3423 ToRegister(instr->InputAt(1)).is(eax)); | 3423 ToRegister(instr->right()).is(eax)); |
3424 ASSERT(ToDoubleRegister(instr->InputAt(0)).is(xmm2)); | 3424 ASSERT(ToDoubleRegister(instr->left()).is(xmm2)); |
3425 ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); | 3425 ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); |
3426 | 3426 |
3427 if (exponent_type.IsTagged()) { | 3427 if (exponent_type.IsTagged()) { |
3428 Label no_deopt; | 3428 Label no_deopt; |
3429 __ JumpIfSmi(eax, &no_deopt); | 3429 __ JumpIfSmi(eax, &no_deopt); |
3430 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); | 3430 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); |
3431 DeoptimizeIf(not_equal, instr->environment()); | 3431 DeoptimizeIf(not_equal, instr->environment()); |
3432 __ bind(&no_deopt); | 3432 __ bind(&no_deopt); |
3433 MathPowStub stub(MathPowStub::TAGGED); | 3433 MathPowStub stub(MathPowStub::TAGGED); |
3434 __ CallStub(&stub); | 3434 __ CallStub(&stub); |
(...skipping 17 matching lines...) Expand all Loading... |
3452 virtual LInstruction* instr() { return instr_; } | 3452 virtual LInstruction* instr() { return instr_; } |
3453 private: | 3453 private: |
3454 LRandom* instr_; | 3454 LRandom* instr_; |
3455 }; | 3455 }; |
3456 | 3456 |
3457 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); | 3457 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); |
3458 | 3458 |
3459 // Having marked this instruction as a call we can use any | 3459 // Having marked this instruction as a call we can use any |
3460 // registers. | 3460 // registers. |
3461 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3461 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
3462 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 3462 ASSERT(ToRegister(instr->global_object()).is(eax)); |
3463 // Assert that the register size is indeed the size of each seed. | 3463 // Assert that the register size is indeed the size of each seed. |
3464 static const int kSeedSize = sizeof(uint32_t); | 3464 static const int kSeedSize = sizeof(uint32_t); |
3465 STATIC_ASSERT(kPointerSize == kSeedSize); | 3465 STATIC_ASSERT(kPointerSize == kSeedSize); |
3466 | 3466 |
3467 __ mov(eax, FieldOperand(eax, GlobalObject::kNativeContextOffset)); | 3467 __ mov(eax, FieldOperand(eax, GlobalObject::kNativeContextOffset)); |
3468 static const int kRandomSeedOffset = | 3468 static const int kRandomSeedOffset = |
3469 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; | 3469 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; |
3470 __ mov(ebx, FieldOperand(eax, kRandomSeedOffset)); | 3470 __ mov(ebx, FieldOperand(eax, kRandomSeedOffset)); |
3471 // ebx: FixedArray of the native context's random seeds | 3471 // ebx: FixedArray of the native context's random seeds |
3472 | 3472 |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3709 | 3709 |
3710 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3710 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
3711 Register object = ToRegister(instr->object()); | 3711 Register object = ToRegister(instr->object()); |
3712 Register value = ToRegister(instr->value()); | 3712 Register value = ToRegister(instr->value()); |
3713 int offset = instr->offset(); | 3713 int offset = instr->offset(); |
3714 | 3714 |
3715 if (!instr->transition().is_null()) { | 3715 if (!instr->transition().is_null()) { |
3716 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3716 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { |
3717 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 3717 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
3718 } else { | 3718 } else { |
3719 Register temp = ToRegister(instr->TempAt(0)); | 3719 Register temp = ToRegister(instr->temp()); |
3720 Register temp_map = ToRegister(instr->TempAt(1)); | 3720 Register temp_map = ToRegister(instr->temp_map()); |
3721 __ mov(temp_map, instr->transition()); | 3721 __ mov(temp_map, instr->transition()); |
3722 __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map); | 3722 __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map); |
3723 // Update the write barrier for the map field. | 3723 // Update the write barrier for the map field. |
3724 __ RecordWriteField(object, | 3724 __ RecordWriteField(object, |
3725 HeapObject::kMapOffset, | 3725 HeapObject::kMapOffset, |
3726 temp_map, | 3726 temp_map, |
3727 temp, | 3727 temp, |
3728 kSaveFPRegs, | 3728 kSaveFPRegs, |
3729 OMIT_REMEMBERED_SET, | 3729 OMIT_REMEMBERED_SET, |
3730 OMIT_SMI_CHECK); | 3730 OMIT_SMI_CHECK); |
3731 } | 3731 } |
3732 } | 3732 } |
3733 | 3733 |
3734 // Do the store. | 3734 // Do the store. |
3735 HType type = instr->hydrogen()->value()->type(); | 3735 HType type = instr->hydrogen()->value()->type(); |
3736 SmiCheck check_needed = | 3736 SmiCheck check_needed = |
3737 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 3737 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3738 if (instr->is_in_object()) { | 3738 if (instr->is_in_object()) { |
3739 __ mov(FieldOperand(object, offset), value); | 3739 __ mov(FieldOperand(object, offset), value); |
3740 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3740 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3741 Register temp = ToRegister(instr->TempAt(0)); | 3741 Register temp = ToRegister(instr->temp()); |
3742 // Update the write barrier for the object for in-object properties. | 3742 // Update the write barrier for the object for in-object properties. |
3743 __ RecordWriteField(object, | 3743 __ RecordWriteField(object, |
3744 offset, | 3744 offset, |
3745 value, | 3745 value, |
3746 temp, | 3746 temp, |
3747 kSaveFPRegs, | 3747 kSaveFPRegs, |
3748 EMIT_REMEMBERED_SET, | 3748 EMIT_REMEMBERED_SET, |
3749 check_needed); | 3749 check_needed); |
3750 } | 3750 } |
3751 } else { | 3751 } else { |
3752 Register temp = ToRegister(instr->TempAt(0)); | 3752 Register temp = ToRegister(instr->temp()); |
3753 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 3753 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
3754 __ mov(FieldOperand(temp, offset), value); | 3754 __ mov(FieldOperand(temp, offset), value); |
3755 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3755 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3756 // Update the write barrier for the properties array. | 3756 // Update the write barrier for the properties array. |
3757 // object is used as a scratch register. | 3757 // object is used as a scratch register. |
3758 __ RecordWriteField(temp, | 3758 __ RecordWriteField(temp, |
3759 offset, | 3759 offset, |
3760 value, | 3760 value, |
3761 object, | 3761 object, |
3762 kSaveFPRegs, | 3762 kSaveFPRegs, |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3938 | 3938 |
3939 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3939 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3940 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3940 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3941 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3941 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3942 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3942 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3943 } | 3943 } |
3944 | 3944 |
3945 | 3945 |
3946 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 3946 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
3947 Register object_reg = ToRegister(instr->object()); | 3947 Register object_reg = ToRegister(instr->object()); |
3948 Register new_map_reg = ToRegister(instr->new_map_reg()); | 3948 Register new_map_reg = ToRegister(instr->new_map_temp()); |
3949 | 3949 |
3950 Handle<Map> from_map = instr->original_map(); | 3950 Handle<Map> from_map = instr->original_map(); |
3951 Handle<Map> to_map = instr->transitioned_map(); | 3951 Handle<Map> to_map = instr->transitioned_map(); |
3952 ElementsKind from_kind = from_map->elements_kind(); | 3952 ElementsKind from_kind = from_map->elements_kind(); |
3953 ElementsKind to_kind = to_map->elements_kind(); | 3953 ElementsKind to_kind = to_map->elements_kind(); |
3954 | 3954 |
3955 Label not_applicable; | 3955 Label not_applicable; |
3956 bool is_simple_map_transition = | 3956 bool is_simple_map_transition = |
3957 IsSimpleMapChangeTransition(from_kind, to_kind); | 3957 IsSimpleMapChangeTransition(from_kind, to_kind); |
3958 Label::Distance branch_distance = | 3958 Label::Distance branch_distance = |
3959 is_simple_map_transition ? Label::kNear : Label::kFar; | 3959 is_simple_map_transition ? Label::kNear : Label::kFar; |
3960 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 3960 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
3961 __ j(not_equal, ¬_applicable, branch_distance); | 3961 __ j(not_equal, ¬_applicable, branch_distance); |
3962 if (is_simple_map_transition) { | 3962 if (is_simple_map_transition) { |
3963 Register object_reg = ToRegister(instr->object()); | 3963 Register object_reg = ToRegister(instr->object()); |
3964 Handle<Map> map = instr->hydrogen()->transitioned_map(); | 3964 Handle<Map> map = instr->hydrogen()->transitioned_map(); |
3965 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), | 3965 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), |
3966 Immediate(map)); | 3966 Immediate(map)); |
3967 // Write barrier. | 3967 // Write barrier. |
3968 ASSERT_NE(instr->temp_reg(), NULL); | 3968 ASSERT_NE(instr->temp(), NULL); |
3969 __ RecordWriteForMap(object_reg, to_map, new_map_reg, | 3969 __ RecordWriteForMap(object_reg, to_map, new_map_reg, |
3970 ToRegister(instr->temp_reg()), | 3970 ToRegister(instr->temp()), |
3971 kDontSaveFPRegs); | 3971 kDontSaveFPRegs); |
3972 } else if (IsFastSmiElementsKind(from_kind) && | 3972 } else if (IsFastSmiElementsKind(from_kind) && |
3973 IsFastDoubleElementsKind(to_kind)) { | 3973 IsFastDoubleElementsKind(to_kind)) { |
3974 __ mov(new_map_reg, to_map); | 3974 __ mov(new_map_reg, to_map); |
3975 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3975 Register fixed_object_reg = ToRegister(instr->temp()); |
3976 ASSERT(fixed_object_reg.is(edx)); | 3976 ASSERT(fixed_object_reg.is(edx)); |
3977 ASSERT(new_map_reg.is(ebx)); | 3977 ASSERT(new_map_reg.is(ebx)); |
3978 __ mov(fixed_object_reg, object_reg); | 3978 __ mov(fixed_object_reg, object_reg); |
3979 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3979 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
3980 RelocInfo::CODE_TARGET, instr); | 3980 RelocInfo::CODE_TARGET, instr); |
3981 } else if (IsFastDoubleElementsKind(from_kind) && | 3981 } else if (IsFastDoubleElementsKind(from_kind) && |
3982 IsFastObjectElementsKind(to_kind)) { | 3982 IsFastObjectElementsKind(to_kind)) { |
3983 __ mov(new_map_reg, to_map); | 3983 __ mov(new_map_reg, to_map); |
3984 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3984 Register fixed_object_reg = ToRegister(instr->temp()); |
3985 ASSERT(fixed_object_reg.is(edx)); | 3985 ASSERT(fixed_object_reg.is(edx)); |
3986 ASSERT(new_map_reg.is(ebx)); | 3986 ASSERT(new_map_reg.is(ebx)); |
3987 __ mov(fixed_object_reg, object_reg); | 3987 __ mov(fixed_object_reg, object_reg); |
3988 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3988 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
3989 RelocInfo::CODE_TARGET, instr); | 3989 RelocInfo::CODE_TARGET, instr); |
3990 } else { | 3990 } else { |
3991 UNREACHABLE(); | 3991 UNREACHABLE(); |
3992 } | 3992 } |
3993 __ bind(¬_applicable); | 3993 __ bind(¬_applicable); |
3994 } | 3994 } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4107 | 4107 |
4108 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4108 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
4109 EmitPushTaggedOperand(instr->left()); | 4109 EmitPushTaggedOperand(instr->left()); |
4110 EmitPushTaggedOperand(instr->right()); | 4110 EmitPushTaggedOperand(instr->right()); |
4111 StringAddStub stub(NO_STRING_CHECK_IN_STUB); | 4111 StringAddStub stub(NO_STRING_CHECK_IN_STUB); |
4112 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4112 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
4113 } | 4113 } |
4114 | 4114 |
4115 | 4115 |
4116 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4116 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4117 LOperand* input = instr->InputAt(0); | 4117 LOperand* input = instr->value(); |
4118 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4118 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4119 LOperand* output = instr->result(); | 4119 LOperand* output = instr->result(); |
4120 ASSERT(output->IsDoubleRegister()); | 4120 ASSERT(output->IsDoubleRegister()); |
4121 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); | 4121 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); |
4122 } | 4122 } |
4123 | 4123 |
4124 | 4124 |
4125 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4125 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
4126 LOperand* input = instr->InputAt(0); | 4126 LOperand* input = instr->value(); |
4127 LOperand* output = instr->result(); | 4127 LOperand* output = instr->result(); |
4128 LOperand* temp = instr->TempAt(0); | 4128 LOperand* temp = instr->temp(); |
4129 | 4129 |
4130 __ LoadUint32(ToDoubleRegister(output), | 4130 __ LoadUint32(ToDoubleRegister(output), |
4131 ToRegister(input), | 4131 ToRegister(input), |
4132 ToDoubleRegister(temp)); | 4132 ToDoubleRegister(temp)); |
4133 } | 4133 } |
4134 | 4134 |
4135 | 4135 |
4136 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4136 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
4137 class DeferredNumberTagI: public LDeferredCode { | 4137 class DeferredNumberTagI: public LDeferredCode { |
4138 public: | 4138 public: |
4139 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 4139 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
4140 : LDeferredCode(codegen), instr_(instr) { } | 4140 : LDeferredCode(codegen), instr_(instr) { } |
4141 virtual void Generate() { | 4141 virtual void Generate() { |
4142 codegen()->DoDeferredNumberTagI(instr_, | 4142 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), SIGNED_INT32); |
4143 instr_->InputAt(0), | |
4144 SIGNED_INT32); | |
4145 } | 4143 } |
4146 virtual LInstruction* instr() { return instr_; } | 4144 virtual LInstruction* instr() { return instr_; } |
4147 private: | 4145 private: |
4148 LNumberTagI* instr_; | 4146 LNumberTagI* instr_; |
4149 }; | 4147 }; |
4150 | 4148 |
4151 LOperand* input = instr->InputAt(0); | 4149 LOperand* input = instr->value(); |
4152 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4150 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4153 Register reg = ToRegister(input); | 4151 Register reg = ToRegister(input); |
4154 | 4152 |
4155 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); | 4153 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
4156 __ SmiTag(reg); | 4154 __ SmiTag(reg); |
4157 __ j(overflow, deferred->entry()); | 4155 __ j(overflow, deferred->entry()); |
4158 __ bind(deferred->exit()); | 4156 __ bind(deferred->exit()); |
4159 } | 4157 } |
4160 | 4158 |
4161 | 4159 |
4162 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4160 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
4163 class DeferredNumberTagU: public LDeferredCode { | 4161 class DeferredNumberTagU: public LDeferredCode { |
4164 public: | 4162 public: |
4165 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4163 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
4166 : LDeferredCode(codegen), instr_(instr) { } | 4164 : LDeferredCode(codegen), instr_(instr) { } |
4167 virtual void Generate() { | 4165 virtual void Generate() { |
4168 codegen()->DoDeferredNumberTagI(instr_, | 4166 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), UNSIGNED_INT32); |
4169 instr_->InputAt(0), | |
4170 UNSIGNED_INT32); | |
4171 } | 4167 } |
4172 virtual LInstruction* instr() { return instr_; } | 4168 virtual LInstruction* instr() { return instr_; } |
4173 private: | 4169 private: |
4174 LNumberTagU* instr_; | 4170 LNumberTagU* instr_; |
4175 }; | 4171 }; |
4176 | 4172 |
4177 LOperand* input = instr->InputAt(0); | 4173 LOperand* input = instr->value(); |
4178 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4174 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4179 Register reg = ToRegister(input); | 4175 Register reg = ToRegister(input); |
4180 | 4176 |
4181 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4177 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
4182 __ cmp(reg, Immediate(Smi::kMaxValue)); | 4178 __ cmp(reg, Immediate(Smi::kMaxValue)); |
4183 __ j(above, deferred->entry()); | 4179 __ j(above, deferred->entry()); |
4184 __ SmiTag(reg); | 4180 __ SmiTag(reg); |
4185 __ bind(deferred->exit()); | 4181 __ bind(deferred->exit()); |
4186 } | 4182 } |
4187 | 4183 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4244 class DeferredNumberTagD: public LDeferredCode { | 4240 class DeferredNumberTagD: public LDeferredCode { |
4245 public: | 4241 public: |
4246 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4242 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
4247 : LDeferredCode(codegen), instr_(instr) { } | 4243 : LDeferredCode(codegen), instr_(instr) { } |
4248 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4244 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
4249 virtual LInstruction* instr() { return instr_; } | 4245 virtual LInstruction* instr() { return instr_; } |
4250 private: | 4246 private: |
4251 LNumberTagD* instr_; | 4247 LNumberTagD* instr_; |
4252 }; | 4248 }; |
4253 | 4249 |
4254 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 4250 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
4255 Register reg = ToRegister(instr->result()); | 4251 Register reg = ToRegister(instr->result()); |
4256 Register tmp = ToRegister(instr->TempAt(0)); | 4252 Register tmp = ToRegister(instr->temp()); |
4257 | 4253 |
4258 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4254 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
4259 if (FLAG_inline_new) { | 4255 if (FLAG_inline_new) { |
4260 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); | 4256 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); |
4261 } else { | 4257 } else { |
4262 __ jmp(deferred->entry()); | 4258 __ jmp(deferred->entry()); |
4263 } | 4259 } |
4264 __ bind(deferred->exit()); | 4260 __ bind(deferred->exit()); |
4265 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 4261 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
4266 } | 4262 } |
(...skipping 14 matching lines...) Expand all Loading... |
4281 // not have easy access to the local context. | 4277 // not have easy access to the local context. |
4282 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4278 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4283 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 4279 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
4284 RecordSafepointWithRegisters( | 4280 RecordSafepointWithRegisters( |
4285 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4281 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4286 __ StoreToSafepointRegisterSlot(reg, eax); | 4282 __ StoreToSafepointRegisterSlot(reg, eax); |
4287 } | 4283 } |
4288 | 4284 |
4289 | 4285 |
4290 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4286 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4291 LOperand* input = instr->InputAt(0); | 4287 LOperand* input = instr->value(); |
4292 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4288 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4293 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4289 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
4294 __ SmiTag(ToRegister(input)); | 4290 __ SmiTag(ToRegister(input)); |
4295 } | 4291 } |
4296 | 4292 |
4297 | 4293 |
4298 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4294 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
4299 LOperand* input = instr->InputAt(0); | 4295 LOperand* input = instr->value(); |
4300 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4296 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4301 if (instr->needs_check()) { | 4297 if (instr->needs_check()) { |
4302 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 4298 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
4303 DeoptimizeIf(not_zero, instr->environment()); | 4299 DeoptimizeIf(not_zero, instr->environment()); |
4304 } else { | 4300 } else { |
4305 if (FLAG_debug_code) { | 4301 if (FLAG_debug_code) { |
4306 __ AbortIfNotSmi(ToRegister(input)); | 4302 __ AbortIfNotSmi(ToRegister(input)); |
4307 } | 4303 } |
4308 } | 4304 } |
4309 __ SmiUntag(ToRegister(input)); | 4305 __ SmiUntag(ToRegister(input)); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4358 __ bind(&load_smi); | 4354 __ bind(&load_smi); |
4359 __ SmiUntag(input_reg); // Untag smi before converting to float. | 4355 __ SmiUntag(input_reg); // Untag smi before converting to float. |
4360 __ cvtsi2sd(result_reg, Operand(input_reg)); | 4356 __ cvtsi2sd(result_reg, Operand(input_reg)); |
4361 __ SmiTag(input_reg); // Retag smi. | 4357 __ SmiTag(input_reg); // Retag smi. |
4362 __ bind(&done); | 4358 __ bind(&done); |
4363 } | 4359 } |
4364 | 4360 |
4365 | 4361 |
4366 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 4362 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
4367 Label done, heap_number; | 4363 Label done, heap_number; |
4368 Register input_reg = ToRegister(instr->InputAt(0)); | 4364 Register input_reg = ToRegister(instr->value()); |
4369 | 4365 |
4370 // Heap number map check. | 4366 // Heap number map check. |
4371 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 4367 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
4372 factory()->heap_number_map()); | 4368 factory()->heap_number_map()); |
4373 | 4369 |
4374 if (instr->truncating()) { | 4370 if (instr->truncating()) { |
4375 __ j(equal, &heap_number, Label::kNear); | 4371 __ j(equal, &heap_number, Label::kNear); |
4376 // Check for undefined. Undefined is converted to zero for truncating | 4372 // Check for undefined. Undefined is converted to zero for truncating |
4377 // conversions. | 4373 // conversions. |
4378 __ cmp(input_reg, factory()->undefined_value()); | 4374 __ cmp(input_reg, factory()->undefined_value()); |
(...skipping 20 matching lines...) Expand all Loading... |
4399 DeoptimizeIf(no_condition, instr->environment()); | 4395 DeoptimizeIf(no_condition, instr->environment()); |
4400 | 4396 |
4401 // Reserve space for 64 bit answer. | 4397 // Reserve space for 64 bit answer. |
4402 __ bind(&convert); | 4398 __ bind(&convert); |
4403 __ sub(Operand(esp), Immediate(kDoubleSize)); | 4399 __ sub(Operand(esp), Immediate(kDoubleSize)); |
4404 // Do conversion, which cannot fail because we checked the exponent. | 4400 // Do conversion, which cannot fail because we checked the exponent. |
4405 __ fisttp_d(Operand(esp, 0)); | 4401 __ fisttp_d(Operand(esp, 0)); |
4406 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. | 4402 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. |
4407 __ add(Operand(esp), Immediate(kDoubleSize)); | 4403 __ add(Operand(esp), Immediate(kDoubleSize)); |
4408 } else { | 4404 } else { |
4409 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); | 4405 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); |
4410 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4406 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4411 __ cvttsd2si(input_reg, Operand(xmm0)); | 4407 __ cvttsd2si(input_reg, Operand(xmm0)); |
4412 __ cmp(input_reg, 0x80000000u); | 4408 __ cmp(input_reg, 0x80000000u); |
4413 __ j(not_equal, &done); | 4409 __ j(not_equal, &done); |
4414 // Check if the input was 0x8000000 (kMinInt). | 4410 // Check if the input was 0x8000000 (kMinInt). |
4415 // If no, then we got an overflow and we deoptimize. | 4411 // If no, then we got an overflow and we deoptimize. |
4416 ExternalReference min_int = ExternalReference::address_of_min_int(); | 4412 ExternalReference min_int = ExternalReference::address_of_min_int(); |
4417 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); | 4413 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); |
4418 __ ucomisd(xmm_temp, xmm0); | 4414 __ ucomisd(xmm_temp, xmm0); |
4419 DeoptimizeIf(not_equal, instr->environment()); | 4415 DeoptimizeIf(not_equal, instr->environment()); |
4420 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 4416 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
4421 } | 4417 } |
4422 } else { | 4418 } else { |
4423 // Deoptimize if we don't have a heap number. | 4419 // Deoptimize if we don't have a heap number. |
4424 DeoptimizeIf(not_equal, instr->environment()); | 4420 DeoptimizeIf(not_equal, instr->environment()); |
4425 | 4421 |
4426 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); | 4422 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); |
4427 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4423 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4428 __ cvttsd2si(input_reg, Operand(xmm0)); | 4424 __ cvttsd2si(input_reg, Operand(xmm0)); |
4429 __ cvtsi2sd(xmm_temp, Operand(input_reg)); | 4425 __ cvtsi2sd(xmm_temp, Operand(input_reg)); |
4430 __ ucomisd(xmm0, xmm_temp); | 4426 __ ucomisd(xmm0, xmm_temp); |
4431 DeoptimizeIf(not_equal, instr->environment()); | 4427 DeoptimizeIf(not_equal, instr->environment()); |
4432 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 4428 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
4433 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4429 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
4434 __ test(input_reg, Operand(input_reg)); | 4430 __ test(input_reg, Operand(input_reg)); |
4435 __ j(not_zero, &done); | 4431 __ j(not_zero, &done); |
4436 __ movmskpd(input_reg, xmm0); | 4432 __ movmskpd(input_reg, xmm0); |
4437 __ and_(input_reg, 1); | 4433 __ and_(input_reg, 1); |
4438 DeoptimizeIf(not_zero, instr->environment()); | 4434 DeoptimizeIf(not_zero, instr->environment()); |
4439 } | 4435 } |
4440 } | 4436 } |
4441 __ bind(&done); | 4437 __ bind(&done); |
4442 } | 4438 } |
4443 | 4439 |
4444 | 4440 |
4445 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4441 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
4446 class DeferredTaggedToI: public LDeferredCode { | 4442 class DeferredTaggedToI: public LDeferredCode { |
4447 public: | 4443 public: |
4448 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4444 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
4449 : LDeferredCode(codegen), instr_(instr) { } | 4445 : LDeferredCode(codegen), instr_(instr) { } |
4450 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 4446 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
4451 virtual LInstruction* instr() { return instr_; } | 4447 virtual LInstruction* instr() { return instr_; } |
4452 private: | 4448 private: |
4453 LTaggedToI* instr_; | 4449 LTaggedToI* instr_; |
4454 }; | 4450 }; |
4455 | 4451 |
4456 LOperand* input = instr->InputAt(0); | 4452 LOperand* input = instr->value(); |
4457 ASSERT(input->IsRegister()); | 4453 ASSERT(input->IsRegister()); |
4458 ASSERT(input->Equals(instr->result())); | 4454 ASSERT(input->Equals(instr->result())); |
4459 | 4455 |
4460 Register input_reg = ToRegister(input); | 4456 Register input_reg = ToRegister(input); |
4461 | 4457 |
4462 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 4458 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
4463 | 4459 |
4464 // Smi check. | 4460 // Smi check. |
4465 __ JumpIfNotSmi(input_reg, deferred->entry()); | 4461 __ JumpIfNotSmi(input_reg, deferred->entry()); |
4466 | 4462 |
4467 // Smi to int32 conversion | 4463 // Smi to int32 conversion |
4468 __ SmiUntag(input_reg); // Untag smi. | 4464 __ SmiUntag(input_reg); // Untag smi. |
4469 | 4465 |
4470 __ bind(deferred->exit()); | 4466 __ bind(deferred->exit()); |
4471 } | 4467 } |
4472 | 4468 |
4473 | 4469 |
4474 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4470 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
4475 LOperand* input = instr->InputAt(0); | 4471 LOperand* input = instr->value(); |
4476 ASSERT(input->IsRegister()); | 4472 ASSERT(input->IsRegister()); |
4477 LOperand* temp = instr->TempAt(0); | 4473 LOperand* temp = instr->temp(); |
4478 ASSERT(temp == NULL || temp->IsRegister()); | 4474 ASSERT(temp == NULL || temp->IsRegister()); |
4479 LOperand* result = instr->result(); | 4475 LOperand* result = instr->result(); |
4480 ASSERT(result->IsDoubleRegister()); | 4476 ASSERT(result->IsDoubleRegister()); |
4481 | 4477 |
4482 Register input_reg = ToRegister(input); | 4478 Register input_reg = ToRegister(input); |
4483 XMMRegister result_reg = ToDoubleRegister(result); | 4479 XMMRegister result_reg = ToDoubleRegister(result); |
4484 | 4480 |
4485 bool deoptimize_on_minus_zero = | 4481 bool deoptimize_on_minus_zero = |
4486 instr->hydrogen()->deoptimize_on_minus_zero(); | 4482 instr->hydrogen()->deoptimize_on_minus_zero(); |
4487 Register temp_reg = deoptimize_on_minus_zero ? ToRegister(temp) : no_reg; | 4483 Register temp_reg = deoptimize_on_minus_zero ? ToRegister(temp) : no_reg; |
4488 | 4484 |
4489 EmitNumberUntagD(input_reg, | 4485 EmitNumberUntagD(input_reg, |
4490 temp_reg, | 4486 temp_reg, |
4491 result_reg, | 4487 result_reg, |
4492 instr->hydrogen()->deoptimize_on_undefined(), | 4488 instr->hydrogen()->deoptimize_on_undefined(), |
4493 deoptimize_on_minus_zero, | 4489 deoptimize_on_minus_zero, |
4494 instr->environment()); | 4490 instr->environment()); |
4495 } | 4491 } |
4496 | 4492 |
4497 | 4493 |
4498 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4494 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
4499 LOperand* input = instr->InputAt(0); | 4495 LOperand* input = instr->value(); |
4500 ASSERT(input->IsDoubleRegister()); | 4496 ASSERT(input->IsDoubleRegister()); |
4501 LOperand* result = instr->result(); | 4497 LOperand* result = instr->result(); |
4502 ASSERT(result->IsRegister()); | 4498 ASSERT(result->IsRegister()); |
4503 | 4499 |
4504 XMMRegister input_reg = ToDoubleRegister(input); | 4500 XMMRegister input_reg = ToDoubleRegister(input); |
4505 Register result_reg = ToRegister(result); | 4501 Register result_reg = ToRegister(result); |
4506 | 4502 |
4507 if (instr->truncating()) { | 4503 if (instr->truncating()) { |
4508 // Performs a truncating conversion of a floating point number as used by | 4504 // Performs a truncating conversion of a floating point number as used by |
4509 // the JS bitwise operations. | 4505 // the JS bitwise operations. |
(...skipping 17 matching lines...) Expand all Loading... |
4527 DeoptimizeIf(no_condition, instr->environment()); | 4523 DeoptimizeIf(no_condition, instr->environment()); |
4528 __ bind(&convert); | 4524 __ bind(&convert); |
4529 // Do conversion, which cannot fail because we checked the exponent. | 4525 // Do conversion, which cannot fail because we checked the exponent. |
4530 __ fld_d(Operand(esp, 0)); | 4526 __ fld_d(Operand(esp, 0)); |
4531 __ fisttp_d(Operand(esp, 0)); | 4527 __ fisttp_d(Operand(esp, 0)); |
4532 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | 4528 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. |
4533 __ add(Operand(esp), Immediate(kDoubleSize)); | 4529 __ add(Operand(esp), Immediate(kDoubleSize)); |
4534 __ bind(&done); | 4530 __ bind(&done); |
4535 } else { | 4531 } else { |
4536 Label done; | 4532 Label done; |
4537 Register temp_reg = ToRegister(instr->TempAt(0)); | 4533 Register temp_reg = ToRegister(instr->temp()); |
4538 XMMRegister xmm_scratch = xmm0; | 4534 XMMRegister xmm_scratch = xmm0; |
4539 | 4535 |
4540 // If cvttsd2si succeeded, we're done. Otherwise, we attempt | 4536 // If cvttsd2si succeeded, we're done. Otherwise, we attempt |
4541 // manual conversion. | 4537 // manual conversion. |
4542 __ j(not_equal, &done, Label::kNear); | 4538 __ j(not_equal, &done, Label::kNear); |
4543 | 4539 |
4544 // Get high 32 bits of the input in result_reg and temp_reg. | 4540 // Get high 32 bits of the input in result_reg and temp_reg. |
4545 __ pshufd(xmm_scratch, input_reg, 1); | 4541 __ pshufd(xmm_scratch, input_reg, 1); |
4546 __ movd(Operand(temp_reg), xmm_scratch); | 4542 __ movd(Operand(temp_reg), xmm_scratch); |
4547 __ mov(result_reg, temp_reg); | 4543 __ mov(result_reg, temp_reg); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4606 // deoptimize. | 4602 // deoptimize. |
4607 __ and_(result_reg, 1); | 4603 __ and_(result_reg, 1); |
4608 DeoptimizeIf(not_zero, instr->environment()); | 4604 DeoptimizeIf(not_zero, instr->environment()); |
4609 } | 4605 } |
4610 __ bind(&done); | 4606 __ bind(&done); |
4611 } | 4607 } |
4612 } | 4608 } |
4613 | 4609 |
4614 | 4610 |
4615 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4611 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
4616 LOperand* input = instr->InputAt(0); | 4612 LOperand* input = instr->value(); |
4617 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 4613 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
4618 DeoptimizeIf(not_zero, instr->environment()); | 4614 DeoptimizeIf(not_zero, instr->environment()); |
4619 } | 4615 } |
4620 | 4616 |
4621 | 4617 |
4622 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4618 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
4623 LOperand* input = instr->InputAt(0); | 4619 LOperand* input = instr->value(); |
4624 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 4620 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
4625 DeoptimizeIf(zero, instr->environment()); | 4621 DeoptimizeIf(zero, instr->environment()); |
4626 } | 4622 } |
4627 | 4623 |
4628 | 4624 |
4629 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4625 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
4630 Register input = ToRegister(instr->InputAt(0)); | 4626 Register input = ToRegister(instr->value()); |
4631 Register temp = ToRegister(instr->TempAt(0)); | 4627 Register temp = ToRegister(instr->temp()); |
4632 | 4628 |
4633 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 4629 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
4634 | 4630 |
4635 if (instr->hydrogen()->is_interval_check()) { | 4631 if (instr->hydrogen()->is_interval_check()) { |
4636 InstanceType first; | 4632 InstanceType first; |
4637 InstanceType last; | 4633 InstanceType last; |
4638 instr->hydrogen()->GetCheckInterval(&first, &last); | 4634 instr->hydrogen()->GetCheckInterval(&first, &last); |
4639 | 4635 |
4640 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 4636 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
4641 static_cast<int8_t>(first)); | 4637 static_cast<int8_t>(first)); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4691 CompareMapMode mode, | 4687 CompareMapMode mode, |
4692 LEnvironment* env) { | 4688 LEnvironment* env) { |
4693 Label success; | 4689 Label success; |
4694 __ CompareMap(reg, map, &success, mode); | 4690 __ CompareMap(reg, map, &success, mode); |
4695 DeoptimizeIf(not_equal, env); | 4691 DeoptimizeIf(not_equal, env); |
4696 __ bind(&success); | 4692 __ bind(&success); |
4697 } | 4693 } |
4698 | 4694 |
4699 | 4695 |
4700 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4696 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
4701 LOperand* input = instr->InputAt(0); | 4697 LOperand* input = instr->value(); |
4702 ASSERT(input->IsRegister()); | 4698 ASSERT(input->IsRegister()); |
4703 Register reg = ToRegister(input); | 4699 Register reg = ToRegister(input); |
4704 | 4700 |
4705 Label success; | 4701 Label success; |
4706 SmallMapList* map_set = instr->hydrogen()->map_set(); | 4702 SmallMapList* map_set = instr->hydrogen()->map_set(); |
4707 for (int i = 0; i < map_set->length() - 1; i++) { | 4703 for (int i = 0; i < map_set->length() - 1; i++) { |
4708 Handle<Map> map = map_set->at(i); | 4704 Handle<Map> map = map_set->at(i); |
4709 __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP); | 4705 __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP); |
4710 __ j(equal, &success); | 4706 __ j(equal, &success); |
4711 } | 4707 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4757 // smi | 4753 // smi |
4758 __ bind(&is_smi); | 4754 __ bind(&is_smi); |
4759 __ SmiUntag(input_reg); | 4755 __ SmiUntag(input_reg); |
4760 __ ClampUint8(input_reg); | 4756 __ ClampUint8(input_reg); |
4761 | 4757 |
4762 __ bind(&done); | 4758 __ bind(&done); |
4763 } | 4759 } |
4764 | 4760 |
4765 | 4761 |
4766 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 4762 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
4767 Register reg = ToRegister(instr->TempAt(0)); | 4763 Register reg = ToRegister(instr->temp()); |
4768 | 4764 |
4769 Handle<JSObject> holder = instr->holder(); | 4765 Handle<JSObject> holder = instr->holder(); |
4770 Handle<JSObject> current_prototype = instr->prototype(); | 4766 Handle<JSObject> current_prototype = instr->prototype(); |
4771 | 4767 |
4772 // Load prototype object. | 4768 // Load prototype object. |
4773 __ LoadHeapObject(reg, current_prototype); | 4769 __ LoadHeapObject(reg, current_prototype); |
4774 | 4770 |
4775 // Check prototype maps up to the holder. | 4771 // Check prototype maps up to the holder. |
4776 while (!current_prototype.is_identical_to(holder)) { | 4772 while (!current_prototype.is_identical_to(holder)) { |
4777 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), | 4773 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), |
(...skipping 19 matching lines...) Expand all Loading... |
4797 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } | 4793 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } |
4798 virtual LInstruction* instr() { return instr_; } | 4794 virtual LInstruction* instr() { return instr_; } |
4799 private: | 4795 private: |
4800 LAllocateObject* instr_; | 4796 LAllocateObject* instr_; |
4801 }; | 4797 }; |
4802 | 4798 |
4803 DeferredAllocateObject* deferred = | 4799 DeferredAllocateObject* deferred = |
4804 new(zone()) DeferredAllocateObject(this, instr); | 4800 new(zone()) DeferredAllocateObject(this, instr); |
4805 | 4801 |
4806 Register result = ToRegister(instr->result()); | 4802 Register result = ToRegister(instr->result()); |
4807 Register scratch = ToRegister(instr->TempAt(0)); | 4803 Register scratch = ToRegister(instr->temp()); |
4808 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); | 4804 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); |
4809 Handle<Map> initial_map(constructor->initial_map()); | 4805 Handle<Map> initial_map(constructor->initial_map()); |
4810 int instance_size = initial_map->instance_size(); | 4806 int instance_size = initial_map->instance_size(); |
4811 ASSERT(initial_map->pre_allocated_property_fields() + | 4807 ASSERT(initial_map->pre_allocated_property_fields() + |
4812 initial_map->unused_property_fields() - | 4808 initial_map->unused_property_fields() - |
4813 initial_map->inobject_properties() == 0); | 4809 initial_map->inobject_properties() == 0); |
4814 | 4810 |
4815 // Allocate memory for the object. The initial map might change when | 4811 // Allocate memory for the object. The initial map might change when |
4816 // the constructor's prototype changes, but instance size and property | 4812 // the constructor's prototype changes, but instance size and property |
4817 // counts remain unchanged (if slack tracking finished). | 4813 // counts remain unchanged (if slack tracking finished). |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5116 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 5112 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
5117 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); | 5113 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); |
5118 } else { | 5114 } else { |
5119 FastCloneShallowObjectStub stub(properties_count); | 5115 FastCloneShallowObjectStub stub(properties_count); |
5120 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 5116 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
5121 } | 5117 } |
5122 } | 5118 } |
5123 | 5119 |
5124 | 5120 |
5125 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5121 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
5126 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 5122 ASSERT(ToRegister(instr->value()).is(eax)); |
5127 __ push(eax); | 5123 __ push(eax); |
5128 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5124 CallRuntime(Runtime::kToFastProperties, 1, instr); |
5129 } | 5125 } |
5130 | 5126 |
5131 | 5127 |
5132 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5128 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
5133 ASSERT(ToRegister(instr->context()).is(esi)); | 5129 ASSERT(ToRegister(instr->context()).is(esi)); |
5134 Label materialized; | 5130 Label materialized; |
5135 // Registers will be used as follows: | 5131 // Registers will be used as follows: |
5136 // ecx = literals array. | 5132 // ecx = literals array. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5196 __ push(Immediate(shared_info)); | 5192 __ push(Immediate(shared_info)); |
5197 __ push(Immediate(pretenure | 5193 __ push(Immediate(pretenure |
5198 ? factory()->true_value() | 5194 ? factory()->true_value() |
5199 : factory()->false_value())); | 5195 : factory()->false_value())); |
5200 CallRuntime(Runtime::kNewClosure, 3, instr); | 5196 CallRuntime(Runtime::kNewClosure, 3, instr); |
5201 } | 5197 } |
5202 } | 5198 } |
5203 | 5199 |
5204 | 5200 |
5205 void LCodeGen::DoTypeof(LTypeof* instr) { | 5201 void LCodeGen::DoTypeof(LTypeof* instr) { |
5206 LOperand* input = instr->InputAt(1); | 5202 LOperand* input = instr->value(); |
5207 EmitPushTaggedOperand(input); | 5203 EmitPushTaggedOperand(input); |
5208 CallRuntime(Runtime::kTypeof, 1, instr); | 5204 CallRuntime(Runtime::kTypeof, 1, instr); |
5209 } | 5205 } |
5210 | 5206 |
5211 | 5207 |
5212 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5208 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
5213 Register input = ToRegister(instr->InputAt(0)); | 5209 Register input = ToRegister(instr->value()); |
5214 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5210 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
5215 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5211 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
5216 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 5212 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
5217 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 5213 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
5218 | 5214 |
5219 Condition final_branch_condition = | 5215 Condition final_branch_condition = |
5220 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); | 5216 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); |
5221 if (final_branch_condition != no_condition) { | 5217 if (final_branch_condition != no_condition) { |
5222 EmitBranch(true_block, false_block, final_branch_condition); | 5218 EmitBranch(true_block, false_block, final_branch_condition); |
5223 } | 5219 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5287 final_branch_condition = zero; | 5283 final_branch_condition = zero; |
5288 | 5284 |
5289 } else { | 5285 } else { |
5290 __ jmp(false_label); | 5286 __ jmp(false_label); |
5291 } | 5287 } |
5292 return final_branch_condition; | 5288 return final_branch_condition; |
5293 } | 5289 } |
5294 | 5290 |
5295 | 5291 |
5296 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5292 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
5297 Register temp = ToRegister(instr->TempAt(0)); | 5293 Register temp = ToRegister(instr->temp()); |
5298 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5294 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
5299 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5295 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
5300 | 5296 |
5301 EmitIsConstructCall(temp); | 5297 EmitIsConstructCall(temp); |
5302 EmitBranch(true_block, false_block, equal); | 5298 EmitBranch(true_block, false_block, equal); |
5303 } | 5299 } |
5304 | 5300 |
5305 | 5301 |
5306 void LCodeGen::EmitIsConstructCall(Register temp) { | 5302 void LCodeGen::EmitIsConstructCall(Register temp) { |
5307 // Get the frame pointer for the calling frame. | 5303 // Get the frame pointer for the calling frame. |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5545 FixedArray::kHeaderSize - kPointerSize)); | 5541 FixedArray::kHeaderSize - kPointerSize)); |
5546 __ bind(&done); | 5542 __ bind(&done); |
5547 } | 5543 } |
5548 | 5544 |
5549 | 5545 |
5550 #undef __ | 5546 #undef __ |
5551 | 5547 |
5552 } } // namespace v8::internal | 5548 } } // namespace v8::internal |
5553 | 5549 |
5554 #endif // V8_TARGET_ARCH_IA32 | 5550 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |