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 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
500 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1); | 500 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1); |
501 | 501 |
502 // Clobber clobbered registers when running with the debug-code flag | 502 // Clobber clobbered registers when running with the debug-code flag |
503 // turned on to provoke errors. | 503 // turned on to provoke errors. |
504 if (emit_debug_code()) { | 504 if (emit_debug_code()) { |
505 Move(address, kZapValue, Assembler::RelocInfoNone()); | 505 Move(address, kZapValue, Assembler::RelocInfoNone()); |
506 Move(value, kZapValue, Assembler::RelocInfoNone()); | 506 Move(value, kZapValue, Assembler::RelocInfoNone()); |
507 } | 507 } |
508 } | 508 } |
509 | 509 |
510 void MacroAssembler::RecordWriteCodeEntryField(Register js_function, | |
511 Register code_entry, | |
512 Register scratch) { | |
513 const int offset = JSFunction::kCodeEntryOffset; | |
514 | |
515 // Since a code entry (value) is always in old space, we don't need to update | |
516 // remembered set. If incremental marking is off, there is nothing for us to | |
517 // do. | |
518 if (!FLAG_incremental_marking) return; | |
519 | |
520 AssertNotSmi(js_function); | |
521 | |
522 if (emit_debug_code()) { | |
523 Label ok; | |
524 leap(scratch, FieldOperand(js_function, offset)); | |
525 cmpp(code_entry, Operand(scratch, 0)); | |
526 j(equal, &ok, Label::kNear); | |
527 int3(); | |
528 bind(&ok); | |
529 } | |
530 | |
531 // First, check if a write barrier is even needed. The tests below | |
532 // catch stores of Smis and stores into young gen. | |
533 Label done; | |
534 | |
535 CheckPageFlag(code_entry, scratch, | |
536 MemoryChunk::kPointersToHereAreInterestingMask, zero, &done, | |
537 Label::kNear); | |
538 CheckPageFlag(js_function, scratch, | |
539 MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done, | |
540 Label::kNear); | |
541 | |
542 // Save input registers. | |
543 Push(js_function); | |
544 Push(code_entry); | |
545 | |
546 const Register dst = scratch; | |
547 leap(dst, FieldOperand(js_function, offset)); | |
548 | |
549 // Save caller-saved registers. | |
550 PushCallerSaved(kDontSaveFPRegs, js_function, code_entry); | |
551 | |
552 int argument_count = 3; | |
553 PrepareCallCFunction(argument_count); | |
554 | |
555 // Load the argument registers. It's easier if the input registers are fixed. | |
556 DCHECK(js_function.is(rdi)); | |
ulan
2016/02/04 07:00:52
Let's move this up, to make it clear that it is a
mvstanton
2016/02/04 07:47:22
Done.
| |
557 DCHECK(code_entry.is(rcx)); | |
558 DCHECK(dst.is(rax)); | |
559 | |
560 if (arg_reg_1.is(rcx)) { | |
561 // Windows calling convention. | |
562 DCHECK(arg_reg_2.is(rdx) && arg_reg_3.is(r8)); | |
563 | |
564 movp(arg_reg_1, js_function); // rcx gets rdi. | |
565 movp(arg_reg_2, dst); // rdx gets rax. | |
566 } else if (arg_reg_1.is(rdi)) { | |
567 // AMD64 calling convention. | |
ulan
2016/02/04 07:00:52
no need for "if", just DCHECK(arg_reg_1.is(rdi));
mvstanton
2016/02/04 07:47:22
Done.
| |
568 DCHECK(arg_reg_2.is(rsi) && arg_reg_3.is(rdx)); | |
569 | |
570 // rdi is already loaded with js_function. | |
571 movp(arg_reg_2, dst); // rsi gets rax. | |
572 } else { | |
573 // There are no other calling conventions. | |
574 UNREACHABLE(); | |
575 } | |
576 Move(arg_reg_3, ExternalReference::isolate_address(isolate())); | |
577 | |
578 { | |
579 AllowExternalCallThatCantCauseGC scope(this); | |
580 CallCFunction( | |
581 ExternalReference::incremental_marking_record_write_code_entry_function( | |
582 isolate()), | |
583 argument_count); | |
584 } | |
585 | |
586 // Restore caller-saved registers. | |
587 PopCallerSaved(kDontSaveFPRegs, js_function, code_entry); | |
588 | |
589 // Restore input registers. | |
590 Pop(code_entry); | |
591 Pop(js_function); | |
592 | |
593 bind(&done); | |
594 } | |
510 | 595 |
511 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { | 596 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { |
512 if (emit_debug_code()) Check(cc, reason); | 597 if (emit_debug_code()) Check(cc, reason); |
513 } | 598 } |
514 | 599 |
515 | 600 |
516 void MacroAssembler::AssertFastElements(Register elements) { | 601 void MacroAssembler::AssertFastElements(Register elements) { |
517 if (emit_debug_code()) { | 602 if (emit_debug_code()) { |
518 Label ok; | 603 Label ok; |
519 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 604 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
(...skipping 4991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5511 movl(rax, dividend); | 5596 movl(rax, dividend); |
5512 shrl(rax, Immediate(31)); | 5597 shrl(rax, Immediate(31)); |
5513 addl(rdx, rax); | 5598 addl(rdx, rax); |
5514 } | 5599 } |
5515 | 5600 |
5516 | 5601 |
5517 } // namespace internal | 5602 } // namespace internal |
5518 } // namespace v8 | 5603 } // namespace v8 |
5519 | 5604 |
5520 #endif // V8_TARGET_ARCH_X64 | 5605 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |