]> git.saurik.com Git - apple/javascriptcore.git/blame - jit/SpecializedThunkJIT.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / jit / SpecializedThunkJIT.h
CommitLineData
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
38namespace 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
A
131#else
132#if !CPU(X86)
133 // The src register is not clobbered by moveDoubleToInts with ARM, MIPS and SH4 macro assemblers, so let's use it.
134 moveDoubleToInts(src, regT0, regT1);
14957cd0 135#else
4e4e5a6f
A
136 storeDouble(src, Address(stackPointerRegister, -(int)sizeof(double)));
137 loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - sizeof(double)), regT1);
138 loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - sizeof(double)), regT0);
81345200 139#endif
6fe7ccc8
A
140 Jump lowNonZero = branchTestPtr(NonZero, regT1);
141 Jump highNonZero = branchTestPtr(NonZero, regT0);
142 move(TrustedImm32(0), regT0);
143 move(TrustedImm32(Int32Tag), regT1);
144 lowNonZero.link(this);
145 highNonZero.link(this);
4e4e5a6f 146#endif
81345200 147 emitFunctionEpilogue();
4e4e5a6f
A
148 ret();
149 }
150
151 void returnInt32(RegisterID src)
152 {
153 if (src != regT0)
154 move(src, regT0);
155 tagReturnAsInt32();
81345200 156 emitFunctionEpilogue();
4e4e5a6f
A
157 ret();
158 }
159
160 void returnJSCell(RegisterID src)
161 {
162 if (src != regT0)
163 move(src, regT0);
164 tagReturnAsJSCell();
81345200 165 emitFunctionEpilogue();
4e4e5a6f
A
166 ret();
167 }
168
81345200 169 MacroAssemblerCodeRef finalize(MacroAssemblerCodePtr fallback, const char* thunkKind)
4e4e5a6f 170 {
81345200 171 LinkBuffer patchBuffer(*m_vm, *this, GLOBAL_THUNK_ID);
14957cd0 172 patchBuffer.link(m_failures, CodeLocationLabel(fallback));
6fe7ccc8
A
173 for (unsigned i = 0; i < m_calls.size(); i++)
174 patchBuffer.link(m_calls[i].first, m_calls[i].second);
93a37866 175 return FINALIZE_CODE(patchBuffer, ("Specialized thunk for %s", thunkKind));
4e4e5a6f 176 }
6fe7ccc8
A
177
178 // Assumes that the target function uses fpRegister0 as the first argument
179 // and return value. Like any sensible architecture would.
180 void callDoubleToDouble(FunctionPtr function)
4e4e5a6f 181 {
6fe7ccc8 182 m_calls.append(std::make_pair(call(), function));
4e4e5a6f 183 }
93a37866
A
184
185 void callDoubleToDoublePreservingReturn(FunctionPtr function)
186 {
187 if (!isX86())
188 preserveReturnAddressAfterCall(regT3);
189 callDoubleToDouble(function);
190 if (!isX86())
191 restoreReturnAddressBeforeReturn(regT3);
192 }
4e4e5a6f 193
6fe7ccc8
A
194 private:
195
4e4e5a6f
A
196 void tagReturnAsInt32()
197 {
198#if USE(JSVALUE64)
93a37866 199 or64(tagTypeNumberRegister, regT0);
4e4e5a6f 200#else
14957cd0 201 move(TrustedImm32(JSValue::Int32Tag), regT1);
4e4e5a6f
A
202#endif
203 }
204
205 void tagReturnAsJSCell()
206 {
207#if USE(JSVALUE32_64)
14957cd0 208 move(TrustedImm32(JSValue::CellTag), regT1);
4e4e5a6f
A
209#endif
210 }
211
4e4e5a6f 212 MacroAssembler::JumpList m_failures;
81345200 213 Vector<std::pair<Call, FunctionPtr>> m_calls;
4e4e5a6f
A
214 };
215
216}
217
218#endif // ENABLE(JIT)
219
220#endif // SpecializedThunkJIT_h