| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 RegExpExecStub stub; | 957 RegExpExecStub stub; |
| 958 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 958 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 959 break; | 959 break; |
| 960 } | 960 } |
| 961 case CodeStub::SubString: { | 961 case CodeStub::SubString: { |
| 962 SubStringStub stub; | 962 SubStringStub stub; |
| 963 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 963 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 964 break; | 964 break; |
| 965 } | 965 } |
| 966 case CodeStub::StringCharAt: { | 966 case CodeStub::StringCharAt: { |
| 967 Abort("StringCharAtStub unimplemented."); | 967 StringCharAtStub stub; |
| 968 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 968 break; | 969 break; |
| 969 } | 970 } |
| 970 case CodeStub::MathPow: { | 971 case CodeStub::MathPow: { |
| 971 Abort("MathPowStub unimplemented."); | 972 Abort("MathPowStub unimplemented."); |
| 972 break; | 973 break; |
| 973 } | 974 } |
| 974 case CodeStub::NumberToString: { | 975 case CodeStub::NumberToString: { |
| 975 NumberToStringStub stub; | 976 NumberToStringStub stub; |
| 976 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 977 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 977 break; | 978 break; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1008 public: | 1009 public: |
| 1009 DeferredModI(LCodeGen* codegen, LModI* instr) | 1010 DeferredModI(LCodeGen* codegen, LModI* instr) |
| 1010 : LDeferredCode(codegen), instr_(instr) { } | 1011 : LDeferredCode(codegen), instr_(instr) { } |
| 1011 virtual void Generate() { | 1012 virtual void Generate() { |
| 1012 codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD); | 1013 codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD); |
| 1013 } | 1014 } |
| 1014 private: | 1015 private: |
| 1015 LModI* instr_; | 1016 LModI* instr_; |
| 1016 }; | 1017 }; |
| 1017 // These registers hold untagged 32 bit values. | 1018 // These registers hold untagged 32 bit values. |
| 1018 Register left = ToRegister(instr->left()); | 1019 Register left = ToRegister(instr->InputAt(0)); |
| 1019 Register right = ToRegister(instr->right()); | 1020 Register right = ToRegister(instr->InputAt(1)); |
| 1020 Register result = ToRegister(instr->result()); | 1021 Register result = ToRegister(instr->result()); |
| 1021 Register scratch = scratch0(); | 1022 Register scratch = scratch0(); |
| 1022 | 1023 |
| 1023 Label deoptimize, done; | 1024 Label deoptimize, done; |
| 1024 // Check for x % 0. | 1025 // Check for x % 0. |
| 1025 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1026 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1026 __ tst(right, Operand(right)); | 1027 __ tst(right, Operand(right)); |
| 1027 __ b(eq, &deoptimize); | 1028 __ b(eq, &deoptimize); |
| 1028 } | 1029 } |
| 1029 | 1030 |
| 1030 // Check for (0 % -x) that will produce negative zero. | 1031 // Check for (0 % -x) that will produce negative zero. |
| 1031 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1032 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1032 Label ok; | 1033 Label ok; |
| 1033 __ tst(left, Operand(left)); | 1034 __ tst(left, Operand(left)); |
| 1034 __ b(ne, &ok); | 1035 __ b(ne, &ok); |
| 1035 __ tst(right, Operand(right)); | 1036 __ tst(right, Operand(right)); |
| 1036 __ b(pl, &ok); | 1037 __ b(pl, &ok); |
| 1037 __ b(al, &deoptimize); | 1038 __ b(al, &deoptimize); |
| 1038 __ bind(&ok); | 1039 __ bind(&ok); |
| 1039 } | 1040 } |
| 1040 | 1041 |
| 1042 // Try a few common cases before using the generic stub. |
| 1043 Label call_stub; |
| 1044 const int kUnfolds = 3; |
| 1045 // Skip if either side is negative. |
| 1046 __ cmp(left, Operand(0)); |
| 1047 __ cmp(right, Operand(0), NegateCondition(mi)); |
| 1048 __ b(mi, &call_stub); |
| 1049 // If the right hand side is smaller than the (nonnegative) |
| 1050 // left hand side, it is the result. Else try a few subtractions |
| 1051 // of the left hand side. |
| 1052 __ mov(scratch, left); |
| 1053 for (int i = 0; i < kUnfolds; i++) { |
| 1054 // Check if the left hand side is less or equal than the |
| 1055 // the right hand side. |
| 1056 __ cmp(scratch, right); |
| 1057 __ mov(result, scratch, LeaveCC, lt); |
| 1058 __ b(lt, &done); |
| 1059 // If not, reduce the left hand side by the right hand |
| 1060 // side and check again. |
| 1061 if (i < kUnfolds - 1) __ sub(scratch, scratch, right); |
| 1062 } |
| 1063 |
| 1064 // Check for power of two on the right hand side. |
| 1065 __ sub(scratch, right, Operand(1), SetCC); |
| 1066 __ b(mi, &call_stub); |
| 1067 __ tst(scratch, right); |
| 1068 __ b(ne, &call_stub); |
| 1069 // Perform modulo operation. |
| 1070 __ and_(result, scratch, Operand(left)); |
| 1071 |
| 1072 __ bind(&call_stub); |
| 1041 // Call the generic stub. The numbers in r0 and r1 have | 1073 // Call the generic stub. The numbers in r0 and r1 have |
| 1042 // to be tagged to Smis. If that is not possible, deoptimize. | 1074 // to be tagged to Smis. If that is not possible, deoptimize. |
| 1043 DeferredModI* deferred = new DeferredModI(this, instr); | 1075 DeferredModI* deferred = new DeferredModI(this, instr); |
| 1044 __ TrySmiTag(left, &deoptimize, scratch); | 1076 __ TrySmiTag(left, &deoptimize, scratch); |
| 1045 __ TrySmiTag(right, &deoptimize, scratch); | 1077 __ TrySmiTag(right, &deoptimize, scratch); |
| 1046 | 1078 |
| 1047 __ b(al, deferred->entry()); | 1079 __ b(al, deferred->entry()); |
| 1048 __ bind(deferred->exit()); | 1080 __ bind(deferred->exit()); |
| 1049 | 1081 |
| 1050 // If the result in r0 is a Smi, untag it, else deoptimize. | 1082 // If the result in r0 is a Smi, untag it, else deoptimize. |
| 1051 __ BranchOnNotSmi(result, &deoptimize); | 1083 __ BranchOnNotSmi(result, &deoptimize); |
| 1052 __ mov(result, Operand(result, ASR, 1)); | 1084 __ SmiUntag(result); |
| 1053 | 1085 |
| 1054 __ b(al, &done); | 1086 __ b(al, &done); |
| 1055 __ bind(&deoptimize); | 1087 __ bind(&deoptimize); |
| 1056 DeoptimizeIf(al, instr->environment()); | 1088 DeoptimizeIf(al, instr->environment()); |
| 1057 __ bind(&done); | 1089 __ bind(&done); |
| 1058 } | 1090 } |
| 1059 | 1091 |
| 1060 | 1092 |
| 1061 void LCodeGen::DoDivI(LDivI* instr) { | 1093 void LCodeGen::DoDivI(LDivI* instr) { |
| 1062 class DeferredDivI: public LDeferredCode { | 1094 class DeferredDivI: public LDeferredCode { |
| 1063 public: | 1095 public: |
| 1064 DeferredDivI(LCodeGen* codegen, LDivI* instr) | 1096 DeferredDivI(LCodeGen* codegen, LDivI* instr) |
| 1065 : LDeferredCode(codegen), instr_(instr) { } | 1097 : LDeferredCode(codegen), instr_(instr) { } |
| 1066 virtual void Generate() { | 1098 virtual void Generate() { |
| 1067 codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV); | 1099 codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV); |
| 1068 } | 1100 } |
| 1069 private: | 1101 private: |
| 1070 LDivI* instr_; | 1102 LDivI* instr_; |
| 1071 }; | 1103 }; |
| 1072 | 1104 |
| 1073 const Register left = ToRegister(instr->left()); | 1105 const Register left = ToRegister(instr->InputAt(0)); |
| 1074 const Register right = ToRegister(instr->right()); | 1106 const Register right = ToRegister(instr->InputAt(1)); |
| 1075 const Register scratch = scratch0(); | 1107 const Register scratch = scratch0(); |
| 1076 const Register result = ToRegister(instr->result()); | 1108 const Register result = ToRegister(instr->result()); |
| 1077 | 1109 |
| 1078 // Check for x / 0. | 1110 // Check for x / 0. |
| 1079 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1111 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1080 __ tst(right, right); | 1112 __ tst(right, right); |
| 1081 DeoptimizeIf(eq, instr->environment()); | 1113 DeoptimizeIf(eq, instr->environment()); |
| 1082 } | 1114 } |
| 1083 | 1115 |
| 1084 // Check for (0 / -x) that will produce negative zero. | 1116 // Check for (0 / -x) that will produce negative zero. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1131 __ BranchOnNotSmi(result, &deoptimize); | 1163 __ BranchOnNotSmi(result, &deoptimize); |
| 1132 __ SmiUntag(result); | 1164 __ SmiUntag(result); |
| 1133 __ b(&done); | 1165 __ b(&done); |
| 1134 | 1166 |
| 1135 __ bind(&deoptimize); | 1167 __ bind(&deoptimize); |
| 1136 DeoptimizeIf(al, instr->environment()); | 1168 DeoptimizeIf(al, instr->environment()); |
| 1137 __ bind(&done); | 1169 __ bind(&done); |
| 1138 } | 1170 } |
| 1139 | 1171 |
| 1140 | 1172 |
| 1141 void LCodeGen::DoDeferredGenericBinaryStub(LBinaryOperation* instr, | 1173 template<int T> |
| 1174 void LCodeGen::DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr, |
| 1142 Token::Value op) { | 1175 Token::Value op) { |
| 1143 Register left = ToRegister(instr->left()); | 1176 Register left = ToRegister(instr->InputAt(0)); |
| 1144 Register right = ToRegister(instr->right()); | 1177 Register right = ToRegister(instr->InputAt(1)); |
| 1145 | 1178 |
| 1146 __ PushSafepointRegistersAndDoubles(); | 1179 __ PushSafepointRegistersAndDoubles(); |
| 1147 GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right); | 1180 GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right); |
| 1148 __ CallStub(&stub); | 1181 __ CallStub(&stub); |
| 1149 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1182 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
| 1150 0, | 1183 0, |
| 1151 Safepoint::kNoDeoptimizationIndex); | 1184 Safepoint::kNoDeoptimizationIndex); |
| 1152 // Overwrite the stored value of r0 with the result of the stub. | 1185 // Overwrite the stored value of r0 with the result of the stub. |
| 1153 __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters * | 1186 __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters * |
| 1154 kDoubleSize)); | 1187 kDoubleSize)); |
| 1155 __ PopSafepointRegistersAndDoubles(); | 1188 __ PopSafepointRegistersAndDoubles(); |
| 1156 } | 1189 } |
| 1157 | 1190 |
| 1158 | 1191 |
| 1159 void LCodeGen::DoMulI(LMulI* instr) { | 1192 void LCodeGen::DoMulI(LMulI* instr) { |
| 1160 Register scratch = scratch0(); | 1193 Register scratch = scratch0(); |
| 1161 Register left = ToRegister(instr->left()); | 1194 Register left = ToRegister(instr->InputAt(0)); |
| 1162 Register right = EmitLoadRegister(instr->right(), scratch); | 1195 Register right = EmitLoadRegister(instr->InputAt(1), scratch); |
| 1163 | 1196 |
| 1164 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && | 1197 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 1165 !instr->right()->IsConstantOperand()) { | 1198 !instr->InputAt(1)->IsConstantOperand()) { |
| 1166 __ orr(ToRegister(instr->temp()), left, right); | 1199 __ orr(ToRegister(instr->TempAt(0)), left, right); |
| 1167 } | 1200 } |
| 1168 | 1201 |
| 1169 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1202 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1170 // scratch:left = left * right. | 1203 // scratch:left = left * right. |
| 1171 __ smull(scratch, left, left, right); | 1204 __ smull(scratch, left, left, right); |
| 1172 __ mov(ip, Operand(left, ASR, 31)); | 1205 __ mov(ip, Operand(left, ASR, 31)); |
| 1173 __ cmp(ip, Operand(scratch)); | 1206 __ cmp(ip, Operand(scratch)); |
| 1174 DeoptimizeIf(ne, instr->environment()); | 1207 DeoptimizeIf(ne, instr->environment()); |
| 1175 } else { | 1208 } else { |
| 1176 __ mul(left, left, right); | 1209 __ mul(left, left, right); |
| 1177 } | 1210 } |
| 1178 | 1211 |
| 1179 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1212 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1180 // Bail out if the result is supposed to be negative zero. | 1213 // Bail out if the result is supposed to be negative zero. |
| 1181 Label done; | 1214 Label done; |
| 1182 __ tst(left, Operand(left)); | 1215 __ tst(left, Operand(left)); |
| 1183 __ b(ne, &done); | 1216 __ b(ne, &done); |
| 1184 if (instr->right()->IsConstantOperand()) { | 1217 if (instr->InputAt(1)->IsConstantOperand()) { |
| 1185 if (ToInteger32(LConstantOperand::cast(instr->right())) < 0) { | 1218 if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) < 0) { |
| 1186 DeoptimizeIf(no_condition, instr->environment()); | 1219 DeoptimizeIf(no_condition, instr->environment()); |
| 1187 } | 1220 } |
| 1188 } else { | 1221 } else { |
| 1189 // Test the non-zero operand for negative sign. | 1222 // Test the non-zero operand for negative sign. |
| 1190 __ cmp(ToRegister(instr->temp()), Operand(0)); | 1223 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
| 1191 DeoptimizeIf(mi, instr->environment()); | 1224 DeoptimizeIf(mi, instr->environment()); |
| 1192 } | 1225 } |
| 1193 __ bind(&done); | 1226 __ bind(&done); |
| 1194 } | 1227 } |
| 1195 } | 1228 } |
| 1196 | 1229 |
| 1197 | 1230 |
| 1198 void LCodeGen::DoBitI(LBitI* instr) { | 1231 void LCodeGen::DoBitI(LBitI* instr) { |
| 1199 LOperand* left = instr->left(); | 1232 LOperand* left = instr->InputAt(0); |
| 1200 LOperand* right = instr->right(); | 1233 LOperand* right = instr->InputAt(1); |
| 1201 ASSERT(left->Equals(instr->result())); | 1234 ASSERT(left->Equals(instr->result())); |
| 1202 ASSERT(left->IsRegister()); | 1235 ASSERT(left->IsRegister()); |
| 1203 Register result = ToRegister(left); | 1236 Register result = ToRegister(left); |
| 1204 Register right_reg = EmitLoadRegister(right, ip); | 1237 Register right_reg = EmitLoadRegister(right, ip); |
| 1205 switch (instr->op()) { | 1238 switch (instr->op()) { |
| 1206 case Token::BIT_AND: | 1239 case Token::BIT_AND: |
| 1207 __ and_(result, ToRegister(left), Operand(right_reg)); | 1240 __ and_(result, ToRegister(left), Operand(right_reg)); |
| 1208 break; | 1241 break; |
| 1209 case Token::BIT_OR: | 1242 case Token::BIT_OR: |
| 1210 __ orr(result, ToRegister(left), Operand(right_reg)); | 1243 __ orr(result, ToRegister(left), Operand(right_reg)); |
| 1211 break; | 1244 break; |
| 1212 case Token::BIT_XOR: | 1245 case Token::BIT_XOR: |
| 1213 __ eor(result, ToRegister(left), Operand(right_reg)); | 1246 __ eor(result, ToRegister(left), Operand(right_reg)); |
| 1214 break; | 1247 break; |
| 1215 default: | 1248 default: |
| 1216 UNREACHABLE(); | 1249 UNREACHABLE(); |
| 1217 break; | 1250 break; |
| 1218 } | 1251 } |
| 1219 } | 1252 } |
| 1220 | 1253 |
| 1221 | 1254 |
| 1222 void LCodeGen::DoShiftI(LShiftI* instr) { | 1255 void LCodeGen::DoShiftI(LShiftI* instr) { |
| 1223 Register scratch = scratch0(); | 1256 Register scratch = scratch0(); |
| 1224 LOperand* left = instr->left(); | 1257 LOperand* left = instr->InputAt(0); |
| 1225 LOperand* right = instr->right(); | 1258 LOperand* right = instr->InputAt(1); |
| 1226 ASSERT(left->Equals(instr->result())); | 1259 ASSERT(left->Equals(instr->result())); |
| 1227 ASSERT(left->IsRegister()); | 1260 ASSERT(left->IsRegister()); |
| 1228 Register result = ToRegister(left); | 1261 Register result = ToRegister(left); |
| 1229 if (right->IsRegister()) { | 1262 if (right->IsRegister()) { |
| 1230 // Mask the right operand. | 1263 // Mask the right operand. |
| 1231 __ and_(scratch, ToRegister(right), Operand(0x1F)); | 1264 __ and_(scratch, ToRegister(right), Operand(0x1F)); |
| 1232 switch (instr->op()) { | 1265 switch (instr->op()) { |
| 1233 case Token::SAR: | 1266 case Token::SAR: |
| 1234 __ mov(result, Operand(result, ASR, scratch)); | 1267 __ mov(result, Operand(result, ASR, scratch)); |
| 1235 break; | 1268 break; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 break; | 1305 break; |
| 1273 default: | 1306 default: |
| 1274 UNREACHABLE(); | 1307 UNREACHABLE(); |
| 1275 break; | 1308 break; |
| 1276 } | 1309 } |
| 1277 } | 1310 } |
| 1278 } | 1311 } |
| 1279 | 1312 |
| 1280 | 1313 |
| 1281 void LCodeGen::DoSubI(LSubI* instr) { | 1314 void LCodeGen::DoSubI(LSubI* instr) { |
| 1282 Register left = ToRegister(instr->left()); | 1315 Register left = ToRegister(instr->InputAt(0)); |
| 1283 Register right = EmitLoadRegister(instr->right(), ip); | 1316 Register right = EmitLoadRegister(instr->InputAt(1), ip); |
| 1284 ASSERT(instr->left()->Equals(instr->result())); | 1317 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 1285 __ sub(left, left, right, SetCC); | 1318 __ sub(left, left, right, SetCC); |
| 1286 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1319 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1287 DeoptimizeIf(vs, instr->environment()); | 1320 DeoptimizeIf(vs, instr->environment()); |
| 1288 } | 1321 } |
| 1289 } | 1322 } |
| 1290 | 1323 |
| 1291 | 1324 |
| 1292 void LCodeGen::DoConstantI(LConstantI* instr) { | 1325 void LCodeGen::DoConstantI(LConstantI* instr) { |
| 1293 ASSERT(instr->result()->IsRegister()); | 1326 ASSERT(instr->result()->IsRegister()); |
| 1294 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1327 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 1295 } | 1328 } |
| 1296 | 1329 |
| 1297 | 1330 |
| 1298 void LCodeGen::DoConstantD(LConstantD* instr) { | 1331 void LCodeGen::DoConstantD(LConstantD* instr) { |
| 1299 ASSERT(instr->result()->IsDoubleRegister()); | 1332 ASSERT(instr->result()->IsDoubleRegister()); |
| 1300 DwVfpRegister result = ToDoubleRegister(instr->result()); | 1333 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 1301 double v = instr->value(); | 1334 double v = instr->value(); |
| 1302 __ vmov(result, v); | 1335 __ vmov(result, v); |
| 1303 } | 1336 } |
| 1304 | 1337 |
| 1305 | 1338 |
| 1306 void LCodeGen::DoConstantT(LConstantT* instr) { | 1339 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1307 ASSERT(instr->result()->IsRegister()); | 1340 ASSERT(instr->result()->IsRegister()); |
| 1308 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1341 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 1309 } | 1342 } |
| 1310 | 1343 |
| 1311 | 1344 |
| 1312 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1345 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 1313 Register result = ToRegister(instr->result()); | 1346 Register result = ToRegister(instr->result()); |
| 1314 Register array = ToRegister(instr->input()); | 1347 Register array = ToRegister(instr->InputAt(0)); |
| 1315 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); | 1348 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); |
| 1316 } | 1349 } |
| 1317 | 1350 |
| 1318 | 1351 |
| 1319 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | 1352 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { |
| 1320 Register result = ToRegister(instr->result()); | 1353 Register result = ToRegister(instr->result()); |
| 1321 Register array = ToRegister(instr->input()); | 1354 Register array = ToRegister(instr->InputAt(0)); |
| 1322 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); | 1355 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); |
| 1323 } | 1356 } |
| 1324 | 1357 |
| 1325 | 1358 |
| 1326 void LCodeGen::DoValueOf(LValueOf* instr) { | 1359 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 1327 Register input = ToRegister(instr->input()); | 1360 Register input = ToRegister(instr->InputAt(0)); |
| 1328 Register result = ToRegister(instr->result()); | 1361 Register result = ToRegister(instr->result()); |
| 1329 Register map = ToRegister(instr->temporary()); | 1362 Register map = ToRegister(instr->TempAt(0)); |
| 1330 ASSERT(input.is(result)); | 1363 ASSERT(input.is(result)); |
| 1331 Label done; | 1364 Label done; |
| 1332 | 1365 |
| 1333 // If the object is a smi return the object. | 1366 // If the object is a smi return the object. |
| 1334 __ tst(input, Operand(kSmiTagMask)); | 1367 __ tst(input, Operand(kSmiTagMask)); |
| 1335 __ b(eq, &done); | 1368 __ b(eq, &done); |
| 1336 | 1369 |
| 1337 // If the object is not a value type, return the object. | 1370 // If the object is not a value type, return the object. |
| 1338 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | 1371 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); |
| 1339 __ b(ne, &done); | 1372 __ b(ne, &done); |
| 1340 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); | 1373 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); |
| 1341 | 1374 |
| 1342 __ bind(&done); | 1375 __ bind(&done); |
| 1343 } | 1376 } |
| 1344 | 1377 |
| 1345 | 1378 |
| 1346 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1379 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1347 LOperand* input = instr->input(); | 1380 LOperand* input = instr->InputAt(0); |
| 1348 ASSERT(input->Equals(instr->result())); | 1381 ASSERT(input->Equals(instr->result())); |
| 1349 __ mvn(ToRegister(input), Operand(ToRegister(input))); | 1382 __ mvn(ToRegister(input), Operand(ToRegister(input))); |
| 1350 } | 1383 } |
| 1351 | 1384 |
| 1352 | 1385 |
| 1353 void LCodeGen::DoThrow(LThrow* instr) { | 1386 void LCodeGen::DoThrow(LThrow* instr) { |
| 1354 Register input_reg = EmitLoadRegister(instr->input(), ip); | 1387 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
| 1355 __ push(input_reg); | 1388 __ push(input_reg); |
| 1356 CallRuntime(Runtime::kThrow, 1, instr); | 1389 CallRuntime(Runtime::kThrow, 1, instr); |
| 1357 | 1390 |
| 1358 if (FLAG_debug_code) { | 1391 if (FLAG_debug_code) { |
| 1359 __ stop("Unreachable code."); | 1392 __ stop("Unreachable code."); |
| 1360 } | 1393 } |
| 1361 } | 1394 } |
| 1362 | 1395 |
| 1363 | 1396 |
| 1364 void LCodeGen::DoAddI(LAddI* instr) { | 1397 void LCodeGen::DoAddI(LAddI* instr) { |
| 1365 LOperand* left = instr->left(); | 1398 LOperand* left = instr->InputAt(0); |
| 1366 LOperand* right = instr->right(); | 1399 LOperand* right = instr->InputAt(1); |
| 1367 ASSERT(left->Equals(instr->result())); | 1400 ASSERT(left->Equals(instr->result())); |
| 1368 | 1401 |
| 1369 Register right_reg = EmitLoadRegister(right, ip); | 1402 Register right_reg = EmitLoadRegister(right, ip); |
| 1370 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), SetCC); | 1403 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), SetCC); |
| 1371 | 1404 |
| 1372 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1405 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1373 DeoptimizeIf(vs, instr->environment()); | 1406 DeoptimizeIf(vs, instr->environment()); |
| 1374 } | 1407 } |
| 1375 } | 1408 } |
| 1376 | 1409 |
| 1377 | 1410 |
| 1378 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1411 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 1379 DoubleRegister left = ToDoubleRegister(instr->left()); | 1412 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); |
| 1380 DoubleRegister right = ToDoubleRegister(instr->right()); | 1413 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); |
| 1381 switch (instr->op()) { | 1414 switch (instr->op()) { |
| 1382 case Token::ADD: | 1415 case Token::ADD: |
| 1383 __ vadd(left, left, right); | 1416 __ vadd(left, left, right); |
| 1384 break; | 1417 break; |
| 1385 case Token::SUB: | 1418 case Token::SUB: |
| 1386 __ vsub(left, left, right); | 1419 __ vsub(left, left, right); |
| 1387 break; | 1420 break; |
| 1388 case Token::MUL: | 1421 case Token::MUL: |
| 1389 __ vmul(left, left, right); | 1422 __ vmul(left, left, right); |
| 1390 break; | 1423 break; |
| 1391 case Token::DIV: | 1424 case Token::DIV: |
| 1392 __ vdiv(left, left, right); | 1425 __ vdiv(left, left, right); |
| 1393 break; | 1426 break; |
| 1394 case Token::MOD: { | 1427 case Token::MOD: { |
| 1395 Abort("DoArithmeticD unimplemented for MOD."); | 1428 Abort("DoArithmeticD unimplemented for MOD."); |
| 1396 break; | 1429 break; |
| 1397 } | 1430 } |
| 1398 default: | 1431 default: |
| 1399 UNREACHABLE(); | 1432 UNREACHABLE(); |
| 1400 break; | 1433 break; |
| 1401 } | 1434 } |
| 1402 } | 1435 } |
| 1403 | 1436 |
| 1404 | 1437 |
| 1405 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1438 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1406 ASSERT(ToRegister(instr->left()).is(r1)); | 1439 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); |
| 1407 ASSERT(ToRegister(instr->right()).is(r0)); | 1440 ASSERT(ToRegister(instr->InputAt(1)).is(r0)); |
| 1408 ASSERT(ToRegister(instr->result()).is(r0)); | 1441 ASSERT(ToRegister(instr->result()).is(r0)); |
| 1409 | 1442 |
| 1410 // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current | 1443 // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current |
| 1411 // GenericBinaryOpStub: | 1444 // GenericBinaryOpStub: |
| 1412 // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1445 // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1413 GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0); | 1446 GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0); |
| 1414 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1447 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1415 } | 1448 } |
| 1416 | 1449 |
| 1417 | 1450 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1441 } | 1474 } |
| 1442 } | 1475 } |
| 1443 | 1476 |
| 1444 | 1477 |
| 1445 void LCodeGen::DoBranch(LBranch* instr) { | 1478 void LCodeGen::DoBranch(LBranch* instr) { |
| 1446 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1479 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1447 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1480 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1448 | 1481 |
| 1449 Representation r = instr->hydrogen()->representation(); | 1482 Representation r = instr->hydrogen()->representation(); |
| 1450 if (r.IsInteger32()) { | 1483 if (r.IsInteger32()) { |
| 1451 Register reg = ToRegister(instr->input()); | 1484 Register reg = ToRegister(instr->InputAt(0)); |
| 1452 __ cmp(reg, Operand(0)); | 1485 __ cmp(reg, Operand(0)); |
| 1453 EmitBranch(true_block, false_block, nz); | 1486 EmitBranch(true_block, false_block, nz); |
| 1454 } else if (r.IsDouble()) { | 1487 } else if (r.IsDouble()) { |
| 1455 DoubleRegister reg = ToDoubleRegister(instr->input()); | 1488 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0)); |
| 1456 Register scratch = scratch0(); | 1489 Register scratch = scratch0(); |
| 1457 | 1490 |
| 1458 // Test the double value. Zero and NaN are false. | 1491 // Test the double value. Zero and NaN are false. |
| 1459 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 1492 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); |
| 1460 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1493 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
| 1461 EmitBranch(true_block, false_block, ne); | 1494 EmitBranch(true_block, false_block, ne); |
| 1462 } else { | 1495 } else { |
| 1463 ASSERT(r.IsTagged()); | 1496 ASSERT(r.IsTagged()); |
| 1464 Register reg = ToRegister(instr->input()); | 1497 Register reg = ToRegister(instr->InputAt(0)); |
| 1465 if (instr->hydrogen()->type().IsBoolean()) { | 1498 if (instr->hydrogen()->type().IsBoolean()) { |
| 1466 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 1499 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 1467 __ cmp(reg, ip); | 1500 __ cmp(reg, ip); |
| 1468 EmitBranch(true_block, false_block, eq); | 1501 EmitBranch(true_block, false_block, eq); |
| 1469 } else { | 1502 } else { |
| 1470 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1503 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1471 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1504 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1472 | 1505 |
| 1473 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1506 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 1474 __ cmp(reg, ip); | 1507 __ cmp(reg, ip); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1597 Abort("DoCmpID unimplemented."); | 1630 Abort("DoCmpID unimplemented."); |
| 1598 } | 1631 } |
| 1599 | 1632 |
| 1600 | 1633 |
| 1601 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1634 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
| 1602 Abort("DoCmpIDAndBranch unimplemented."); | 1635 Abort("DoCmpIDAndBranch unimplemented."); |
| 1603 } | 1636 } |
| 1604 | 1637 |
| 1605 | 1638 |
| 1606 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1639 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
| 1607 Register left = ToRegister(instr->left()); | 1640 Register left = ToRegister(instr->InputAt(0)); |
| 1608 Register right = ToRegister(instr->right()); | 1641 Register right = ToRegister(instr->InputAt(1)); |
| 1609 Register result = ToRegister(instr->result()); | 1642 Register result = ToRegister(instr->result()); |
| 1610 | 1643 |
| 1611 __ cmp(left, Operand(right)); | 1644 __ cmp(left, Operand(right)); |
| 1612 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); | 1645 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); |
| 1613 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); | 1646 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); |
| 1614 Abort("DoCmpJSObjectEq untested."); | |
| 1615 } | 1647 } |
| 1616 | 1648 |
| 1617 | 1649 |
| 1618 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1650 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
| 1619 Abort("DoCmpJSObjectEqAndBranch unimplemented."); | 1651 Register left = ToRegister(instr->InputAt(0)); |
| 1652 Register right = ToRegister(instr->InputAt(1)); |
| 1653 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1654 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1655 |
| 1656 __ cmp(left, Operand(right)); |
| 1657 EmitBranch(true_block, false_block, eq); |
| 1620 } | 1658 } |
| 1621 | 1659 |
| 1622 | 1660 |
| 1623 void LCodeGen::DoIsNull(LIsNull* instr) { | 1661 void LCodeGen::DoIsNull(LIsNull* instr) { |
| 1624 Register reg = ToRegister(instr->input()); | 1662 Register reg = ToRegister(instr->InputAt(0)); |
| 1625 Register result = ToRegister(instr->result()); | 1663 Register result = ToRegister(instr->result()); |
| 1626 | 1664 |
| 1627 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1665 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 1628 __ cmp(reg, ip); | 1666 __ cmp(reg, ip); |
| 1629 if (instr->is_strict()) { | 1667 if (instr->is_strict()) { |
| 1630 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); | 1668 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); |
| 1631 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); | 1669 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); |
| 1632 } else { | 1670 } else { |
| 1633 Label true_value, false_value, done; | 1671 Label true_value, false_value, done; |
| 1634 __ b(eq, &true_value); | 1672 __ b(eq, &true_value); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1649 __ jmp(&done); | 1687 __ jmp(&done); |
| 1650 __ bind(&true_value); | 1688 __ bind(&true_value); |
| 1651 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1689 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1652 __ bind(&done); | 1690 __ bind(&done); |
| 1653 } | 1691 } |
| 1654 } | 1692 } |
| 1655 | 1693 |
| 1656 | 1694 |
| 1657 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1695 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
| 1658 Register scratch = scratch0(); | 1696 Register scratch = scratch0(); |
| 1659 Register reg = ToRegister(instr->input()); | 1697 Register reg = ToRegister(instr->InputAt(0)); |
| 1660 | 1698 |
| 1661 // TODO(fsc): If the expression is known to be a smi, then it's | 1699 // TODO(fsc): If the expression is known to be a smi, then it's |
| 1662 // definitely not null. Jump to the false block. | 1700 // definitely not null. Jump to the false block. |
| 1663 | 1701 |
| 1664 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1702 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1665 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1703 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1666 | 1704 |
| 1667 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1705 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 1668 __ cmp(reg, ip); | 1706 __ cmp(reg, ip); |
| 1669 if (instr->is_strict()) { | 1707 if (instr->is_strict()) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1703 | 1741 |
| 1704 | 1742 |
| 1705 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1743 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 1706 Abort("DoIsObjectAndBranch unimplemented."); | 1744 Abort("DoIsObjectAndBranch unimplemented."); |
| 1707 } | 1745 } |
| 1708 | 1746 |
| 1709 | 1747 |
| 1710 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1748 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
| 1711 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1749 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1712 Register result = ToRegister(instr->result()); | 1750 Register result = ToRegister(instr->result()); |
| 1713 Register input_reg = EmitLoadRegister(instr->input(), ip); | 1751 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
| 1714 __ tst(input_reg, Operand(kSmiTagMask)); | 1752 __ tst(input_reg, Operand(kSmiTagMask)); |
| 1715 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1753 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1716 Label done; | 1754 Label done; |
| 1717 __ b(eq, &done); | 1755 __ b(eq, &done); |
| 1718 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1756 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1719 __ bind(&done); | 1757 __ bind(&done); |
| 1720 } | 1758 } |
| 1721 | 1759 |
| 1722 | 1760 |
| 1723 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1761 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 1724 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1762 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1725 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1763 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1726 | 1764 |
| 1727 Register input_reg = EmitLoadRegister(instr->input(), ip); | 1765 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
| 1728 __ tst(input_reg, Operand(kSmiTagMask)); | 1766 __ tst(input_reg, Operand(kSmiTagMask)); |
| 1729 EmitBranch(true_block, false_block, eq); | 1767 EmitBranch(true_block, false_block, eq); |
| 1730 } | 1768 } |
| 1731 | 1769 |
| 1732 | 1770 |
| 1733 InstanceType LHasInstanceType::TestType() { | 1771 static InstanceType TestType(HHasInstanceType* instr) { |
| 1734 InstanceType from = hydrogen()->from(); | 1772 InstanceType from = instr->from(); |
| 1735 InstanceType to = hydrogen()->to(); | 1773 InstanceType to = instr->to(); |
| 1736 if (from == FIRST_TYPE) return to; | 1774 if (from == FIRST_TYPE) return to; |
| 1737 ASSERT(from == to || to == LAST_TYPE); | 1775 ASSERT(from == to || to == LAST_TYPE); |
| 1738 return from; | 1776 return from; |
| 1739 } | 1777 } |
| 1740 | 1778 |
| 1741 | 1779 |
| 1742 Condition LHasInstanceType::BranchCondition() { | 1780 static Condition BranchCondition(HHasInstanceType* instr) { |
| 1743 InstanceType from = hydrogen()->from(); | 1781 InstanceType from = instr->from(); |
| 1744 InstanceType to = hydrogen()->to(); | 1782 InstanceType to = instr->to(); |
| 1745 if (from == to) return eq; | 1783 if (from == to) return eq; |
| 1746 if (to == LAST_TYPE) return hs; | 1784 if (to == LAST_TYPE) return hs; |
| 1747 if (from == FIRST_TYPE) return ls; | 1785 if (from == FIRST_TYPE) return ls; |
| 1748 UNREACHABLE(); | 1786 UNREACHABLE(); |
| 1749 return eq; | 1787 return eq; |
| 1750 } | 1788 } |
| 1751 | 1789 |
| 1752 | 1790 |
| 1753 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1791 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
| 1754 Abort("DoHasInstanceType unimplemented."); | 1792 Register input = ToRegister(instr->InputAt(0)); |
| 1793 Register result = ToRegister(instr->result()); |
| 1794 |
| 1795 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1796 Label done; |
| 1797 __ tst(input, Operand(kSmiTagMask)); |
| 1798 __ LoadRoot(result, Heap::kFalseValueRootIndex, eq); |
| 1799 __ b(eq, &done); |
| 1800 __ CompareObjectType(input, result, result, TestType(instr->hydrogen())); |
| 1801 Condition cond = BranchCondition(instr->hydrogen()); |
| 1802 __ LoadRoot(result, Heap::kTrueValueRootIndex, cond); |
| 1803 __ LoadRoot(result, Heap::kFalseValueRootIndex, NegateCondition(cond)); |
| 1804 __ bind(&done); |
| 1755 } | 1805 } |
| 1756 | 1806 |
| 1757 | 1807 |
| 1758 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1808 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 1759 Register scratch = scratch0(); | 1809 Register scratch = scratch0(); |
| 1760 Register input = ToRegister(instr->input()); | 1810 Register input = ToRegister(instr->InputAt(0)); |
| 1761 | 1811 |
| 1762 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1812 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1763 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1813 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1764 | 1814 |
| 1765 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1815 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1766 | 1816 |
| 1767 __ tst(input, Operand(kSmiTagMask)); | 1817 __ tst(input, Operand(kSmiTagMask)); |
| 1768 __ b(eq, false_label); | 1818 __ b(eq, false_label); |
| 1769 | 1819 |
| 1770 __ CompareObjectType(input, scratch, scratch, instr->TestType()); | 1820 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); |
| 1771 EmitBranch(true_block, false_block, instr->BranchCondition()); | 1821 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
| 1772 } | 1822 } |
| 1773 | 1823 |
| 1774 | 1824 |
| 1775 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1825 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
| 1776 Abort("DoHasCachedArrayIndex unimplemented."); | 1826 Abort("DoHasCachedArrayIndex unimplemented."); |
| 1777 } | 1827 } |
| 1778 | 1828 |
| 1779 | 1829 |
| 1780 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1830 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 1781 LHasCachedArrayIndexAndBranch* instr) { | 1831 LHasCachedArrayIndexAndBranch* instr) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1834 // booted. This routine isn't expected to work for random API-created | 1884 // booted. This routine isn't expected to work for random API-created |
| 1835 // classes and it doesn't have to because you can't access it with natives | 1885 // classes and it doesn't have to because you can't access it with natives |
| 1836 // syntax. Since both sides are symbols it is sufficient to use an identity | 1886 // syntax. Since both sides are symbols it is sufficient to use an identity |
| 1837 // comparison. | 1887 // comparison. |
| 1838 __ cmp(temp, Operand(class_name)); | 1888 __ cmp(temp, Operand(class_name)); |
| 1839 // End with the answer in flags. | 1889 // End with the answer in flags. |
| 1840 } | 1890 } |
| 1841 | 1891 |
| 1842 | 1892 |
| 1843 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1893 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
| 1844 Register input = ToRegister(instr->input()); | 1894 Register input = ToRegister(instr->InputAt(0)); |
| 1845 Register result = ToRegister(instr->result()); | 1895 Register result = ToRegister(instr->result()); |
| 1846 ASSERT(input.is(result)); | 1896 ASSERT(input.is(result)); |
| 1847 Handle<String> class_name = instr->hydrogen()->class_name(); | 1897 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1848 | 1898 |
| 1849 Label done, is_true, is_false; | 1899 Label done, is_true, is_false; |
| 1850 | 1900 |
| 1851 EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input); | 1901 EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input); |
| 1852 __ b(ne, &is_false); | 1902 __ b(ne, &is_false); |
| 1853 | 1903 |
| 1854 __ bind(&is_true); | 1904 __ bind(&is_true); |
| 1855 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1905 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1856 __ jmp(&done); | 1906 __ jmp(&done); |
| 1857 | 1907 |
| 1858 __ bind(&is_false); | 1908 __ bind(&is_false); |
| 1859 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1909 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1860 __ bind(&done); | 1910 __ bind(&done); |
| 1861 } | 1911 } |
| 1862 | 1912 |
| 1863 | 1913 |
| 1864 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1914 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 1865 Register input = ToRegister(instr->input()); | 1915 Register input = ToRegister(instr->InputAt(0)); |
| 1866 Register temp = scratch0(); | 1916 Register temp = scratch0(); |
| 1867 Register temp2 = ToRegister(instr->temporary()); | 1917 Register temp2 = ToRegister(instr->TempAt(0)); |
| 1868 Handle<String> class_name = instr->hydrogen()->class_name(); | 1918 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1869 | 1919 |
| 1870 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1920 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1871 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1921 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1872 | 1922 |
| 1873 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1923 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1874 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1924 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1875 | 1925 |
| 1876 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 1926 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
| 1877 | 1927 |
| 1878 EmitBranch(true_block, false_block, eq); | 1928 EmitBranch(true_block, false_block, eq); |
| 1879 } | 1929 } |
| 1880 | 1930 |
| 1881 | 1931 |
| 1882 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1932 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 1883 Register reg = ToRegister(instr->input()); | 1933 Register reg = ToRegister(instr->InputAt(0)); |
| 1884 Register temp = ToRegister(instr->temp()); | 1934 Register temp = ToRegister(instr->TempAt(0)); |
| 1885 int true_block = instr->true_block_id(); | 1935 int true_block = instr->true_block_id(); |
| 1886 int false_block = instr->false_block_id(); | 1936 int false_block = instr->false_block_id(); |
| 1887 | 1937 |
| 1888 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1938 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1889 __ cmp(temp, Operand(instr->map())); | 1939 __ cmp(temp, Operand(instr->map())); |
| 1890 EmitBranch(true_block, false_block, eq); | 1940 EmitBranch(true_block, false_block, eq); |
| 1891 } | 1941 } |
| 1892 | 1942 |
| 1893 | 1943 |
| 1894 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1944 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1895 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. | 1945 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); // Object is in r0. |
| 1896 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. | 1946 ASSERT(ToRegister(instr->InputAt(1)).is(r1)); // Function is in r1. |
| 1897 | 1947 |
| 1898 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1948 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 1899 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1949 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1900 | 1950 |
| 1901 Label true_value, done; | 1951 Label true_value, done; |
| 1902 __ tst(r0, r0); | 1952 __ tst(r0, r0); |
| 1903 __ mov(r0, Operand(Factory::false_value()), LeaveCC, ne); | 1953 __ mov(r0, Operand(Factory::false_value()), LeaveCC, ne); |
| 1904 __ mov(r0, Operand(Factory::true_value()), LeaveCC, eq); | 1954 __ mov(r0, Operand(Factory::true_value()), LeaveCC, eq); |
| 1905 } | 1955 } |
| 1906 | 1956 |
| 1907 | 1957 |
| 1908 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1958 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
| 1909 Abort("DoInstanceOfAndBranch unimplemented."); | 1959 Abort("DoInstanceOfAndBranch unimplemented."); |
| 1910 } | 1960 } |
| 1911 | 1961 |
| 1912 | 1962 |
| 1913 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 1963 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
| 1914 Abort("DoInstanceOfKnownGlobal unimplemented."); | 1964 class DeferredInstanceOfKnownGlobal: public LDeferredCode { |
| 1965 public: |
| 1966 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
| 1967 LInstanceOfKnownGlobal* instr) |
| 1968 : LDeferredCode(codegen), instr_(instr) { } |
| 1969 virtual void Generate() { |
| 1970 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); |
| 1971 } |
| 1972 |
| 1973 Label* map_check() { return &map_check_; } |
| 1974 |
| 1975 private: |
| 1976 LInstanceOfKnownGlobal* instr_; |
| 1977 Label map_check_; |
| 1978 }; |
| 1979 |
| 1980 DeferredInstanceOfKnownGlobal* deferred; |
| 1981 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
| 1982 |
| 1983 Label done, false_result; |
| 1984 Register object = ToRegister(instr->InputAt(0)); |
| 1985 Register temp = ToRegister(instr->TempAt(0)); |
| 1986 Register result = ToRegister(instr->result()); |
| 1987 |
| 1988 ASSERT(object.is(r0)); |
| 1989 ASSERT(result.is(r0)); |
| 1990 |
| 1991 // A Smi is not instance of anything. |
| 1992 __ BranchOnSmi(object, &false_result); |
| 1993 |
| 1994 // This is the inlined call site instanceof cache. The two occurences of the |
| 1995 // hole value will be patched to the last map/result pair generated by the |
| 1996 // instanceof stub. |
| 1997 Label cache_miss; |
| 1998 Register map = temp; |
| 1999 __ ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 2000 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 2001 // We use Factory::the_hole_value() on purpose instead of loading from the |
| 2002 // root array to force relocation to be able to later patch with |
| 2003 // the cached map. |
| 2004 __ mov(ip, Operand(Factory::the_hole_value())); |
| 2005 __ cmp(map, Operand(ip)); |
| 2006 __ b(ne, &cache_miss); |
| 2007 // We use Factory::the_hole_value() on purpose instead of loading from the |
| 2008 // root array to force relocation to be able to later patch |
| 2009 // with true or false. |
| 2010 __ mov(result, Operand(Factory::the_hole_value())); |
| 2011 __ b(&done); |
| 2012 |
| 2013 // The inlined call site cache did not match. Check null and string before |
| 2014 // calling the deferred code. |
| 2015 __ bind(&cache_miss); |
| 2016 // Null is not instance of anything. |
| 2017 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 2018 __ cmp(object, Operand(ip)); |
| 2019 __ b(eq, &false_result); |
| 2020 |
| 2021 // String values is not instance of anything. |
| 2022 Condition is_string = masm_->IsObjectStringType(object, temp); |
| 2023 __ b(is_string, &false_result); |
| 2024 |
| 2025 // Go to the deferred code. |
| 2026 __ b(deferred->entry()); |
| 2027 |
| 2028 __ bind(&false_result); |
| 2029 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 2030 |
| 2031 // Here result has either true or false. Deferred code also produces true or |
| 2032 // false object. |
| 2033 __ bind(deferred->exit()); |
| 2034 __ bind(&done); |
| 2035 } |
| 2036 |
| 2037 |
| 2038 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| 2039 Label* map_check) { |
| 2040 Register result = ToRegister(instr->result()); |
| 2041 ASSERT(result.is(r0)); |
| 2042 |
| 2043 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
| 2044 flags = static_cast<InstanceofStub::Flags>( |
| 2045 flags | InstanceofStub::kArgsInRegisters); |
| 2046 flags = static_cast<InstanceofStub::Flags>( |
| 2047 flags | InstanceofStub::kCallSiteInlineCheck); |
| 2048 flags = static_cast<InstanceofStub::Flags>( |
| 2049 flags | InstanceofStub::kReturnTrueFalseObject); |
| 2050 InstanceofStub stub(flags); |
| 2051 |
| 2052 __ PushSafepointRegisters(); |
| 2053 |
| 2054 // Get the temp register reserved by the instruction. This needs to be r4 as |
| 2055 // its slot of the pushing of safepoint registers is used to communicate the |
| 2056 // offset to the location of the map check. |
| 2057 Register temp = ToRegister(instr->TempAt(0)); |
| 2058 ASSERT(temp.is(r4)); |
| 2059 __ mov(InstanceofStub::right(), Operand(instr->function())); |
| 2060 static const int kAdditionalDelta = 4; |
| 2061 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
| 2062 Label before_push_delta; |
| 2063 __ bind(&before_push_delta); |
| 2064 __ BlockConstPoolFor(kAdditionalDelta); |
| 2065 __ mov(temp, Operand(delta * kPointerSize)); |
| 2066 __ StoreToSafepointRegisterSlot(temp); |
| 2067 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 2068 ASSERT_EQ(kAdditionalDelta, |
| 2069 masm_->InstructionsGeneratedSince(&before_push_delta)); |
| 2070 RecordSafepointWithRegisters( |
| 2071 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 2072 // Put the result value into the result register slot and |
| 2073 // restore all registers. |
| 2074 __ StoreToSafepointRegisterSlot(result); |
| 2075 |
| 2076 __ PopSafepointRegisters(); |
| 1915 } | 2077 } |
| 1916 | 2078 |
| 1917 | 2079 |
| 1918 static Condition ComputeCompareCondition(Token::Value op) { | 2080 static Condition ComputeCompareCondition(Token::Value op) { |
| 1919 switch (op) { | 2081 switch (op) { |
| 1920 case Token::EQ_STRICT: | 2082 case Token::EQ_STRICT: |
| 1921 case Token::EQ: | 2083 case Token::EQ: |
| 1922 return eq; | 2084 return eq; |
| 1923 case Token::LT: | 2085 case Token::LT: |
| 1924 return lt; | 2086 return lt; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1981 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); | 2143 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); |
| 1982 if (instr->hydrogen()->check_hole_value()) { | 2144 if (instr->hydrogen()->check_hole_value()) { |
| 1983 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2145 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 1984 __ cmp(result, ip); | 2146 __ cmp(result, ip); |
| 1985 DeoptimizeIf(eq, instr->environment()); | 2147 DeoptimizeIf(eq, instr->environment()); |
| 1986 } | 2148 } |
| 1987 } | 2149 } |
| 1988 | 2150 |
| 1989 | 2151 |
| 1990 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { | 2152 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { |
| 1991 Register value = ToRegister(instr->input()); | 2153 Register value = ToRegister(instr->InputAt(0)); |
| 1992 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); | 2154 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); |
| 1993 __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); | 2155 __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); |
| 1994 } | 2156 } |
| 1995 | 2157 |
| 1996 | 2158 |
| 1997 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2159 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 1998 // TODO(antonm): load a context with a separate instruction. | 2160 // TODO(antonm): load a context with a separate instruction. |
| 1999 Register result = ToRegister(instr->result()); | 2161 Register result = ToRegister(instr->result()); |
| 2000 __ LoadContext(result, instr->context_chain_length()); | 2162 __ LoadContext(result, instr->context_chain_length()); |
| 2001 __ ldr(result, ContextOperand(result, instr->slot_index())); | 2163 __ ldr(result, ContextOperand(result, instr->slot_index())); |
| 2002 } | 2164 } |
| 2003 | 2165 |
| 2004 | 2166 |
| 2005 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2167 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 2006 Register object = ToRegister(instr->input()); | 2168 Register object = ToRegister(instr->InputAt(0)); |
| 2007 Register result = ToRegister(instr->result()); | 2169 Register result = ToRegister(instr->result()); |
| 2008 if (instr->hydrogen()->is_in_object()) { | 2170 if (instr->hydrogen()->is_in_object()) { |
| 2009 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); | 2171 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); |
| 2010 } else { | 2172 } else { |
| 2011 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2173 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 2012 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); | 2174 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); |
| 2013 } | 2175 } |
| 2014 } | 2176 } |
| 2015 | 2177 |
| 2016 | 2178 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2063 // in initial map. | 2225 // in initial map. |
| 2064 __ bind(&non_instance); | 2226 __ bind(&non_instance); |
| 2065 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); | 2227 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); |
| 2066 | 2228 |
| 2067 // All done. | 2229 // All done. |
| 2068 __ bind(&done); | 2230 __ bind(&done); |
| 2069 } | 2231 } |
| 2070 | 2232 |
| 2071 | 2233 |
| 2072 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2234 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
| 2073 ASSERT(instr->result()->Equals(instr->input())); | 2235 ASSERT(instr->result()->Equals(instr->InputAt(0))); |
| 2074 Register reg = ToRegister(instr->input()); | 2236 Register reg = ToRegister(instr->InputAt(0)); |
| 2075 Register scratch = scratch0(); | 2237 Register scratch = scratch0(); |
| 2076 | 2238 |
| 2077 __ ldr(reg, FieldMemOperand(reg, JSObject::kElementsOffset)); | 2239 __ ldr(reg, FieldMemOperand(reg, JSObject::kElementsOffset)); |
| 2078 if (FLAG_debug_code) { | 2240 if (FLAG_debug_code) { |
| 2079 Label done; | 2241 Label done; |
| 2080 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2242 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2081 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 2243 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 2082 __ cmp(scratch, ip); | 2244 __ cmp(scratch, ip); |
| 2083 __ b(eq, &done); | 2245 __ b(eq, &done); |
| 2084 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); | 2246 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2145 __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2307 __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 2146 | 2308 |
| 2147 // Result is the frame pointer for the frame if not adapted and for the real | 2309 // Result is the frame pointer for the frame if not adapted and for the real |
| 2148 // frame below the adaptor frame if adapted. | 2310 // frame below the adaptor frame if adapted. |
| 2149 __ mov(result, fp, LeaveCC, ne); | 2311 __ mov(result, fp, LeaveCC, ne); |
| 2150 __ mov(result, scratch, LeaveCC, eq); | 2312 __ mov(result, scratch, LeaveCC, eq); |
| 2151 } | 2313 } |
| 2152 | 2314 |
| 2153 | 2315 |
| 2154 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2316 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 2155 Register elem = ToRegister(instr->input()); | 2317 Register elem = ToRegister(instr->InputAt(0)); |
| 2156 Register result = ToRegister(instr->result()); | 2318 Register result = ToRegister(instr->result()); |
| 2157 | 2319 |
| 2158 Label done; | 2320 Label done; |
| 2159 | 2321 |
| 2160 // If no arguments adaptor frame the number of arguments is fixed. | 2322 // If no arguments adaptor frame the number of arguments is fixed. |
| 2161 __ cmp(fp, elem); | 2323 __ cmp(fp, elem); |
| 2162 __ mov(result, Operand(scope()->num_parameters())); | 2324 __ mov(result, Operand(scope()->num_parameters())); |
| 2163 __ b(eq, &done); | 2325 __ b(eq, &done); |
| 2164 | 2326 |
| 2165 // Arguments adaptor frame present. Get argument length from there. | 2327 // Arguments adaptor frame present. Get argument length from there. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2230 // which is r0, as expected by InvokeFunction. | 2392 // which is r0, as expected by InvokeFunction. |
| 2231 v8::internal::ParameterCount actual(receiver); | 2393 v8::internal::ParameterCount actual(receiver); |
| 2232 SafepointGenerator safepoint_generator(this, | 2394 SafepointGenerator safepoint_generator(this, |
| 2233 instr->pointer_map(), | 2395 instr->pointer_map(), |
| 2234 Safepoint::kNoDeoptimizationIndex); | 2396 Safepoint::kNoDeoptimizationIndex); |
| 2235 __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator); | 2397 __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator); |
| 2236 } | 2398 } |
| 2237 | 2399 |
| 2238 | 2400 |
| 2239 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2401 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 2240 LOperand* argument = instr->input(); | 2402 LOperand* argument = instr->InputAt(0); |
| 2241 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 2403 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
| 2242 Abort("DoPushArgument not implemented for double type."); | 2404 Abort("DoPushArgument not implemented for double type."); |
| 2243 } else { | 2405 } else { |
| 2244 Register argument_reg = EmitLoadRegister(argument, ip); | 2406 Register argument_reg = EmitLoadRegister(argument, ip); |
| 2245 __ push(argument_reg); | 2407 __ push(argument_reg); |
| 2246 } | 2408 } |
| 2247 } | 2409 } |
| 2248 | 2410 |
| 2249 | 2411 |
| 2250 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 2412 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2294 | 2456 |
| 2295 | 2457 |
| 2296 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2458 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 2297 ASSERT(ToRegister(instr->result()).is(r0)); | 2459 ASSERT(ToRegister(instr->result()).is(r0)); |
| 2298 __ mov(r1, Operand(instr->function())); | 2460 __ mov(r1, Operand(instr->function())); |
| 2299 CallKnownFunction(instr->function(), instr->arity(), instr); | 2461 CallKnownFunction(instr->function(), instr->arity(), instr); |
| 2300 } | 2462 } |
| 2301 | 2463 |
| 2302 | 2464 |
| 2303 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2465 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 2304 Abort("DoDeferredMathAbsTaggedHeapNumber unimplemented."); | 2466 Register input = ToRegister(instr->InputAt(0)); |
| 2467 Register scratch = scratch0(); |
| 2468 |
| 2469 // Deoptimize if not a heap number. |
| 2470 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 2471 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 2472 __ cmp(scratch, Operand(ip)); |
| 2473 DeoptimizeIf(ne, instr->environment()); |
| 2474 |
| 2475 Label done; |
| 2476 |
| 2477 Label negative; |
| 2478 __ ldr(scratch, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 2479 // Check the sign of the argument. If the argument is positive, just |
| 2480 // return it. We do not need to patch the stack since |input| and |
| 2481 // |result| are the same register and |input| will be restored |
| 2482 // unchanged by popping safepoint registers. |
| 2483 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
| 2484 __ b(ne, &negative); |
| 2485 __ jmp(&done); |
| 2486 |
| 2487 __ bind(&negative); |
| 2488 // Preserve the value of all registers. |
| 2489 __ PushSafepointRegisters(); |
| 2490 |
| 2491 Register tmp = input.is(r0) ? r1 : r0; |
| 2492 Register tmp2 = input.is(r2) ? r3 : r2; |
| 2493 Register tmp3 = input.is(r4) ? r5 : r4; |
| 2494 |
| 2495 Label allocated, slow; |
| 2496 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 2497 __ AllocateHeapNumber(tmp, tmp2, tmp3, scratch, &slow); |
| 2498 __ b(&allocated); |
| 2499 |
| 2500 // Slow case: Call the runtime system to do the number allocation. |
| 2501 __ bind(&slow); |
| 2502 |
| 2503 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 2504 RecordSafepointWithRegisters( |
| 2505 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 2506 // Set the pointer to the new heap number in tmp. |
| 2507 if (!tmp.is(r0)) __ mov(tmp, Operand(r0)); |
| 2508 |
| 2509 // Restore input_reg after call to runtime. |
| 2510 MemOperand input_register_slot = masm()->SafepointRegisterSlot(input); |
| 2511 __ ldr(input, input_register_slot); |
| 2512 |
| 2513 __ bind(&allocated); |
| 2514 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 2515 __ bic(tmp2, tmp2, Operand(HeapNumber::kSignMask)); |
| 2516 __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kExponentOffset)); |
| 2517 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
| 2518 __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kMantissaOffset)); |
| 2519 |
| 2520 __ str(tmp, input_register_slot); |
| 2521 __ PopSafepointRegisters(); |
| 2522 |
| 2523 __ bind(&done); |
| 2524 } |
| 2525 |
| 2526 |
| 2527 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 2528 Label is_positive; |
| 2529 uint32_t kSignMask = 0x80000000u; |
| 2530 Register input = ToRegister(instr->InputAt(0)); |
| 2531 __ tst(input, Operand(kSignMask)); |
| 2532 __ b(eq, &is_positive); |
| 2533 __ rsb(input, input, Operand(0), SetCC); |
| 2534 // Deoptimize on overflow. |
| 2535 DeoptimizeIf(vs, instr->environment()); |
| 2536 __ bind(&is_positive); |
| 2305 } | 2537 } |
| 2306 | 2538 |
| 2307 | 2539 |
| 2308 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2540 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
| 2309 Abort("DoMathAbs unimplemented."); | 2541 // Class for deferred case. |
| 2542 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 2543 public: |
| 2544 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
| 2545 LUnaryMathOperation* instr) |
| 2546 : LDeferredCode(codegen), instr_(instr) { } |
| 2547 virtual void Generate() { |
| 2548 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 2549 } |
| 2550 private: |
| 2551 LUnaryMathOperation* instr_; |
| 2552 }; |
| 2553 |
| 2554 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 2555 Representation r = instr->hydrogen()->value()->representation(); |
| 2556 if (r.IsDouble()) { |
| 2557 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 2558 // __ vabs(input, input); |
| 2559 Abort("Double DoMathAbs unimplemented"); |
| 2560 } else if (r.IsInteger32()) { |
| 2561 EmitIntegerMathAbs(instr); |
| 2562 } else { |
| 2563 // Representation is tagged. |
| 2564 DeferredMathAbsTaggedHeapNumber* deferred = |
| 2565 new DeferredMathAbsTaggedHeapNumber(this, instr); |
| 2566 Register input = ToRegister(instr->InputAt(0)); |
| 2567 // Smi check. |
| 2568 __ BranchOnNotSmi(input, deferred->entry()); |
| 2569 // If smi, handle it directly. |
| 2570 EmitIntegerMathAbs(instr); |
| 2571 __ bind(deferred->exit()); |
| 2572 } |
| 2310 } | 2573 } |
| 2311 | 2574 |
| 2312 | 2575 |
| 2313 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 2576 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| 2314 DoubleRegister input = ToDoubleRegister(instr->input()); | 2577 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 2315 Register result = ToRegister(instr->result()); | 2578 Register result = ToRegister(instr->result()); |
| 2316 Register prev_fpscr = ToRegister(instr->temp()); | 2579 Register prev_fpscr = ToRegister(instr->TempAt(0)); |
| 2317 SwVfpRegister single_scratch = double_scratch0().low(); | 2580 SwVfpRegister single_scratch = double_scratch0().low(); |
| 2318 Register scratch = scratch0(); | 2581 Register scratch = scratch0(); |
| 2319 | 2582 |
| 2320 // Set custom FPCSR: | 2583 // Set custom FPCSR: |
| 2321 // - Set rounding mode to "Round towards Minus Infinity". | 2584 // - Set rounding mode to "Round towards Minus Infinity". |
| 2322 // - Clear vfp cumulative exception flags. | 2585 // - Clear vfp cumulative exception flags. |
| 2323 // - Make sure Flush-to-zero mode control bit is unset. | 2586 // - Make sure Flush-to-zero mode control bit is unset. |
| 2324 __ vmrs(prev_fpscr); | 2587 __ vmrs(prev_fpscr); |
| 2325 __ bic(scratch, prev_fpscr, | 2588 __ bic(scratch, prev_fpscr, |
| 2326 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); | 2589 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2348 __ cmp(result, Operand(0)); | 2611 __ cmp(result, Operand(0)); |
| 2349 __ b(ne, &done); | 2612 __ b(ne, &done); |
| 2350 __ vmov(scratch, input.high()); | 2613 __ vmov(scratch, input.high()); |
| 2351 __ tst(scratch, Operand(HeapNumber::kSignMask)); | 2614 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
| 2352 DeoptimizeIf(ne, instr->environment()); | 2615 DeoptimizeIf(ne, instr->environment()); |
| 2353 __ bind(&done); | 2616 __ bind(&done); |
| 2354 } | 2617 } |
| 2355 | 2618 |
| 2356 | 2619 |
| 2357 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 2620 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 2358 DoubleRegister input = ToDoubleRegister(instr->input()); | 2621 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 2359 ASSERT(ToDoubleRegister(instr->result()).is(input)); | 2622 ASSERT(ToDoubleRegister(instr->result()).is(input)); |
| 2360 __ vsqrt(input, input); | 2623 __ vsqrt(input, input); |
| 2361 } | 2624 } |
| 2362 | 2625 |
| 2363 | 2626 |
| 2364 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { | 2627 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { |
| 2365 switch (instr->op()) { | 2628 switch (instr->op()) { |
| 2366 case kMathAbs: | 2629 case kMathAbs: |
| 2367 DoMathAbs(instr); | 2630 DoMathAbs(instr); |
| 2368 break; | 2631 break; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2424 | 2687 |
| 2425 | 2688 |
| 2426 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 2689 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 2427 ASSERT(ToRegister(instr->result()).is(r0)); | 2690 ASSERT(ToRegister(instr->result()).is(r0)); |
| 2428 __ mov(r1, Operand(instr->target())); | 2691 __ mov(r1, Operand(instr->target())); |
| 2429 CallKnownFunction(instr->target(), instr->arity(), instr); | 2692 CallKnownFunction(instr->target(), instr->arity(), instr); |
| 2430 } | 2693 } |
| 2431 | 2694 |
| 2432 | 2695 |
| 2433 void LCodeGen::DoCallNew(LCallNew* instr) { | 2696 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 2434 ASSERT(ToRegister(instr->input()).is(r1)); | 2697 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); |
| 2435 ASSERT(ToRegister(instr->result()).is(r0)); | 2698 ASSERT(ToRegister(instr->result()).is(r0)); |
| 2436 | 2699 |
| 2437 Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); | 2700 Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); |
| 2438 __ mov(r0, Operand(instr->arity())); | 2701 __ mov(r0, Operand(instr->arity())); |
| 2439 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); | 2702 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); |
| 2440 } | 2703 } |
| 2441 | 2704 |
| 2442 | 2705 |
| 2443 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 2706 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 2444 CallRuntime(instr->function(), instr->arity(), instr); | 2707 CallRuntime(instr->function(), instr->arity(), instr); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2523 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 2786 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 2524 ASSERT(ToRegister(instr->object()).is(r2)); | 2787 ASSERT(ToRegister(instr->object()).is(r2)); |
| 2525 ASSERT(ToRegister(instr->key()).is(r1)); | 2788 ASSERT(ToRegister(instr->key()).is(r1)); |
| 2526 ASSERT(ToRegister(instr->value()).is(r0)); | 2789 ASSERT(ToRegister(instr->value()).is(r0)); |
| 2527 | 2790 |
| 2528 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 2791 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 2529 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2792 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2530 } | 2793 } |
| 2531 | 2794 |
| 2532 | 2795 |
| 2796 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 2797 class DeferredStringCharCodeAt: public LDeferredCode { |
| 2798 public: |
| 2799 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 2800 : LDeferredCode(codegen), instr_(instr) { } |
| 2801 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } |
| 2802 private: |
| 2803 LStringCharCodeAt* instr_; |
| 2804 }; |
| 2805 |
| 2806 Register scratch = scratch0(); |
| 2807 Register string = ToRegister(instr->string()); |
| 2808 Register index = no_reg; |
| 2809 int const_index = -1; |
| 2810 if (instr->index()->IsConstantOperand()) { |
| 2811 const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 2812 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 2813 if (!Smi::IsValid(const_index)) { |
| 2814 // Guaranteed to be out of bounds because of the assert above. |
| 2815 // So the bounds check that must dominate this instruction must |
| 2816 // have deoptimized already. |
| 2817 if (FLAG_debug_code) { |
| 2818 __ Abort("StringCharCodeAt: out of bounds index."); |
| 2819 } |
| 2820 // No code needs to be generated. |
| 2821 return; |
| 2822 } |
| 2823 } else { |
| 2824 index = ToRegister(instr->index()); |
| 2825 } |
| 2826 Register result = ToRegister(instr->result()); |
| 2827 |
| 2828 DeferredStringCharCodeAt* deferred = |
| 2829 new DeferredStringCharCodeAt(this, instr); |
| 2830 |
| 2831 Label flat_string, ascii_string, done; |
| 2832 |
| 2833 // Fetch the instance type of the receiver into result register. |
| 2834 __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 2835 __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); |
| 2836 |
| 2837 // We need special handling for non-flat strings. |
| 2838 STATIC_ASSERT(kSeqStringTag == 0); |
| 2839 __ tst(result, Operand(kStringRepresentationMask)); |
| 2840 __ b(eq, &flat_string); |
| 2841 |
| 2842 // Handle non-flat strings. |
| 2843 __ tst(result, Operand(kIsConsStringMask)); |
| 2844 __ b(eq, deferred->entry()); |
| 2845 |
| 2846 // ConsString. |
| 2847 // Check whether the right hand side is the empty string (i.e. if |
| 2848 // this is really a flat string in a cons string). If that is not |
| 2849 // the case we would rather go to the runtime system now to flatten |
| 2850 // the string. |
| 2851 __ ldr(scratch, FieldMemOperand(string, ConsString::kSecondOffset)); |
| 2852 __ LoadRoot(ip, Heap::kEmptyStringRootIndex); |
| 2853 __ cmp(scratch, ip); |
| 2854 __ b(ne, deferred->entry()); |
| 2855 // Get the first of the two strings and load its instance type. |
| 2856 __ ldr(string, FieldMemOperand(string, ConsString::kFirstOffset)); |
| 2857 __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 2858 __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); |
| 2859 // If the first cons component is also non-flat, then go to runtime. |
| 2860 STATIC_ASSERT(kSeqStringTag == 0); |
| 2861 __ tst(result, Operand(kStringRepresentationMask)); |
| 2862 __ b(ne, deferred->entry()); |
| 2863 |
| 2864 // Check for 1-byte or 2-byte string. |
| 2865 __ bind(&flat_string); |
| 2866 STATIC_ASSERT(kAsciiStringTag != 0); |
| 2867 __ tst(result, Operand(kStringEncodingMask)); |
| 2868 __ b(ne, &ascii_string); |
| 2869 |
| 2870 // 2-byte string. |
| 2871 // Load the 2-byte character code into the result register. |
| 2872 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 2873 if (instr->index()->IsConstantOperand()) { |
| 2874 __ ldrh(result, |
| 2875 FieldMemOperand(string, |
| 2876 SeqTwoByteString::kHeaderSize + 2 * const_index)); |
| 2877 } else { |
| 2878 __ add(scratch, |
| 2879 string, |
| 2880 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
| 2881 __ ldrh(result, MemOperand(scratch, index, LSL, 1)); |
| 2882 } |
| 2883 __ jmp(&done); |
| 2884 |
| 2885 // ASCII string. |
| 2886 // Load the byte into the result register. |
| 2887 __ bind(&ascii_string); |
| 2888 if (instr->index()->IsConstantOperand()) { |
| 2889 __ ldrb(result, FieldMemOperand(string, |
| 2890 SeqAsciiString::kHeaderSize + const_index)); |
| 2891 } else { |
| 2892 __ add(scratch, |
| 2893 string, |
| 2894 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 2895 __ ldrb(result, MemOperand(scratch, index)); |
| 2896 } |
| 2897 __ bind(&done); |
| 2898 __ bind(deferred->exit()); |
| 2899 } |
| 2900 |
| 2901 |
| 2902 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
| 2903 Register string = ToRegister(instr->string()); |
| 2904 Register result = ToRegister(instr->result()); |
| 2905 Register scratch = scratch0(); |
| 2906 |
| 2907 // TODO(3095996): Get rid of this. For now, we need to make the |
| 2908 // result register contain a valid pointer because it is already |
| 2909 // contained in the register pointer map. |
| 2910 __ mov(result, Operand(0)); |
| 2911 |
| 2912 __ PushSafepointRegisters(); |
| 2913 __ push(string); |
| 2914 // Push the index as a smi. This is safe because of the checks in |
| 2915 // DoStringCharCodeAt above. |
| 2916 if (instr->index()->IsConstantOperand()) { |
| 2917 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 2918 __ mov(scratch, Operand(Smi::FromInt(const_index))); |
| 2919 __ push(scratch); |
| 2920 } else { |
| 2921 Register index = ToRegister(instr->index()); |
| 2922 __ SmiTag(index); |
| 2923 __ push(index); |
| 2924 } |
| 2925 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt); |
| 2926 RecordSafepointWithRegisters( |
| 2927 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); |
| 2928 if (FLAG_debug_code) { |
| 2929 __ AbortIfNotSmi(r0); |
| 2930 } |
| 2931 __ SmiUntag(r0); |
| 2932 MemOperand result_stack_slot = masm()->SafepointRegisterSlot(result); |
| 2933 __ str(r0, result_stack_slot); |
| 2934 __ PopSafepointRegisters(); |
| 2935 } |
| 2936 |
| 2937 |
| 2938 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 2939 Register string = ToRegister(instr->InputAt(0)); |
| 2940 Register result = ToRegister(instr->result()); |
| 2941 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); |
| 2942 } |
| 2943 |
| 2944 |
| 2533 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 2945 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 2534 LOperand* input = instr->input(); | 2946 LOperand* input = instr->InputAt(0); |
| 2535 ASSERT(input->IsRegister() || input->IsStackSlot()); | 2947 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 2536 LOperand* output = instr->result(); | 2948 LOperand* output = instr->result(); |
| 2537 ASSERT(output->IsDoubleRegister()); | 2949 ASSERT(output->IsDoubleRegister()); |
| 2538 SwVfpRegister single_scratch = double_scratch0().low(); | 2950 SwVfpRegister single_scratch = double_scratch0().low(); |
| 2539 if (input->IsStackSlot()) { | 2951 if (input->IsStackSlot()) { |
| 2540 Register scratch = scratch0(); | 2952 Register scratch = scratch0(); |
| 2541 __ ldr(scratch, ToMemOperand(input)); | 2953 __ ldr(scratch, ToMemOperand(input)); |
| 2542 __ vmov(single_scratch, scratch); | 2954 __ vmov(single_scratch, scratch); |
| 2543 } else { | 2955 } else { |
| 2544 __ vmov(single_scratch, ToRegister(input)); | 2956 __ vmov(single_scratch, ToRegister(input)); |
| 2545 } | 2957 } |
| 2546 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); | 2958 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); |
| 2547 } | 2959 } |
| 2548 | 2960 |
| 2549 | 2961 |
| 2550 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 2962 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 2551 class DeferredNumberTagI: public LDeferredCode { | 2963 class DeferredNumberTagI: public LDeferredCode { |
| 2552 public: | 2964 public: |
| 2553 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 2965 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
| 2554 : LDeferredCode(codegen), instr_(instr) { } | 2966 : LDeferredCode(codegen), instr_(instr) { } |
| 2555 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } | 2967 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } |
| 2556 private: | 2968 private: |
| 2557 LNumberTagI* instr_; | 2969 LNumberTagI* instr_; |
| 2558 }; | 2970 }; |
| 2559 | 2971 |
| 2560 LOperand* input = instr->input(); | 2972 LOperand* input = instr->InputAt(0); |
| 2561 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 2973 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 2562 Register reg = ToRegister(input); | 2974 Register reg = ToRegister(input); |
| 2563 | 2975 |
| 2564 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); | 2976 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); |
| 2565 __ SmiTag(reg, SetCC); | 2977 __ SmiTag(reg, SetCC); |
| 2566 __ b(vs, deferred->entry()); | 2978 __ b(vs, deferred->entry()); |
| 2567 __ bind(deferred->exit()); | 2979 __ bind(deferred->exit()); |
| 2568 } | 2980 } |
| 2569 | 2981 |
| 2570 | 2982 |
| 2571 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 2983 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
| 2572 Label slow; | 2984 Label slow; |
| 2573 Register reg = ToRegister(instr->input()); | 2985 Register reg = ToRegister(instr->InputAt(0)); |
| 2574 DoubleRegister dbl_scratch = d0; | 2986 DoubleRegister dbl_scratch = d0; |
| 2575 SwVfpRegister flt_scratch = s0; | 2987 SwVfpRegister flt_scratch = s0; |
| 2576 | 2988 |
| 2577 // Preserve the value of all registers. | 2989 // Preserve the value of all registers. |
| 2578 __ PushSafepointRegisters(); | 2990 __ PushSafepointRegisters(); |
| 2579 | 2991 |
| 2580 // There was overflow, so bits 30 and 31 of the original integer | 2992 // There was overflow, so bits 30 and 31 of the original integer |
| 2581 // disagree. Try to allocate a heap number in new space and store | 2993 // disagree. Try to allocate a heap number in new space and store |
| 2582 // the value in there. If that fails, call the runtime system. | 2994 // the value in there. If that fails, call the runtime system. |
| 2583 Label done; | 2995 Label done; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2620 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 3032 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 2621 class DeferredNumberTagD: public LDeferredCode { | 3033 class DeferredNumberTagD: public LDeferredCode { |
| 2622 public: | 3034 public: |
| 2623 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 3035 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 2624 : LDeferredCode(codegen), instr_(instr) { } | 3036 : LDeferredCode(codegen), instr_(instr) { } |
| 2625 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 3037 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 2626 private: | 3038 private: |
| 2627 LNumberTagD* instr_; | 3039 LNumberTagD* instr_; |
| 2628 }; | 3040 }; |
| 2629 | 3041 |
| 2630 DoubleRegister input_reg = ToDoubleRegister(instr->input()); | 3042 DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2631 Register scratch = scratch0(); | 3043 Register scratch = scratch0(); |
| 2632 Register reg = ToRegister(instr->result()); | 3044 Register reg = ToRegister(instr->result()); |
| 2633 Register temp1 = ToRegister(instr->temp1()); | 3045 Register temp1 = ToRegister(instr->TempAt(0)); |
| 2634 Register temp2 = ToRegister(instr->temp2()); | 3046 Register temp2 = ToRegister(instr->TempAt(1)); |
| 2635 | 3047 |
| 2636 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); | 3048 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); |
| 2637 if (FLAG_inline_new) { | 3049 if (FLAG_inline_new) { |
| 2638 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 3050 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 2639 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); | 3051 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); |
| 2640 } else { | 3052 } else { |
| 2641 __ jmp(deferred->entry()); | 3053 __ jmp(deferred->entry()); |
| 2642 } | 3054 } |
| 2643 __ bind(deferred->exit()); | 3055 __ bind(deferred->exit()); |
| 2644 __ sub(ip, reg, Operand(kHeapObjectTag)); | 3056 __ sub(ip, reg, Operand(kHeapObjectTag)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2657 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 3069 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 2658 RecordSafepointWithRegisters( | 3070 RecordSafepointWithRegisters( |
| 2659 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | 3071 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 2660 int reg_stack_index = __ SafepointRegisterStackIndex(reg.code()); | 3072 int reg_stack_index = __ SafepointRegisterStackIndex(reg.code()); |
| 2661 __ str(r0, MemOperand(sp, reg_stack_index * kPointerSize)); | 3073 __ str(r0, MemOperand(sp, reg_stack_index * kPointerSize)); |
| 2662 __ PopSafepointRegisters(); | 3074 __ PopSafepointRegisters(); |
| 2663 } | 3075 } |
| 2664 | 3076 |
| 2665 | 3077 |
| 2666 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 3078 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 2667 LOperand* input = instr->input(); | 3079 LOperand* input = instr->InputAt(0); |
| 2668 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3080 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 2669 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 3081 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 2670 __ SmiTag(ToRegister(input)); | 3082 __ SmiTag(ToRegister(input)); |
| 2671 } | 3083 } |
| 2672 | 3084 |
| 2673 | 3085 |
| 2674 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 3086 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 2675 LOperand* input = instr->input(); | 3087 LOperand* input = instr->InputAt(0); |
| 2676 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3088 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 2677 if (instr->needs_check()) { | 3089 if (instr->needs_check()) { |
| 2678 __ tst(ToRegister(input), Operand(kSmiTagMask)); | 3090 __ tst(ToRegister(input), Operand(kSmiTagMask)); |
| 2679 DeoptimizeIf(ne, instr->environment()); | 3091 DeoptimizeIf(ne, instr->environment()); |
| 2680 } | 3092 } |
| 2681 __ SmiUntag(ToRegister(input)); | 3093 __ SmiUntag(ToRegister(input)); |
| 2682 } | 3094 } |
| 2683 | 3095 |
| 2684 | 3096 |
| 2685 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3097 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2732 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 3144 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 2733 : LDeferredCode(codegen), instr_(instr) { } | 3145 : LDeferredCode(codegen), instr_(instr) { } |
| 2734 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 3146 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 2735 private: | 3147 private: |
| 2736 LTaggedToI* instr_; | 3148 LTaggedToI* instr_; |
| 2737 }; | 3149 }; |
| 2738 | 3150 |
| 2739 | 3151 |
| 2740 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3152 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 2741 Label done; | 3153 Label done; |
| 2742 Register input_reg = ToRegister(instr->input()); | 3154 Register input_reg = ToRegister(instr->InputAt(0)); |
| 2743 Register scratch = scratch0(); | 3155 Register scratch = scratch0(); |
| 2744 DoubleRegister dbl_scratch = d0; | 3156 DoubleRegister dbl_scratch = d0; |
| 2745 SwVfpRegister flt_scratch = s0; | 3157 SwVfpRegister flt_scratch = s0; |
| 2746 DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp()); | 3158 DoubleRegister dbl_tmp = ToDoubleRegister(instr->TempAt(0)); |
| 2747 | 3159 |
| 2748 // Heap number map check. | 3160 // Heap number map check. |
| 2749 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 3161 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 2750 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3162 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 2751 __ cmp(scratch, Operand(ip)); | 3163 __ cmp(scratch, Operand(ip)); |
| 2752 | 3164 |
| 2753 if (instr->truncating()) { | 3165 if (instr->truncating()) { |
| 2754 Label heap_number; | 3166 Label heap_number; |
| 2755 __ b(eq, &heap_number); | 3167 __ b(eq, &heap_number); |
| 2756 // Check for undefined. Undefined is converted to zero for truncating | 3168 // Check for undefined. Undefined is converted to zero for truncating |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2793 __ vmov(lr, ip, dbl_tmp); | 3205 __ vmov(lr, ip, dbl_tmp); |
| 2794 __ tst(ip, Operand(1 << 31)); // Test sign bit. | 3206 __ tst(ip, Operand(1 << 31)); // Test sign bit. |
| 2795 DeoptimizeIf(ne, instr->environment()); | 3207 DeoptimizeIf(ne, instr->environment()); |
| 2796 } | 3208 } |
| 2797 } | 3209 } |
| 2798 __ bind(&done); | 3210 __ bind(&done); |
| 2799 } | 3211 } |
| 2800 | 3212 |
| 2801 | 3213 |
| 2802 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 3214 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 2803 LOperand* input = instr->input(); | 3215 LOperand* input = instr->InputAt(0); |
| 2804 ASSERT(input->IsRegister()); | 3216 ASSERT(input->IsRegister()); |
| 2805 ASSERT(input->Equals(instr->result())); | 3217 ASSERT(input->Equals(instr->result())); |
| 2806 | 3218 |
| 2807 Register input_reg = ToRegister(input); | 3219 Register input_reg = ToRegister(input); |
| 2808 | 3220 |
| 2809 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); | 3221 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); |
| 2810 | 3222 |
| 2811 // Smi check. | 3223 // Smi check. |
| 2812 __ tst(input_reg, Operand(kSmiTagMask)); | 3224 __ tst(input_reg, Operand(kSmiTagMask)); |
| 2813 __ b(ne, deferred->entry()); | 3225 __ b(ne, deferred->entry()); |
| 2814 | 3226 |
| 2815 // Smi to int32 conversion | 3227 // Smi to int32 conversion |
| 2816 __ SmiUntag(input_reg); // Untag smi. | 3228 __ SmiUntag(input_reg); // Untag smi. |
| 2817 | 3229 |
| 2818 __ bind(deferred->exit()); | 3230 __ bind(deferred->exit()); |
| 2819 } | 3231 } |
| 2820 | 3232 |
| 2821 | 3233 |
| 2822 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 3234 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 2823 LOperand* input = instr->input(); | 3235 LOperand* input = instr->InputAt(0); |
| 2824 ASSERT(input->IsRegister()); | 3236 ASSERT(input->IsRegister()); |
| 2825 LOperand* result = instr->result(); | 3237 LOperand* result = instr->result(); |
| 2826 ASSERT(result->IsDoubleRegister()); | 3238 ASSERT(result->IsDoubleRegister()); |
| 2827 | 3239 |
| 2828 Register input_reg = ToRegister(input); | 3240 Register input_reg = ToRegister(input); |
| 2829 DoubleRegister result_reg = ToDoubleRegister(result); | 3241 DoubleRegister result_reg = ToDoubleRegister(result); |
| 2830 | 3242 |
| 2831 EmitNumberUntagD(input_reg, result_reg, instr->environment()); | 3243 EmitNumberUntagD(input_reg, result_reg, instr->environment()); |
| 2832 } | 3244 } |
| 2833 | 3245 |
| 2834 | 3246 |
| 2835 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 3247 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 2836 Abort("DoDoubleToI unimplemented."); | 3248 Abort("DoDoubleToI unimplemented."); |
| 2837 } | 3249 } |
| 2838 | 3250 |
| 2839 | 3251 |
| 2840 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 3252 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 2841 LOperand* input = instr->input(); | 3253 LOperand* input = instr->InputAt(0); |
| 2842 ASSERT(input->IsRegister()); | 3254 ASSERT(input->IsRegister()); |
| 2843 __ tst(ToRegister(input), Operand(kSmiTagMask)); | 3255 __ tst(ToRegister(input), Operand(kSmiTagMask)); |
| 2844 DeoptimizeIf(instr->condition(), instr->environment()); | 3256 DeoptimizeIf(instr->condition(), instr->environment()); |
| 2845 } | 3257 } |
| 2846 | 3258 |
| 2847 | 3259 |
| 2848 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 3260 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 2849 Register input = ToRegister(instr->input()); | 3261 Register input = ToRegister(instr->InputAt(0)); |
| 2850 Register scratch = scratch0(); | 3262 Register scratch = scratch0(); |
| 2851 InstanceType first = instr->hydrogen()->first(); | 3263 InstanceType first = instr->hydrogen()->first(); |
| 2852 InstanceType last = instr->hydrogen()->last(); | 3264 InstanceType last = instr->hydrogen()->last(); |
| 2853 | 3265 |
| 2854 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3266 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 2855 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 3267 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 2856 __ cmp(scratch, Operand(first)); | 3268 __ cmp(scratch, Operand(first)); |
| 2857 | 3269 |
| 2858 // If there is only one type in the interval check for equality. | 3270 // If there is only one type in the interval check for equality. |
| 2859 if (first == last) { | 3271 if (first == last) { |
| 2860 DeoptimizeIf(ne, instr->environment()); | 3272 DeoptimizeIf(ne, instr->environment()); |
| 2861 } else { | 3273 } else { |
| 2862 DeoptimizeIf(lo, instr->environment()); | 3274 DeoptimizeIf(lo, instr->environment()); |
| 2863 // Omit check for the last type. | 3275 // Omit check for the last type. |
| 2864 if (last != LAST_TYPE) { | 3276 if (last != LAST_TYPE) { |
| 2865 __ cmp(scratch, Operand(last)); | 3277 __ cmp(scratch, Operand(last)); |
| 2866 DeoptimizeIf(hi, instr->environment()); | 3278 DeoptimizeIf(hi, instr->environment()); |
| 2867 } | 3279 } |
| 2868 } | 3280 } |
| 2869 } | 3281 } |
| 2870 | 3282 |
| 2871 | 3283 |
| 2872 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 3284 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
| 2873 ASSERT(instr->input()->IsRegister()); | 3285 ASSERT(instr->InputAt(0)->IsRegister()); |
| 2874 Register reg = ToRegister(instr->input()); | 3286 Register reg = ToRegister(instr->InputAt(0)); |
| 2875 __ cmp(reg, Operand(instr->hydrogen()->target())); | 3287 __ cmp(reg, Operand(instr->hydrogen()->target())); |
| 2876 DeoptimizeIf(ne, instr->environment()); | 3288 DeoptimizeIf(ne, instr->environment()); |
| 2877 } | 3289 } |
| 2878 | 3290 |
| 2879 | 3291 |
| 2880 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 3292 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
| 2881 Register scratch = scratch0(); | 3293 Register scratch = scratch0(); |
| 2882 LOperand* input = instr->input(); | 3294 LOperand* input = instr->InputAt(0); |
| 2883 ASSERT(input->IsRegister()); | 3295 ASSERT(input->IsRegister()); |
| 2884 Register reg = ToRegister(input); | 3296 Register reg = ToRegister(input); |
| 2885 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 3297 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2886 __ cmp(scratch, Operand(instr->hydrogen()->map())); | 3298 __ cmp(scratch, Operand(instr->hydrogen()->map())); |
| 2887 DeoptimizeIf(ne, instr->environment()); | 3299 DeoptimizeIf(ne, instr->environment()); |
| 2888 } | 3300 } |
| 2889 | 3301 |
| 2890 | 3302 |
| 2891 void LCodeGen::LoadHeapObject(Register result, | 3303 void LCodeGen::LoadHeapObject(Register result, |
| 2892 Handle<HeapObject> object) { | 3304 Handle<HeapObject> object) { |
| 2893 if (Heap::InNewSpace(*object)) { | 3305 if (Heap::InNewSpace(*object)) { |
| 2894 Handle<JSGlobalPropertyCell> cell = | 3306 Handle<JSGlobalPropertyCell> cell = |
| 2895 Factory::NewJSGlobalPropertyCell(object); | 3307 Factory::NewJSGlobalPropertyCell(object); |
| 2896 __ mov(result, Operand(cell)); | 3308 __ mov(result, Operand(cell)); |
| 2897 __ ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset)); | 3309 __ ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset)); |
| 2898 } else { | 3310 } else { |
| 2899 __ mov(result, Operand(object)); | 3311 __ mov(result, Operand(object)); |
| 2900 } | 3312 } |
| 2901 } | 3313 } |
| 2902 | 3314 |
| 2903 | 3315 |
| 2904 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 3316 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 2905 Register temp1 = ToRegister(instr->temp1()); | 3317 Register temp1 = ToRegister(instr->TempAt(0)); |
| 2906 Register temp2 = ToRegister(instr->temp2()); | 3318 Register temp2 = ToRegister(instr->TempAt(1)); |
| 2907 | 3319 |
| 2908 Handle<JSObject> holder = instr->holder(); | 3320 Handle<JSObject> holder = instr->holder(); |
| 2909 Handle<JSObject> current_prototype = instr->prototype(); | 3321 Handle<JSObject> current_prototype = instr->prototype(); |
| 2910 | 3322 |
| 2911 // Load prototype object. | 3323 // Load prototype object. |
| 2912 LoadHeapObject(temp1, current_prototype); | 3324 LoadHeapObject(temp1, current_prototype); |
| 2913 | 3325 |
| 2914 // Check prototype maps up to the holder. | 3326 // Check prototype maps up to the holder. |
| 2915 while (!current_prototype.is_identical_to(holder)) { | 3327 while (!current_prototype.is_identical_to(holder)) { |
| 2916 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); | 3328 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3044 __ mov(r1, Operand(pretenure | 3456 __ mov(r1, Operand(pretenure |
| 3045 ? Factory::true_value() | 3457 ? Factory::true_value() |
| 3046 : Factory::false_value())); | 3458 : Factory::false_value())); |
| 3047 __ Push(cp, r2, r1); | 3459 __ Push(cp, r2, r1); |
| 3048 CallRuntime(Runtime::kNewClosure, 3, instr); | 3460 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 3049 } | 3461 } |
| 3050 } | 3462 } |
| 3051 | 3463 |
| 3052 | 3464 |
| 3053 void LCodeGen::DoTypeof(LTypeof* instr) { | 3465 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 3054 Register input = ToRegister(instr->input()); | 3466 Register input = ToRegister(instr->InputAt(0)); |
| 3055 __ push(input); | 3467 __ push(input); |
| 3056 CallRuntime(Runtime::kTypeof, 1, instr); | 3468 CallRuntime(Runtime::kTypeof, 1, instr); |
| 3057 } | 3469 } |
| 3058 | 3470 |
| 3059 | 3471 |
| 3060 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 3472 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
| 3061 Register input = ToRegister(instr->input()); | 3473 Register input = ToRegister(instr->InputAt(0)); |
| 3062 Register result = ToRegister(instr->result()); | 3474 Register result = ToRegister(instr->result()); |
| 3063 Label true_label; | 3475 Label true_label; |
| 3064 Label false_label; | 3476 Label false_label; |
| 3065 Label done; | 3477 Label done; |
| 3066 | 3478 |
| 3067 Condition final_branch_condition = EmitTypeofIs(&true_label, | 3479 Condition final_branch_condition = EmitTypeofIs(&true_label, |
| 3068 &false_label, | 3480 &false_label, |
| 3069 input, | 3481 input, |
| 3070 instr->type_literal()); | 3482 instr->type_literal()); |
| 3071 __ b(final_branch_condition, &true_label); | 3483 __ b(final_branch_condition, &true_label); |
| 3072 __ bind(&false_label); | 3484 __ bind(&false_label); |
| 3073 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 3485 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 3074 __ b(&done); | 3486 __ b(&done); |
| 3075 | 3487 |
| 3076 __ bind(&true_label); | 3488 __ bind(&true_label); |
| 3077 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 3489 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 3078 | 3490 |
| 3079 __ bind(&done); | 3491 __ bind(&done); |
| 3080 } | 3492 } |
| 3081 | 3493 |
| 3082 | 3494 |
| 3083 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 3495 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 3084 Register input = ToRegister(instr->input()); | 3496 Register input = ToRegister(instr->InputAt(0)); |
| 3085 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 3497 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 3086 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 3498 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 3087 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 3499 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 3088 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 3500 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 3089 | 3501 |
| 3090 Condition final_branch_condition = EmitTypeofIs(true_label, | 3502 Condition final_branch_condition = EmitTypeofIs(true_label, |
| 3091 false_label, | 3503 false_label, |
| 3092 input, | 3504 input, |
| 3093 instr->type_literal()); | 3505 instr->type_literal()); |
| 3094 | 3506 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3214 | 3626 |
| 3215 | 3627 |
| 3216 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 3628 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
| 3217 Abort("DoOsrEntry unimplemented."); | 3629 Abort("DoOsrEntry unimplemented."); |
| 3218 } | 3630 } |
| 3219 | 3631 |
| 3220 | 3632 |
| 3221 #undef __ | 3633 #undef __ |
| 3222 | 3634 |
| 3223 } } // namespace v8::internal | 3635 } } // namespace v8::internal |
| OLD | NEW |