OLD | NEW |
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 27 matching lines...) Expand all Loading... |
38 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \ | 38 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \ |
39 V(CallFunction) \ | 39 V(CallFunction) \ |
40 V(UnaryOp) \ | 40 V(UnaryOp) \ |
41 V(BinaryOp) \ | 41 V(BinaryOp) \ |
42 V(StringAdd) \ | 42 V(StringAdd) \ |
43 V(SubString) \ | 43 V(SubString) \ |
44 V(StringCompare) \ | 44 V(StringCompare) \ |
45 V(Compare) \ | 45 V(Compare) \ |
46 V(CompareIC) \ | 46 V(CompareIC) \ |
47 V(MathPow) \ | 47 V(MathPow) \ |
| 48 V(RecordWrite) \ |
| 49 V(StoreBufferOverflow) \ |
| 50 V(RegExpExec) \ |
48 V(TranscendentalCache) \ | 51 V(TranscendentalCache) \ |
49 V(Instanceof) \ | 52 V(Instanceof) \ |
50 /* All stubs above this line only exist in a few versions, which are */ \ | |
51 /* generated ahead of time. Therefore compiling a call to one of */ \ | |
52 /* them can't cause a new stub to be compiled, so compiling a call to */ \ | |
53 /* them is GC safe. The ones below this line exist in many variants */ \ | |
54 /* so code compiling a call to one can cause a GC. This means they */ \ | |
55 /* can't be called from other stubs, since stub generation code is */ \ | |
56 /* not GC safe. */ \ | |
57 V(ConvertToDouble) \ | 53 V(ConvertToDouble) \ |
58 V(WriteInt32ToHeapNumber) \ | 54 V(WriteInt32ToHeapNumber) \ |
59 V(StackCheck) \ | 55 V(StackCheck) \ |
60 V(FastNewClosure) \ | 56 V(FastNewClosure) \ |
61 V(FastNewContext) \ | 57 V(FastNewContext) \ |
62 V(FastCloneShallowArray) \ | 58 V(FastCloneShallowArray) \ |
63 V(RevertToNumber) \ | 59 V(RevertToNumber) \ |
64 V(ToBoolean) \ | 60 V(ToBoolean) \ |
65 V(ToNumber) \ | 61 V(ToNumber) \ |
66 V(CounterOp) \ | 62 V(CounterOp) \ |
67 V(ArgumentsAccess) \ | 63 V(ArgumentsAccess) \ |
68 V(RegExpExec) \ | |
69 V(RegExpConstructResult) \ | 64 V(RegExpConstructResult) \ |
70 V(NumberToString) \ | 65 V(NumberToString) \ |
71 V(CEntry) \ | 66 V(CEntry) \ |
72 V(JSEntry) \ | 67 V(JSEntry) \ |
73 V(KeyedLoadElement) \ | 68 V(KeyedLoadElement) \ |
74 V(KeyedStoreElement) \ | 69 V(KeyedStoreElement) \ |
75 V(DebuggerStatement) \ | 70 V(DebuggerStatement) \ |
76 V(StringDictionaryNegativeLookup) | 71 V(StringDictionaryLookup) |
77 | 72 |
78 // List of code stubs only used on ARM platforms. | 73 // List of code stubs only used on ARM platforms. |
79 #ifdef V8_TARGET_ARCH_ARM | 74 #ifdef V8_TARGET_ARCH_ARM |
80 #define CODE_STUB_LIST_ARM(V) \ | 75 #define CODE_STUB_LIST_ARM(V) \ |
81 V(GetProperty) \ | 76 V(GetProperty) \ |
82 V(SetProperty) \ | 77 V(SetProperty) \ |
83 V(InvokeBuiltin) \ | 78 V(InvokeBuiltin) \ |
84 V(RegExpCEntry) \ | 79 V(RegExpCEntry) \ |
85 V(DirectCEntry) | 80 V(DirectCEntry) |
86 #else | 81 #else |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 | 130 |
136 // Gets the major key from a code object that is a code stub or binary op IC. | 131 // Gets the major key from a code object that is a code stub or binary op IC. |
137 static Major GetMajorKey(Code* code_stub) { | 132 static Major GetMajorKey(Code* code_stub) { |
138 return static_cast<Major>(code_stub->major_key()); | 133 return static_cast<Major>(code_stub->major_key()); |
139 } | 134 } |
140 | 135 |
141 static const char* MajorName(Major major_key, bool allow_unknown_keys); | 136 static const char* MajorName(Major major_key, bool allow_unknown_keys); |
142 | 137 |
143 virtual ~CodeStub() {} | 138 virtual ~CodeStub() {} |
144 | 139 |
| 140 bool CompilingCallsToThisStubIsGCSafe() { |
| 141 bool is_pregenerated = IsPregenerated(); |
| 142 Code* code = NULL; |
| 143 CHECK(!is_pregenerated || FindCodeInCache(&code)); |
| 144 return is_pregenerated; |
| 145 } |
| 146 |
| 147 // See comment above, where Instanceof is defined. |
| 148 virtual bool IsPregenerated() { return false; } |
| 149 |
| 150 static void GenerateStubsAheadOfTime(); |
| 151 static void GenerateFPStubs(); |
| 152 |
| 153 // Some stubs put untagged junk on the stack that cannot be scanned by the |
| 154 // GC. This means that we must be statically sure that no GC can occur while |
| 155 // they are running. If that is the case they should override this to return |
| 156 // true, which will cause an assertion if we try to call something that can |
| 157 // GC or if we try to put a stack frame on top of the junk, which would not |
| 158 // result in a traversable stack. |
| 159 virtual bool SometimesSetsUpAFrame() { return true; } |
| 160 |
145 protected: | 161 protected: |
146 static const int kMajorBits = 6; | 162 static const int kMajorBits = 6; |
147 static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits; | 163 static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits; |
148 | 164 |
149 private: | 165 private: |
150 // Lookup the code in the (possibly custom) cache. | 166 // Lookup the code in the (possibly custom) cache. |
151 bool FindCodeInCache(Code** code_out); | 167 bool FindCodeInCache(Code** code_out); |
152 | 168 |
153 // Nonvirtual wrapper around the stub-specific Generate function. Call | 169 // Nonvirtual wrapper around the stub-specific Generate function. Call |
154 // this function to set up the macro assembler and generate the code. | 170 // this function to set up the macro assembler and generate the code. |
155 void GenerateCode(MacroAssembler* masm); | 171 void GenerateCode(MacroAssembler* masm); |
156 | 172 |
157 // Generates the assembler code for the stub. | 173 // Generates the assembler code for the stub. |
158 virtual void Generate(MacroAssembler* masm) = 0; | 174 virtual void Generate(MacroAssembler* masm) = 0; |
159 | 175 |
160 // Perform bookkeeping required after code generation when stub code is | 176 // Perform bookkeeping required after code generation when stub code is |
161 // initially generated. | 177 // initially generated. |
162 void RecordCodeGeneration(Code* code, MacroAssembler* masm); | 178 void RecordCodeGeneration(Code* code, MacroAssembler* masm); |
163 | 179 |
164 // Finish the code object after it has been generated. | 180 // Finish the code object after it has been generated. |
165 virtual void FinishCode(Code* code) { } | 181 virtual void FinishCode(Code* code) { } |
166 | 182 |
| 183 // Returns true if TryGetCode should fail if it failed |
| 184 // to register newly generated stub in the stub cache. |
| 185 virtual bool MustBeInStubCache() { return false; } |
| 186 |
| 187 // Activate newly generated stub. Is called after |
| 188 // registering stub in the stub cache. |
| 189 virtual void Activate(Code* code) { } |
| 190 |
167 // Returns information for computing the number key. | 191 // Returns information for computing the number key. |
168 virtual Major MajorKey() = 0; | 192 virtual Major MajorKey() = 0; |
169 virtual int MinorKey() = 0; | 193 virtual int MinorKey() = 0; |
170 | 194 |
171 // BinaryOpStub needs to override this. | 195 // BinaryOpStub needs to override this. |
172 virtual int GetCodeKind(); | 196 virtual int GetCodeKind(); |
173 | 197 |
174 // BinaryOpStub needs to override this. | 198 // BinaryOpStub needs to override this. |
175 virtual InlineCacheState GetICState() { | 199 virtual InlineCacheState GetICState() { |
176 return UNINITIALIZED; | 200 return UNINITIALIZED; |
177 } | 201 } |
178 | 202 |
179 // Returns a name for logging/debugging purposes. | 203 // Returns a name for logging/debugging purposes. |
180 SmartArrayPointer<const char> GetName(); | 204 SmartArrayPointer<const char> GetName(); |
181 virtual void PrintName(StringStream* stream) { | 205 virtual void PrintName(StringStream* stream); |
182 stream->Add("%s", MajorName(MajorKey(), false)); | |
183 } | |
184 | 206 |
185 // Returns whether the code generated for this stub needs to be allocated as | 207 // Returns whether the code generated for this stub needs to be allocated as |
186 // a fixed (non-moveable) code object. | 208 // a fixed (non-moveable) code object. |
187 virtual bool NeedsImmovableCode() { return false; } | 209 virtual bool NeedsImmovableCode() { return false; } |
188 | 210 |
189 // Computes the key based on major and minor. | 211 // Computes the key based on major and minor. |
190 uint32_t GetKey() { | 212 uint32_t GetKey() { |
191 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); | 213 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); |
192 return MinorKeyBits::encode(MinorKey()) | | 214 return MinorKeyBits::encode(MinorKey()) | |
193 MajorKeyBits::encode(MajorKey()); | 215 MajorKeyBits::encode(MajorKey()); |
194 } | 216 } |
195 | 217 |
196 // See comment above, where Instanceof is defined. | |
197 bool AllowsStubCalls() { return MajorKey() <= Instanceof; } | |
198 | |
199 class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {}; | 218 class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {}; |
200 class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {}; | 219 class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {}; |
201 | 220 |
202 friend class BreakPointIterator; | 221 friend class BreakPointIterator; |
203 }; | 222 }; |
204 | 223 |
205 | 224 |
206 // Helper interface to prepare to/restore after making runtime calls. | 225 // Helper interface to prepare to/restore after making runtime calls. |
207 class RuntimeCallHelper { | 226 class RuntimeCallHelper { |
208 public: | 227 public: |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 Register scratch); | 543 Register scratch); |
525 | 544 |
526 // Unfortunately you have to run without snapshots to see most of these | 545 // Unfortunately you have to run without snapshots to see most of these |
527 // names in the profile since most compare stubs end up in the snapshot. | 546 // names in the profile since most compare stubs end up in the snapshot. |
528 virtual void PrintName(StringStream* stream); | 547 virtual void PrintName(StringStream* stream); |
529 }; | 548 }; |
530 | 549 |
531 | 550 |
532 class CEntryStub : public CodeStub { | 551 class CEntryStub : public CodeStub { |
533 public: | 552 public: |
534 explicit CEntryStub(int result_size) | 553 explicit CEntryStub(int result_size, |
535 : result_size_(result_size), save_doubles_(false) { } | 554 SaveFPRegsMode save_doubles = kDontSaveFPRegs) |
| 555 : result_size_(result_size), save_doubles_(save_doubles) { } |
536 | 556 |
537 void Generate(MacroAssembler* masm); | 557 void Generate(MacroAssembler* masm); |
538 void SaveDoubles() { save_doubles_ = true; } | 558 |
| 559 // The version of this stub that doesn't save doubles is generated ahead of |
| 560 // time, so it's OK to call it from other stubs that can't cope with GC during |
| 561 // their code generation. On machines that always have gp registers (x64) we |
| 562 // can generate both variants ahead of time. |
| 563 virtual bool IsPregenerated(); |
| 564 static void GenerateAheadOfTime(); |
539 | 565 |
540 private: | 566 private: |
541 void GenerateCore(MacroAssembler* masm, | 567 void GenerateCore(MacroAssembler* masm, |
542 Label* throw_normal_exception, | 568 Label* throw_normal_exception, |
543 Label* throw_termination_exception, | 569 Label* throw_termination_exception, |
544 Label* throw_out_of_memory_exception, | 570 Label* throw_out_of_memory_exception, |
545 bool do_gc, | 571 bool do_gc, |
546 bool always_allocate_scope); | 572 bool always_allocate_scope); |
547 void GenerateThrowTOS(MacroAssembler* masm); | 573 void GenerateThrowTOS(MacroAssembler* masm); |
548 void GenerateThrowUncatchable(MacroAssembler* masm, | 574 void GenerateThrowUncatchable(MacroAssembler* masm, |
549 UncatchableExceptionType type); | 575 UncatchableExceptionType type); |
550 | 576 |
551 // Number of pointers/values returned. | 577 // Number of pointers/values returned. |
552 const int result_size_; | 578 const int result_size_; |
553 bool save_doubles_; | 579 SaveFPRegsMode save_doubles_; |
554 | 580 |
555 Major MajorKey() { return CEntry; } | 581 Major MajorKey() { return CEntry; } |
556 int MinorKey(); | 582 int MinorKey(); |
557 | 583 |
558 bool NeedsImmovableCode(); | 584 bool NeedsImmovableCode(); |
559 }; | 585 }; |
560 | 586 |
561 | 587 |
562 class JSEntryStub : public CodeStub { | 588 class JSEntryStub : public CodeStub { |
563 public: | 589 public: |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 }; | 666 }; |
641 | 667 |
642 | 668 |
643 class CallFunctionStub: public CodeStub { | 669 class CallFunctionStub: public CodeStub { |
644 public: | 670 public: |
645 CallFunctionStub(int argc, CallFunctionFlags flags) | 671 CallFunctionStub(int argc, CallFunctionFlags flags) |
646 : argc_(argc), flags_(flags) { } | 672 : argc_(argc), flags_(flags) { } |
647 | 673 |
648 void Generate(MacroAssembler* masm); | 674 void Generate(MacroAssembler* masm); |
649 | 675 |
| 676 virtual void FinishCode(Code* code); |
| 677 |
| 678 static void Clear(Heap* heap, Address address); |
| 679 |
| 680 static Object* GetCachedValue(Address address); |
| 681 |
650 static int ExtractArgcFromMinorKey(int minor_key) { | 682 static int ExtractArgcFromMinorKey(int minor_key) { |
651 return ArgcBits::decode(minor_key); | 683 return ArgcBits::decode(minor_key); |
652 } | 684 } |
653 | 685 |
| 686 // The object that indicates an uninitialized cache. |
| 687 static Handle<Object> UninitializedSentinel(Isolate* isolate) { |
| 688 return isolate->factory()->the_hole_value(); |
| 689 } |
| 690 |
| 691 // A raw version of the uninitialized sentinel that's safe to read during |
| 692 // garbage collection (e.g., for patching the cache). |
| 693 static Object* RawUninitializedSentinel(Heap* heap) { |
| 694 return heap->raw_unchecked_the_hole_value(); |
| 695 } |
| 696 |
| 697 // The object that indicates a megamorphic state. |
| 698 static Handle<Object> MegamorphicSentinel(Isolate* isolate) { |
| 699 return isolate->factory()->undefined_value(); |
| 700 } |
| 701 |
654 private: | 702 private: |
655 int argc_; | 703 int argc_; |
656 CallFunctionFlags flags_; | 704 CallFunctionFlags flags_; |
657 | 705 |
658 virtual void PrintName(StringStream* stream); | 706 virtual void PrintName(StringStream* stream); |
659 | 707 |
660 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>. | 708 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>. |
661 class FlagBits: public BitField<CallFunctionFlags, 0, 1> {}; | 709 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {}; |
662 class ArgcBits: public BitField<unsigned, 1, 32 - 1> {}; | 710 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {}; |
663 | 711 |
664 Major MajorKey() { return CallFunction; } | 712 Major MajorKey() { return CallFunction; } |
665 int MinorKey() { | 713 int MinorKey() { |
666 // Encode the parameters in a unique 32 bit value. | 714 // Encode the parameters in a unique 32 bit value. |
667 return FlagBits::encode(flags_) | ArgcBits::encode(argc_); | 715 return FlagBits::encode(flags_) | ArgcBits::encode(argc_); |
668 } | 716 } |
669 | 717 |
670 bool ReceiverMightBeImplicit() { | 718 bool ReceiverMightBeImplicit() { |
671 return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0; | 719 return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0; |
672 } | 720 } |
| 721 |
| 722 bool RecordCallTarget() { |
| 723 return (flags_ & RECORD_CALL_TARGET) != 0; |
| 724 } |
673 }; | 725 }; |
674 | 726 |
675 | 727 |
676 enum StringIndexFlags { | 728 enum StringIndexFlags { |
677 // Accepts smis or heap numbers. | 729 // Accepts smis or heap numbers. |
678 STRING_INDEX_IS_NUMBER, | 730 STRING_INDEX_IS_NUMBER, |
679 | 731 |
680 // Accepts smis or heap numbers that are valid array indices | 732 // Accepts smis or heap numbers that are valid array indices |
681 // (ECMA-262 15.4). Invalid indices are reported as being out of | 733 // (ECMA-262 15.4). Invalid indices are reported as being out of |
682 // range. | 734 // range. |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
927 static Types no_types() { return Types(); } | 979 static Types no_types() { return Types(); } |
928 static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); } | 980 static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); } |
929 | 981 |
930 explicit ToBooleanStub(Register tos, Types types = Types()) | 982 explicit ToBooleanStub(Register tos, Types types = Types()) |
931 : tos_(tos), types_(types) { } | 983 : tos_(tos), types_(types) { } |
932 | 984 |
933 void Generate(MacroAssembler* masm); | 985 void Generate(MacroAssembler* masm); |
934 virtual int GetCodeKind() { return Code::TO_BOOLEAN_IC; } | 986 virtual int GetCodeKind() { return Code::TO_BOOLEAN_IC; } |
935 virtual void PrintName(StringStream* stream); | 987 virtual void PrintName(StringStream* stream); |
936 | 988 |
| 989 virtual bool SometimesSetsUpAFrame() { return false; } |
| 990 |
937 private: | 991 private: |
938 Major MajorKey() { return ToBoolean; } | 992 Major MajorKey() { return ToBoolean; } |
939 int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); } | 993 int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); } |
940 | 994 |
941 virtual void FinishCode(Code* code) { | 995 virtual void FinishCode(Code* code) { |
942 code->set_to_boolean_state(types_.ToByte()); | 996 code->set_to_boolean_state(types_.ToByte()); |
943 } | 997 } |
944 | 998 |
945 void CheckOddball(MacroAssembler* masm, | 999 void CheckOddball(MacroAssembler* masm, |
946 Type type, | 1000 Type type, |
947 Heap::RootListIndex value, | 1001 Heap::RootListIndex value, |
948 bool result); | 1002 bool result); |
949 void GenerateTypeTransition(MacroAssembler* masm); | 1003 void GenerateTypeTransition(MacroAssembler* masm); |
950 | 1004 |
951 Register tos_; | 1005 Register tos_; |
952 Types types_; | 1006 Types types_; |
953 }; | 1007 }; |
954 | 1008 |
955 } } // namespace v8::internal | 1009 } } // namespace v8::internal |
956 | 1010 |
957 #endif // V8_CODE_STUBS_H_ | 1011 #endif // V8_CODE_STUBS_H_ |
OLD | NEW |