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/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 if (instr->InputAt(1)->IsDoubleRegister()) { \ | 265 if (instr->InputAt(1)->IsDoubleRegister()) { \ |
266 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ | 266 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ |
267 i.InputDoubleRegister(1)); \ | 267 i.InputDoubleRegister(1)); \ |
268 } else { \ | 268 } else { \ |
269 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ | 269 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ |
270 i.InputOperand(1)); \ | 270 i.InputOperand(1)); \ |
271 } \ | 271 } \ |
272 } while (0) | 272 } while (0) |
273 | 273 |
274 | 274 |
275 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ | 275 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ |
| 276 do { \ |
| 277 auto result = i.OutputDoubleRegister(); \ |
| 278 auto buffer = i.InputRegister(0); \ |
| 279 auto index1 = i.InputRegister(1); \ |
| 280 auto index2 = i.InputInt32(2); \ |
| 281 OutOfLineCode* ool; \ |
| 282 if (instr->InputAt(3)->IsRegister()) { \ |
| 283 auto length = i.InputRegister(3); \ |
| 284 DCHECK_EQ(0, index2); \ |
| 285 __ cmpl(index1, length); \ |
| 286 ool = new (zone()) OutOfLineLoadNaN(this, result); \ |
| 287 } else { \ |
| 288 auto length = i.InputInt32(3); \ |
| 289 DCHECK_LE(index2, length); \ |
| 290 __ cmpq(index1, Immediate(length - index2)); \ |
| 291 class OutOfLineLoadFloat FINAL : public OutOfLineCode { \ |
| 292 public: \ |
| 293 OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result, \ |
| 294 Register buffer, Register index1, int32_t index2, \ |
| 295 int32_t length) \ |
| 296 : OutOfLineCode(gen), \ |
| 297 result_(result), \ |
| 298 buffer_(buffer), \ |
| 299 index1_(index1), \ |
| 300 index2_(index2), \ |
| 301 length_(length) {} \ |
| 302 \ |
| 303 void Generate() FINAL { \ |
| 304 __ leal(kScratchRegister, Operand(index1_, index2_)); \ |
| 305 __ pcmpeqd(result_, result_); \ |
| 306 __ cmpl(kScratchRegister, Immediate(length_)); \ |
| 307 __ j(above_equal, exit()); \ |
| 308 __ asm_instr(result_, \ |
| 309 Operand(buffer_, kScratchRegister, times_1, 0)); \ |
| 310 } \ |
| 311 \ |
| 312 private: \ |
| 313 XMMRegister const result_; \ |
| 314 Register const buffer_; \ |
| 315 Register const index1_; \ |
| 316 int32_t const index2_; \ |
| 317 int32_t const length_; \ |
| 318 }; \ |
| 319 ool = new (zone()) \ |
| 320 OutOfLineLoadFloat(this, result, buffer, index1, index2, length); \ |
| 321 } \ |
| 322 __ j(above_equal, ool->entry()); \ |
| 323 __ asm_instr(result, Operand(buffer, index1, times_1, index2)); \ |
| 324 __ bind(ool->exit()); \ |
| 325 } while (false) |
| 326 |
| 327 |
| 328 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
276 do { \ | 329 do { \ |
277 auto result = i.OutputDoubleRegister(); \ | 330 auto result = i.OutputRegister(); \ |
278 auto buffer = i.InputRegister(0); \ | 331 auto buffer = i.InputRegister(0); \ |
279 auto index1 = i.InputRegister(1); \ | 332 auto index1 = i.InputRegister(1); \ |
280 auto index2 = i.InputInt32(2); \ | 333 auto index2 = i.InputInt32(2); \ |
281 OutOfLineCode* ool; \ | 334 OutOfLineCode* ool; \ |
282 if (instr->InputAt(3)->IsRegister()) { \ | 335 if (instr->InputAt(3)->IsRegister()) { \ |
283 auto length = i.InputRegister(3); \ | 336 auto length = i.InputRegister(3); \ |
284 DCHECK_EQ(0, index2); \ | 337 DCHECK_EQ(0, index2); \ |
285 __ cmpl(index1, length); \ | 338 __ cmpl(index1, length); \ |
286 ool = new (zone()) OutOfLineLoadNaN(this, result); \ | 339 ool = new (zone()) OutOfLineLoadZero(this, result); \ |
287 } else { \ | 340 } else { \ |
288 auto length = i.InputInt32(3); \ | 341 auto length = i.InputInt32(3); \ |
289 DCHECK_LE(index2, length); \ | 342 DCHECK_LE(index2, length); \ |
290 __ cmpl(index1, Immediate(length - index2)); \ | 343 __ cmpq(index1, Immediate(length - index2)); \ |
291 if (index2 == 0) { \ | 344 class OutOfLineLoadInteger FINAL : public OutOfLineCode { \ |
292 ool = new (zone()) OutOfLineLoadNaN(this, result); \ | 345 public: \ |
293 } else { \ | 346 OutOfLineLoadInteger(CodeGenerator* gen, Register result, \ |
294 class OutOfLineLoadFloat FINAL : public OutOfLineCode { \ | |
295 public: \ | |
296 OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result, \ | |
297 Register buffer, Register index1, int32_t index2, \ | 347 Register buffer, Register index1, int32_t index2, \ |
298 int32_t length) \ | 348 int32_t length) \ |
299 : OutOfLineCode(gen), \ | 349 : OutOfLineCode(gen), \ |
300 result_(result), \ | 350 result_(result), \ |
301 buffer_(buffer), \ | 351 buffer_(buffer), \ |
302 index1_(index1), \ | 352 index1_(index1), \ |
303 index2_(index2), \ | 353 index2_(index2), \ |
304 length_(length) {} \ | 354 length_(length) {} \ |
305 \ | 355 \ |
306 void Generate() FINAL { \ | 356 void Generate() FINAL { \ |
307 DCHECK_NE(0, index2_); \ | 357 __ leal(kScratchRegister, Operand(index1_, index2_)); \ |
308 __ leal(kScratchRegister, Operand(index1_, index2_)); \ | 358 __ xorl(result_, result_); \ |
309 __ pcmpeqd(result_, result_); \ | 359 __ cmpl(kScratchRegister, Immediate(length_)); \ |
310 __ cmpl(kScratchRegister, Immediate(length_)); \ | 360 __ j(above_equal, exit()); \ |
311 __ j(above_equal, exit()); \ | 361 __ asm_instr(result_, \ |
312 __ asm_instr(result_, \ | 362 Operand(buffer_, kScratchRegister, times_1, 0)); \ |
313 Operand(buffer_, kScratchRegister, times_1, 0)); \ | 363 } \ |
314 } \ | |
315 \ | 364 \ |
316 private: \ | 365 private: \ |
317 XMMRegister const result_; \ | 366 Register const result_; \ |
318 Register const buffer_; \ | 367 Register const buffer_; \ |
319 Register const index1_; \ | 368 Register const index1_; \ |
320 int32_t const index2_; \ | 369 int32_t const index2_; \ |
321 int32_t const length_; \ | 370 int32_t const length_; \ |
322 }; \ | 371 }; \ |
323 ool = new (zone()) \ | 372 ool = new (zone()) \ |
324 OutOfLineLoadFloat(this, result, buffer, index1, index2, length); \ | 373 OutOfLineLoadInteger(this, result, buffer, index1, index2, length); \ |
325 } \ | |
326 } \ | 374 } \ |
327 __ j(above_equal, ool->entry()); \ | 375 __ j(above_equal, ool->entry()); \ |
328 __ asm_instr(result, Operand(buffer, index1, times_1, index2)); \ | 376 __ asm_instr(result, Operand(buffer, index1, times_1, index2)); \ |
329 __ bind(ool->exit()); \ | 377 __ bind(ool->exit()); \ |
330 } while (false) | 378 } while (false) |
331 | 379 |
332 | 380 |
333 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ | 381 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \ |
334 do { \ | 382 do { \ |
335 auto result = i.OutputRegister(); \ | 383 auto buffer = i.InputRegister(0); \ |
336 auto buffer = i.InputRegister(0); \ | 384 auto index1 = i.InputRegister(1); \ |
337 auto index1 = i.InputRegister(1); \ | 385 auto index2 = i.InputInt32(2); \ |
338 auto index2 = i.InputInt32(2); \ | 386 auto value = i.InputDoubleRegister(4); \ |
339 OutOfLineCode* ool; \ | 387 if (instr->InputAt(3)->IsRegister()) { \ |
340 if (instr->InputAt(3)->IsRegister()) { \ | 388 auto length = i.InputRegister(3); \ |
341 auto length = i.InputRegister(3); \ | 389 DCHECK_EQ(0, index2); \ |
342 DCHECK_EQ(0, index2); \ | 390 Label done; \ |
343 __ cmpl(index1, length); \ | 391 __ cmpl(index1, length); \ |
344 ool = new (zone()) OutOfLineLoadZero(this, result); \ | 392 __ j(above_equal, &done, Label::kNear); \ |
345 } else { \ | 393 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
346 auto length = i.InputInt32(3); \ | 394 __ bind(&done); \ |
347 DCHECK_LE(index2, length); \ | 395 } else { \ |
348 __ cmpl(index1, Immediate(length - index2)); \ | 396 auto length = i.InputInt32(3); \ |
349 if (index2 == 0) { \ | 397 DCHECK_LE(index2, length); \ |
350 ool = new (zone()) OutOfLineLoadZero(this, result); \ | 398 __ cmpq(index1, Immediate(length - index2)); \ |
351 } else { \ | 399 class OutOfLineStoreFloat FINAL : public OutOfLineCode { \ |
352 class OutOfLineLoadInteger FINAL : public OutOfLineCode { \ | 400 public: \ |
353 public: \ | 401 OutOfLineStoreFloat(CodeGenerator* gen, Register buffer, \ |
354 OutOfLineLoadInteger(CodeGenerator* gen, Register result, \ | 402 Register index1, int32_t index2, int32_t length, \ |
355 Register buffer, Register index1, \ | 403 XMMRegister value) \ |
356 int32_t index2, int32_t length) \ | 404 : OutOfLineCode(gen), \ |
357 : OutOfLineCode(gen), \ | 405 buffer_(buffer), \ |
358 result_(result), \ | 406 index1_(index1), \ |
359 buffer_(buffer), \ | 407 index2_(index2), \ |
360 index1_(index1), \ | 408 length_(length), \ |
361 index2_(index2), \ | 409 value_(value) {} \ |
362 length_(length) {} \ | 410 \ |
363 \ | 411 void Generate() FINAL { \ |
364 void Generate() FINAL { \ | 412 __ leal(kScratchRegister, Operand(index1_, index2_)); \ |
365 DCHECK_NE(0, index2_); \ | 413 __ cmpl(kScratchRegister, Immediate(length_)); \ |
366 __ leal(kScratchRegister, Operand(index1_, index2_)); \ | 414 __ j(above_equal, exit()); \ |
367 __ xorl(result_, result_); \ | 415 __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0), \ |
368 __ cmpl(kScratchRegister, Immediate(length_)); \ | 416 value_); \ |
369 __ j(above_equal, exit()); \ | 417 } \ |
370 __ asm_instr(result_, \ | 418 \ |
371 Operand(buffer_, kScratchRegister, times_1, 0)); \ | 419 private: \ |
372 } \ | 420 Register const buffer_; \ |
373 \ | 421 Register const index1_; \ |
374 private: \ | 422 int32_t const index2_; \ |
375 Register const result_; \ | 423 int32_t const length_; \ |
376 Register const buffer_; \ | 424 XMMRegister const value_; \ |
377 Register const index1_; \ | 425 }; \ |
378 int32_t const index2_; \ | 426 auto ool = new (zone()) \ |
379 int32_t const length_; \ | 427 OutOfLineStoreFloat(this, buffer, index1, index2, length, value); \ |
380 }; \ | 428 __ j(above_equal, ool->entry()); \ |
381 ool = new (zone()) OutOfLineLoadInteger(this, result, buffer, index1, \ | 429 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
382 index2, length); \ | 430 __ bind(ool->exit()); \ |
383 } \ | 431 } \ |
384 } \ | |
385 __ j(above_equal, ool->entry()); \ | |
386 __ asm_instr(result, Operand(buffer, index1, times_1, index2)); \ | |
387 __ bind(ool->exit()); \ | |
388 } while (false) | 432 } while (false) |
389 | 433 |
390 | 434 |
391 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \ | 435 #define ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Value) \ |
392 do { \ | 436 do { \ |
393 auto buffer = i.InputRegister(0); \ | 437 auto buffer = i.InputRegister(0); \ |
394 auto index1 = i.InputRegister(1); \ | 438 auto index1 = i.InputRegister(1); \ |
395 auto index2 = i.InputInt32(2); \ | 439 auto index2 = i.InputInt32(2); \ |
396 auto value = i.InputDoubleRegister(4); \ | |
397 if (instr->InputAt(3)->IsRegister()) { \ | 440 if (instr->InputAt(3)->IsRegister()) { \ |
398 auto length = i.InputRegister(3); \ | 441 auto length = i.InputRegister(3); \ |
399 DCHECK_EQ(0, index2); \ | 442 DCHECK_EQ(0, index2); \ |
400 Label done; \ | 443 Label done; \ |
401 __ cmpl(index1, length); \ | 444 __ cmpl(index1, length); \ |
402 __ j(above_equal, &done, Label::kNear); \ | 445 __ j(above_equal, &done, Label::kNear); \ |
403 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ | 446 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
404 __ bind(&done); \ | 447 __ bind(&done); \ |
405 } else { \ | 448 } else { \ |
406 auto length = i.InputInt32(3); \ | 449 auto length = i.InputInt32(3); \ |
407 DCHECK_LE(index2, length); \ | 450 DCHECK_LE(index2, length); \ |
408 __ cmpl(index1, Immediate(length - index2)); \ | 451 __ cmpq(index1, Immediate(length - index2)); \ |
409 if (index2 == 0) { \ | 452 class OutOfLineStoreInteger FINAL : public OutOfLineCode { \ |
410 Label done; \ | 453 public: \ |
411 __ j(above_equal, &done, Label::kNear); \ | 454 OutOfLineStoreInteger(CodeGenerator* gen, Register buffer, \ |
412 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ | |
413 __ bind(&done); \ | |
414 } else { \ | |
415 class OutOfLineStoreFloat FINAL : public OutOfLineCode { \ | |
416 public: \ | |
417 OutOfLineStoreFloat(CodeGenerator* gen, Register buffer, \ | |
418 Register index1, int32_t index2, int32_t length, \ | 455 Register index1, int32_t index2, int32_t length, \ |
419 XMMRegister value) \ | 456 Value value) \ |
420 : OutOfLineCode(gen), \ | 457 : OutOfLineCode(gen), \ |
421 buffer_(buffer), \ | 458 buffer_(buffer), \ |
422 index1_(index1), \ | 459 index1_(index1), \ |
423 index2_(index2), \ | 460 index2_(index2), \ |
424 length_(length), \ | 461 length_(length), \ |
425 value_(value) {} \ | 462 value_(value) {} \ |
426 \ | 463 \ |
427 void Generate() FINAL { \ | 464 void Generate() FINAL { \ |
428 DCHECK_NE(0, index2_); \ | 465 __ leal(kScratchRegister, Operand(index1_, index2_)); \ |
429 __ leal(kScratchRegister, Operand(index1_, index2_)); \ | 466 __ cmpl(kScratchRegister, Immediate(length_)); \ |
430 __ cmpl(kScratchRegister, Immediate(length_)); \ | 467 __ j(above_equal, exit()); \ |
431 __ j(above_equal, exit()); \ | 468 __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0), \ |
432 __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0), \ | 469 value_); \ |
433 value_); \ | 470 } \ |
434 } \ | |
435 \ | 471 \ |
436 private: \ | 472 private: \ |
437 Register const buffer_; \ | 473 Register const buffer_; \ |
438 Register const index1_; \ | 474 Register const index1_; \ |
439 int32_t const index2_; \ | 475 int32_t const index2_; \ |
440 int32_t const length_; \ | 476 int32_t const length_; \ |
441 XMMRegister const value_; \ | 477 Value const value_; \ |
442 }; \ | 478 }; \ |
443 auto ool = new (zone()) \ | 479 auto ool = new (zone()) \ |
444 OutOfLineStoreFloat(this, buffer, index1, index2, length, value); \ | 480 OutOfLineStoreInteger(this, buffer, index1, index2, length, value); \ |
445 __ j(above_equal, ool->entry()); \ | 481 __ j(above_equal, ool->entry()); \ |
446 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ | 482 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
447 __ bind(ool->exit()); \ | 483 __ bind(ool->exit()); \ |
448 } \ | |
449 } \ | 484 } \ |
450 } while (false) | 485 } while (false) |
451 | 486 |
452 | 487 |
453 #define ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Value) \ | |
454 do { \ | |
455 auto buffer = i.InputRegister(0); \ | |
456 auto index1 = i.InputRegister(1); \ | |
457 auto index2 = i.InputInt32(2); \ | |
458 if (instr->InputAt(3)->IsRegister()) { \ | |
459 auto length = i.InputRegister(3); \ | |
460 DCHECK_EQ(0, index2); \ | |
461 Label done; \ | |
462 __ cmpl(index1, length); \ | |
463 __ j(above_equal, &done, Label::kNear); \ | |
464 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ | |
465 __ bind(&done); \ | |
466 } else { \ | |
467 auto length = i.InputInt32(3); \ | |
468 DCHECK_LE(index2, length); \ | |
469 __ cmpl(index1, Immediate(length - index2)); \ | |
470 if (index2 == 0) { \ | |
471 Label done; \ | |
472 __ j(above_equal, &done, Label::kNear); \ | |
473 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ | |
474 __ bind(&done); \ | |
475 } else { \ | |
476 class OutOfLineStoreInteger FINAL : public OutOfLineCode { \ | |
477 public: \ | |
478 OutOfLineStoreInteger(CodeGenerator* gen, Register buffer, \ | |
479 Register index1, int32_t index2, \ | |
480 int32_t length, Value value) \ | |
481 : OutOfLineCode(gen), \ | |
482 buffer_(buffer), \ | |
483 index1_(index1), \ | |
484 index2_(index2), \ | |
485 length_(length), \ | |
486 value_(value) {} \ | |
487 \ | |
488 void Generate() FINAL { \ | |
489 DCHECK_NE(0, index2_); \ | |
490 __ leal(kScratchRegister, Operand(index1_, index2_)); \ | |
491 __ cmpl(kScratchRegister, Immediate(length_)); \ | |
492 __ j(above_equal, exit()); \ | |
493 __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0), \ | |
494 value_); \ | |
495 } \ | |
496 \ | |
497 private: \ | |
498 Register const buffer_; \ | |
499 Register const index1_; \ | |
500 int32_t const index2_; \ | |
501 int32_t const length_; \ | |
502 Value const value_; \ | |
503 }; \ | |
504 auto ool = new (zone()) OutOfLineStoreInteger(this, buffer, index1, \ | |
505 index2, length, value); \ | |
506 __ j(above_equal, ool->entry()); \ | |
507 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ | |
508 __ bind(ool->exit()); \ | |
509 } \ | |
510 } \ | |
511 } while (false) | |
512 | |
513 | |
514 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ | 488 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
515 do { \ | 489 do { \ |
516 if (instr->InputAt(4)->IsRegister()) { \ | 490 if (instr->InputAt(4)->IsRegister()) { \ |
517 Register value = i.InputRegister(4); \ | 491 Register value = i.InputRegister(4); \ |
518 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Register); \ | 492 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Register); \ |
519 } else { \ | 493 } else { \ |
520 Immediate value = i.InputImmediate(4); \ | 494 Immediate value = i.InputImmediate(4); \ |
521 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Immediate); \ | 495 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Immediate); \ |
522 } \ | 496 } \ |
523 } while (false) | 497 } while (false) |
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1437 } | 1411 } |
1438 } | 1412 } |
1439 MarkLazyDeoptSite(); | 1413 MarkLazyDeoptSite(); |
1440 } | 1414 } |
1441 | 1415 |
1442 #undef __ | 1416 #undef __ |
1443 | 1417 |
1444 } // namespace internal | 1418 } // namespace internal |
1445 } // namespace compiler | 1419 } // namespace compiler |
1446 } // namespace v8 | 1420 } // namespace v8 |
OLD | NEW |