Fix register allocation bug when pushing addresses (bug 605452, r=sstangl,dmandelin).
[mozilla-central.git] / js / src / methodjit / PunboxAssembler.h
blob77bb9f1570136dd39ed87a5187ff2c897fa75213
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
15 * License.
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 * May 28, 2008.
20 * The Initial Developer of the Original Code is
21 * Brendan Eich <brendan@mozilla.org>
23 * Contributor(s):
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 "methodjit/BaseAssembler.h"
44 #include "methodjit/MachineRegs.h"
45 #include "methodjit/RematInfo.h"
47 namespace js {
48 namespace mjit {
50 struct Imm64 : JSC::MacroAssembler::ImmPtr
52 Imm64(uint64 u)
53 : ImmPtr((const void *)u)
54 { }
57 /* Tag stored in shifted format. */
58 struct ImmTag : JSC::MacroAssembler::ImmPtr
60 ImmTag(JSValueShiftedTag shtag)
61 : ImmPtr((const void *)shtag)
62 { }
65 struct ImmType : ImmTag
67 ImmType(JSValueType type)
68 : ImmTag(JSValueShiftedTag(JSVAL_TYPE_TO_SHIFTED_TAG(type)))
69 { }
72 struct ImmPayload : Imm64
74 ImmPayload(uint64 payload)
75 : Imm64(payload)
76 { }
79 class Assembler : public BaseAssembler
81 static const uint32 PAYLOAD_OFFSET = 0;
83 public:
84 static const JSC::MacroAssembler::Scale JSVAL_SCALE = JSC::MacroAssembler::TimesEight;
86 template <typename T>
87 T payloadOf(T address) {
88 return address;
91 template <typename T>
92 T valueOf(T address) {
93 return address;
96 void loadSlot(RegisterID obj, RegisterID clobber, uint32 slot, bool inlineAccess,
97 RegisterID type, RegisterID data) {
98 JS_ASSERT(type != data);
99 Address address(obj, JSObject::getFixedSlotOffset(slot));
100 if (!inlineAccess) {
101 loadPtr(Address(obj, offsetof(JSObject, slots)), clobber);
102 address = Address(clobber, slot * sizeof(Value));
105 loadValueAsComponents(address, type, data);
108 template <typename T>
109 void loadValue(T address, RegisterID dst) {
110 loadPtr(address, dst);
113 void convertValueToType(RegisterID val) {
114 andPtr(Registers::TypeMaskReg, val);
117 void convertValueToPayload(RegisterID val) {
118 andPtr(Registers::PayloadMaskReg, val);
121 // Returns a label after the one Value load.
122 template <typename T>
123 Label loadValueAsComponents(T address, RegisterID type, RegisterID payload) {
124 loadValue(address, type);
125 Label l = label();
127 move(Registers::PayloadMaskReg, payload);
128 andPtr(type, payload);
129 xorPtr(payload, type);
131 return l;
134 void loadValueAsComponents(const Value &val, RegisterID type, RegisterID payload) {
135 move(Imm64(val.asRawBits() & JSVAL_TAG_MASK), type);
136 move(Imm64(val.asRawBits() & JSVAL_PAYLOAD_MASK), payload);
139 template <typename T>
140 void storeValueFromComponents(RegisterID type, RegisterID payload, T address) {
141 move(type, Registers::ValueReg);
142 orPtr(payload, Registers::ValueReg);
143 storeValue(Registers::ValueReg, address);
146 template <typename T>
147 void storeValueFromComponents(ImmTag type, RegisterID payload, T address) {
148 move(type, Registers::ValueReg);
149 orPtr(payload, Registers::ValueReg);
150 storeValue(Registers::ValueReg, address);
153 template <typename T>
154 void loadTypeTag(T address, RegisterID reg) {
155 loadValue(address, reg);
156 convertValueToType(reg);
159 template <typename T>
160 void storeTypeTag(ImmTag imm, T address) {
161 loadPayload(address, Registers::ValueReg);
162 orPtr(imm, Registers::ValueReg);
163 storePtr(Registers::ValueReg, valueOf(address));
166 template <typename T>
167 void storeTypeTag(RegisterID reg, T address) {
168 /* The type tag must be stored in shifted format. */
169 loadPayload(address, Registers::ValueReg);
170 orPtr(reg, Registers::ValueReg);
171 storePtr(Registers::ValueReg, valueOf(address));
174 template <typename T>
175 void loadPayload(T address, RegisterID reg) {
176 loadValue(address, reg);
177 convertValueToPayload(reg);
180 template <typename T>
181 void storePayload(RegisterID reg, T address) {
182 /* Not for doubles. */
183 loadTypeTag(address, Registers::ValueReg);
184 orPtr(reg, Registers::ValueReg);
185 storePtr(Registers::ValueReg, valueOf(address));
188 template <typename T>
189 void storePayload(ImmPayload imm, T address) {
190 /* Not for doubles. */
191 storePtr(imm, valueOf(address));
194 template <typename T>
195 void storeValue(RegisterID reg, T address) {
196 storePtr(reg, valueOf(address));
199 template <typename T>
200 void storeValue(const Value &v, T address) {
201 jsval_layout jv;
202 jv.asBits = JSVAL_BITS(Jsvalify(v));
204 storePtr(Imm64(jv.asBits), valueOf(address));
207 template <typename T>
208 void storeValue(const ValueRemat &vr, T address) {
209 if (vr.isConstant)
210 storeValue(Valueify(vr.u.v), address);
211 else if (vr.u.s.isTypeKnown)
212 storeValueFromComponents(ImmType(vr.u.s.type.knownType), vr.u.s.data, address);
213 else
214 storeValueFromComponents(vr.u.s.type.reg, vr.u.s.data, address);
217 void loadPrivate(Address privAddr, RegisterID to) {
218 loadPtr(privAddr, to);
219 lshiftPtr(Imm32(1), to);
222 void loadFunctionPrivate(RegisterID base, RegisterID to) {
223 Address priv(base, offsetof(JSObject, privateData));
224 loadPtr(priv, to);
227 Jump testNull(Assembler::Condition cond, RegisterID reg) {
228 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_NULL));
231 Jump testNull(Assembler::Condition cond, Address address) {
232 loadValue(address, Registers::ValueReg);
233 return testNull(cond, Registers::ValueReg);
236 Jump testUndefined(Assembler::Condition cond, RegisterID reg) {
237 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_UNDEFINED));
240 Jump testUndefined(Assembler::Condition cond, Address address) {
241 loadValue(address, Registers::ValueReg);
242 return testUndefined(cond, Registers::ValueReg);
245 Jump testInt32(Assembler::Condition cond, RegisterID reg) {
246 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_INT32));
249 Jump testInt32(Assembler::Condition cond, Address address) {
250 loadTypeTag(address, Registers::ValueReg);
251 return testInt32(cond, Registers::ValueReg);
254 Jump testNumber(Assembler::Condition cond, RegisterID reg) {
255 cond = (cond == Assembler::Equal) ? Assembler::Below : Assembler::AboveOrEqual;
256 return branchPtr(cond, reg,
257 ImmTag(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET));
260 Jump testNumber(Assembler::Condition cond, Address address) {
261 loadValue(address, Registers::ValueReg);
262 return testNumber(cond, Registers::ValueReg);
265 Jump testPrimitive(Assembler::Condition cond, RegisterID reg) {
266 cond = (cond == Assembler::Equal) ? Assembler::Below : Assembler::AboveOrEqual;
267 return branchPtr(cond, reg,
268 ImmTag(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET));
271 Jump testPrimitive(Assembler::Condition cond, Address address) {
272 loadValue(address, Registers::ValueReg);
273 return testPrimitive(cond, Registers::ValueReg);
276 Jump testObject(Assembler::Condition cond, RegisterID reg) {
277 cond = (cond == Assembler::Equal) ? Assembler::AboveOrEqual : Assembler::Below;
278 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_OBJECT));
281 Jump testObject(Assembler::Condition cond, Address address) {
282 loadValue(address, Registers::ValueReg);
283 return testObject(cond, Registers::ValueReg);
286 Jump testDouble(Assembler::Condition cond, RegisterID reg) {
287 cond = (cond == Assembler::Equal) ? Assembler::BelowOrEqual : Assembler::Above;
288 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_MAX_DOUBLE));
291 Jump testDouble(Assembler::Condition cond, Address address) {
292 loadValue(address, Registers::ValueReg);
293 return testDouble(cond, Registers::ValueReg);
296 Jump testBoolean(Assembler::Condition cond, RegisterID reg) {
297 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_BOOLEAN));
300 Jump testBoolean(Assembler::Condition cond, Address address) {
301 loadTypeTag(address, Registers::ValueReg);
302 return testBoolean(cond, Registers::ValueReg);
305 Jump testString(Assembler::Condition cond, RegisterID reg) {
306 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_STRING));
309 Jump testString(Assembler::Condition cond, Address address) {
310 loadTypeTag(address, Registers::ValueReg);
311 return testString(cond, Registers::ValueReg);
315 } /* namespace mjit */
316 } /* namespace js */
318 #endif