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