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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 // cp: Callee's context. | 131 // cp: Callee's context. |
132 // fp: Caller's frame pointer. | 132 // fp: Caller's frame pointer. |
133 // lr: Caller's pc. | 133 // lr: Caller's pc. |
134 | 134 |
135 // Strict mode functions and builtins need to replace the receiver | 135 // Strict mode functions and builtins need to replace the receiver |
136 // with undefined when called as functions (without an explicit | 136 // with undefined when called as functions (without an explicit |
137 // receiver object). r5 is zero for method calls and non-zero for | 137 // receiver object). r5 is zero for method calls and non-zero for |
138 // function calls. | 138 // function calls. |
139 if (!info_->is_classic_mode() || info_->is_native()) { | 139 if (!info_->is_classic_mode() || info_->is_native()) { |
140 Label ok; | 140 Label ok; |
141 __ cmp(r5, Operand(0)); | 141 __ cmp(r5, Operand::Zero()); |
142 __ b(eq, &ok); | 142 __ b(eq, &ok); |
143 int receiver_offset = scope()->num_parameters() * kPointerSize; | 143 int receiver_offset = scope()->num_parameters() * kPointerSize; |
144 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 144 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
145 __ str(r2, MemOperand(sp, receiver_offset)); | 145 __ str(r2, MemOperand(sp, receiver_offset)); |
146 __ bind(&ok); | 146 __ bind(&ok); |
147 } | 147 } |
148 | 148 |
149 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 149 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
150 __ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP. | 150 __ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP. |
151 | 151 |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 return Operand(constant->Integer32Value()); | 417 return Operand(constant->Integer32Value()); |
418 } else if (r.IsDouble()) { | 418 } else if (r.IsDouble()) { |
419 Abort("ToOperand Unsupported double immediate."); | 419 Abort("ToOperand Unsupported double immediate."); |
420 } | 420 } |
421 ASSERT(r.IsTagged()); | 421 ASSERT(r.IsTagged()); |
422 return Operand(constant->handle()); | 422 return Operand(constant->handle()); |
423 } else if (op->IsRegister()) { | 423 } else if (op->IsRegister()) { |
424 return Operand(ToRegister(op)); | 424 return Operand(ToRegister(op)); |
425 } else if (op->IsDoubleRegister()) { | 425 } else if (op->IsDoubleRegister()) { |
426 Abort("ToOperand IsDoubleRegister unimplemented"); | 426 Abort("ToOperand IsDoubleRegister unimplemented"); |
427 return Operand(0); | 427 return Operand::Zero(); |
428 } | 428 } |
429 // Stack slots not implemented, use ToMemOperand instead. | 429 // Stack slots not implemented, use ToMemOperand instead. |
430 UNREACHABLE(); | 430 UNREACHABLE(); |
431 return Operand(0); | 431 return Operand::Zero(); |
432 } | 432 } |
433 | 433 |
434 | 434 |
435 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { | 435 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { |
436 ASSERT(!op->IsRegister()); | 436 ASSERT(!op->IsRegister()); |
437 ASSERT(!op->IsDoubleRegister()); | 437 ASSERT(!op->IsDoubleRegister()); |
438 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); | 438 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); |
439 int index = op->index(); | 439 int index = op->index(); |
440 if (index >= 0) { | 440 if (index >= 0) { |
441 // Local or spill slot. Skip the frame pointer, function, and | 441 // Local or spill slot. Skip the frame pointer, function, and |
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 953 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
954 Register dividend = ToRegister(instr->left()); | 954 Register dividend = ToRegister(instr->left()); |
955 Register result = ToRegister(instr->result()); | 955 Register result = ToRegister(instr->result()); |
956 | 956 |
957 int32_t divisor = | 957 int32_t divisor = |
958 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 958 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
959 | 959 |
960 if (divisor < 0) divisor = -divisor; | 960 if (divisor < 0) divisor = -divisor; |
961 | 961 |
962 Label positive_dividend, done; | 962 Label positive_dividend, done; |
963 __ cmp(dividend, Operand(0)); | 963 __ cmp(dividend, Operand::Zero()); |
964 __ b(pl, &positive_dividend); | 964 __ b(pl, &positive_dividend); |
965 __ rsb(result, dividend, Operand(0)); | 965 __ rsb(result, dividend, Operand::Zero()); |
966 __ and_(result, result, Operand(divisor - 1), SetCC); | 966 __ and_(result, result, Operand(divisor - 1), SetCC); |
967 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 967 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
968 DeoptimizeIf(eq, instr->environment()); | 968 DeoptimizeIf(eq, instr->environment()); |
969 } | 969 } |
970 __ rsb(result, result, Operand(0)); | 970 __ rsb(result, result, Operand::Zero()); |
971 __ b(&done); | 971 __ b(&done); |
972 __ bind(&positive_dividend); | 972 __ bind(&positive_dividend); |
973 __ and_(result, dividend, Operand(divisor - 1)); | 973 __ and_(result, dividend, Operand(divisor - 1)); |
974 __ bind(&done); | 974 __ bind(&done); |
975 return; | 975 return; |
976 } | 976 } |
977 | 977 |
978 // These registers hold untagged 32 bit values. | 978 // These registers hold untagged 32 bit values. |
979 Register left = ToRegister(instr->left()); | 979 Register left = ToRegister(instr->left()); |
980 Register right = ToRegister(instr->right()); | 980 Register right = ToRegister(instr->right()); |
981 Register result = ToRegister(instr->result()); | 981 Register result = ToRegister(instr->result()); |
982 Label done; | 982 Label done; |
983 | 983 |
984 if (CpuFeatures::IsSupported(SUDIV)) { | 984 if (CpuFeatures::IsSupported(SUDIV)) { |
985 CpuFeatures::Scope scope(SUDIV); | 985 CpuFeatures::Scope scope(SUDIV); |
986 // Check for x % 0. | 986 // Check for x % 0. |
987 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 987 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
988 __ cmp(right, Operand(0)); | 988 __ cmp(right, Operand::Zero()); |
989 DeoptimizeIf(eq, instr->environment()); | 989 DeoptimizeIf(eq, instr->environment()); |
990 } | 990 } |
991 | 991 |
992 // For r3 = r1 % r2; we can have the following ARM code | 992 // For r3 = r1 % r2; we can have the following ARM code |
993 // sdiv r3, r1, r2 | 993 // sdiv r3, r1, r2 |
994 // mls r3, r3, r2, r1 | 994 // mls r3, r3, r2, r1 |
995 | 995 |
996 __ sdiv(result, left, right); | 996 __ sdiv(result, left, right); |
997 __ mls(result, result, right, left); | 997 __ mls(result, result, right, left); |
998 __ cmp(result, Operand(0)); | 998 __ cmp(result, Operand::Zero()); |
999 __ b(ne, &done); | 999 __ b(ne, &done); |
1000 | 1000 |
1001 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1001 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1002 __ cmp(left, Operand(0)); | 1002 __ cmp(left, Operand::Zero()); |
1003 DeoptimizeIf(lt, instr->environment()); | 1003 DeoptimizeIf(lt, instr->environment()); |
1004 } | 1004 } |
1005 } else { | 1005 } else { |
1006 Register scratch = scratch0(); | 1006 Register scratch = scratch0(); |
1007 Register scratch2 = ToRegister(instr->temp()); | 1007 Register scratch2 = ToRegister(instr->temp()); |
1008 DwVfpRegister dividend = ToDoubleRegister(instr->temp2()); | 1008 DwVfpRegister dividend = ToDoubleRegister(instr->temp2()); |
1009 DwVfpRegister divisor = ToDoubleRegister(instr->temp3()); | 1009 DwVfpRegister divisor = ToDoubleRegister(instr->temp3()); |
1010 DwVfpRegister quotient = double_scratch0(); | 1010 DwVfpRegister quotient = double_scratch0(); |
1011 | 1011 |
1012 ASSERT(!dividend.is(divisor)); | 1012 ASSERT(!dividend.is(divisor)); |
1013 ASSERT(!dividend.is(quotient)); | 1013 ASSERT(!dividend.is(quotient)); |
1014 ASSERT(!divisor.is(quotient)); | 1014 ASSERT(!divisor.is(quotient)); |
1015 ASSERT(!scratch.is(left)); | 1015 ASSERT(!scratch.is(left)); |
1016 ASSERT(!scratch.is(right)); | 1016 ASSERT(!scratch.is(right)); |
1017 ASSERT(!scratch.is(result)); | 1017 ASSERT(!scratch.is(result)); |
1018 | 1018 |
1019 Label vfp_modulo, both_positive, right_negative; | 1019 Label vfp_modulo, both_positive, right_negative; |
1020 | 1020 |
1021 // Check for x % 0. | 1021 // Check for x % 0. |
1022 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1022 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
1023 __ cmp(right, Operand(0)); | 1023 __ cmp(right, Operand::Zero()); |
1024 DeoptimizeIf(eq, instr->environment()); | 1024 DeoptimizeIf(eq, instr->environment()); |
1025 } | 1025 } |
1026 | 1026 |
1027 __ Move(result, left); | 1027 __ Move(result, left); |
1028 | 1028 |
1029 // (0 % x) must yield 0 (if x is finite, which is the case here). | 1029 // (0 % x) must yield 0 (if x is finite, which is the case here). |
1030 __ cmp(left, Operand(0)); | 1030 __ cmp(left, Operand::Zero()); |
1031 __ b(eq, &done); | 1031 __ b(eq, &done); |
1032 // Preload right in a vfp register. | 1032 // Preload right in a vfp register. |
1033 __ vmov(divisor.low(), right); | 1033 __ vmov(divisor.low(), right); |
1034 __ b(lt, &vfp_modulo); | 1034 __ b(lt, &vfp_modulo); |
1035 | 1035 |
1036 __ cmp(left, Operand(right)); | 1036 __ cmp(left, Operand(right)); |
1037 __ b(lt, &done); | 1037 __ b(lt, &done); |
1038 | 1038 |
1039 // Check for (positive) power of two on the right hand side. | 1039 // Check for (positive) power of two on the right hand side. |
1040 __ JumpIfNotPowerOfTwoOrZeroAndNeg(right, | 1040 __ JumpIfNotPowerOfTwoOrZeroAndNeg(right, |
1041 scratch, | 1041 scratch, |
1042 &right_negative, | 1042 &right_negative, |
1043 &both_positive); | 1043 &both_positive); |
1044 // Perform modulo operation (scratch contains right - 1). | 1044 // Perform modulo operation (scratch contains right - 1). |
1045 __ and_(result, scratch, Operand(left)); | 1045 __ and_(result, scratch, Operand(left)); |
1046 __ b(&done); | 1046 __ b(&done); |
1047 | 1047 |
1048 __ bind(&right_negative); | 1048 __ bind(&right_negative); |
1049 // Negate right. The sign of the divisor does not matter. | 1049 // Negate right. The sign of the divisor does not matter. |
1050 __ rsb(right, right, Operand(0)); | 1050 __ rsb(right, right, Operand::Zero()); |
1051 | 1051 |
1052 __ bind(&both_positive); | 1052 __ bind(&both_positive); |
1053 const int kUnfolds = 3; | 1053 const int kUnfolds = 3; |
1054 // If the right hand side is smaller than the (nonnegative) | 1054 // If the right hand side is smaller than the (nonnegative) |
1055 // left hand side, the left hand side is the result. | 1055 // left hand side, the left hand side is the result. |
1056 // Else try a few subtractions of the left hand side. | 1056 // Else try a few subtractions of the left hand side. |
1057 __ mov(scratch, left); | 1057 __ mov(scratch, left); |
1058 for (int i = 0; i < kUnfolds; i++) { | 1058 for (int i = 0; i < kUnfolds; i++) { |
1059 // Check if the left hand side is less or equal than the | 1059 // Check if the left hand side is less or equal than the |
1060 // the right hand side. | 1060 // the right hand side. |
(...skipping 30 matching lines...) Expand all Loading... |
1091 __ vcvt_s32_f64(double_scratch.low(), double_scratch); | 1091 __ vcvt_s32_f64(double_scratch.low(), double_scratch); |
1092 __ vmov(scratch, double_scratch.low()); | 1092 __ vmov(scratch, double_scratch.low()); |
1093 | 1093 |
1094 if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1094 if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1095 __ sub(result, left, scratch); | 1095 __ sub(result, left, scratch); |
1096 } else { | 1096 } else { |
1097 Label ok; | 1097 Label ok; |
1098 // Check for -0. | 1098 // Check for -0. |
1099 __ sub(scratch2, left, scratch, SetCC); | 1099 __ sub(scratch2, left, scratch, SetCC); |
1100 __ b(ne, &ok); | 1100 __ b(ne, &ok); |
1101 __ cmp(left, Operand(0)); | 1101 __ cmp(left, Operand::Zero()); |
1102 DeoptimizeIf(mi, instr->environment()); | 1102 DeoptimizeIf(mi, instr->environment()); |
1103 __ bind(&ok); | 1103 __ bind(&ok); |
1104 // Load the result and we are done. | 1104 // Load the result and we are done. |
1105 __ mov(result, scratch2); | 1105 __ mov(result, scratch2); |
1106 } | 1106 } |
1107 } | 1107 } |
1108 __ bind(&done); | 1108 __ bind(&done); |
1109 } | 1109 } |
1110 | 1110 |
1111 | 1111 |
(...skipping 14 matching lines...) Expand all Loading... |
1126 | 1126 |
1127 switch (divisor_abs) { | 1127 switch (divisor_abs) { |
1128 case 0: | 1128 case 0: |
1129 DeoptimizeIf(al, environment); | 1129 DeoptimizeIf(al, environment); |
1130 return; | 1130 return; |
1131 | 1131 |
1132 case 1: | 1132 case 1: |
1133 if (divisor > 0) { | 1133 if (divisor > 0) { |
1134 __ Move(result, dividend); | 1134 __ Move(result, dividend); |
1135 } else { | 1135 } else { |
1136 __ rsb(result, dividend, Operand(0), SetCC); | 1136 __ rsb(result, dividend, Operand::Zero(), SetCC); |
1137 DeoptimizeIf(vs, environment); | 1137 DeoptimizeIf(vs, environment); |
1138 } | 1138 } |
1139 // Compute the remainder. | 1139 // Compute the remainder. |
1140 __ mov(remainder, Operand(0)); | 1140 __ mov(remainder, Operand::Zero()); |
1141 return; | 1141 return; |
1142 | 1142 |
1143 default: | 1143 default: |
1144 if (IsPowerOf2(divisor_abs)) { | 1144 if (IsPowerOf2(divisor_abs)) { |
1145 // Branch and condition free code for integer division by a power | 1145 // Branch and condition free code for integer division by a power |
1146 // of two. | 1146 // of two. |
1147 int32_t power = WhichPowerOf2(divisor_abs); | 1147 int32_t power = WhichPowerOf2(divisor_abs); |
1148 if (power > 1) { | 1148 if (power > 1) { |
1149 __ mov(scratch, Operand(dividend, ASR, power - 1)); | 1149 __ mov(scratch, Operand(dividend, ASR, power - 1)); |
1150 } | 1150 } |
1151 __ add(scratch, dividend, Operand(scratch, LSR, 32 - power)); | 1151 __ add(scratch, dividend, Operand(scratch, LSR, 32 - power)); |
1152 __ mov(result, Operand(scratch, ASR, power)); | 1152 __ mov(result, Operand(scratch, ASR, power)); |
1153 // Negate if necessary. | 1153 // Negate if necessary. |
1154 // We don't need to check for overflow because the case '-1' is | 1154 // We don't need to check for overflow because the case '-1' is |
1155 // handled separately. | 1155 // handled separately. |
1156 if (divisor < 0) { | 1156 if (divisor < 0) { |
1157 ASSERT(divisor != -1); | 1157 ASSERT(divisor != -1); |
1158 __ rsb(result, result, Operand(0)); | 1158 __ rsb(result, result, Operand::Zero()); |
1159 } | 1159 } |
1160 // Compute the remainder. | 1160 // Compute the remainder. |
1161 if (divisor > 0) { | 1161 if (divisor > 0) { |
1162 __ sub(remainder, dividend, Operand(result, LSL, power)); | 1162 __ sub(remainder, dividend, Operand(result, LSL, power)); |
1163 } else { | 1163 } else { |
1164 __ add(remainder, dividend, Operand(result, LSL, power)); | 1164 __ add(remainder, dividend, Operand(result, LSL, power)); |
1165 } | 1165 } |
1166 return; | 1166 return; |
1167 } else { | 1167 } else { |
1168 // Use magic numbers for a few specific divisors. | 1168 // Use magic numbers for a few specific divisors. |
(...skipping 15 matching lines...) Expand all Loading... |
1184 | 1184 |
1185 __ mov(ip, Operand(M)); | 1185 __ mov(ip, Operand(M)); |
1186 __ smull(ip, scratch, dividend, ip); | 1186 __ smull(ip, scratch, dividend, ip); |
1187 if (M < 0) { | 1187 if (M < 0) { |
1188 __ add(scratch, scratch, Operand(dividend)); | 1188 __ add(scratch, scratch, Operand(dividend)); |
1189 } | 1189 } |
1190 if (s > 0) { | 1190 if (s > 0) { |
1191 __ mov(scratch, Operand(scratch, ASR, s)); | 1191 __ mov(scratch, Operand(scratch, ASR, s)); |
1192 } | 1192 } |
1193 __ add(result, scratch, Operand(dividend, LSR, 31)); | 1193 __ add(result, scratch, Operand(dividend, LSR, 31)); |
1194 if (divisor < 0) __ rsb(result, result, Operand(0)); | 1194 if (divisor < 0) __ rsb(result, result, Operand::Zero()); |
1195 // Compute the remainder. | 1195 // Compute the remainder. |
1196 __ mov(ip, Operand(divisor)); | 1196 __ mov(ip, Operand(divisor)); |
1197 // This sequence could be replaced with 'mls' when | 1197 // This sequence could be replaced with 'mls' when |
1198 // it gets implemented. | 1198 // it gets implemented. |
1199 __ mul(scratch, result, ip); | 1199 __ mul(scratch, result, ip); |
1200 __ sub(remainder, dividend, scratch); | 1200 __ sub(remainder, dividend, scratch); |
1201 } | 1201 } |
1202 } | 1202 } |
1203 } | 1203 } |
1204 | 1204 |
(...skipping 14 matching lines...) Expand all Loading... |
1219 LDivI* instr_; | 1219 LDivI* instr_; |
1220 }; | 1220 }; |
1221 | 1221 |
1222 const Register left = ToRegister(instr->left()); | 1222 const Register left = ToRegister(instr->left()); |
1223 const Register right = ToRegister(instr->right()); | 1223 const Register right = ToRegister(instr->right()); |
1224 const Register scratch = scratch0(); | 1224 const Register scratch = scratch0(); |
1225 const Register result = ToRegister(instr->result()); | 1225 const Register result = ToRegister(instr->result()); |
1226 | 1226 |
1227 // Check for x / 0. | 1227 // Check for x / 0. |
1228 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1228 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
1229 __ cmp(right, Operand(0)); | 1229 __ cmp(right, Operand::Zero()); |
1230 DeoptimizeIf(eq, instr->environment()); | 1230 DeoptimizeIf(eq, instr->environment()); |
1231 } | 1231 } |
1232 | 1232 |
1233 // Check for (0 / -x) that will produce negative zero. | 1233 // Check for (0 / -x) that will produce negative zero. |
1234 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1234 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1235 Label left_not_zero; | 1235 Label left_not_zero; |
1236 __ cmp(left, Operand(0)); | 1236 __ cmp(left, Operand::Zero()); |
1237 __ b(ne, &left_not_zero); | 1237 __ b(ne, &left_not_zero); |
1238 __ cmp(right, Operand(0)); | 1238 __ cmp(right, Operand::Zero()); |
1239 DeoptimizeIf(mi, instr->environment()); | 1239 DeoptimizeIf(mi, instr->environment()); |
1240 __ bind(&left_not_zero); | 1240 __ bind(&left_not_zero); |
1241 } | 1241 } |
1242 | 1242 |
1243 // Check for (-kMinInt / -1). | 1243 // Check for (-kMinInt / -1). |
1244 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1244 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1245 Label left_not_min_int; | 1245 Label left_not_min_int; |
1246 __ cmp(left, Operand(kMinInt)); | 1246 __ cmp(left, Operand(kMinInt)); |
1247 __ b(ne, &left_not_min_int); | 1247 __ b(ne, &left_not_min_int); |
1248 __ cmp(right, Operand(-1)); | 1248 __ cmp(right, Operand(-1)); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 const Register left = ToRegister(instr->left()); | 1292 const Register left = ToRegister(instr->left()); |
1293 const Register remainder = ToRegister(instr->temp()); | 1293 const Register remainder = ToRegister(instr->temp()); |
1294 const Register scratch = scratch0(); | 1294 const Register scratch = scratch0(); |
1295 | 1295 |
1296 // We only optimize this for division by constants, because the standard | 1296 // We only optimize this for division by constants, because the standard |
1297 // integer division routine is usually slower than transitionning to VFP. | 1297 // integer division routine is usually slower than transitionning to VFP. |
1298 // This could be optimized on processors with SDIV available. | 1298 // This could be optimized on processors with SDIV available. |
1299 ASSERT(instr->right()->IsConstantOperand()); | 1299 ASSERT(instr->right()->IsConstantOperand()); |
1300 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); | 1300 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); |
1301 if (divisor < 0) { | 1301 if (divisor < 0) { |
1302 __ cmp(left, Operand(0)); | 1302 __ cmp(left, Operand::Zero()); |
1303 DeoptimizeIf(eq, instr->environment()); | 1303 DeoptimizeIf(eq, instr->environment()); |
1304 } | 1304 } |
1305 EmitSignedIntegerDivisionByConstant(result, | 1305 EmitSignedIntegerDivisionByConstant(result, |
1306 left, | 1306 left, |
1307 divisor, | 1307 divisor, |
1308 remainder, | 1308 remainder, |
1309 scratch, | 1309 scratch, |
1310 instr->environment()); | 1310 instr->environment()); |
1311 // We operated a truncating division. Correct the result if necessary. | 1311 // We operated a truncating division. Correct the result if necessary. |
1312 __ cmp(remainder, Operand(0)); | 1312 __ cmp(remainder, Operand::Zero()); |
1313 __ teq(remainder, Operand(divisor), ne); | 1313 __ teq(remainder, Operand(divisor), ne); |
1314 __ sub(result, result, Operand(1), LeaveCC, mi); | 1314 __ sub(result, result, Operand(1), LeaveCC, mi); |
1315 } | 1315 } |
1316 | 1316 |
1317 | 1317 |
1318 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, | 1318 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, |
1319 LOperand* left_argument, | 1319 LOperand* left_argument, |
1320 LOperand* right_argument, | 1320 LOperand* right_argument, |
1321 Token::Value op) { | 1321 Token::Value op) { |
1322 Register left = ToRegister(left_argument); | 1322 Register left = ToRegister(left_argument); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1358 bool bailout_on_minus_zero = | 1358 bool bailout_on_minus_zero = |
1359 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1359 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
1360 | 1360 |
1361 if (right_op->IsConstantOperand() && !can_overflow) { | 1361 if (right_op->IsConstantOperand() && !can_overflow) { |
1362 // Use optimized code for specific constants. | 1362 // Use optimized code for specific constants. |
1363 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1363 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
1364 | 1364 |
1365 if (bailout_on_minus_zero && (constant < 0)) { | 1365 if (bailout_on_minus_zero && (constant < 0)) { |
1366 // The case of a null constant will be handled separately. | 1366 // The case of a null constant will be handled separately. |
1367 // If constant is negative and left is null, the result should be -0. | 1367 // If constant is negative and left is null, the result should be -0. |
1368 __ cmp(left, Operand(0)); | 1368 __ cmp(left, Operand::Zero()); |
1369 DeoptimizeIf(eq, instr->environment()); | 1369 DeoptimizeIf(eq, instr->environment()); |
1370 } | 1370 } |
1371 | 1371 |
1372 switch (constant) { | 1372 switch (constant) { |
1373 case -1: | 1373 case -1: |
1374 __ rsb(result, left, Operand(0)); | 1374 __ rsb(result, left, Operand::Zero()); |
1375 break; | 1375 break; |
1376 case 0: | 1376 case 0: |
1377 if (bailout_on_minus_zero) { | 1377 if (bailout_on_minus_zero) { |
1378 // If left is strictly negative and the constant is null, the | 1378 // If left is strictly negative and the constant is null, the |
1379 // result is -0. Deoptimize if required, otherwise return 0. | 1379 // result is -0. Deoptimize if required, otherwise return 0. |
1380 __ cmp(left, Operand(0)); | 1380 __ cmp(left, Operand::Zero()); |
1381 DeoptimizeIf(mi, instr->environment()); | 1381 DeoptimizeIf(mi, instr->environment()); |
1382 } | 1382 } |
1383 __ mov(result, Operand(0)); | 1383 __ mov(result, Operand::Zero()); |
1384 break; | 1384 break; |
1385 case 1: | 1385 case 1: |
1386 __ Move(result, left); | 1386 __ Move(result, left); |
1387 break; | 1387 break; |
1388 default: | 1388 default: |
1389 // Multiplying by powers of two and powers of two plus or minus | 1389 // Multiplying by powers of two and powers of two plus or minus |
1390 // one can be done faster with shifted operands. | 1390 // one can be done faster with shifted operands. |
1391 // For other constants we emit standard code. | 1391 // For other constants we emit standard code. |
1392 int32_t mask = constant >> 31; | 1392 int32_t mask = constant >> 31; |
1393 uint32_t constant_abs = (constant + mask) ^ mask; | 1393 uint32_t constant_abs = (constant + mask) ^ mask; |
1394 | 1394 |
1395 if (IsPowerOf2(constant_abs) || | 1395 if (IsPowerOf2(constant_abs) || |
1396 IsPowerOf2(constant_abs - 1) || | 1396 IsPowerOf2(constant_abs - 1) || |
1397 IsPowerOf2(constant_abs + 1)) { | 1397 IsPowerOf2(constant_abs + 1)) { |
1398 if (IsPowerOf2(constant_abs)) { | 1398 if (IsPowerOf2(constant_abs)) { |
1399 int32_t shift = WhichPowerOf2(constant_abs); | 1399 int32_t shift = WhichPowerOf2(constant_abs); |
1400 __ mov(result, Operand(left, LSL, shift)); | 1400 __ mov(result, Operand(left, LSL, shift)); |
1401 } else if (IsPowerOf2(constant_abs - 1)) { | 1401 } else if (IsPowerOf2(constant_abs - 1)) { |
1402 int32_t shift = WhichPowerOf2(constant_abs - 1); | 1402 int32_t shift = WhichPowerOf2(constant_abs - 1); |
1403 __ add(result, left, Operand(left, LSL, shift)); | 1403 __ add(result, left, Operand(left, LSL, shift)); |
1404 } else if (IsPowerOf2(constant_abs + 1)) { | 1404 } else if (IsPowerOf2(constant_abs + 1)) { |
1405 int32_t shift = WhichPowerOf2(constant_abs + 1); | 1405 int32_t shift = WhichPowerOf2(constant_abs + 1); |
1406 __ rsb(result, left, Operand(left, LSL, shift)); | 1406 __ rsb(result, left, Operand(left, LSL, shift)); |
1407 } | 1407 } |
1408 | 1408 |
1409 // Correct the sign of the result is the constant is negative. | 1409 // Correct the sign of the result is the constant is negative. |
1410 if (constant < 0) __ rsb(result, result, Operand(0)); | 1410 if (constant < 0) __ rsb(result, result, Operand::Zero()); |
1411 | 1411 |
1412 } else { | 1412 } else { |
1413 // Generate standard code. | 1413 // Generate standard code. |
1414 __ mov(ip, Operand(constant)); | 1414 __ mov(ip, Operand(constant)); |
1415 __ mul(result, left, ip); | 1415 __ mul(result, left, ip); |
1416 } | 1416 } |
1417 } | 1417 } |
1418 | 1418 |
1419 } else { | 1419 } else { |
1420 Register right = EmitLoadRegister(right_op, scratch); | 1420 Register right = EmitLoadRegister(right_op, scratch); |
1421 if (bailout_on_minus_zero) { | 1421 if (bailout_on_minus_zero) { |
1422 __ orr(ToRegister(instr->temp()), left, right); | 1422 __ orr(ToRegister(instr->temp()), left, right); |
1423 } | 1423 } |
1424 | 1424 |
1425 if (can_overflow) { | 1425 if (can_overflow) { |
1426 // scratch:result = left * right. | 1426 // scratch:result = left * right. |
1427 __ smull(result, scratch, left, right); | 1427 __ smull(result, scratch, left, right); |
1428 __ cmp(scratch, Operand(result, ASR, 31)); | 1428 __ cmp(scratch, Operand(result, ASR, 31)); |
1429 DeoptimizeIf(ne, instr->environment()); | 1429 DeoptimizeIf(ne, instr->environment()); |
1430 } else { | 1430 } else { |
1431 __ mul(result, left, right); | 1431 __ mul(result, left, right); |
1432 } | 1432 } |
1433 | 1433 |
1434 if (bailout_on_minus_zero) { | 1434 if (bailout_on_minus_zero) { |
1435 // Bail out if the result is supposed to be negative zero. | 1435 // Bail out if the result is supposed to be negative zero. |
1436 Label done; | 1436 Label done; |
1437 __ cmp(result, Operand(0)); | 1437 __ cmp(result, Operand::Zero()); |
1438 __ b(ne, &done); | 1438 __ b(ne, &done); |
1439 __ cmp(ToRegister(instr->temp()), Operand(0)); | 1439 __ cmp(ToRegister(instr->temp()), Operand::Zero()); |
1440 DeoptimizeIf(mi, instr->environment()); | 1440 DeoptimizeIf(mi, instr->environment()); |
1441 __ bind(&done); | 1441 __ bind(&done); |
1442 } | 1442 } |
1443 } | 1443 } |
1444 } | 1444 } |
1445 | 1445 |
1446 | 1446 |
1447 void LCodeGen::DoBitI(LBitI* instr) { | 1447 void LCodeGen::DoBitI(LBitI* instr) { |
1448 LOperand* left_op = instr->left(); | 1448 LOperand* left_op = instr->left(); |
1449 LOperand* right_op = instr->right(); | 1449 LOperand* right_op = instr->right(); |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1866 } | 1866 } |
1867 | 1867 |
1868 | 1868 |
1869 void LCodeGen::DoBranch(LBranch* instr) { | 1869 void LCodeGen::DoBranch(LBranch* instr) { |
1870 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1870 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1871 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1871 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1872 | 1872 |
1873 Representation r = instr->hydrogen()->value()->representation(); | 1873 Representation r = instr->hydrogen()->value()->representation(); |
1874 if (r.IsInteger32()) { | 1874 if (r.IsInteger32()) { |
1875 Register reg = ToRegister(instr->value()); | 1875 Register reg = ToRegister(instr->value()); |
1876 __ cmp(reg, Operand(0)); | 1876 __ cmp(reg, Operand::Zero()); |
1877 EmitBranch(true_block, false_block, ne); | 1877 EmitBranch(true_block, false_block, ne); |
1878 } else if (r.IsDouble()) { | 1878 } else if (r.IsDouble()) { |
1879 DoubleRegister reg = ToDoubleRegister(instr->value()); | 1879 DoubleRegister reg = ToDoubleRegister(instr->value()); |
1880 Register scratch = scratch0(); | 1880 Register scratch = scratch0(); |
1881 | 1881 |
1882 // Test the double value. Zero and NaN are false. | 1882 // Test the double value. Zero and NaN are false. |
1883 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 1883 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); |
1884 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1884 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
1885 EmitBranch(true_block, false_block, eq); | 1885 EmitBranch(true_block, false_block, eq); |
1886 } else { | 1886 } else { |
1887 ASSERT(r.IsTagged()); | 1887 ASSERT(r.IsTagged()); |
1888 Register reg = ToRegister(instr->value()); | 1888 Register reg = ToRegister(instr->value()); |
1889 HType type = instr->hydrogen()->value()->type(); | 1889 HType type = instr->hydrogen()->value()->type(); |
1890 if (type.IsBoolean()) { | 1890 if (type.IsBoolean()) { |
1891 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1891 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
1892 EmitBranch(true_block, false_block, eq); | 1892 EmitBranch(true_block, false_block, eq); |
1893 } else if (type.IsSmi()) { | 1893 } else if (type.IsSmi()) { |
1894 __ cmp(reg, Operand(0)); | 1894 __ cmp(reg, Operand::Zero()); |
1895 EmitBranch(true_block, false_block, ne); | 1895 EmitBranch(true_block, false_block, ne); |
1896 } else { | 1896 } else { |
1897 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1897 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1898 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1898 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1899 | 1899 |
1900 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 1900 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
1901 // Avoid deopts in the case where we've never executed this path before. | 1901 // Avoid deopts in the case where we've never executed this path before. |
1902 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 1902 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
1903 | 1903 |
1904 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 1904 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
1905 // undefined -> false. | 1905 // undefined -> false. |
1906 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 1906 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
1907 __ b(eq, false_label); | 1907 __ b(eq, false_label); |
1908 } | 1908 } |
1909 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 1909 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
1910 // Boolean -> its value. | 1910 // Boolean -> its value. |
1911 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1911 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
1912 __ b(eq, true_label); | 1912 __ b(eq, true_label); |
1913 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 1913 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
1914 __ b(eq, false_label); | 1914 __ b(eq, false_label); |
1915 } | 1915 } |
1916 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 1916 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
1917 // 'null' -> false. | 1917 // 'null' -> false. |
1918 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 1918 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
1919 __ b(eq, false_label); | 1919 __ b(eq, false_label); |
1920 } | 1920 } |
1921 | 1921 |
1922 if (expected.Contains(ToBooleanStub::SMI)) { | 1922 if (expected.Contains(ToBooleanStub::SMI)) { |
1923 // Smis: 0 -> false, all other -> true. | 1923 // Smis: 0 -> false, all other -> true. |
1924 __ cmp(reg, Operand(0)); | 1924 __ cmp(reg, Operand::Zero()); |
1925 __ b(eq, false_label); | 1925 __ b(eq, false_label); |
1926 __ JumpIfSmi(reg, true_label); | 1926 __ JumpIfSmi(reg, true_label); |
1927 } else if (expected.NeedsMap()) { | 1927 } else if (expected.NeedsMap()) { |
1928 // If we need a map later and have a Smi -> deopt. | 1928 // If we need a map later and have a Smi -> deopt. |
1929 __ tst(reg, Operand(kSmiTagMask)); | 1929 __ tst(reg, Operand(kSmiTagMask)); |
1930 DeoptimizeIf(eq, instr->environment()); | 1930 DeoptimizeIf(eq, instr->environment()); |
1931 } | 1931 } |
1932 | 1932 |
1933 const Register map = scratch0(); | 1933 const Register map = scratch0(); |
1934 if (expected.NeedsMap()) { | 1934 if (expected.NeedsMap()) { |
(...skipping 12 matching lines...) Expand all Loading... |
1947 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); | 1947 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); |
1948 __ b(ge, true_label); | 1948 __ b(ge, true_label); |
1949 } | 1949 } |
1950 | 1950 |
1951 if (expected.Contains(ToBooleanStub::STRING)) { | 1951 if (expected.Contains(ToBooleanStub::STRING)) { |
1952 // String value -> false iff empty. | 1952 // String value -> false iff empty. |
1953 Label not_string; | 1953 Label not_string; |
1954 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | 1954 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
1955 __ b(ge, ¬_string); | 1955 __ b(ge, ¬_string); |
1956 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); | 1956 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); |
1957 __ cmp(ip, Operand(0)); | 1957 __ cmp(ip, Operand::Zero()); |
1958 __ b(ne, true_label); | 1958 __ b(ne, true_label); |
1959 __ b(false_label); | 1959 __ b(false_label); |
1960 __ bind(¬_string); | 1960 __ bind(¬_string); |
1961 } | 1961 } |
1962 | 1962 |
1963 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 1963 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
1964 // heap number -> false iff +0, -0, or NaN. | 1964 // heap number -> false iff +0, -0, or NaN. |
1965 DoubleRegister dbl_scratch = double_scratch0(); | 1965 DoubleRegister dbl_scratch = double_scratch0(); |
1966 Label not_heap_number; | 1966 Label not_heap_number; |
1967 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 1967 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2240 } | 2240 } |
2241 | 2241 |
2242 | 2242 |
2243 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2243 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
2244 Token::Value op = instr->op(); | 2244 Token::Value op = instr->op(); |
2245 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2245 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2246 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2246 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2247 | 2247 |
2248 Handle<Code> ic = CompareIC::GetUninitialized(op); | 2248 Handle<Code> ic = CompareIC::GetUninitialized(op); |
2249 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2249 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2250 __ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined. | 2250 |
| 2251 // This instruction also signals no smi code inlined. |
| 2252 __ cmp(r0, Operand::Zero()); |
2251 | 2253 |
2252 Condition condition = ComputeCompareCondition(op); | 2254 Condition condition = ComputeCompareCondition(op); |
2253 | 2255 |
2254 EmitBranch(true_block, false_block, condition); | 2256 EmitBranch(true_block, false_block, condition); |
2255 } | 2257 } |
2256 | 2258 |
2257 | 2259 |
2258 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2260 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
2259 InstanceType from = instr->from(); | 2261 InstanceType from = instr->from(); |
2260 InstanceType to = instr->to(); | 2262 InstanceType to = instr->to(); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2414 } | 2416 } |
2415 | 2417 |
2416 | 2418 |
2417 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2419 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2418 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. | 2420 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. |
2419 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. | 2421 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. |
2420 | 2422 |
2421 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2423 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
2422 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2424 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2423 | 2425 |
2424 __ cmp(r0, Operand(0)); | 2426 __ cmp(r0, Operand::Zero()); |
2425 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); | 2427 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); |
2426 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); | 2428 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); |
2427 } | 2429 } |
2428 | 2430 |
2429 | 2431 |
2430 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2432 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
2431 class DeferredInstanceOfKnownGlobal: public LDeferredCode { | 2433 class DeferredInstanceOfKnownGlobal: public LDeferredCode { |
2432 public: | 2434 public: |
2433 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, | 2435 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
2434 LInstanceOfKnownGlobal* instr) | 2436 LInstanceOfKnownGlobal* instr) |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2554 // restore all registers. | 2556 // restore all registers. |
2555 __ StoreToSafepointRegisterSlot(result, result); | 2557 __ StoreToSafepointRegisterSlot(result, result); |
2556 } | 2558 } |
2557 | 2559 |
2558 | 2560 |
2559 void LCodeGen::DoCmpT(LCmpT* instr) { | 2561 void LCodeGen::DoCmpT(LCmpT* instr) { |
2560 Token::Value op = instr->op(); | 2562 Token::Value op = instr->op(); |
2561 | 2563 |
2562 Handle<Code> ic = CompareIC::GetUninitialized(op); | 2564 Handle<Code> ic = CompareIC::GetUninitialized(op); |
2563 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2565 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2564 __ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined. | 2566 |
| 2567 // This instruction also signals no smi code inlined. |
| 2568 __ cmp(r0, Operand::Zero()); |
2565 | 2569 |
2566 Condition condition = ComputeCompareCondition(op); | 2570 Condition condition = ComputeCompareCondition(op); |
2567 __ LoadRoot(ToRegister(instr->result()), | 2571 __ LoadRoot(ToRegister(instr->result()), |
2568 Heap::kTrueValueRootIndex, | 2572 Heap::kTrueValueRootIndex, |
2569 condition); | 2573 condition); |
2570 __ LoadRoot(ToRegister(instr->result()), | 2574 __ LoadRoot(ToRegister(instr->result()), |
2571 Heap::kFalseValueRootIndex, | 2575 Heap::kFalseValueRootIndex, |
2572 NegateCondition(condition)); | 2576 NegateCondition(condition)); |
2573 } | 2577 } |
2574 | 2578 |
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3233 // number of arguments. | 3237 // number of arguments. |
3234 __ push(receiver); | 3238 __ push(receiver); |
3235 __ mov(receiver, length); | 3239 __ mov(receiver, length); |
3236 // The arguments are at a one pointer size offset from elements. | 3240 // The arguments are at a one pointer size offset from elements. |
3237 __ add(elements, elements, Operand(1 * kPointerSize)); | 3241 __ add(elements, elements, Operand(1 * kPointerSize)); |
3238 | 3242 |
3239 // Loop through the arguments pushing them onto the execution | 3243 // Loop through the arguments pushing them onto the execution |
3240 // stack. | 3244 // stack. |
3241 Label invoke, loop; | 3245 Label invoke, loop; |
3242 // length is a small non-negative integer, due to the test above. | 3246 // length is a small non-negative integer, due to the test above. |
3243 __ cmp(length, Operand(0)); | 3247 __ cmp(length, Operand::Zero()); |
3244 __ b(eq, &invoke); | 3248 __ b(eq, &invoke); |
3245 __ bind(&loop); | 3249 __ bind(&loop); |
3246 __ ldr(scratch, MemOperand(elements, length, LSL, 2)); | 3250 __ ldr(scratch, MemOperand(elements, length, LSL, 2)); |
3247 __ push(scratch); | 3251 __ push(scratch); |
3248 __ sub(length, length, Operand(1), SetCC); | 3252 __ sub(length, length, Operand(1), SetCC); |
3249 __ b(ne, &loop); | 3253 __ b(ne, &loop); |
3250 | 3254 |
3251 __ bind(&invoke); | 3255 __ bind(&invoke); |
3252 ASSERT(instr->HasPointerMap()); | 3256 ASSERT(instr->HasPointerMap()); |
3253 LPointerMap* pointers = instr->pointer_map(); | 3257 LPointerMap* pointers = instr->pointer_map(); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3437 __ StoreToSafepointRegisterSlot(tmp1, result); | 3441 __ StoreToSafepointRegisterSlot(tmp1, result); |
3438 } | 3442 } |
3439 | 3443 |
3440 __ bind(&done); | 3444 __ bind(&done); |
3441 } | 3445 } |
3442 | 3446 |
3443 | 3447 |
3444 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 3448 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
3445 Register input = ToRegister(instr->value()); | 3449 Register input = ToRegister(instr->value()); |
3446 Register result = ToRegister(instr->result()); | 3450 Register result = ToRegister(instr->result()); |
3447 __ cmp(input, Operand(0)); | 3451 __ cmp(input, Operand::Zero()); |
3448 __ Move(result, input, pl); | 3452 __ Move(result, input, pl); |
3449 // We can make rsb conditional because the previous cmp instruction | 3453 // We can make rsb conditional because the previous cmp instruction |
3450 // will clear the V (overflow) flag and rsb won't set this flag | 3454 // will clear the V (overflow) flag and rsb won't set this flag |
3451 // if input is positive. | 3455 // if input is positive. |
3452 __ rsb(result, input, Operand(0), SetCC, mi); | 3456 __ rsb(result, input, Operand::Zero(), SetCC, mi); |
3453 // Deoptimize on overflow. | 3457 // Deoptimize on overflow. |
3454 DeoptimizeIf(vs, instr->environment()); | 3458 DeoptimizeIf(vs, instr->environment()); |
3455 } | 3459 } |
3456 | 3460 |
3457 | 3461 |
3458 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 3462 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
3459 // Class for deferred case. | 3463 // Class for deferred case. |
3460 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3464 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
3461 public: | 3465 public: |
3462 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3466 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3499 __ EmitVFPTruncate(kRoundToMinusInf, | 3503 __ EmitVFPTruncate(kRoundToMinusInf, |
3500 result, | 3504 result, |
3501 input, | 3505 input, |
3502 scratch, | 3506 scratch, |
3503 double_scratch0()); | 3507 double_scratch0()); |
3504 DeoptimizeIf(ne, instr->environment()); | 3508 DeoptimizeIf(ne, instr->environment()); |
3505 | 3509 |
3506 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3510 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3507 // Test for -0. | 3511 // Test for -0. |
3508 Label done; | 3512 Label done; |
3509 __ cmp(result, Operand(0)); | 3513 __ cmp(result, Operand::Zero()); |
3510 __ b(ne, &done); | 3514 __ b(ne, &done); |
3511 __ vmov(scratch, input.high()); | 3515 __ vmov(scratch, input.high()); |
3512 __ tst(scratch, Operand(HeapNumber::kSignMask)); | 3516 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
3513 DeoptimizeIf(ne, instr->environment()); | 3517 DeoptimizeIf(ne, instr->environment()); |
3514 __ bind(&done); | 3518 __ bind(&done); |
3515 } | 3519 } |
3516 } | 3520 } |
3517 | 3521 |
3518 | 3522 |
3519 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 3523 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
3520 DoubleRegister input = ToDoubleRegister(instr->value()); | 3524 DoubleRegister input = ToDoubleRegister(instr->value()); |
3521 Register result = ToRegister(instr->result()); | 3525 Register result = ToRegister(instr->result()); |
3522 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); | 3526 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); |
3523 Register scratch = scratch0(); | 3527 Register scratch = scratch0(); |
3524 Label done, check_sign_on_zero; | 3528 Label done, check_sign_on_zero; |
3525 | 3529 |
3526 // Extract exponent bits. | 3530 // Extract exponent bits. |
3527 __ vmov(result, input.high()); | 3531 __ vmov(result, input.high()); |
3528 __ ubfx(scratch, | 3532 __ ubfx(scratch, |
3529 result, | 3533 result, |
3530 HeapNumber::kExponentShift, | 3534 HeapNumber::kExponentShift, |
3531 HeapNumber::kExponentBits); | 3535 HeapNumber::kExponentBits); |
3532 | 3536 |
3533 // If the number is in ]-0.5, +0.5[, the result is +/- 0. | 3537 // If the number is in ]-0.5, +0.5[, the result is +/- 0. |
3534 __ cmp(scratch, Operand(HeapNumber::kExponentBias - 2)); | 3538 __ cmp(scratch, Operand(HeapNumber::kExponentBias - 2)); |
3535 __ mov(result, Operand(0), LeaveCC, le); | 3539 __ mov(result, Operand::Zero(), LeaveCC, le); |
3536 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3540 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3537 __ b(le, &check_sign_on_zero); | 3541 __ b(le, &check_sign_on_zero); |
3538 } else { | 3542 } else { |
3539 __ b(le, &done); | 3543 __ b(le, &done); |
3540 } | 3544 } |
3541 | 3545 |
3542 // The following conversion will not work with numbers | 3546 // The following conversion will not work with numbers |
3543 // outside of ]-2^32, 2^32[. | 3547 // outside of ]-2^32, 2^32[. |
3544 __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32)); | 3548 __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32)); |
3545 DeoptimizeIf(ge, instr->environment()); | 3549 DeoptimizeIf(ge, instr->environment()); |
3546 | 3550 |
3547 __ Vmov(double_scratch0(), 0.5, scratch); | 3551 __ Vmov(double_scratch0(), 0.5, scratch); |
3548 __ vadd(double_scratch0(), input, double_scratch0()); | 3552 __ vadd(double_scratch0(), input, double_scratch0()); |
3549 | 3553 |
3550 // Save the original sign for later comparison. | 3554 // Save the original sign for later comparison. |
3551 __ and_(scratch, result, Operand(HeapNumber::kSignMask)); | 3555 __ and_(scratch, result, Operand(HeapNumber::kSignMask)); |
3552 | 3556 |
3553 // Check sign of the result: if the sign changed, the input | 3557 // Check sign of the result: if the sign changed, the input |
3554 // value was in ]0.5, 0[ and the result should be -0. | 3558 // value was in ]0.5, 0[ and the result should be -0. |
3555 __ vmov(result, double_scratch0().high()); | 3559 __ vmov(result, double_scratch0().high()); |
3556 __ eor(result, result, Operand(scratch), SetCC); | 3560 __ eor(result, result, Operand(scratch), SetCC); |
3557 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3561 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3558 DeoptimizeIf(mi, instr->environment()); | 3562 DeoptimizeIf(mi, instr->environment()); |
3559 } else { | 3563 } else { |
3560 __ mov(result, Operand(0), LeaveCC, mi); | 3564 __ mov(result, Operand::Zero(), LeaveCC, mi); |
3561 __ b(mi, &done); | 3565 __ b(mi, &done); |
3562 } | 3566 } |
3563 | 3567 |
3564 __ EmitVFPTruncate(kRoundToMinusInf, | 3568 __ EmitVFPTruncate(kRoundToMinusInf, |
3565 result, | 3569 result, |
3566 double_scratch0(), | 3570 double_scratch0(), |
3567 scratch, | 3571 scratch, |
3568 double_scratch1); | 3572 double_scratch1); |
3569 DeoptimizeIf(ne, instr->environment()); | 3573 DeoptimizeIf(ne, instr->environment()); |
3570 | 3574 |
3571 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3575 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3572 // Test for -0. | 3576 // Test for -0. |
3573 __ cmp(result, Operand(0)); | 3577 __ cmp(result, Operand::Zero()); |
3574 __ b(ne, &done); | 3578 __ b(ne, &done); |
3575 __ bind(&check_sign_on_zero); | 3579 __ bind(&check_sign_on_zero); |
3576 __ vmov(scratch, input.high()); | 3580 __ vmov(scratch, input.high()); |
3577 __ tst(scratch, Operand(HeapNumber::kSignMask)); | 3581 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
3578 DeoptimizeIf(ne, instr->environment()); | 3582 DeoptimizeIf(ne, instr->environment()); |
3579 } | 3583 } |
3580 __ bind(&done); | 3584 __ bind(&done); |
3581 } | 3585 } |
3582 | 3586 |
3583 | 3587 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3663 STATIC_ASSERT(kPointerSize == kSeedSize); | 3667 STATIC_ASSERT(kPointerSize == kSeedSize); |
3664 | 3668 |
3665 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset)); | 3669 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset)); |
3666 static const int kRandomSeedOffset = | 3670 static const int kRandomSeedOffset = |
3667 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; | 3671 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; |
3668 __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset)); | 3672 __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset)); |
3669 // r2: FixedArray of the native context's random seeds | 3673 // r2: FixedArray of the native context's random seeds |
3670 | 3674 |
3671 // Load state[0]. | 3675 // Load state[0]. |
3672 __ ldr(r1, FieldMemOperand(r2, ByteArray::kHeaderSize)); | 3676 __ ldr(r1, FieldMemOperand(r2, ByteArray::kHeaderSize)); |
3673 __ cmp(r1, Operand(0)); | 3677 __ cmp(r1, Operand::Zero()); |
3674 __ b(eq, deferred->entry()); | 3678 __ b(eq, deferred->entry()); |
3675 // Load state[1]. | 3679 // Load state[1]. |
3676 __ ldr(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize)); | 3680 __ ldr(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize)); |
3677 // r1: state[0]. | 3681 // r1: state[0]. |
3678 // r0: state[1]. | 3682 // r0: state[1]. |
3679 | 3683 |
3680 // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) | 3684 // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) |
3681 __ and_(r3, r1, Operand(0xFFFF)); | 3685 __ and_(r3, r1, Operand(0xFFFF)); |
3682 __ mov(r4, Operand(18273)); | 3686 __ mov(r4, Operand(18273)); |
3683 __ mul(r3, r3, r4); | 3687 __ mul(r3, r3, r4); |
(...skipping 14 matching lines...) Expand all Loading... |
3698 __ add(r0, r0, Operand(r1, LSL, 14)); | 3702 __ add(r0, r0, Operand(r1, LSL, 14)); |
3699 | 3703 |
3700 __ bind(deferred->exit()); | 3704 __ bind(deferred->exit()); |
3701 // 0x41300000 is the top half of 1.0 x 2^20 as a double. | 3705 // 0x41300000 is the top half of 1.0 x 2^20 as a double. |
3702 // Create this constant using mov/orr to avoid PC relative load. | 3706 // Create this constant using mov/orr to avoid PC relative load. |
3703 __ mov(r1, Operand(0x41000000)); | 3707 __ mov(r1, Operand(0x41000000)); |
3704 __ orr(r1, r1, Operand(0x300000)); | 3708 __ orr(r1, r1, Operand(0x300000)); |
3705 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. | 3709 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. |
3706 __ vmov(d7, r0, r1); | 3710 __ vmov(d7, r0, r1); |
3707 // Move 0x4130000000000000 to VFP. | 3711 // Move 0x4130000000000000 to VFP. |
3708 __ mov(r0, Operand(0, RelocInfo::NONE)); | 3712 __ mov(r0, Operand::Zero()); |
3709 __ vmov(d8, r0, r1); | 3713 __ vmov(d8, r0, r1); |
3710 // Subtract and store the result in the heap number. | 3714 // Subtract and store the result in the heap number. |
3711 __ vsub(d7, d7, d8); | 3715 __ vsub(d7, d7, d8); |
3712 } | 3716 } |
3713 | 3717 |
3714 | 3718 |
3715 void LCodeGen::DoDeferredRandom(LRandom* instr) { | 3719 void LCodeGen::DoDeferredRandom(LRandom* instr) { |
3716 __ PrepareCallCFunction(1, scratch0()); | 3720 __ PrepareCallCFunction(1, scratch0()); |
3717 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | 3721 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); |
3718 // Return value is in r0. | 3722 // Return value is in r0. |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4246 | 4250 |
4247 | 4251 |
4248 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { | 4252 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
4249 Register string = ToRegister(instr->string()); | 4253 Register string = ToRegister(instr->string()); |
4250 Register result = ToRegister(instr->result()); | 4254 Register result = ToRegister(instr->result()); |
4251 Register scratch = scratch0(); | 4255 Register scratch = scratch0(); |
4252 | 4256 |
4253 // TODO(3095996): Get rid of this. For now, we need to make the | 4257 // TODO(3095996): Get rid of this. For now, we need to make the |
4254 // result register contain a valid pointer because it is already | 4258 // result register contain a valid pointer because it is already |
4255 // contained in the register pointer map. | 4259 // contained in the register pointer map. |
4256 __ mov(result, Operand(0)); | 4260 __ mov(result, Operand::Zero()); |
4257 | 4261 |
4258 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4262 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4259 __ push(string); | 4263 __ push(string); |
4260 // Push the index as a smi. This is safe because of the checks in | 4264 // Push the index as a smi. This is safe because of the checks in |
4261 // DoStringCharCodeAt above. | 4265 // DoStringCharCodeAt above. |
4262 if (instr->index()->IsConstantOperand()) { | 4266 if (instr->index()->IsConstantOperand()) { |
4263 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 4267 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
4264 __ mov(scratch, Operand(Smi::FromInt(const_index))); | 4268 __ mov(scratch, Operand(Smi::FromInt(const_index))); |
4265 __ push(scratch); | 4269 __ push(scratch); |
4266 } else { | 4270 } else { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4306 } | 4310 } |
4307 | 4311 |
4308 | 4312 |
4309 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { | 4313 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { |
4310 Register char_code = ToRegister(instr->char_code()); | 4314 Register char_code = ToRegister(instr->char_code()); |
4311 Register result = ToRegister(instr->result()); | 4315 Register result = ToRegister(instr->result()); |
4312 | 4316 |
4313 // TODO(3095996): Get rid of this. For now, we need to make the | 4317 // TODO(3095996): Get rid of this. For now, we need to make the |
4314 // result register contain a valid pointer because it is already | 4318 // result register contain a valid pointer because it is already |
4315 // contained in the register pointer map. | 4319 // contained in the register pointer map. |
4316 __ mov(result, Operand(0)); | 4320 __ mov(result, Operand::Zero()); |
4317 | 4321 |
4318 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4322 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4319 __ SmiTag(char_code); | 4323 __ SmiTag(char_code); |
4320 __ push(char_code); | 4324 __ push(char_code); |
4321 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 4325 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); |
4322 __ StoreToSafepointRegisterSlot(r0, result); | 4326 __ StoreToSafepointRegisterSlot(r0, result); |
4323 } | 4327 } |
4324 | 4328 |
4325 | 4329 |
4326 void LCodeGen::DoStringLength(LStringLength* instr) { | 4330 void LCodeGen::DoStringLength(LStringLength* instr) { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4443 __ Move(dst, r5); | 4447 __ Move(dst, r5); |
4444 __ b(&done); | 4448 __ b(&done); |
4445 } | 4449 } |
4446 | 4450 |
4447 // Slow case: Call the runtime system to do the number allocation. | 4451 // Slow case: Call the runtime system to do the number allocation. |
4448 __ bind(&slow); | 4452 __ bind(&slow); |
4449 | 4453 |
4450 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 4454 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
4451 // register is stored, as this register is in the pointer map, but contains an | 4455 // register is stored, as this register is in the pointer map, but contains an |
4452 // integer value. | 4456 // integer value. |
4453 __ mov(ip, Operand(0)); | 4457 __ mov(ip, Operand::Zero()); |
4454 __ StoreToSafepointRegisterSlot(ip, dst); | 4458 __ StoreToSafepointRegisterSlot(ip, dst); |
4455 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4459 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
4456 __ Move(dst, r0); | 4460 __ Move(dst, r0); |
4457 __ sub(dst, dst, Operand(kHeapObjectTag)); | 4461 __ sub(dst, dst, Operand(kHeapObjectTag)); |
4458 | 4462 |
4459 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4463 // Done. Put the value in dbl_scratch into the value of the allocated heap |
4460 // number. | 4464 // number. |
4461 __ bind(&done); | 4465 __ bind(&done); |
4462 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); | 4466 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); |
4463 __ add(dst, dst, Operand(kHeapObjectTag)); | 4467 __ add(dst, dst, Operand(kHeapObjectTag)); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4496 // Now that we have finished with the object's real address tag it | 4500 // Now that we have finished with the object's real address tag it |
4497 __ add(reg, reg, Operand(kHeapObjectTag)); | 4501 __ add(reg, reg, Operand(kHeapObjectTag)); |
4498 } | 4502 } |
4499 | 4503 |
4500 | 4504 |
4501 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4505 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
4502 // TODO(3095996): Get rid of this. For now, we need to make the | 4506 // TODO(3095996): Get rid of this. For now, we need to make the |
4503 // result register contain a valid pointer because it is already | 4507 // result register contain a valid pointer because it is already |
4504 // contained in the register pointer map. | 4508 // contained in the register pointer map. |
4505 Register reg = ToRegister(instr->result()); | 4509 Register reg = ToRegister(instr->result()); |
4506 __ mov(reg, Operand(0)); | 4510 __ mov(reg, Operand::Zero()); |
4507 | 4511 |
4508 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4512 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4509 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4513 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
4510 __ sub(r0, r0, Operand(kHeapObjectTag)); | 4514 __ sub(r0, r0, Operand(kHeapObjectTag)); |
4511 __ StoreToSafepointRegisterSlot(r0, reg); | 4515 __ StoreToSafepointRegisterSlot(r0, reg); |
4512 } | 4516 } |
4513 | 4517 |
4514 | 4518 |
4515 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4519 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4516 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4520 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4566 __ vldr(result_reg, ip, HeapNumber::kValueOffset); | 4570 __ vldr(result_reg, ip, HeapNumber::kValueOffset); |
4567 __ jmp(&done); | 4571 __ jmp(&done); |
4568 | 4572 |
4569 __ bind(&heap_number); | 4573 __ bind(&heap_number); |
4570 } | 4574 } |
4571 // Heap number to double register conversion. | 4575 // Heap number to double register conversion. |
4572 __ sub(ip, input_reg, Operand(kHeapObjectTag)); | 4576 __ sub(ip, input_reg, Operand(kHeapObjectTag)); |
4573 __ vldr(result_reg, ip, HeapNumber::kValueOffset); | 4577 __ vldr(result_reg, ip, HeapNumber::kValueOffset); |
4574 if (deoptimize_on_minus_zero) { | 4578 if (deoptimize_on_minus_zero) { |
4575 __ vmov(ip, result_reg.low()); | 4579 __ vmov(ip, result_reg.low()); |
4576 __ cmp(ip, Operand(0)); | 4580 __ cmp(ip, Operand::Zero()); |
4577 __ b(ne, &done); | 4581 __ b(ne, &done); |
4578 __ vmov(ip, result_reg.high()); | 4582 __ vmov(ip, result_reg.high()); |
4579 __ cmp(ip, Operand(HeapNumber::kSignMask)); | 4583 __ cmp(ip, Operand(HeapNumber::kSignMask)); |
4580 DeoptimizeIf(eq, env); | 4584 DeoptimizeIf(eq, env); |
4581 } | 4585 } |
4582 __ jmp(&done); | 4586 __ jmp(&done); |
4583 | 4587 |
4584 // Smi to double register conversion | 4588 // Smi to double register conversion |
4585 __ bind(&load_smi); | 4589 __ bind(&load_smi); |
4586 // scratch: untagged value of input_reg | 4590 // scratch: untagged value of input_reg |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4621 !scratch3.is(scratch2)); | 4625 !scratch3.is(scratch2)); |
4622 // Performs a truncating conversion of a floating point number as used by | 4626 // Performs a truncating conversion of a floating point number as used by |
4623 // the JS bitwise operations. | 4627 // the JS bitwise operations. |
4624 Label heap_number; | 4628 Label heap_number; |
4625 __ b(eq, &heap_number); | 4629 __ b(eq, &heap_number); |
4626 // Check for undefined. Undefined is converted to zero for truncating | 4630 // Check for undefined. Undefined is converted to zero for truncating |
4627 // conversions. | 4631 // conversions. |
4628 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4632 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
4629 __ cmp(input_reg, Operand(ip)); | 4633 __ cmp(input_reg, Operand(ip)); |
4630 DeoptimizeIf(ne, instr->environment()); | 4634 DeoptimizeIf(ne, instr->environment()); |
4631 __ mov(input_reg, Operand(0)); | 4635 __ mov(input_reg, Operand::Zero()); |
4632 __ b(&done); | 4636 __ b(&done); |
4633 | 4637 |
4634 __ bind(&heap_number); | 4638 __ bind(&heap_number); |
4635 __ sub(scratch1, input_reg, Operand(kHeapObjectTag)); | 4639 __ sub(scratch1, input_reg, Operand(kHeapObjectTag)); |
4636 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset); | 4640 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset); |
4637 | 4641 |
4638 __ EmitECMATruncate(input_reg, | 4642 __ EmitECMATruncate(input_reg, |
4639 double_scratch2, | 4643 double_scratch2, |
4640 single_scratch, | 4644 single_scratch, |
4641 scratch1, | 4645 scratch1, |
4642 scratch2, | 4646 scratch2, |
4643 scratch3); | 4647 scratch3); |
4644 | 4648 |
4645 } else { | 4649 } else { |
4646 CpuFeatures::Scope scope(VFP3); | 4650 CpuFeatures::Scope scope(VFP3); |
4647 // Deoptimize if we don't have a heap number. | 4651 // Deoptimize if we don't have a heap number. |
4648 DeoptimizeIf(ne, instr->environment()); | 4652 DeoptimizeIf(ne, instr->environment()); |
4649 | 4653 |
4650 __ sub(ip, input_reg, Operand(kHeapObjectTag)); | 4654 __ sub(ip, input_reg, Operand(kHeapObjectTag)); |
4651 __ vldr(double_scratch, ip, HeapNumber::kValueOffset); | 4655 __ vldr(double_scratch, ip, HeapNumber::kValueOffset); |
4652 __ EmitVFPTruncate(kRoundToZero, | 4656 __ EmitVFPTruncate(kRoundToZero, |
4653 input_reg, | 4657 input_reg, |
4654 double_scratch, | 4658 double_scratch, |
4655 scratch1, | 4659 scratch1, |
4656 double_scratch2, | 4660 double_scratch2, |
4657 kCheckForInexactConversion); | 4661 kCheckForInexactConversion); |
4658 DeoptimizeIf(ne, instr->environment()); | 4662 DeoptimizeIf(ne, instr->environment()); |
4659 | 4663 |
4660 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4664 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
4661 __ cmp(input_reg, Operand(0)); | 4665 __ cmp(input_reg, Operand::Zero()); |
4662 __ b(ne, &done); | 4666 __ b(ne, &done); |
4663 __ vmov(scratch1, double_scratch.high()); | 4667 __ vmov(scratch1, double_scratch.high()); |
4664 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 4668 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
4665 DeoptimizeIf(ne, instr->environment()); | 4669 DeoptimizeIf(ne, instr->environment()); |
4666 } | 4670 } |
4667 } | 4671 } |
4668 __ bind(&done); | 4672 __ bind(&done); |
4669 } | 4673 } |
4670 | 4674 |
4671 | 4675 |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4880 | 4884 |
4881 // Check for heap number | 4885 // Check for heap number |
4882 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4886 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
4883 __ cmp(scratch, Operand(factory()->heap_number_map())); | 4887 __ cmp(scratch, Operand(factory()->heap_number_map())); |
4884 __ b(eq, &heap_number); | 4888 __ b(eq, &heap_number); |
4885 | 4889 |
4886 // Check for undefined. Undefined is converted to zero for clamping | 4890 // Check for undefined. Undefined is converted to zero for clamping |
4887 // conversions. | 4891 // conversions. |
4888 __ cmp(input_reg, Operand(factory()->undefined_value())); | 4892 __ cmp(input_reg, Operand(factory()->undefined_value())); |
4889 DeoptimizeIf(ne, instr->environment()); | 4893 DeoptimizeIf(ne, instr->environment()); |
4890 __ mov(result_reg, Operand(0)); | 4894 __ mov(result_reg, Operand::Zero()); |
4891 __ jmp(&done); | 4895 __ jmp(&done); |
4892 | 4896 |
4893 // Heap number | 4897 // Heap number |
4894 __ bind(&heap_number); | 4898 __ bind(&heap_number); |
4895 __ vldr(double_scratch0(), FieldMemOperand(input_reg, | 4899 __ vldr(double_scratch0(), FieldMemOperand(input_reg, |
4896 HeapNumber::kValueOffset)); | 4900 HeapNumber::kValueOffset)); |
4897 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); | 4901 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); |
4898 __ jmp(&done); | 4902 __ jmp(&done); |
4899 | 4903 |
4900 // smi | 4904 // smi |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5000 | 5004 |
5001 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { | 5005 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { |
5002 Register result = ToRegister(instr->result()); | 5006 Register result = ToRegister(instr->result()); |
5003 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); | 5007 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); |
5004 Handle<Map> initial_map(constructor->initial_map()); | 5008 Handle<Map> initial_map(constructor->initial_map()); |
5005 int instance_size = initial_map->instance_size(); | 5009 int instance_size = initial_map->instance_size(); |
5006 | 5010 |
5007 // TODO(3095996): Get rid of this. For now, we need to make the | 5011 // TODO(3095996): Get rid of this. For now, we need to make the |
5008 // result register contain a valid pointer because it is already | 5012 // result register contain a valid pointer because it is already |
5009 // contained in the register pointer map. | 5013 // contained in the register pointer map. |
5010 __ mov(result, Operand(0)); | 5014 __ mov(result, Operand::Zero()); |
5011 | 5015 |
5012 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5016 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
5013 __ mov(r0, Operand(Smi::FromInt(instance_size))); | 5017 __ mov(r0, Operand(Smi::FromInt(instance_size))); |
5014 __ push(r0); | 5018 __ push(r0); |
5015 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); | 5019 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); |
5016 __ StoreToSafepointRegisterSlot(r0, result); | 5020 __ StoreToSafepointRegisterSlot(r0, result); |
5017 } | 5021 } |
5018 | 5022 |
5019 | 5023 |
5020 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 5024 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5628 __ b(ne, &load_cache); | 5632 __ b(ne, &load_cache); |
5629 __ mov(result, Operand(isolate()->factory()->empty_fixed_array())); | 5633 __ mov(result, Operand(isolate()->factory()->empty_fixed_array())); |
5630 __ jmp(&done); | 5634 __ jmp(&done); |
5631 | 5635 |
5632 __ bind(&load_cache); | 5636 __ bind(&load_cache); |
5633 __ LoadInstanceDescriptors(map, result, scratch); | 5637 __ LoadInstanceDescriptors(map, result, scratch); |
5634 __ ldr(result, | 5638 __ ldr(result, |
5635 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); | 5639 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); |
5636 __ ldr(result, | 5640 __ ldr(result, |
5637 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); | 5641 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); |
5638 __ cmp(result, Operand(0)); | 5642 __ cmp(result, Operand::Zero()); |
5639 DeoptimizeIf(eq, instr->environment()); | 5643 DeoptimizeIf(eq, instr->environment()); |
5640 | 5644 |
5641 __ bind(&done); | 5645 __ bind(&done); |
5642 } | 5646 } |
5643 | 5647 |
5644 | 5648 |
5645 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5649 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
5646 Register object = ToRegister(instr->value()); | 5650 Register object = ToRegister(instr->value()); |
5647 Register map = ToRegister(instr->map()); | 5651 Register map = ToRegister(instr->map()); |
5648 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); | 5652 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); |
5649 __ cmp(map, scratch0()); | 5653 __ cmp(map, scratch0()); |
5650 DeoptimizeIf(ne, instr->environment()); | 5654 DeoptimizeIf(ne, instr->environment()); |
5651 } | 5655 } |
5652 | 5656 |
5653 | 5657 |
5654 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { | 5658 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { |
5655 Register object = ToRegister(instr->object()); | 5659 Register object = ToRegister(instr->object()); |
5656 Register index = ToRegister(instr->index()); | 5660 Register index = ToRegister(instr->index()); |
5657 Register result = ToRegister(instr->result()); | 5661 Register result = ToRegister(instr->result()); |
5658 Register scratch = scratch0(); | 5662 Register scratch = scratch0(); |
5659 | 5663 |
5660 Label out_of_object, done; | 5664 Label out_of_object, done; |
5661 __ cmp(index, Operand(0)); | 5665 __ cmp(index, Operand::Zero()); |
5662 __ b(lt, &out_of_object); | 5666 __ b(lt, &out_of_object); |
5663 | 5667 |
5664 STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize); | 5668 STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize); |
5665 __ add(scratch, object, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5669 __ add(scratch, object, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
5666 __ ldr(result, FieldMemOperand(scratch, JSObject::kHeaderSize)); | 5670 __ ldr(result, FieldMemOperand(scratch, JSObject::kHeaderSize)); |
5667 | 5671 |
5668 __ b(&done); | 5672 __ b(&done); |
5669 | 5673 |
5670 __ bind(&out_of_object); | 5674 __ bind(&out_of_object); |
5671 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5675 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
5672 // Index is equal to negated out of object property index plus 1. | 5676 // Index is equal to negated out of object property index plus 1. |
5673 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5677 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
5674 __ ldr(result, FieldMemOperand(scratch, | 5678 __ ldr(result, FieldMemOperand(scratch, |
5675 FixedArray::kHeaderSize - kPointerSize)); | 5679 FixedArray::kHeaderSize - kPointerSize)); |
5676 __ bind(&done); | 5680 __ bind(&done); |
5677 } | 5681 } |
5678 | 5682 |
5679 | 5683 |
5680 #undef __ | 5684 #undef __ |
5681 | 5685 |
5682 } } // namespace v8::internal | 5686 } } // namespace v8::internal |
OLD | NEW |