]> git.saurik.com Git - apple/javascriptcore.git/blame - jit/JSInterfaceJIT.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / jit / JSInterfaceJIT.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 JSInterfaceJIT_h
27#define JSInterfaceJIT_h
28
6fe7ccc8 29#include "BytecodeConventions.h"
81345200
A
30#include "CCallHelpers.h"
31#include "FPRInfo.h"
32#include "GPRInfo.h"
4e4e5a6f 33#include "JITCode.h"
81345200 34#include "JITOperations.h"
4e4e5a6f 35#include "JITStubs.h"
93a37866
A
36#include "JSCJSValue.h"
37#include "JSStack.h"
6fe7ccc8 38#include "JSString.h"
4e4e5a6f 39#include "MacroAssembler.h"
4e4e5a6f
A
40#include <wtf/Vector.h>
41
93a37866
A
42#if ENABLE(JIT)
43
4e4e5a6f 44namespace JSC {
81345200 45 class JSInterfaceJIT : public CCallHelpers, public GPRInfo, public FPRInfo {
4e4e5a6f 46 public:
81345200
A
47 JSInterfaceJIT(VM* vm, CodeBlock* codeBlock = 0)
48 : CCallHelpers(vm, codeBlock)
49 {
50 }
4e4e5a6f 51
14957cd0
A
52#if USE(JSVALUE32_64)
53 // Can't just propogate JSValue::Int32Tag as visual studio doesn't like it
54 static const unsigned Int32Tag = 0xffffffff;
55 COMPILE_ASSERT(Int32Tag == JSValue::Int32Tag, Int32Tag_out_of_sync);
56#else
81345200 57 static const unsigned Int32Tag = static_cast<unsigned>(TagTypeNumber >> 32);
14957cd0 58#endif
4e4e5a6f
A
59 inline Jump emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload);
60 inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst);
61 inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch);
62
63#if USE(JSVALUE32_64)
64 inline Jump emitJumpIfNotJSCell(unsigned virtualRegisterIndex);
14957cd0 65 inline Address tagFor(int index, RegisterID base = callFrameRegister);
4e4e5a6f
A
66#endif
67
14957cd0 68#if USE(JSVALUE64)
93a37866 69 Jump emitJumpIfNotJSCell(RegisterID);
4e4e5a6f
A
70 Jump emitJumpIfImmediateNumber(RegisterID reg);
71 Jump emitJumpIfNotImmediateNumber(RegisterID reg);
72 void emitFastArithImmToInt(RegisterID reg);
93a37866 73 void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
4e4e5a6f
A
74#endif
75
81345200 76 Jump emitJumpIfNotType(RegisterID baseReg, JSType);
93a37866
A
77
78 void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry, RegisterID to, RegisterID from = callFrameRegister);
79 void emitPutToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry);
80 void emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry);
81 void emitPutCellToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry);
82
14957cd0
A
83 inline Address payloadFor(int index, RegisterID base = callFrameRegister);
84 inline Address intPayloadFor(int index, RegisterID base = callFrameRegister);
85 inline Address intTagFor(int index, RegisterID base = callFrameRegister);
86 inline Address addressFor(int index, RegisterID base = callFrameRegister);
4e4e5a6f
A
87 };
88
89 struct ThunkHelpers {
4e4e5a6f
A
90 static unsigned jsStringLengthOffset() { return OBJECT_OFFSETOF(JSString, m_length); }
91 static unsigned jsStringValueOffset() { return OBJECT_OFFSETOF(JSString, m_value); }
92 };
93
94#if USE(JSVALUE32_64)
95 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload)
96 {
97 loadPtr(payloadFor(virtualRegisterIndex), payload);
98 return emitJumpIfNotJSCell(virtualRegisterIndex);
99 }
100
101 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(unsigned virtualRegisterIndex)
102 {
103 ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
14957cd0 104 return branch32(NotEqual, tagFor(virtualRegisterIndex), TrustedImm32(JSValue::CellTag));
4e4e5a6f
A
105 }
106
107 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
108 {
109 ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
110 loadPtr(payloadFor(virtualRegisterIndex), dst);
14957cd0 111 return branch32(NotEqual, tagFor(static_cast<int>(virtualRegisterIndex)), TrustedImm32(JSValue::Int32Tag));
4e4e5a6f
A
112 }
113
14957cd0 114 inline JSInterfaceJIT::Address JSInterfaceJIT::tagFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 115 {
14957cd0
A
116 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
117 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag));
4e4e5a6f
A
118 }
119
14957cd0 120 inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 121 {
14957cd0
A
122 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
123 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
124 }
125
126 inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
127 {
128 return payloadFor(virtualRegisterIndex, base);
129 }
130
131 inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
132 {
133 return tagFor(virtualRegisterIndex, base);
4e4e5a6f
A
134 }
135
136 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
137 {
138 ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
139 loadPtr(tagFor(virtualRegisterIndex), scratch);
14957cd0
A
140 Jump isDouble = branch32(Below, scratch, TrustedImm32(JSValue::LowestTag));
141 Jump notInt = branch32(NotEqual, scratch, TrustedImm32(JSValue::Int32Tag));
4e4e5a6f
A
142 loadPtr(payloadFor(virtualRegisterIndex), scratch);
143 convertInt32ToDouble(scratch, dst);
144 Jump done = jump();
145 isDouble.link(this);
146 loadDouble(addressFor(virtualRegisterIndex), dst);
147 done.link(this);
148 return notInt;
6fe7ccc8
A
149 }
150
4e4e5a6f
A
151#endif
152
153#if USE(JSVALUE64)
93a37866
A
154 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(RegisterID reg)
155 {
156 return branchTest64(NonZero, reg, tagMaskRegister);
157 }
158
4e4e5a6f
A
159 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfImmediateNumber(RegisterID reg)
160 {
93a37866 161 return branchTest64(NonZero, reg, tagTypeNumberRegister);
4e4e5a6f
A
162 }
163 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotImmediateNumber(RegisterID reg)
164 {
93a37866 165 return branchTest64(Zero, reg, tagTypeNumberRegister);
4e4e5a6f
A
166 }
167 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID dst)
168 {
93a37866
A
169 load64(addressFor(virtualRegisterIndex), dst);
170 return branchTest64(NonZero, dst, tagMaskRegister);
4e4e5a6f
A
171 }
172
173 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
174 {
93a37866
A
175 load64(addressFor(virtualRegisterIndex), dst);
176 Jump result = branch64(Below, dst, tagTypeNumberRegister);
4e4e5a6f
A
177 zeroExtend32ToPtr(dst, dst);
178 return result;
179 }
180
181 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
182 {
93a37866 183 load64(addressFor(virtualRegisterIndex), scratch);
4e4e5a6f 184 Jump notNumber = emitJumpIfNotImmediateNumber(scratch);
93a37866 185 Jump notInt = branch64(Below, scratch, tagTypeNumberRegister);
4e4e5a6f
A
186 convertInt32ToDouble(scratch, dst);
187 Jump done = jump();
188 notInt.link(this);
93a37866
A
189 add64(tagTypeNumberRegister, scratch);
190 move64ToDouble(scratch, dst);
4e4e5a6f
A
191 done.link(this);
192 return notNumber;
193 }
6fe7ccc8 194
4e4e5a6f
A
195 ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID)
196 {
197 }
198
93a37866
A
199 // operand is int32_t, must have been zero-extended if register is 64-bit.
200 ALWAYS_INLINE void JSInterfaceJIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest)
201 {
202 if (src != dest)
203 move(src, dest);
204 or64(tagTypeNumberRegister, dest);
205 }
4e4e5a6f
A
206#endif
207
14957cd0
A
208#if USE(JSVALUE64)
209 inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 210 {
14957cd0
A
211 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
212 return addressFor(virtualRegisterIndex, base);
4e4e5a6f
A
213 }
214
14957cd0 215 inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 216 {
14957cd0
A
217 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
218 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
4e4e5a6f 219 }
14957cd0 220 inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 221 {
14957cd0
A
222 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
223 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
4e4e5a6f
A
224 }
225#endif
226
81345200 227 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotType(RegisterID baseReg, JSType type)
93a37866 228 {
81345200 229 return branch8(NotEqual, Address(baseReg, JSCell::typeInfoTypeOffset()), TrustedImm32(type));
93a37866
A
230 }
231
232 ALWAYS_INLINE void JSInterfaceJIT::emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
233 {
234 loadPtr(Address(from, entry * sizeof(Register)), to);
235 }
236
237 ALWAYS_INLINE void JSInterfaceJIT::emitPutToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry)
238 {
239#if USE(JSVALUE32_64)
240 storePtr(from, payloadFor(entry, callFrameRegister));
241#else
242 store64(from, addressFor(entry, callFrameRegister));
243#endif
244 }
245
246 ALWAYS_INLINE void JSInterfaceJIT::emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry entry)
247 {
248 storePtr(TrustedImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));
249 }
250
251 ALWAYS_INLINE void JSInterfaceJIT::emitPutCellToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry)
252 {
253#if USE(JSVALUE32_64)
254 store32(TrustedImm32(JSValue::CellTag), tagFor(entry, callFrameRegister));
255 store32(from, payloadFor(entry, callFrameRegister));
256#else
257 store64(from, addressFor(entry, callFrameRegister));
258#endif
259 }
260
14957cd0 261 inline JSInterfaceJIT::Address JSInterfaceJIT::addressFor(int virtualRegisterIndex, RegisterID base)
4e4e5a6f 262 {
14957cd0
A
263 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
264 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)));
4e4e5a6f
A
265 }
266
93a37866
A
267} // namespace JSC
268
269#endif // ENABLE(JIT)
4e4e5a6f
A
270
271#endif // JSInterfaceJIT_h