1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=99:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
20 * The Initial Developer of the Original Code is
21 * Brendan Eich <brendan@mozilla.org>
24 * Sean Stangl <sstangl@mozilla.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #if !defined jsjaeger_assembler64_h__ && defined JS_METHODJIT && defined JS_PUNBOX64
41 #define jsjaeger_assembler64_h__
43 #include "assembler/assembler/MacroAssembler.h"
44 #include "methodjit/MachineRegs.h"
45 #include "methodjit/RematInfo.h"
51 struct Imm64 : JSC::MacroAssembler::ImmPtr
54 : ImmPtr((const void *)u)
58 /* Tag stored in shifted format. */
59 struct ImmTag : JSC::MacroAssembler::ImmPtr
61 ImmTag(JSValueShiftedTag shtag)
62 : ImmPtr((const void *)shtag)
66 struct ImmType : ImmTag
68 ImmType(JSValueType type)
69 : ImmTag(JSValueShiftedTag(JSVAL_TYPE_TO_SHIFTED_TAG(type)))
73 struct ImmPayload : Imm64
75 ImmPayload(uint64 payload)
80 class PunboxAssembler : public JSC::MacroAssembler
82 static const uint32 PAYLOAD_OFFSET = 0;
85 static const JSC::MacroAssembler::Scale JSVAL_SCALE = JSC::MacroAssembler::TimesEight;
88 T payloadOf(T address) {
93 T valueOf(T address) {
97 void loadInlineSlot(RegisterID objReg, uint32 slot,
98 RegisterID typeReg, RegisterID dataReg) {
99 Address address(objReg, JSObject::getFixedSlotOffset(slot));
100 loadValueAsComponents(address, typeReg, dataReg);
103 template <typename T>
104 void loadValue(T address, RegisterID dst) {
105 loadPtr(address, dst);
108 void convertValueToType(RegisterID val) {
109 andPtr(Registers::TypeMaskReg, val);
112 void convertValueToPayload(RegisterID val) {
113 andPtr(Registers::PayloadMaskReg, val);
116 // Returns a label after the one Value load.
117 template <typename T>
118 Label loadValueAsComponents(T address, RegisterID type, RegisterID payload) {
119 loadValue(address, type);
122 move(Registers::PayloadMaskReg, payload);
123 andPtr(type, payload);
124 xorPtr(payload, type);
129 void loadValueAsComponents(const Value &val, RegisterID type, RegisterID payload) {
130 move(Imm64(val.asRawBits() & JSVAL_TAG_MASK), type);
131 move(Imm64(val.asRawBits() & JSVAL_PAYLOAD_MASK), payload);
135 * Load a (64b) js::Value from 'address' into 'type' and 'payload', and
136 * return a label which can be used by
137 * Repatcher::patchAddressOffsetForValue to patch the address offset.
139 Label loadValueWithAddressOffsetPatch(Address address, RegisterID type, RegisterID payload) {
140 return loadValueAsComponents(address, type, payload);
143 template <typename T>
144 void storeValueFromComponents(RegisterID type, RegisterID payload, T address) {
145 move(type, Registers::ValueReg);
146 orPtr(payload, Registers::ValueReg);
147 storeValue(Registers::ValueReg, address);
150 template <typename T>
151 void storeValueFromComponents(ImmTag type, RegisterID payload, T address) {
152 move(type, Registers::ValueReg);
153 orPtr(payload, Registers::ValueReg);
154 storeValue(Registers::ValueReg, address);
158 * Store a (64b) js::Value from 'type' and 'payload' into 'address', and
159 * return a label which can be used by
160 * Repatcher::patchAddressOffsetForValueStore to patch the address offset.
162 DataLabel32 storeValueWithAddressOffsetPatch(RegisterID type, RegisterID payload, Address address) {
163 move(type, Registers::ValueReg);
164 orPtr(payload, Registers::ValueReg);
165 return storePtrWithAddressOffsetPatch(Registers::ValueReg, address);
168 /* Overload for constant type. */
169 DataLabel32 storeValueWithAddressOffsetPatch(ImmTag type, RegisterID payload, Address address) {
170 move(type, Registers::ValueReg);
171 orPtr(payload, Registers::ValueReg);
172 return storePtrWithAddressOffsetPatch(Registers::ValueReg, address);
175 /* Overload for constant type and constant data. */
176 DataLabel32 storeValueWithAddressOffsetPatch(const Value &v, Address address) {
178 jv.asBits = JSVAL_BITS(Jsvalify(v));
180 move(ImmPtr(reinterpret_cast<void*>(jv.asBits)), Registers::ValueReg);
181 return storePtrWithAddressOffsetPatch(Registers::ValueReg, valueOf(address));
184 /* Overloaded for store with value remat info. */
185 DataLabel32 storeValueWithAddressOffsetPatch(const ValueRemat &vr, Address address) {
186 if (vr.isConstant()) {
187 return storeValueWithAddressOffsetPatch(vr.value(), address);
188 } else if (vr.isTypeKnown()) {
189 ImmType type(vr.knownType());
190 RegisterID data(vr.dataReg());
191 return storeValueWithAddressOffsetPatch(type, data, address);
193 RegisterID type(vr.typeReg());
194 RegisterID data(vr.dataReg());
195 return storeValueWithAddressOffsetPatch(type, data, address);
199 template <typename T>
200 void loadTypeTag(T address, RegisterID reg) {
201 loadValue(address, reg);
202 convertValueToType(reg);
205 template <typename T>
206 void storeTypeTag(ImmTag imm, T address) {
207 loadPayload(address, Registers::ValueReg);
208 orPtr(imm, Registers::ValueReg);
209 storePtr(Registers::ValueReg, valueOf(address));
212 template <typename T>
213 void storeTypeTag(RegisterID reg, T address) {
214 /* The type tag must be stored in shifted format. */
215 loadPayload(address, Registers::ValueReg);
216 orPtr(reg, Registers::ValueReg);
217 storePtr(Registers::ValueReg, valueOf(address));
220 template <typename T>
221 void loadPayload(T address, RegisterID reg) {
222 loadValue(address, reg);
223 convertValueToPayload(reg);
226 template <typename T>
227 void storePayload(RegisterID reg, T address) {
228 /* Not for doubles. */
229 loadTypeTag(address, Registers::ValueReg);
230 orPtr(reg, Registers::ValueReg);
231 storePtr(Registers::ValueReg, valueOf(address));
234 template <typename T>
235 void storePayload(ImmPayload imm, T address) {
236 /* Not for doubles. */
237 storePtr(imm, valueOf(address));
240 template <typename T>
241 void storeValue(RegisterID reg, T address) {
242 storePtr(reg, valueOf(address));
245 template <typename T>
246 void storeValue(const Value &v, T address) {
248 jv.asBits = JSVAL_BITS(Jsvalify(v));
250 storePtr(Imm64(jv.asBits), valueOf(address));
253 template <typename T>
254 void storeValue(const ValueRemat &vr, T address) {
256 storeValue(vr.value(), address);
257 else if (vr.isTypeKnown())
258 storeValueFromComponents(ImmType(vr.knownType()), vr.dataReg(), address);
260 storeValueFromComponents(vr.typeReg(), vr.dataReg(), address);
263 template <typename T>
264 Jump guardNotHole(T address) {
265 loadTypeTag(address, Registers::ValueReg);
266 return branchPtr(Equal, Registers::ValueReg, ImmType(JSVAL_TYPE_MAGIC));
269 void loadPrivate(Address privAddr, RegisterID to) {
270 loadPtr(privAddr, to);
271 lshiftPtr(Imm32(1), to);
274 void loadObjPrivate(RegisterID base, RegisterID to) {
275 Address priv(base, offsetof(JSObject, privateData));
279 Jump testNull(Condition cond, RegisterID reg) {
280 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_NULL));
283 Jump testNull(Condition cond, Address address) {
284 loadValue(address, Registers::ValueReg);
285 return testNull(cond, Registers::ValueReg);
288 Jump testUndefined(Condition cond, RegisterID reg) {
289 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_UNDEFINED));
292 Jump testUndefined(Condition cond, Address address) {
293 loadValue(address, Registers::ValueReg);
294 return testUndefined(cond, Registers::ValueReg);
297 Jump testInt32(Condition cond, RegisterID reg) {
298 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_INT32));
301 Jump testInt32(Condition cond, Address address) {
302 loadTypeTag(address, Registers::ValueReg);
303 return testInt32(cond, Registers::ValueReg);
306 Jump testNumber(Condition cond, RegisterID reg) {
307 cond = (cond == Equal) ? Below : AboveOrEqual;
308 return branchPtr(cond, reg,
309 ImmTag(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET));
312 Jump testNumber(Condition cond, Address address) {
313 loadValue(address, Registers::ValueReg);
314 return testNumber(cond, Registers::ValueReg);
317 Jump testPrimitive(Condition cond, RegisterID reg) {
318 cond = (cond == Equal) ? Below : AboveOrEqual;
319 return branchPtr(cond, reg,
320 ImmTag(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET));
323 Jump testPrimitive(Condition cond, Address address) {
324 loadValue(address, Registers::ValueReg);
325 return testPrimitive(cond, Registers::ValueReg);
328 Jump testObject(Condition cond, RegisterID reg) {
329 cond = (cond == Equal) ? AboveOrEqual : Below;
330 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_OBJECT));
333 Jump testObject(Condition cond, Address address) {
334 loadValue(address, Registers::ValueReg);
335 return testObject(cond, Registers::ValueReg);
338 Jump testDouble(Condition cond, RegisterID reg) {
339 cond = (cond == Equal) ? BelowOrEqual : Above;
340 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_MAX_DOUBLE));
343 Jump testDouble(Condition cond, Address address) {
344 loadValue(address, Registers::ValueReg);
345 return testDouble(cond, Registers::ValueReg);
348 Jump testBoolean(Condition cond, RegisterID reg) {
349 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_BOOLEAN));
352 Jump testBoolean(Condition cond, Address address) {
353 loadTypeTag(address, Registers::ValueReg);
354 return testBoolean(cond, Registers::ValueReg);
357 Jump testString(Condition cond, RegisterID reg) {
358 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_STRING));
361 Jump testString(Condition cond, Address address) {
362 loadTypeTag(address, Registers::ValueReg);
363 return testString(cond, Registers::ValueReg);
366 void breakDouble(FPRegisterID srcDest, RegisterID typeReg, RegisterID dataReg) {
367 m_assembler.movq_rr(srcDest, typeReg);
368 move(Registers::PayloadMaskReg, dataReg);
369 andPtr(typeReg, dataReg);
370 xorPtr(dataReg, typeReg);
373 void fastLoadDouble(RegisterID dataReg, RegisterID typeReg, FPRegisterID fpReg) {
374 move(typeReg, Registers::ValueReg);
375 orPtr(dataReg, Registers::ValueReg);
376 m_assembler.movq_rr(Registers::ValueReg, fpReg);
379 void loadStaticDouble(const double *dp, FPRegisterID dest, RegisterID scratch) {
382 move(ImmPtr(reinterpret_cast<void*>(du.u64)), scratch);
383 m_assembler.movq_rr(scratch, dest);
386 template <typename T>
387 Jump fastArrayLoadSlot(T address, RegisterID typeReg, RegisterID dataReg) {
388 loadValueAsComponents(address, typeReg, dataReg);
389 return branchPtr(Equal, typeReg, ImmType(JSVAL_TYPE_MAGIC));
393 typedef PunboxAssembler ValueAssembler;
395 } /* namespace mjit */