OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
6 | 6 |
7 #include "v8.h" | 7 #include "v8.h" |
8 | 8 |
9 #if V8_TARGET_ARCH_ARM | 9 #if V8_TARGET_ARCH_ARM |
10 | 10 |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
446 | 446 |
447 | 447 |
448 void MacroAssembler::RecordWriteField( | 448 void MacroAssembler::RecordWriteField( |
449 Register object, | 449 Register object, |
450 int offset, | 450 int offset, |
451 Register value, | 451 Register value, |
452 Register dst, | 452 Register dst, |
453 LinkRegisterStatus lr_status, | 453 LinkRegisterStatus lr_status, |
454 SaveFPRegsMode save_fp, | 454 SaveFPRegsMode save_fp, |
455 RememberedSetAction remembered_set_action, | 455 RememberedSetAction remembered_set_action, |
456 SmiCheck smi_check) { | 456 SmiCheck smi_check, |
457 bool value_is_in_new_space) { | |
457 // First, check if a write barrier is even needed. The tests below | 458 // First, check if a write barrier is even needed. The tests below |
458 // catch stores of Smis. | 459 // catch stores of Smis. |
459 Label done; | 460 Label done; |
460 | 461 |
461 // Skip barrier if writing a smi. | 462 // Skip barrier if writing a smi. |
462 if (smi_check == INLINE_SMI_CHECK) { | 463 if (smi_check == INLINE_SMI_CHECK) { |
463 JumpIfSmi(value, &done); | 464 JumpIfSmi(value, &done); |
464 } | 465 } |
465 | 466 |
466 // Although the object register is tagged, the offset is relative to the start | 467 // Although the object register is tagged, the offset is relative to the start |
467 // of the object, so so offset must be a multiple of kPointerSize. | 468 // of the object, so so offset must be a multiple of kPointerSize. |
468 ASSERT(IsAligned(offset, kPointerSize)); | 469 ASSERT(IsAligned(offset, kPointerSize)); |
469 | 470 |
470 add(dst, object, Operand(offset - kHeapObjectTag)); | 471 add(dst, object, Operand(offset - kHeapObjectTag)); |
471 if (emit_debug_code()) { | 472 if (emit_debug_code()) { |
472 Label ok; | 473 Label ok; |
473 tst(dst, Operand((1 << kPointerSizeLog2) - 1)); | 474 tst(dst, Operand((1 << kPointerSizeLog2) - 1)); |
474 b(eq, &ok); | 475 b(eq, &ok); |
475 stop("Unaligned cell in write barrier"); | 476 stop("Unaligned cell in write barrier"); |
476 bind(&ok); | 477 bind(&ok); |
477 } | 478 } |
478 | 479 |
479 RecordWrite(object, | 480 RecordWrite(object, |
480 dst, | 481 dst, |
481 value, | 482 value, |
482 lr_status, | 483 lr_status, |
483 save_fp, | 484 save_fp, |
484 remembered_set_action, | 485 remembered_set_action, |
485 OMIT_SMI_CHECK); | 486 OMIT_SMI_CHECK, |
487 value_is_in_new_space); | |
486 | 488 |
487 bind(&done); | 489 bind(&done); |
488 | 490 |
489 // Clobber clobbered input registers when running with the debug-code flag | 491 // Clobber clobbered input registers when running with the debug-code flag |
490 // turned on to provoke errors. | 492 // turned on to provoke errors. |
491 if (emit_debug_code()) { | 493 if (emit_debug_code()) { |
492 mov(value, Operand(BitCast<int32_t>(kZapValue + 4))); | 494 mov(value, Operand(BitCast<int32_t>(kZapValue + 4))); |
493 mov(dst, Operand(BitCast<int32_t>(kZapValue + 8))); | 495 mov(dst, Operand(BitCast<int32_t>(kZapValue + 8))); |
494 } | 496 } |
495 } | 497 } |
496 | 498 |
497 | 499 |
500 // Will clobber 4 registers: object, map, dst, ip. The | |
501 // register 'object' contains a heap object pointer. | |
502 void MacroAssembler::RecordWriteForMap(Register object, | |
503 Register map, | |
504 Register dst, | |
505 LinkRegisterStatus lr_status, | |
506 SaveFPRegsMode fp_mode) { | |
507 Label done; | |
508 | |
509 if (emit_debug_code()) { | |
510 ldr(dst, FieldMemOperand(map, HeapObject::kMapOffset)); | |
511 cmp(dst, Operand(isolate()->factory()->meta_map())); | |
512 Check(eq, kWrongAddressOrValuePassedToRecordWrite); | |
513 } | |
514 | |
515 // Count number of write barriers in generated code. | |
516 isolate()->counters()->write_barriers_static()->Increment(); | |
517 // TODO(mstarzinger): Dynamic counter missing. | |
Hannes Payer (out of office)
2014/06/03 05:51:48
why TODO?
Benedikt Meurer
2014/06/03 07:48:02
I just copied the TODO.
| |
518 | |
519 if (emit_debug_code()) { | |
520 ldr(ip, FieldMemOperand(object, HeapObject::kMapOffset)); | |
521 cmp(ip, map); | |
522 Check(eq, kWrongAddressOrValuePassedToRecordWrite); | |
523 } | |
524 | |
525 // A single check of the map's pages interesting flag suffices, since it is | |
526 // only set during incremental collection, and then it's also guaranteed that | |
527 // the from object's page's interesting flag is also set. This optimization | |
528 // relies on the fact that maps can never be in new space. | |
529 CheckPageFlag(map, | |
530 map, // Used as scratch. | |
531 MemoryChunk::kPointersToHereAreInterestingMask, | |
532 eq, | |
533 &done); | |
534 | |
535 add(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag)); | |
536 if (emit_debug_code()) { | |
537 Label ok; | |
538 tst(dst, Operand((1 << kPointerSizeLog2) - 1)); | |
539 b(eq, &ok); | |
540 stop("Unaligned cell in write barrier"); | |
541 bind(&ok); | |
542 } | |
543 | |
544 // Record the actual write. | |
545 if (lr_status == kLRHasNotBeenSaved) { | |
546 push(lr); | |
547 } | |
548 RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET, | |
549 fp_mode); | |
550 CallStub(&stub); | |
551 if (lr_status == kLRHasNotBeenSaved) { | |
552 pop(lr); | |
553 } | |
554 | |
555 bind(&done); | |
556 | |
557 // Clobber clobbered registers when running with the debug-code flag | |
558 // turned on to provoke errors. | |
559 if (emit_debug_code()) { | |
560 mov(dst, Operand(BitCast<int32_t>(kZapValue + 12))); | |
561 mov(map, Operand(BitCast<int32_t>(kZapValue + 16))); | |
562 } | |
563 } | |
564 | |
565 | |
498 // Will clobber 4 registers: object, address, scratch, ip. The | 566 // Will clobber 4 registers: object, address, scratch, ip. The |
499 // register 'object' contains a heap object pointer. The heap object | 567 // register 'object' contains a heap object pointer. The heap object |
500 // tag is shifted away. | 568 // tag is shifted away. |
501 void MacroAssembler::RecordWrite(Register object, | 569 void MacroAssembler::RecordWrite(Register object, |
502 Register address, | 570 Register address, |
503 Register value, | 571 Register value, |
504 LinkRegisterStatus lr_status, | 572 LinkRegisterStatus lr_status, |
505 SaveFPRegsMode fp_mode, | 573 SaveFPRegsMode fp_mode, |
506 RememberedSetAction remembered_set_action, | 574 RememberedSetAction remembered_set_action, |
507 SmiCheck smi_check) { | 575 SmiCheck smi_check, |
576 bool value_is_in_new_space) { | |
508 ASSERT(!object.is(value)); | 577 ASSERT(!object.is(value)); |
509 if (emit_debug_code()) { | 578 if (emit_debug_code()) { |
510 ldr(ip, MemOperand(address)); | 579 ldr(ip, MemOperand(address)); |
511 cmp(ip, value); | 580 cmp(ip, value); |
512 Check(eq, kWrongAddressOrValuePassedToRecordWrite); | 581 Check(eq, kWrongAddressOrValuePassedToRecordWrite); |
513 } | 582 } |
514 | 583 |
515 // Count number of write barriers in generated code. | 584 // Count number of write barriers in generated code. |
516 isolate()->counters()->write_barriers_static()->Increment(); | 585 isolate()->counters()->write_barriers_static()->Increment(); |
517 // TODO(mstarzinger): Dynamic counter missing. | 586 // TODO(mstarzinger): Dynamic counter missing. |
518 | 587 |
519 // First, check if a write barrier is even needed. The tests below | 588 // First, check if a write barrier is even needed. The tests below |
520 // catch stores of smis and stores into the young generation. | 589 // catch stores of smis and stores into the young generation. |
521 Label done; | 590 Label done; |
522 | 591 |
523 if (smi_check == INLINE_SMI_CHECK) { | 592 if (smi_check == INLINE_SMI_CHECK) { |
524 JumpIfSmi(value, &done); | 593 JumpIfSmi(value, &done); |
525 } | 594 } |
526 | 595 |
527 CheckPageFlag(value, | 596 if (!value_is_in_new_space) { |
528 value, // Used as scratch. | 597 CheckPageFlag(value, |
529 MemoryChunk::kPointersToHereAreInterestingMask, | 598 value, // Used as scratch. |
530 eq, | 599 MemoryChunk::kPointersToHereAreInterestingMask, |
531 &done); | 600 eq, |
601 &done); | |
602 } | |
532 CheckPageFlag(object, | 603 CheckPageFlag(object, |
533 value, // Used as scratch. | 604 value, // Used as scratch. |
534 MemoryChunk::kPointersFromHereAreInterestingMask, | 605 MemoryChunk::kPointersFromHereAreInterestingMask, |
535 eq, | 606 eq, |
536 &done); | 607 &done); |
537 | 608 |
538 // Record the actual write. | 609 // Record the actual write. |
539 if (lr_status == kLRHasNotBeenSaved) { | 610 if (lr_status == kLRHasNotBeenSaved) { |
540 push(lr); | 611 push(lr); |
541 } | 612 } |
(...skipping 3498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4040 sub(result, result, Operand(dividend)); | 4111 sub(result, result, Operand(dividend)); |
4041 } | 4112 } |
4042 if (ms.shift() > 0) mov(result, Operand(result, ASR, ms.shift())); | 4113 if (ms.shift() > 0) mov(result, Operand(result, ASR, ms.shift())); |
4043 add(result, result, Operand(dividend, LSR, 31)); | 4114 add(result, result, Operand(dividend, LSR, 31)); |
4044 } | 4115 } |
4045 | 4116 |
4046 | 4117 |
4047 } } // namespace v8::internal | 4118 } } // namespace v8::internal |
4048 | 4119 |
4049 #endif // V8_TARGET_ARCH_ARM | 4120 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |