| 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 |