| OLD | NEW |
| 1 // Copyright 2010 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 static const Register kSmiConstantRegister = { 15 }; // r15 (callee save). | 51 static const Register kSmiConstantRegister = { 15 }; // r15 (callee save). |
| 52 static const Register kRootRegister = { 13 }; // r13 (callee save). | 52 static const Register kRootRegister = { 13 }; // r13 (callee save). |
| 53 // Value of smi in kSmiConstantRegister. | 53 // Value of smi in kSmiConstantRegister. |
| 54 static const int kSmiConstantRegisterValue = 1; | 54 static const int kSmiConstantRegisterValue = 1; |
| 55 | 55 |
| 56 // Convenience for platform-independent signatures. | 56 // Convenience for platform-independent signatures. |
| 57 typedef Operand MemOperand; | 57 typedef Operand MemOperand; |
| 58 | 58 |
| 59 // Forward declaration. | 59 // Forward declaration. |
| 60 class JumpTarget; | 60 class JumpTarget; |
| 61 class PostCallGenerator; |
| 61 | 62 |
| 62 struct SmiIndex { | 63 struct SmiIndex { |
| 63 SmiIndex(Register index_register, ScaleFactor scale) | 64 SmiIndex(Register index_register, ScaleFactor scale) |
| 64 : reg(index_register), | 65 : reg(index_register), |
| 65 scale(scale) {} | 66 scale(scale) {} |
| 66 Register reg; | 67 Register reg; |
| 67 ScaleFactor scale; | 68 ScaleFactor scale; |
| 68 }; | 69 }; |
| 69 | 70 |
| 70 // MacroAssembler implements a collection of frequently used macros. | 71 // MacroAssembler implements a collection of frequently used macros. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 // argument in register rsi. | 164 // argument in register rsi. |
| 164 void LeaveExitFrame(bool save_doubles = false); | 165 void LeaveExitFrame(bool save_doubles = false); |
| 165 | 166 |
| 166 // Leave the current exit frame. Expects/provides the return value in | 167 // Leave the current exit frame. Expects/provides the return value in |
| 167 // register rax (untouched). | 168 // register rax (untouched). |
| 168 void LeaveApiExitFrame(); | 169 void LeaveApiExitFrame(); |
| 169 | 170 |
| 170 // Push and pop the registers that can hold pointers. | 171 // Push and pop the registers that can hold pointers. |
| 171 void PushSafepointRegisters() { Pushad(); } | 172 void PushSafepointRegisters() { Pushad(); } |
| 172 void PopSafepointRegisters() { Popad(); } | 173 void PopSafepointRegisters() { Popad(); } |
| 173 static int SafepointRegisterStackIndex(int reg_code) { | 174 // Store the value in register src in the safepoint register stack |
| 174 return kSafepointPushRegisterIndices[reg_code]; | 175 // slot for register dst. |
| 175 } | 176 void StoreToSafepointRegisterSlot(Register dst, Register src); |
| 176 | 177 void LoadFromSafepointRegisterSlot(Register dst, Register src); |
| 177 | 178 |
| 178 // --------------------------------------------------------------------------- | 179 // --------------------------------------------------------------------------- |
| 179 // JavaScript invokes | 180 // JavaScript invokes |
| 180 | 181 |
| 181 // Invoke the JavaScript function code by either calling or jumping. | 182 // Invoke the JavaScript function code by either calling or jumping. |
| 182 void InvokeCode(Register code, | 183 void InvokeCode(Register code, |
| 183 const ParameterCount& expected, | 184 const ParameterCount& expected, |
| 184 const ParameterCount& actual, | 185 const ParameterCount& actual, |
| 185 InvokeFlag flag); | 186 InvokeFlag flag, |
| 187 PostCallGenerator* post_call_generator = NULL); |
| 186 | 188 |
| 187 void InvokeCode(Handle<Code> code, | 189 void InvokeCode(Handle<Code> code, |
| 188 const ParameterCount& expected, | 190 const ParameterCount& expected, |
| 189 const ParameterCount& actual, | 191 const ParameterCount& actual, |
| 190 RelocInfo::Mode rmode, | 192 RelocInfo::Mode rmode, |
| 191 InvokeFlag flag); | 193 InvokeFlag flag, |
| 194 PostCallGenerator* post_call_generator = NULL); |
| 192 | 195 |
| 193 // Invoke the JavaScript function in the given register. Changes the | 196 // Invoke the JavaScript function in the given register. Changes the |
| 194 // current context to the context in the function before invoking. | 197 // current context to the context in the function before invoking. |
| 195 void InvokeFunction(Register function, | 198 void InvokeFunction(Register function, |
| 196 const ParameterCount& actual, | 199 const ParameterCount& actual, |
| 197 InvokeFlag flag); | 200 InvokeFlag flag, |
| 201 PostCallGenerator* post_call_generator = NULL); |
| 198 | 202 |
| 199 void InvokeFunction(JSFunction* function, | 203 void InvokeFunction(JSFunction* function, |
| 200 const ParameterCount& actual, | 204 const ParameterCount& actual, |
| 201 InvokeFlag flag); | 205 InvokeFlag flag, |
| 206 PostCallGenerator* post_call_generator = NULL); |
| 202 | 207 |
| 203 // Invoke specified builtin JavaScript function. Adds an entry to | 208 // Invoke specified builtin JavaScript function. Adds an entry to |
| 204 // the unresolved list if the name does not resolve. | 209 // the unresolved list if the name does not resolve. |
| 205 void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag); | 210 void InvokeBuiltin(Builtins::JavaScript id, |
| 211 InvokeFlag flag, |
| 212 PostCallGenerator* post_call_generator = NULL); |
| 206 | 213 |
| 207 // Store the function for the given builtin in the target register. | 214 // Store the function for the given builtin in the target register. |
| 208 void GetBuiltinFunction(Register target, Builtins::JavaScript id); | 215 void GetBuiltinFunction(Register target, Builtins::JavaScript id); |
| 209 | 216 |
| 210 // Store the code object for the given builtin in the target register. | 217 // Store the code object for the given builtin in the target register. |
| 211 void GetBuiltinEntry(Register target, Builtins::JavaScript id); | 218 void GetBuiltinEntry(Register target, Builtins::JavaScript id); |
| 212 | 219 |
| 213 | 220 |
| 214 // --------------------------------------------------------------------------- | 221 // --------------------------------------------------------------------------- |
| 215 // Smi tagging, untagging and operations on tagged smis. | 222 // Smi tagging, untagging and operations on tagged smis. |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 | 661 |
| 655 // Abort execution if argument is not a number. Used in debug code. | 662 // Abort execution if argument is not a number. Used in debug code. |
| 656 void AbortIfNotNumber(Register object); | 663 void AbortIfNotNumber(Register object); |
| 657 | 664 |
| 658 // Abort execution if argument is a smi. Used in debug code. | 665 // Abort execution if argument is a smi. Used in debug code. |
| 659 void AbortIfSmi(Register object); | 666 void AbortIfSmi(Register object); |
| 660 | 667 |
| 661 // Abort execution if argument is not a smi. Used in debug code. | 668 // Abort execution if argument is not a smi. Used in debug code. |
| 662 void AbortIfNotSmi(Register object); | 669 void AbortIfNotSmi(Register object); |
| 663 | 670 |
| 671 // Abort execution if argument is a string. Used in debug code. |
| 672 void AbortIfNotString(Register object); |
| 673 |
| 664 // Abort execution if argument is not the root value with the given index. | 674 // Abort execution if argument is not the root value with the given index. |
| 665 void AbortIfNotRootValue(Register src, | 675 void AbortIfNotRootValue(Register src, |
| 666 Heap::RootListIndex root_value_index, | 676 Heap::RootListIndex root_value_index, |
| 667 const char* message); | 677 const char* message); |
| 668 | 678 |
| 669 // --------------------------------------------------------------------------- | 679 // --------------------------------------------------------------------------- |
| 670 // Exception handling | 680 // Exception handling |
| 671 | 681 |
| 672 // Push a new try handler and link into try handler chain. The return | 682 // Push a new try handler and link into try handler chain. The return |
| 673 // address must be pushed before calling this helper. | 683 // address must be pushed before calling this helper. |
| 674 void PushTryHandler(CodeLocation try_location, HandlerType type); | 684 void PushTryHandler(CodeLocation try_location, HandlerType type); |
| 675 | 685 |
| 676 // Unlink the stack handler on top of the stack from the try handler chain. | 686 // Unlink the stack handler on top of the stack from the try handler chain. |
| 677 void PopTryHandler(); | 687 void PopTryHandler(); |
| 678 | 688 |
| 689 // Activate the top handler in the try hander chain and pass the |
| 690 // thrown value. |
| 691 void Throw(Register value); |
| 692 |
| 693 // Propagate an uncatchable exception out of the current JS stack. |
| 694 void ThrowUncatchable(UncatchableExceptionType type, Register value); |
| 695 |
| 679 // --------------------------------------------------------------------------- | 696 // --------------------------------------------------------------------------- |
| 680 // Inline caching support | 697 // Inline caching support |
| 681 | 698 |
| 682 // Generate code for checking access rights - used for security checks | 699 // Generate code for checking access rights - used for security checks |
| 683 // on access to global objects across environments. The holder register | 700 // on access to global objects across environments. The holder register |
| 684 // is left untouched, but the scratch register and kScratchRegister, | 701 // is left untouched, but the scratch register and kScratchRegister, |
| 685 // which must be different, are clobbered. | 702 // which must be different, are clobbered. |
| 686 void CheckAccessGlobalProxy(Register holder_reg, | 703 void CheckAccessGlobalProxy(Register holder_reg, |
| 687 Register scratch, | 704 Register scratch, |
| 688 Label* miss); | 705 Label* miss); |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 956 // Verify restrictions about code generated in stubs. | 973 // Verify restrictions about code generated in stubs. |
| 957 void set_generating_stub(bool value) { generating_stub_ = value; } | 974 void set_generating_stub(bool value) { generating_stub_ = value; } |
| 958 bool generating_stub() { return generating_stub_; } | 975 bool generating_stub() { return generating_stub_; } |
| 959 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } | 976 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } |
| 960 bool allow_stub_calls() { return allow_stub_calls_; } | 977 bool allow_stub_calls() { return allow_stub_calls_; } |
| 961 | 978 |
| 962 private: | 979 private: |
| 963 // Order general registers are pushed by Pushad. | 980 // Order general registers are pushed by Pushad. |
| 964 // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r12, r14. | 981 // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r12, r14. |
| 965 static int kSafepointPushRegisterIndices[Register::kNumRegisters]; | 982 static int kSafepointPushRegisterIndices[Register::kNumRegisters]; |
| 983 static const int kNumSafepointSavedRegisters = 11; |
| 984 |
| 966 bool generating_stub_; | 985 bool generating_stub_; |
| 967 bool allow_stub_calls_; | 986 bool allow_stub_calls_; |
| 968 | 987 |
| 969 // Returns a register holding the smi value. The register MUST NOT be | 988 // Returns a register holding the smi value. The register MUST NOT be |
| 970 // modified. It may be the "smi 1 constant" register. | 989 // modified. It may be the "smi 1 constant" register. |
| 971 Register GetSmiConstant(Smi* value); | 990 Register GetSmiConstant(Smi* value); |
| 972 | 991 |
| 973 // Moves the smi value to the destination register. | 992 // Moves the smi value to the destination register. |
| 974 void LoadSmiConstant(Register dst, Smi* value); | 993 void LoadSmiConstant(Register dst, Smi* value); |
| 975 | 994 |
| 976 // This handle will be patched with the code object on installation. | 995 // This handle will be patched with the code object on installation. |
| 977 Handle<Object> code_object_; | 996 Handle<Object> code_object_; |
| 978 | 997 |
| 979 // Helper functions for generating invokes. | 998 // Helper functions for generating invokes. |
| 980 template <typename LabelType> | 999 template <typename LabelType> |
| 981 void InvokePrologue(const ParameterCount& expected, | 1000 void InvokePrologue(const ParameterCount& expected, |
| 982 const ParameterCount& actual, | 1001 const ParameterCount& actual, |
| 983 Handle<Code> code_constant, | 1002 Handle<Code> code_constant, |
| 984 Register code_register, | 1003 Register code_register, |
| 985 LabelType* done, | 1004 LabelType* done, |
| 986 InvokeFlag flag); | 1005 InvokeFlag flag, |
| 1006 PostCallGenerator* post_call_generator); |
| 987 | 1007 |
| 988 // Activation support. | 1008 // Activation support. |
| 989 void EnterFrame(StackFrame::Type type); | 1009 void EnterFrame(StackFrame::Type type); |
| 990 void LeaveFrame(StackFrame::Type type); | 1010 void LeaveFrame(StackFrame::Type type); |
| 991 | 1011 |
| 992 void EnterExitFramePrologue(bool save_rax); | 1012 void EnterExitFramePrologue(bool save_rax); |
| 993 | 1013 |
| 994 // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack | 1014 // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack |
| 995 // accessible via StackSpaceOperand. | 1015 // accessible via StackSpaceOperand. |
| 996 void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles); | 1016 void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1007 // Update allocation top with value in result_end register. | 1027 // Update allocation top with value in result_end register. |
| 1008 // If scratch is valid, it contains the address of the allocation top. | 1028 // If scratch is valid, it contains the address of the allocation top. |
| 1009 void UpdateAllocationTopHelper(Register result_end, Register scratch); | 1029 void UpdateAllocationTopHelper(Register result_end, Register scratch); |
| 1010 | 1030 |
| 1011 // Helper for PopHandleScope. Allowed to perform a GC and returns | 1031 // Helper for PopHandleScope. Allowed to perform a GC and returns |
| 1012 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and | 1032 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and |
| 1013 // possibly returns a failure object indicating an allocation failure. | 1033 // possibly returns a failure object indicating an allocation failure. |
| 1014 Object* PopHandleScopeHelper(Register saved, | 1034 Object* PopHandleScopeHelper(Register saved, |
| 1015 Register scratch, | 1035 Register scratch, |
| 1016 bool gc_allowed); | 1036 bool gc_allowed); |
| 1037 |
| 1038 |
| 1039 // Compute memory operands for safepoint stack slots. |
| 1040 Operand SafepointRegisterSlot(Register reg); |
| 1041 static int SafepointRegisterStackIndex(int reg_code) { |
| 1042 return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1; |
| 1043 } |
| 1044 |
| 1045 // Needs access to SafepointRegisterStackIndex for optimized frame |
| 1046 // traversal. |
| 1047 friend class OptimizedFrame; |
| 1017 }; | 1048 }; |
| 1018 | 1049 |
| 1019 | 1050 |
| 1020 // The code patcher is used to patch (typically) small parts of code e.g. for | 1051 // The code patcher is used to patch (typically) small parts of code e.g. for |
| 1021 // debugging and other types of instrumentation. When using the code patcher | 1052 // debugging and other types of instrumentation. When using the code patcher |
| 1022 // the exact number of bytes specified must be emitted. Is not legal to emit | 1053 // the exact number of bytes specified must be emitted. Is not legal to emit |
| 1023 // relocation information. If any of these constraints are violated it causes | 1054 // relocation information. If any of these constraints are violated it causes |
| 1024 // an assertion. | 1055 // an assertion. |
| 1025 class CodePatcher { | 1056 class CodePatcher { |
| 1026 public: | 1057 public: |
| 1027 CodePatcher(byte* address, int size); | 1058 CodePatcher(byte* address, int size); |
| 1028 virtual ~CodePatcher(); | 1059 virtual ~CodePatcher(); |
| 1029 | 1060 |
| 1030 // Macro assembler to emit code. | 1061 // Macro assembler to emit code. |
| 1031 MacroAssembler* masm() { return &masm_; } | 1062 MacroAssembler* masm() { return &masm_; } |
| 1032 | 1063 |
| 1033 private: | 1064 private: |
| 1034 byte* address_; // The address of the code being patched. | 1065 byte* address_; // The address of the code being patched. |
| 1035 int size_; // Number of bytes of the expected patch size. | 1066 int size_; // Number of bytes of the expected patch size. |
| 1036 MacroAssembler masm_; // Macro assembler used to generate the code. | 1067 MacroAssembler masm_; // Macro assembler used to generate the code. |
| 1037 }; | 1068 }; |
| 1038 | 1069 |
| 1039 | 1070 |
| 1071 // Helper class for generating code or data associated with the code |
| 1072 // right after a call instruction. As an example this can be used to |
| 1073 // generate safepoint data after calls for crankshaft. |
| 1074 class PostCallGenerator { |
| 1075 public: |
| 1076 PostCallGenerator() { } |
| 1077 virtual ~PostCallGenerator() { } |
| 1078 virtual void Generate() = 0; |
| 1079 }; |
| 1080 |
| 1081 |
| 1040 // ----------------------------------------------------------------------------- | 1082 // ----------------------------------------------------------------------------- |
| 1041 // Static helper functions. | 1083 // Static helper functions. |
| 1042 | 1084 |
| 1043 // Generate an Operand for loading a field from an object. | 1085 // Generate an Operand for loading a field from an object. |
| 1044 static inline Operand FieldOperand(Register object, int offset) { | 1086 static inline Operand FieldOperand(Register object, int offset) { |
| 1045 return Operand(object, offset - kHeapObjectTag); | 1087 return Operand(object, offset - kHeapObjectTag); |
| 1046 } | 1088 } |
| 1047 | 1089 |
| 1048 | 1090 |
| 1049 // Generate an Operand for loading an indexed field from an object. | 1091 // Generate an Operand for loading an indexed field from an object. |
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1736 } | 1778 } |
| 1737 } | 1779 } |
| 1738 | 1780 |
| 1739 | 1781 |
| 1740 template <typename LabelType> | 1782 template <typename LabelType> |
| 1741 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 1783 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
| 1742 const ParameterCount& actual, | 1784 const ParameterCount& actual, |
| 1743 Handle<Code> code_constant, | 1785 Handle<Code> code_constant, |
| 1744 Register code_register, | 1786 Register code_register, |
| 1745 LabelType* done, | 1787 LabelType* done, |
| 1746 InvokeFlag flag) { | 1788 InvokeFlag flag, |
| 1789 PostCallGenerator* post_call_generator) { |
| 1747 bool definitely_matches = false; | 1790 bool definitely_matches = false; |
| 1748 NearLabel invoke; | 1791 NearLabel invoke; |
| 1749 if (expected.is_immediate()) { | 1792 if (expected.is_immediate()) { |
| 1750 ASSERT(actual.is_immediate()); | 1793 ASSERT(actual.is_immediate()); |
| 1751 if (expected.immediate() == actual.immediate()) { | 1794 if (expected.immediate() == actual.immediate()) { |
| 1752 definitely_matches = true; | 1795 definitely_matches = true; |
| 1753 } else { | 1796 } else { |
| 1754 Set(rax, actual.immediate()); | 1797 Set(rax, actual.immediate()); |
| 1755 if (expected.immediate() == | 1798 if (expected.immediate() == |
| 1756 SharedFunctionInfo::kDontAdaptArgumentsSentinel) { | 1799 SharedFunctionInfo::kDontAdaptArgumentsSentinel) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1788 Builtins::ArgumentsAdaptorTrampoline)); | 1831 Builtins::ArgumentsAdaptorTrampoline)); |
| 1789 if (!code_constant.is_null()) { | 1832 if (!code_constant.is_null()) { |
| 1790 movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); | 1833 movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); |
| 1791 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 1834 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 1792 } else if (!code_register.is(rdx)) { | 1835 } else if (!code_register.is(rdx)) { |
| 1793 movq(rdx, code_register); | 1836 movq(rdx, code_register); |
| 1794 } | 1837 } |
| 1795 | 1838 |
| 1796 if (flag == CALL_FUNCTION) { | 1839 if (flag == CALL_FUNCTION) { |
| 1797 Call(adaptor, RelocInfo::CODE_TARGET); | 1840 Call(adaptor, RelocInfo::CODE_TARGET); |
| 1841 if (post_call_generator != NULL) post_call_generator->Generate(); |
| 1798 jmp(done); | 1842 jmp(done); |
| 1799 } else { | 1843 } else { |
| 1800 Jump(adaptor, RelocInfo::CODE_TARGET); | 1844 Jump(adaptor, RelocInfo::CODE_TARGET); |
| 1801 } | 1845 } |
| 1802 bind(&invoke); | 1846 bind(&invoke); |
| 1803 } | 1847 } |
| 1804 } | 1848 } |
| 1805 | 1849 |
| 1806 | 1850 |
| 1807 } } // namespace v8::internal | 1851 } } // namespace v8::internal |
| 1808 | 1852 |
| 1809 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ | 1853 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ |
| OLD | NEW |