OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 public: | 184 public: |
185 OutOfLineLoadInteger(CodeGenerator* gen, Register result) | 185 OutOfLineLoadInteger(CodeGenerator* gen, Register result) |
186 : OutOfLineCode(gen), result_(result) {} | 186 : OutOfLineCode(gen), result_(result) {} |
187 | 187 |
188 void Generate() final { __ xor_(result_, result_); } | 188 void Generate() final { __ xor_(result_, result_); } |
189 | 189 |
190 private: | 190 private: |
191 Register const result_; | 191 Register const result_; |
192 }; | 192 }; |
193 | 193 |
194 | 194 class OutOfLineLoadNaN final : public OutOfLineCode { |
195 class OutOfLineLoadFloat final : public OutOfLineCode { | |
196 public: | 195 public: |
197 OutOfLineLoadFloat(CodeGenerator* gen, X87Register result) | 196 OutOfLineLoadNaN(CodeGenerator* gen, X87Register result) |
198 : OutOfLineCode(gen), result_(result) {} | 197 : OutOfLineCode(gen), result_(result) {} |
199 | 198 |
200 void Generate() final { | 199 void Generate() final { |
201 DCHECK(result_.code() == 0); | 200 DCHECK(result_.code() == 0); |
202 USE(result_); | 201 USE(result_); |
203 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | |
204 __ VerifyX87StackDepth(1); | |
205 } | |
206 __ fstp(0); | 202 __ fstp(0); |
207 __ push(Immediate(0xffffffff)); | 203 __ push(Immediate(0xffffffff)); |
208 __ push(Immediate(0x7fffffff)); | 204 __ push(Immediate(0x7fffffff)); |
209 __ fld_d(MemOperand(esp, 0)); | 205 __ fld_d(MemOperand(esp, 0)); |
210 __ lea(esp, Operand(esp, kDoubleSize)); | 206 __ lea(esp, Operand(esp, kDoubleSize)); |
211 } | 207 } |
212 | 208 |
213 private: | 209 private: |
214 X87Register const result_; | 210 X87Register const result_; |
215 }; | 211 }; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 Register const object_; | 264 Register const object_; |
269 Operand const operand_; | 265 Operand const operand_; |
270 Register const value_; | 266 Register const value_; |
271 Register const scratch0_; | 267 Register const scratch0_; |
272 Register const scratch1_; | 268 Register const scratch1_; |
273 RecordWriteMode const mode_; | 269 RecordWriteMode const mode_; |
274 }; | 270 }; |
275 | 271 |
276 } // namespace | 272 } // namespace |
277 | 273 |
278 | 274 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ |
279 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ | 275 do { \ |
280 do { \ | 276 auto result = i.OutputDoubleRegister(); \ |
281 auto result = i.OutputDoubleRegister(); \ | 277 auto offset = i.InputRegister(0); \ |
282 auto offset = i.InputRegister(0); \ | 278 DCHECK(result.code() == 0); \ |
283 DCHECK(result.code() == 0); \ | 279 if (instr->InputAt(1)->IsRegister()) { \ |
284 if (instr->InputAt(1)->IsRegister()) { \ | 280 __ cmp(offset, i.InputRegister(1)); \ |
285 __ cmp(offset, i.InputRegister(1)); \ | 281 } else { \ |
286 } else { \ | 282 __ cmp(offset, i.InputImmediate(1)); \ |
287 __ cmp(offset, i.InputImmediate(1)); \ | 283 } \ |
288 } \ | 284 OutOfLineCode* ool = new (zone()) OutOfLineLoadNaN(this, result); \ |
289 OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \ | 285 __ j(above_equal, ool->entry()); \ |
290 __ j(above_equal, ool->entry()); \ | 286 __ fstp(0); \ |
291 __ fstp(0); \ | 287 __ asm_instr(i.MemoryOperand(2)); \ |
292 __ asm_instr(i.MemoryOperand(2)); \ | 288 __ bind(ool->exit()); \ |
293 __ bind(ool->exit()); \ | |
294 } while (false) | 289 } while (false) |
295 | 290 |
296 | |
297 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ | 291 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
298 do { \ | 292 do { \ |
299 auto result = i.OutputRegister(); \ | 293 auto result = i.OutputRegister(); \ |
300 auto offset = i.InputRegister(0); \ | 294 auto offset = i.InputRegister(0); \ |
301 if (instr->InputAt(1)->IsRegister()) { \ | 295 if (instr->InputAt(1)->IsRegister()) { \ |
302 __ cmp(offset, i.InputRegister(1)); \ | 296 __ cmp(offset, i.InputRegister(1)); \ |
303 } else { \ | 297 } else { \ |
304 __ cmp(offset, i.InputImmediate(1)); \ | 298 __ cmp(offset, i.InputImmediate(1)); \ |
305 } \ | 299 } \ |
306 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ | 300 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ |
(...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 __ fstp(0); | 1151 __ fstp(0); |
1158 __ fld_s(MemOperand(esp, kFloatSize)); | 1152 __ fld_s(MemOperand(esp, kFloatSize)); |
1159 __ fld_s(MemOperand(esp, 0)); | 1153 __ fld_s(MemOperand(esp, 0)); |
1160 __ fdivp(); | 1154 __ fdivp(); |
1161 // Clear stack. | 1155 // Clear stack. |
1162 __ lea(esp, Operand(esp, 2 * kFloatSize)); | 1156 __ lea(esp, Operand(esp, 2 * kFloatSize)); |
1163 // Restore the default value of control word. | 1157 // Restore the default value of control word. |
1164 __ X87SetFPUCW(0x037F); | 1158 __ X87SetFPUCW(0x037F); |
1165 break; | 1159 break; |
1166 } | 1160 } |
1167 case kX87Float32Max: { | |
1168 Label check_nan_left, check_zero, return_left, return_right; | |
1169 Condition condition = below; | |
1170 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | |
1171 __ VerifyX87StackDepth(1); | |
1172 } | |
1173 __ fstp(0); | |
1174 __ fld_s(MemOperand(esp, kFloatSize)); | |
1175 __ fld_s(MemOperand(esp, 0)); | |
1176 __ fld(1); | |
1177 __ fld(1); | |
1178 __ FCmp(); | |
1179 | 1161 |
1180 // At least one NaN. | |
1181 // Return the second operands if one of the two operands is NaN | |
1182 __ j(parity_even, &return_right, Label::kNear); | |
1183 __ j(equal, &check_zero, Label::kNear); // left == right. | |
1184 __ j(condition, &return_left, Label::kNear); | |
1185 __ jmp(&return_right, Label::kNear); | |
1186 | |
1187 __ bind(&check_zero); | |
1188 __ fld(0); | |
1189 __ fldz(); | |
1190 __ FCmp(); | |
1191 __ j(not_equal, &return_left, Label::kNear); // left == right != 0. | |
1192 | |
1193 __ fadd(1); | |
1194 __ jmp(&return_left, Label::kNear); | |
1195 | |
1196 __ bind(&return_right); | |
1197 __ fxch(); | |
1198 | |
1199 __ bind(&return_left); | |
1200 __ fstp(0); | |
1201 __ lea(esp, Operand(esp, 2 * kFloatSize)); | |
1202 break; | |
1203 } | |
1204 case kX87Float32Min: { | |
1205 Label check_nan_left, check_zero, return_left, return_right; | |
1206 Condition condition = above; | |
1207 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | |
1208 __ VerifyX87StackDepth(1); | |
1209 } | |
1210 __ fstp(0); | |
1211 __ fld_s(MemOperand(esp, kFloatSize)); | |
1212 __ fld_s(MemOperand(esp, 0)); | |
1213 __ fld(1); | |
1214 __ fld(1); | |
1215 __ FCmp(); | |
1216 // At least one NaN. | |
1217 // Return the second operands if one of the two operands is NaN | |
1218 __ j(parity_even, &return_right, Label::kNear); | |
1219 __ j(equal, &check_zero, Label::kNear); // left == right. | |
1220 __ j(condition, &return_left, Label::kNear); | |
1221 __ jmp(&return_right, Label::kNear); | |
1222 | |
1223 __ bind(&check_zero); | |
1224 __ fld(0); | |
1225 __ fldz(); | |
1226 __ FCmp(); | |
1227 __ j(not_equal, &return_left, Label::kNear); // left == right != 0. | |
1228 // At this point, both left and right are either 0 or -0. | |
1229 // Push st0 and st1 to stack, then pop them to temp registers and OR them, | |
1230 // load it to left. | |
1231 __ push(eax); | |
1232 __ fld(1); | |
1233 __ fld(1); | |
1234 __ sub(esp, Immediate(2 * kPointerSize)); | |
1235 __ fstp_s(MemOperand(esp, 0)); | |
1236 __ fstp_s(MemOperand(esp, kPointerSize)); | |
1237 __ pop(eax); | |
1238 __ xor_(MemOperand(esp, 0), eax); | |
1239 __ fstp(0); | |
1240 __ fld_s(MemOperand(esp, 0)); | |
1241 __ pop(eax); // restore esp | |
1242 __ pop(eax); // restore esp | |
1243 __ jmp(&return_left, Label::kNear); | |
1244 | |
1245 | |
1246 __ bind(&return_right); | |
1247 __ fxch(); | |
1248 | |
1249 __ bind(&return_left); | |
1250 __ fstp(0); | |
1251 __ lea(esp, Operand(esp, 2 * kFloatSize)); | |
1252 break; | |
1253 } | |
1254 case kX87Float32Sqrt: { | 1162 case kX87Float32Sqrt: { |
1255 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 1163 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
1256 __ VerifyX87StackDepth(1); | 1164 __ VerifyX87StackDepth(1); |
1257 } | 1165 } |
1258 __ fstp(0); | 1166 __ fstp(0); |
1259 __ fld_s(MemOperand(esp, 0)); | 1167 __ fld_s(MemOperand(esp, 0)); |
1260 __ fsqrt(); | 1168 __ fsqrt(); |
1261 __ lea(esp, Operand(esp, kFloatSize)); | 1169 __ lea(esp, Operand(esp, kFloatSize)); |
1262 break; | 1170 break; |
1263 } | 1171 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 __ fld_d(MemOperand(eax, 0)); | 1267 __ fld_d(MemOperand(eax, 0)); |
1360 __ fstp_d(Operand(esp, 1 * kDoubleSize)); | 1268 __ fstp_d(Operand(esp, 1 * kDoubleSize)); |
1361 __ fld_d(MemOperand(eax, kDoubleSize)); | 1269 __ fld_d(MemOperand(eax, kDoubleSize)); |
1362 __ fstp_d(Operand(esp, 0)); | 1270 __ fstp_d(Operand(esp, 0)); |
1363 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), | 1271 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), |
1364 4); | 1272 4); |
1365 __ lea(esp, Operand(esp, 2 * kDoubleSize)); | 1273 __ lea(esp, Operand(esp, 2 * kDoubleSize)); |
1366 break; | 1274 break; |
1367 } | 1275 } |
1368 case kX87Float64Max: { | 1276 case kX87Float64Max: { |
1369 Label check_zero, return_left, return_right; | 1277 Label compare_swap, done_compare; |
1370 Condition condition = below; | |
1371 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 1278 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
1372 __ VerifyX87StackDepth(1); | 1279 __ VerifyX87StackDepth(1); |
1373 } | 1280 } |
1374 __ fstp(0); | 1281 __ fstp(0); |
1375 __ fld_d(MemOperand(esp, kDoubleSize)); | 1282 __ fld_d(MemOperand(esp, kDoubleSize)); |
1376 __ fld_d(MemOperand(esp, 0)); | 1283 __ fld_d(MemOperand(esp, 0)); |
1377 __ fld(1); | 1284 __ fld(1); |
1378 __ fld(1); | 1285 __ fld(1); |
1379 __ FCmp(); | 1286 __ FCmp(); |
1380 __ j(parity_even, &return_right, | |
1381 Label::kNear); // At least one NaN, Return right. | |
1382 __ j(equal, &check_zero, Label::kNear); // left == right. | |
1383 __ j(condition, &return_left, Label::kNear); | |
1384 __ jmp(&return_right, Label::kNear); | |
1385 | 1287 |
1386 __ bind(&check_zero); | 1288 auto ool = new (zone()) OutOfLineLoadNaN(this, i.OutputDoubleRegister()); |
1387 __ fld(0); | 1289 __ j(parity_even, ool->entry()); |
1388 __ fldz(); | 1290 __ j(below, &done_compare, Label::kNear); |
1389 __ FCmp(); | 1291 __ j(above, &compare_swap, Label::kNear); |
1390 __ j(not_equal, &return_left, Label::kNear); // left == right != 0. | 1292 __ push(eax); |
| 1293 __ lea(esp, Operand(esp, -kDoubleSize)); |
| 1294 __ fld(1); |
| 1295 __ fstp_d(Operand(esp, 0)); |
| 1296 __ mov(eax, MemOperand(esp, 4)); |
| 1297 __ and_(eax, Immediate(0x80000000)); |
| 1298 __ lea(esp, Operand(esp, kDoubleSize)); |
| 1299 __ pop(eax); |
| 1300 __ j(zero, &done_compare, Label::kNear); |
1391 | 1301 |
1392 __ bind(&return_right); | 1302 __ bind(&compare_swap); |
1393 __ fxch(); | 1303 __ bind(ool->exit()); |
| 1304 __ fxch(1); |
1394 | 1305 |
1395 __ bind(&return_left); | 1306 __ bind(&done_compare); |
1396 __ fstp(0); | 1307 __ fstp(0); |
1397 __ lea(esp, Operand(esp, 2 * kDoubleSize)); | 1308 __ lea(esp, Operand(esp, 2 * kDoubleSize)); |
1398 break; | 1309 break; |
1399 } | 1310 } |
1400 case kX87Float64Min: { | 1311 case kX87Float64Min: { |
1401 Label check_zero, return_left, return_right; | 1312 Label compare_swap, done_compare; |
1402 Condition condition = above; | |
1403 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 1313 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
1404 __ VerifyX87StackDepth(1); | 1314 __ VerifyX87StackDepth(1); |
1405 } | 1315 } |
1406 __ fstp(0); | 1316 __ fstp(0); |
1407 __ fld_d(MemOperand(esp, kDoubleSize)); | 1317 __ fld_d(MemOperand(esp, kDoubleSize)); |
1408 __ fld_d(MemOperand(esp, 0)); | 1318 __ fld_d(MemOperand(esp, 0)); |
1409 __ fld(1); | 1319 __ fld(1); |
1410 __ fld(1); | 1320 __ fld(1); |
1411 __ FCmp(); | 1321 __ FCmp(); |
1412 __ j(parity_even, &return_right, | |
1413 Label::kNear); // At least one NaN, return right value. | |
1414 __ j(equal, &check_zero, Label::kNear); // left == right. | |
1415 __ j(condition, &return_left, Label::kNear); | |
1416 __ jmp(&return_right, Label::kNear); | |
1417 | 1322 |
1418 __ bind(&check_zero); | 1323 auto ool = new (zone()) OutOfLineLoadNaN(this, i.OutputDoubleRegister()); |
| 1324 __ j(parity_even, ool->entry()); |
| 1325 __ j(above, &done_compare, Label::kNear); |
| 1326 __ j(below, &compare_swap, Label::kNear); |
| 1327 __ push(eax); |
| 1328 __ lea(esp, Operand(esp, -kDoubleSize)); |
1419 __ fld(0); | 1329 __ fld(0); |
1420 __ fldz(); | 1330 __ fstp_d(Operand(esp, 0)); |
1421 __ FCmp(); | 1331 __ mov(eax, MemOperand(esp, 4)); |
1422 __ j(not_equal, &return_left, Label::kNear); // left == right != 0. | 1332 __ and_(eax, Immediate(0x80000000)); |
| 1333 __ lea(esp, Operand(esp, kDoubleSize)); |
| 1334 __ pop(eax); |
| 1335 __ j(zero, &done_compare, Label::kNear); |
1423 | 1336 |
1424 __ bind(&return_right); | 1337 __ bind(&compare_swap); |
1425 __ fxch(); | 1338 __ bind(ool->exit()); |
| 1339 __ fxch(1); |
1426 | 1340 |
1427 __ bind(&return_left); | 1341 __ bind(&done_compare); |
1428 __ fstp(0); | 1342 __ fstp(0); |
1429 __ lea(esp, Operand(esp, 2 * kDoubleSize)); | 1343 __ lea(esp, Operand(esp, 2 * kDoubleSize)); |
1430 break; | 1344 break; |
1431 } | 1345 } |
1432 case kX87Float64Abs: { | 1346 case kX87Float64Abs: { |
1433 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 1347 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
1434 __ VerifyX87StackDepth(1); | 1348 __ VerifyX87StackDepth(1); |
1435 } | 1349 } |
1436 __ fstp(0); | 1350 __ fstp(0); |
1437 __ fld_d(MemOperand(esp, 0)); | 1351 __ fld_d(MemOperand(esp, 0)); |
(...skipping 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2702 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2616 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
2703 __ Nop(padding_size); | 2617 __ Nop(padding_size); |
2704 } | 2618 } |
2705 } | 2619 } |
2706 | 2620 |
2707 #undef __ | 2621 #undef __ |
2708 | 2622 |
2709 } // namespace compiler | 2623 } // namespace compiler |
2710 } // namespace internal | 2624 } // namespace internal |
2711 } // namespace v8 | 2625 } // namespace v8 |
OLD | NEW |