]> git.saurik.com Git - apple/javascriptcore.git/blame - jit/SpecializedThunkJIT.h
JavaScriptCore-7601.1.46.3.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 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