Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(592)

Side by Side Diff: src/x64/code-stubs-x64.h

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 TranscendentalCache::Type type_; 52 TranscendentalCache::Type type_;
53 ArgumentType argument_type_; 53 ArgumentType argument_type_;
54 54
55 Major MajorKey() { return TranscendentalCache; } 55 Major MajorKey() { return TranscendentalCache; }
56 int MinorKey() { return type_ | argument_type_; } 56 int MinorKey() { return type_ | argument_type_; }
57 Runtime::FunctionId RuntimeFunction(); 57 Runtime::FunctionId RuntimeFunction();
58 void GenerateOperation(MacroAssembler* masm); 58 void GenerateOperation(MacroAssembler* masm);
59 }; 59 };
60 60
61 61
62 class StoreBufferOverflowStub: public CodeStub {
63 public:
64 explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
65 : save_doubles_(save_fp) { }
66
67 void Generate(MacroAssembler* masm);
68
69 virtual bool IsPregenerated() { return true; }
70 static void GenerateFixedRegStubsAheadOfTime();
71 virtual bool SometimesSetsUpAFrame() { return false; }
72
73 private:
74 SaveFPRegsMode save_doubles_;
75
76 Major MajorKey() { return StoreBufferOverflow; }
77 int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; }
78 };
79
80
81 // Flag that indicates how to generate code for the stub GenericBinaryOpStub.
82 enum GenericBinaryFlags {
83 NO_GENERIC_BINARY_FLAGS = 0,
84 NO_SMI_CODE_IN_STUB = 1 << 0 // Omit smi code in stub.
85 };
86
87
62 class UnaryOpStub: public CodeStub { 88 class UnaryOpStub: public CodeStub {
63 public: 89 public:
64 UnaryOpStub(Token::Value op, 90 UnaryOpStub(Token::Value op,
65 UnaryOverwriteMode mode, 91 UnaryOverwriteMode mode,
66 UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED) 92 UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
67 : op_(op), 93 : op_(op),
68 mode_(mode), 94 mode_(mode),
69 operand_type_(operand_type) { 95 operand_type_(operand_type) {
70 } 96 }
71 97
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 Register r0); 432 Register r0);
407 433
408 static void GeneratePositiveLookup(MacroAssembler* masm, 434 static void GeneratePositiveLookup(MacroAssembler* masm,
409 Label* miss, 435 Label* miss,
410 Label* done, 436 Label* done,
411 Register elements, 437 Register elements,
412 Register name, 438 Register name,
413 Register r0, 439 Register r0,
414 Register r1); 440 Register r1);
415 441
442 virtual bool SometimesSetsUpAFrame() { return false; }
443
416 private: 444 private:
417 static const int kInlinedProbes = 4; 445 static const int kInlinedProbes = 4;
418 static const int kTotalProbes = 20; 446 static const int kTotalProbes = 20;
419 447
420 static const int kCapacityOffset = 448 static const int kCapacityOffset =
421 StringDictionary::kHeaderSize + 449 StringDictionary::kHeaderSize +
422 StringDictionary::kCapacityIndex * kPointerSize; 450 StringDictionary::kCapacityIndex * kPointerSize;
423 451
424 static const int kElementsStartOffset = 452 static const int kElementsStartOffset =
425 StringDictionary::kHeaderSize + 453 StringDictionary::kHeaderSize +
426 StringDictionary::kElementsStartIndex * kPointerSize; 454 StringDictionary::kElementsStartIndex * kPointerSize;
427 455
428 Major MajorKey() { return StringDictionaryNegativeLookup; } 456 Major MajorKey() { return StringDictionaryLookup; }
429 457
430 int MinorKey() { 458 int MinorKey() {
431 return DictionaryBits::encode(dictionary_.code()) | 459 return DictionaryBits::encode(dictionary_.code()) |
432 ResultBits::encode(result_.code()) | 460 ResultBits::encode(result_.code()) |
433 IndexBits::encode(index_.code()) | 461 IndexBits::encode(index_.code()) |
434 LookupModeBits::encode(mode_); 462 LookupModeBits::encode(mode_);
435 } 463 }
436 464
437 class DictionaryBits: public BitField<int, 0, 4> {}; 465 class DictionaryBits: public BitField<int, 0, 4> {};
438 class ResultBits: public BitField<int, 4, 4> {}; 466 class ResultBits: public BitField<int, 4, 4> {};
439 class IndexBits: public BitField<int, 8, 4> {}; 467 class IndexBits: public BitField<int, 8, 4> {};
440 class LookupModeBits: public BitField<LookupMode, 12, 1> {}; 468 class LookupModeBits: public BitField<LookupMode, 12, 1> {};
441 469
442 Register dictionary_; 470 Register dictionary_;
443 Register result_; 471 Register result_;
444 Register index_; 472 Register index_;
445 LookupMode mode_; 473 LookupMode mode_;
446 }; 474 };
447 475
448 476
477 class RecordWriteStub: public CodeStub {
478 public:
479 RecordWriteStub(Register object,
480 Register value,
481 Register address,
482 RememberedSetAction remembered_set_action,
483 SaveFPRegsMode fp_mode)
484 : object_(object),
485 value_(value),
486 address_(address),
487 remembered_set_action_(remembered_set_action),
488 save_fp_regs_mode_(fp_mode),
489 regs_(object, // An input reg.
490 address, // An input reg.
491 value) { // One scratch reg.
492 }
493
494 enum Mode {
495 STORE_BUFFER_ONLY,
496 INCREMENTAL,
497 INCREMENTAL_COMPACTION
498 };
499
500 virtual bool IsPregenerated();
501 static void GenerateFixedRegStubsAheadOfTime();
502 virtual bool SometimesSetsUpAFrame() { return false; }
503
504 static const byte kTwoByteNopInstruction = 0x3c; // Cmpb al, #imm8.
505 static const byte kTwoByteJumpInstruction = 0xeb; // Jmp #imm8.
506
507 static const byte kFiveByteNopInstruction = 0x3d; // Cmpl eax, #imm32.
508 static const byte kFiveByteJumpInstruction = 0xe9; // Jmp #imm32.
509
510 static Mode GetMode(Code* stub) {
511 byte first_instruction = stub->instruction_start()[0];
512 byte second_instruction = stub->instruction_start()[2];
513
514 if (first_instruction == kTwoByteJumpInstruction) {
515 return INCREMENTAL;
516 }
517
518 ASSERT(first_instruction == kTwoByteNopInstruction);
519
520 if (second_instruction == kFiveByteJumpInstruction) {
521 return INCREMENTAL_COMPACTION;
522 }
523
524 ASSERT(second_instruction == kFiveByteNopInstruction);
525
526 return STORE_BUFFER_ONLY;
527 }
528
529 static void Patch(Code* stub, Mode mode) {
530 switch (mode) {
531 case STORE_BUFFER_ONLY:
532 ASSERT(GetMode(stub) == INCREMENTAL ||
533 GetMode(stub) == INCREMENTAL_COMPACTION);
534 stub->instruction_start()[0] = kTwoByteNopInstruction;
535 stub->instruction_start()[2] = kFiveByteNopInstruction;
536 break;
537 case INCREMENTAL:
538 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
539 stub->instruction_start()[0] = kTwoByteJumpInstruction;
540 break;
541 case INCREMENTAL_COMPACTION:
542 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
543 stub->instruction_start()[0] = kTwoByteNopInstruction;
544 stub->instruction_start()[2] = kFiveByteJumpInstruction;
545 break;
546 }
547 ASSERT(GetMode(stub) == mode);
548 CPU::FlushICache(stub->instruction_start(), 7);
549 }
550
551 private:
552 // This is a helper class for freeing up 3 scratch registers, where the third
553 // is always rcx (needed for shift operations). The input is two registers
554 // that must be preserved and one scratch register provided by the caller.
555 class RegisterAllocation {
556 public:
557 RegisterAllocation(Register object,
558 Register address,
559 Register scratch0)
560 : object_orig_(object),
561 address_orig_(address),
562 scratch0_orig_(scratch0),
563 object_(object),
564 address_(address),
565 scratch0_(scratch0) {
566 ASSERT(!AreAliased(scratch0, object, address, no_reg));
567 scratch1_ = GetRegThatIsNotRcxOr(object_, address_, scratch0_);
568 if (scratch0.is(rcx)) {
569 scratch0_ = GetRegThatIsNotRcxOr(object_, address_, scratch1_);
570 }
571 if (object.is(rcx)) {
572 object_ = GetRegThatIsNotRcxOr(address_, scratch0_, scratch1_);
573 }
574 if (address.is(rcx)) {
575 address_ = GetRegThatIsNotRcxOr(object_, scratch0_, scratch1_);
576 }
577 ASSERT(!AreAliased(scratch0_, object_, address_, rcx));
578 }
579
580 void Save(MacroAssembler* masm) {
581 ASSERT(!address_orig_.is(object_));
582 ASSERT(object_.is(object_orig_) || address_.is(address_orig_));
583 ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_));
584 ASSERT(!AreAliased(object_orig_, address_, scratch1_, scratch0_));
585 ASSERT(!AreAliased(object_, address_orig_, scratch1_, scratch0_));
586 // We don't have to save scratch0_orig_ because it was given to us as
587 // a scratch register. But if we had to switch to a different reg then
588 // we should save the new scratch0_.
589 if (!scratch0_.is(scratch0_orig_)) masm->push(scratch0_);
590 if (!rcx.is(scratch0_orig_) &&
591 !rcx.is(object_orig_) &&
592 !rcx.is(address_orig_)) {
593 masm->push(rcx);
594 }
595 masm->push(scratch1_);
596 if (!address_.is(address_orig_)) {
597 masm->push(address_);
598 masm->movq(address_, address_orig_);
599 }
600 if (!object_.is(object_orig_)) {
601 masm->push(object_);
602 masm->movq(object_, object_orig_);
603 }
604 }
605
606 void Restore(MacroAssembler* masm) {
607 // These will have been preserved the entire time, so we just need to move
608 // them back. Only in one case is the orig_ reg different from the plain
609 // one, since only one of them can alias with rcx.
610 if (!object_.is(object_orig_)) {
611 masm->movq(object_orig_, object_);
612 masm->pop(object_);
613 }
614 if (!address_.is(address_orig_)) {
615 masm->movq(address_orig_, address_);
616 masm->pop(address_);
617 }
618 masm->pop(scratch1_);
619 if (!rcx.is(scratch0_orig_) &&
620 !rcx.is(object_orig_) &&
621 !rcx.is(address_orig_)) {
622 masm->pop(rcx);
623 }
624 if (!scratch0_.is(scratch0_orig_)) masm->pop(scratch0_);
625 }
626
627 // If we have to call into C then we need to save and restore all caller-
628 // saved registers that were not already preserved.
629
630 // The three scratch registers (incl. rcx) will be restored by other means
631 // so we don't bother pushing them here. Rbx, rbp and r12-15 are callee
632 // save and don't need to be preserved.
633 void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
634 masm->PushCallerSaved(mode, scratch0_, scratch1_, rcx);
635 }
636
637 inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
638 SaveFPRegsMode mode) {
639 masm->PopCallerSaved(mode, scratch0_, scratch1_, rcx);
640 }
641
642 inline Register object() { return object_; }
643 inline Register address() { return address_; }
644 inline Register scratch0() { return scratch0_; }
645 inline Register scratch1() { return scratch1_; }
646
647 private:
648 Register object_orig_;
649 Register address_orig_;
650 Register scratch0_orig_;
651 Register object_;
652 Register address_;
653 Register scratch0_;
654 Register scratch1_;
655 // Third scratch register is always rcx.
656
657 Register GetRegThatIsNotRcxOr(Register r1,
658 Register r2,
659 Register r3) {
660 for (int i = 0; i < Register::kNumAllocatableRegisters; i++) {
661 Register candidate = Register::FromAllocationIndex(i);
662 if (candidate.is(rcx)) continue;
663 if (candidate.is(r1)) continue;
664 if (candidate.is(r2)) continue;
665 if (candidate.is(r3)) continue;
666 return candidate;
667 }
668 UNREACHABLE();
669 return no_reg;
670 }
671 friend class RecordWriteStub;
672 };
673
674 enum OnNoNeedToInformIncrementalMarker {
675 kReturnOnNoNeedToInformIncrementalMarker,
676 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
677 };
678
679 void Generate(MacroAssembler* masm);
680 void GenerateIncremental(MacroAssembler* masm, Mode mode);
681 void CheckNeedsToInformIncrementalMarker(
682 MacroAssembler* masm,
683 OnNoNeedToInformIncrementalMarker on_no_need,
684 Mode mode);
685 void InformIncrementalMarker(MacroAssembler* masm, Mode mode);
686
687 Major MajorKey() { return RecordWrite; }
688
689 int MinorKey() {
690 return ObjectBits::encode(object_.code()) |
691 ValueBits::encode(value_.code()) |
692 AddressBits::encode(address_.code()) |
693 RememberedSetActionBits::encode(remembered_set_action_) |
694 SaveFPRegsModeBits::encode(save_fp_regs_mode_);
695 }
696
697 bool MustBeInStubCache() {
698 // All stubs must be registered in the stub cache
699 // otherwise IncrementalMarker would not be able to find
700 // and patch it.
701 return true;
702 }
703
704 void Activate(Code* code) {
705 code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
706 }
707
708 class ObjectBits: public BitField<int, 0, 4> {};
709 class ValueBits: public BitField<int, 4, 4> {};
710 class AddressBits: public BitField<int, 8, 4> {};
711 class RememberedSetActionBits: public BitField<RememberedSetAction, 12, 1> {};
712 class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 13, 1> {};
713
714 Register object_;
715 Register value_;
716 Register address_;
717 RememberedSetAction remembered_set_action_;
718 SaveFPRegsMode save_fp_regs_mode_;
719 Label slow_;
720 RegisterAllocation regs_;
721 };
722
723
449 } } // namespace v8::internal 724 } } // namespace v8::internal
450 725
451 #endif // V8_X64_CODE_STUBS_X64_H_ 726 #endif // V8_X64_CODE_STUBS_X64_H_
OLDNEW
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698