blob: 1e45f03004af79bb873c0fab6c77a0dadab02931 [file] [log] [blame]
oliver@apple.comec0e4002010-04-27 03:45:47 +00001/*
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
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000029#include "BytecodeConventions.h"
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +000030#include "CCallHelpers.h"
mark.lam@apple.comab6b5eb2013-11-08 04:05:27 +000031#include "FPRInfo.h"
32#include "GPRInfo.h"
oliver@apple.comec0e4002010-04-27 03:45:47 +000033#include "JITCode.h"
msaboff@apple.coma482c542013-10-04 18:20:40 +000034#include "JITOperations.h"
oliver@apple.comec0e4002010-04-27 03:45:47 +000035#include "JITStubs.h"
mhahnenberg@apple.comc1bc9d32013-01-24 21:39:55 +000036#include "JSCJSValue.h"
mark.lam@apple.com4fbb9c32012-10-09 07:12:56 +000037#include "JSStack.h"
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000038#include "JSString.h"
oliver@apple.comec0e4002010-04-27 03:45:47 +000039#include "MacroAssembler.h"
oliver@apple.comec0e4002010-04-27 03:45:47 +000040#include <wtf/Vector.h>
41
commit-queue@webkit.orgb8419482012-08-30 22:21:48 +000042#if ENABLE(JIT)
43
oliver@apple.comec0e4002010-04-27 03:45:47 +000044namespace JSC {
mark.lam@apple.comab6b5eb2013-11-08 04:05:27 +000045 class JSInterfaceJIT : public CCallHelpers, public GPRInfo, public FPRInfo {
oliver@apple.comec0e4002010-04-27 03:45:47 +000046 public:
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +000047 JSInterfaceJIT(VM* vm, CodeBlock* codeBlock = 0)
48 : CCallHelpers(vm, codeBlock)
49 {
50 }
oliver@apple.comec0e4002010-04-27 03:45:47 +000051
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +000052#if USE(JSVALUE32_64)
53 // Can't just propogate JSValue::Int32Tag as visual studio doesn't like it
barraclough@apple.com11bb59c2011-09-15 19:32:12 +000054 static const unsigned Int32Tag = 0xffffffff;
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +000055 COMPILE_ASSERT(Int32Tag == JSValue::Int32Tag, Int32Tag_out_of_sync);
56#else
bfulgham@apple.comc7f02252013-10-05 00:40:09 +000057 static const unsigned Int32Tag = static_cast<unsigned>(TagTypeNumber >> 32);
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +000058#endif
oliver@apple.comec0e4002010-04-27 03:45:47 +000059 inline Jump emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload);
60 inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst);
oliver@apple.com2bd947e2010-04-29 03:57:16 +000061 inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch);
oliver@apple.comec0e4002010-04-27 03:45:47 +000062
63#if USE(JSVALUE32_64)
64 inline Jump emitJumpIfNotJSCell(unsigned virtualRegisterIndex);
oliver@apple.com88663ea2011-03-14 18:39:40 +000065 inline Address tagFor(int index, RegisterID base = callFrameRegister);
oliver@apple.comec0e4002010-04-27 03:45:47 +000066#endif
oliver@apple.com2bd947e2010-04-29 03:57:16 +000067
oliver@apple.com0cc25c32010-10-19 23:55:08 +000068#if USE(JSVALUE64)
fpizlo@apple.com2ac511c2012-12-27 23:12:27 +000069 Jump emitJumpIfNotJSCell(RegisterID);
oliver@apple.com2bd947e2010-04-29 03:57:16 +000070 Jump emitJumpIfImmediateNumber(RegisterID reg);
71 Jump emitJumpIfNotImmediateNumber(RegisterID reg);
oliver@apple.com26340b42010-05-09 11:42:22 +000072 void emitFastArithImmToInt(RegisterID reg);
fpizlo@apple.com2ac511c2012-12-27 23:12:27 +000073 void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
oliver@apple.com2bd947e2010-04-29 03:57:16 +000074#endif
75
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000076 Jump emitJumpIfNotType(RegisterID baseReg, JSType);
fpizlo@apple.com2ac511c2012-12-27 23:12:27 +000077
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
oliver@apple.com88663ea2011-03-14 18:39:40 +000083 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);
oliver@apple.comec0e4002010-04-27 03:45:47 +000087 };
oliver@apple.com2bd947e2010-04-29 03:57:16 +000088
oliver@apple.com5230bd32010-05-06 19:39:54 +000089 struct ThunkHelpers {
oliver@apple.com5230bd32010-05-06 19:39:54 +000090 static unsigned jsStringLengthOffset() { return OBJECT_OFFSETOF(JSString, m_length); }
91 static unsigned jsStringValueOffset() { return OBJECT_OFFSETOF(JSString, m_value); }
92 };
93
oliver@apple.comec0e4002010-04-27 03:45:47 +000094#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 {
oliver@apple.comfc502ee2010-05-20 00:30:35 +0000103 ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
oliver@apple.combe4e0672011-03-28 17:14:57 +0000104 return branch32(NotEqual, tagFor(virtualRegisterIndex), TrustedImm32(JSValue::CellTag));
oliver@apple.comec0e4002010-04-27 03:45:47 +0000105 }
106
107 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
108 {
oliver@apple.comfc502ee2010-05-20 00:30:35 +0000109 ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
oliver@apple.comec0e4002010-04-27 03:45:47 +0000110 loadPtr(payloadFor(virtualRegisterIndex), dst);
oliver@apple.combe4e0672011-03-28 17:14:57 +0000111 return branch32(NotEqual, tagFor(static_cast<int>(virtualRegisterIndex)), TrustedImm32(JSValue::Int32Tag));
oliver@apple.comec0e4002010-04-27 03:45:47 +0000112 }
113
oliver@apple.com88663ea2011-03-14 18:39:40 +0000114 inline JSInterfaceJIT::Address JSInterfaceJIT::tagFor(int virtualRegisterIndex, RegisterID base)
oliver@apple.comec0e4002010-04-27 03:45:47 +0000115 {
oliver@apple.com88663ea2011-03-14 18:39:40 +0000116 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
117 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag));
oliver@apple.comec0e4002010-04-27 03:45:47 +0000118 }
119
oliver@apple.com88663ea2011-03-14 18:39:40 +0000120 inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
oliver@apple.comec0e4002010-04-27 03:45:47 +0000121 {
oliver@apple.com88663ea2011-03-14 18:39:40 +0000122 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
123 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
oliver@apple.comec0e4002010-04-27 03:45:47 +0000124 }
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000125
oliver@apple.com88663ea2011-03-14 18:39:40 +0000126 inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +0000127 {
128 return payloadFor(virtualRegisterIndex, base);
129 }
130
oliver@apple.com88663ea2011-03-14 18:39:40 +0000131 inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +0000132 {
133 return tagFor(virtualRegisterIndex, base);
134 }
135
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000136 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
137 {
oliver@apple.comfc502ee2010-05-20 00:30:35 +0000138 ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000139 loadPtr(tagFor(virtualRegisterIndex), scratch);
oliver@apple.combe4e0672011-03-28 17:14:57 +0000140 Jump isDouble = branch32(Below, scratch, TrustedImm32(JSValue::LowestTag));
141 Jump notInt = branch32(NotEqual, scratch, TrustedImm32(JSValue::Int32Tag));
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000142 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;
oliver@apple.com5b6a0d32011-07-01 16:33:46 +0000149 }
150
oliver@apple.comec0e4002010-04-27 03:45:47 +0000151#endif
152
153#if USE(JSVALUE64)
fpizlo@apple.com2ac511c2012-12-27 23:12:27 +0000154 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(RegisterID reg)
155 {
156 return branchTest64(NonZero, reg, tagMaskRegister);
157 }
158
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000159 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfImmediateNumber(RegisterID reg)
160 {
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000161 return branchTest64(NonZero, reg, tagTypeNumberRegister);
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000162 }
163 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotImmediateNumber(RegisterID reg)
164 {
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000165 return branchTest64(Zero, reg, tagTypeNumberRegister);
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000166 }
oliver@apple.comec0e4002010-04-27 03:45:47 +0000167 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID dst)
168 {
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000169 load64(addressFor(virtualRegisterIndex), dst);
170 return branchTest64(NonZero, dst, tagMaskRegister);
oliver@apple.comec0e4002010-04-27 03:45:47 +0000171 }
172
173 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
174 {
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000175 load64(addressFor(virtualRegisterIndex), dst);
176 Jump result = branch64(Below, dst, tagTypeNumberRegister);
oliver@apple.comec0e4002010-04-27 03:45:47 +0000177 zeroExtend32ToPtr(dst, dst);
178 return result;
179 }
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000180
181 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
182 {
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000183 load64(addressFor(virtualRegisterIndex), scratch);
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000184 Jump notNumber = emitJumpIfNotImmediateNumber(scratch);
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000185 Jump notInt = branch64(Below, scratch, tagTypeNumberRegister);
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000186 convertInt32ToDouble(scratch, dst);
187 Jump done = jump();
188 notInt.link(this);
yuqiang.xian@intel.com5b1cb732012-10-19 05:46:10 +0000189 add64(tagTypeNumberRegister, scratch);
190 move64ToDouble(scratch, dst);
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000191 done.link(this);
192 return notNumber;
193 }
oliver@apple.com5b6a0d32011-07-01 16:33:46 +0000194
oliver@apple.com26340b42010-05-09 11:42:22 +0000195 ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID)
196 {
197 }
198
fpizlo@apple.com2ac511c2012-12-27 23:12:27 +0000199 // 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 }
oliver@apple.comec0e4002010-04-27 03:45:47 +0000206#endif
207
oliver@apple.com0cc25c32010-10-19 23:55:08 +0000208#if USE(JSVALUE64)
oliver@apple.com88663ea2011-03-14 18:39:40 +0000209 inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
oliver@apple.comec0e4002010-04-27 03:45:47 +0000210 {
oliver@apple.com88663ea2011-03-14 18:39:40 +0000211 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
oliver@apple.comfc502ee2010-05-20 00:30:35 +0000212 return addressFor(virtualRegisterIndex, base);
oliver@apple.comec0e4002010-04-27 03:45:47 +0000213 }
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +0000214
oliver@apple.com88663ea2011-03-14 18:39:40 +0000215 inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +0000216 {
oliver@apple.com88663ea2011-03-14 18:39:40 +0000217 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
218 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +0000219 }
oliver@apple.com88663ea2011-03-14 18:39:40 +0000220 inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +0000221 {
oliver@apple.com88663ea2011-03-14 18:39:40 +0000222 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
223 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
oliver@apple.com9d4f0ec2011-03-14 18:16:36 +0000224 }
oliver@apple.comec0e4002010-04-27 03:45:47 +0000225#endif
226
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000227 ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotType(RegisterID baseReg, JSType type)
fpizlo@apple.com2ac511c2012-12-27 23:12:27 +0000228 {
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000229 return branch8(NotEqual, Address(baseReg, JSCell::typeInfoTypeOffset()), TrustedImm32(type));
fpizlo@apple.com2ac511c2012-12-27 23:12:27 +0000230 }
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
oliver@apple.com88663ea2011-03-14 18:39:40 +0000261 inline JSInterfaceJIT::Address JSInterfaceJIT::addressFor(int virtualRegisterIndex, RegisterID base)
oliver@apple.comec0e4002010-04-27 03:45:47 +0000262 {
oliver@apple.com88663ea2011-03-14 18:39:40 +0000263 ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
264 return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)));
oliver@apple.comec0e4002010-04-27 03:45:47 +0000265 }
266
commit-queue@webkit.orgb8419482012-08-30 22:21:48 +0000267} // namespace JSC
268
269#endif // ENABLE(JIT)
oliver@apple.comec0e4002010-04-27 03:45:47 +0000270
271#endif // JSInterfaceJIT_h