Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(532)

Side by Side Diff: src/arm/lithium-codegen-arm.cc

Issue 6322008: Version 3.0.10... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698