Chromium Code Reviews| 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 |