]>
Commit | Line | Data |
---|---|---|
4e4e5a6f A |
1 | /* |
2 | * Copyright (C) 2010 Apple Inc. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
23 | * THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #ifndef SpecializedThunkJIT_h | |
27 | #define SpecializedThunkJIT_h | |
28 | ||
29 | #if ENABLE(JIT) | |
30 | ||
31 | #include "Executable.h" | |
81345200 A |
32 | #include "JIT.h" |
33 | #include "JITInlines.h" | |
4e4e5a6f | 34 | #include "JSInterfaceJIT.h" |
81345200 | 35 | #include "JSStack.h" |
4e4e5a6f A |
36 | #include "LinkBuffer.h" |
37 | ||
38 | namespace JSC { | |
39 | ||
40 | class SpecializedThunkJIT : public JSInterfaceJIT { | |
41 | public: | |
42 | static const int ThisArgument = -1; | |
81345200 A |
43 | SpecializedThunkJIT(VM* vm, int expectedArgCount) |
44 | : JSInterfaceJIT(vm) | |
4e4e5a6f | 45 | { |
81345200 | 46 | emitFunctionPrologue(); |
4e4e5a6f | 47 | // Check that we have the expected number of arguments |
93a37866 | 48 | m_failures.append(branch32(NotEqual, payloadFor(JSStack::ArgumentCount), TrustedImm32(expectedArgCount + 1))); |
4e4e5a6f A |
49 | } |
50 | ||
81345200 A |
51 | explicit SpecializedThunkJIT(VM* vm) |
52 | : JSInterfaceJIT(vm) | |
53 | { | |
54 | emitFunctionPrologue(); | |
55 | } | |
56 | ||
4e4e5a6f A |
57 | void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch) |
58 | { | |
6fe7ccc8 | 59 | unsigned src = CallFrame::argumentOffset(argument); |
4e4e5a6f A |
60 | m_failures.append(emitLoadDouble(src, dst, scratch)); |
61 | } | |
62 | ||
63 | void loadCellArgument(int argument, RegisterID dst) | |
64 | { | |
6fe7ccc8 | 65 | unsigned src = CallFrame::argumentOffset(argument); |
4e4e5a6f A |
66 | m_failures.append(emitLoadJSCell(src, dst)); |
67 | } | |
68 | ||
93a37866 | 69 | void loadJSStringArgument(VM& vm, int argument, RegisterID dst) |
4e4e5a6f A |
70 | { |
71 | loadCellArgument(argument, dst); | |
81345200 A |
72 | m_failures.append(branchStructure(*this, NotEqual, |
73 | Address(dst, JSCell::structureIDOffset()), | |
74 | vm.stringStructure.get())); | |
75 | } | |
76 | ||
77 | void loadArgumentWithSpecificClass(const ClassInfo* classInfo, int argument, RegisterID dst, RegisterID scratch) | |
78 | { | |
79 | loadCellArgument(argument, dst); | |
80 | emitLoadStructure(dst, scratch, dst); | |
81 | appendFailure(branchPtr(NotEqual, Address(scratch, Structure::classInfoOffset()), TrustedImmPtr(classInfo))); | |
82 | // We have to reload the argument since emitLoadStructure clobbered it. | |
83 | loadCellArgument(argument, dst); | |
4e4e5a6f A |
84 | } |
85 | ||
86 | void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget) | |
87 | { | |
6fe7ccc8 | 88 | unsigned src = CallFrame::argumentOffset(argument); |
4e4e5a6f A |
89 | failTarget = emitLoadInt32(src, dst); |
90 | } | |
91 | ||
92 | void loadInt32Argument(int argument, RegisterID dst) | |
93 | { | |
94 | Jump conversionFailed; | |
95 | loadInt32Argument(argument, dst, conversionFailed); | |
96 | m_failures.append(conversionFailed); | |
97 | } | |
98 | ||
99 | void appendFailure(const Jump& failure) | |
100 | { | |
101 | m_failures.append(failure); | |
102 | } | |
81345200 | 103 | #if USE(JSVALUE64) |
4e4e5a6f A |
104 | void returnJSValue(RegisterID src) |
105 | { | |
106 | if (src != regT0) | |
107 | move(src, regT0); | |
81345200 A |
108 | emitFunctionEpilogue(); |
109 | ret(); | |
110 | } | |
111 | #else | |
112 | void returnJSValue(RegisterID payload, RegisterID tag) | |
113 | { | |
114 | ASSERT_UNUSED(payload, payload == regT0); | |
115 | ASSERT_UNUSED(tag, tag == regT1); | |
116 | emitFunctionEpilogue(); | |
4e4e5a6f A |
117 | ret(); |
118 | } | |
81345200 | 119 | #endif |
4e4e5a6f A |
120 | |
121 | void returnDouble(FPRegisterID src) | |
122 | { | |
123 | #if USE(JSVALUE64) | |
93a37866 A |
124 | moveDoubleTo64(src, regT0); |
125 | Jump zero = branchTest64(Zero, regT0); | |
126 | sub64(tagTypeNumberRegister, regT0); | |
6fe7ccc8 A |
127 | Jump done = jump(); |
128 | zero.link(this); | |
129 | move(tagTypeNumberRegister, regT0); | |
130 | done.link(this); | |
81345200 | 131 | #else |
81345200 | 132 | moveDoubleToInts(src, regT0, regT1); |
6fe7ccc8 A |
133 | Jump lowNonZero = branchTestPtr(NonZero, regT1); |
134 | Jump highNonZero = branchTestPtr(NonZero, regT0); | |
135 | move(TrustedImm32(0), regT0); | |
136 | move(TrustedImm32(Int32Tag), regT1); | |
137 | lowNonZero.link(this); | |
138 | highNonZero.link(this); | |
4e4e5a6f | 139 | #endif |
81345200 | 140 | emitFunctionEpilogue(); |
4e4e5a6f A |
141 | ret(); |
142 | } | |
143 | ||
144 | void returnInt32(RegisterID src) | |
145 | { | |
146 | if (src != regT0) | |
147 | move(src, regT0); | |
148 | tagReturnAsInt32(); | |
81345200 | 149 | emitFunctionEpilogue(); |
4e4e5a6f A |
150 | ret(); |
151 | } | |
152 | ||
153 | void returnJSCell(RegisterID src) | |
154 | { | |
155 | if (src != regT0) | |
156 | move(src, regT0); | |
157 | tagReturnAsJSCell(); | |
81345200 | 158 | emitFunctionEpilogue(); |
4e4e5a6f A |
159 | ret(); |
160 | } | |
161 | ||
81345200 | 162 | MacroAssemblerCodeRef finalize(MacroAssemblerCodePtr fallback, const char* thunkKind) |
4e4e5a6f | 163 | { |
81345200 | 164 | LinkBuffer patchBuffer(*m_vm, *this, GLOBAL_THUNK_ID); |
14957cd0 | 165 | patchBuffer.link(m_failures, CodeLocationLabel(fallback)); |
6fe7ccc8 A |
166 | for (unsigned i = 0; i < m_calls.size(); i++) |
167 | patchBuffer.link(m_calls[i].first, m_calls[i].second); | |
93a37866 | 168 | return FINALIZE_CODE(patchBuffer, ("Specialized thunk for %s", thunkKind)); |
4e4e5a6f | 169 | } |
6fe7ccc8 A |
170 | |
171 | // Assumes that the target function uses fpRegister0 as the first argument | |
172 | // and return value. Like any sensible architecture would. | |
173 | void callDoubleToDouble(FunctionPtr function) | |
4e4e5a6f | 174 | { |
6fe7ccc8 | 175 | m_calls.append(std::make_pair(call(), function)); |
4e4e5a6f | 176 | } |
93a37866 A |
177 | |
178 | void callDoubleToDoublePreservingReturn(FunctionPtr function) | |
179 | { | |
180 | if (!isX86()) | |
181 | preserveReturnAddressAfterCall(regT3); | |
182 | callDoubleToDouble(function); | |
183 | if (!isX86()) | |
184 | restoreReturnAddressBeforeReturn(regT3); | |
185 | } | |
4e4e5a6f | 186 | |
6fe7ccc8 A |
187 | private: |
188 | ||
4e4e5a6f A |
189 | void tagReturnAsInt32() |
190 | { | |
191 | #if USE(JSVALUE64) | |
93a37866 | 192 | or64(tagTypeNumberRegister, regT0); |
4e4e5a6f | 193 | #else |
14957cd0 | 194 | move(TrustedImm32(JSValue::Int32Tag), regT1); |
4e4e5a6f A |
195 | #endif |
196 | } | |
197 | ||
198 | void tagReturnAsJSCell() | |
199 | { | |
200 | #if USE(JSVALUE32_64) | |
14957cd0 | 201 | move(TrustedImm32(JSValue::CellTag), regT1); |
4e4e5a6f A |
202 | #endif |
203 | } | |
204 | ||
4e4e5a6f | 205 | MacroAssembler::JumpList m_failures; |
81345200 | 206 | Vector<std::pair<Call, FunctionPtr>> m_calls; |
4e4e5a6f A |
207 | }; |
208 | ||
209 | } | |
210 | ||
211 | #endif // ENABLE(JIT) | |
212 | ||
213 | #endif // SpecializedThunkJIT_h |