Refactor and improve GETELEM IC (bug 602641, r=dmandelin).
[mozilla-central.git] / js / src / methodjit / PunboxAssembler.h
blob0e14f5b3b904b5835e5a54fcdc6e414ae0860d52
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 "assembler/assembler/MacroAssembler.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 PunboxAssembler : public JSC::MacroAssembler
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 loadInlineSlot(RegisterID objReg, uint32 slot,
97 RegisterID typeReg, RegisterID dataReg) {
98 Address address(objReg, JSObject::getFixedSlotOffset(slot));
99 loadValueAsComponents(address, typeReg, dataReg);
102 template <typename T>
103 void loadValue(T address, RegisterID dst) {
104 loadPtr(address, dst);
107 void convertValueToType(RegisterID val) {
108 andPtr(Registers::TypeMaskReg, val);
111 void convertValueToPayload(RegisterID val) {
112 andPtr(Registers::PayloadMaskReg, val);
115 // Returns a label after the one Value load.
116 template <typename T>
117 Label loadValueAsComponents(T address, RegisterID type, RegisterID payload) {
118 loadValue(address, type);
119 Label l = label();
121 move(Registers::PayloadMaskReg, payload);
122 andPtr(type, payload);
123 xorPtr(payload, type);
125 return l;
128 void loadValueAsComponents(const Value &val, RegisterID type, RegisterID payload) {
129 move(Imm64(val.asRawBits() & JSVAL_TAG_MASK), type);
130 move(Imm64(val.asRawBits() & JSVAL_PAYLOAD_MASK), payload);
133 template <typename T>
134 void storeValueFromComponents(RegisterID type, RegisterID payload, T address) {
135 move(type, Registers::ValueReg);
136 orPtr(payload, Registers::ValueReg);
137 storeValue(Registers::ValueReg, address);
140 template <typename T>
141 void storeValueFromComponents(ImmTag type, RegisterID payload, T address) {
142 move(type, Registers::ValueReg);
143 orPtr(payload, Registers::ValueReg);
144 storeValue(Registers::ValueReg, address);
147 template <typename T>
148 void loadTypeTag(T address, RegisterID reg) {
149 loadValue(address, reg);
150 convertValueToType(reg);
153 template <typename T>
154 void storeTypeTag(ImmTag imm, T address) {
155 loadPayload(address, Registers::ValueReg);
156 orPtr(imm, Registers::ValueReg);
157 storePtr(Registers::ValueReg, valueOf(address));
160 template <typename T>
161 void storeTypeTag(RegisterID reg, T address) {
162 /* The type tag must be stored in shifted format. */
163 loadPayload(address, Registers::ValueReg);
164 orPtr(reg, Registers::ValueReg);
165 storePtr(Registers::ValueReg, valueOf(address));
168 template <typename T>
169 void loadPayload(T address, RegisterID reg) {
170 loadValue(address, reg);
171 convertValueToPayload(reg);
174 template <typename T>
175 void storePayload(RegisterID reg, T address) {
176 /* Not for doubles. */
177 loadTypeTag(address, Registers::ValueReg);
178 orPtr(reg, Registers::ValueReg);
179 storePtr(Registers::ValueReg, valueOf(address));
182 template <typename T>
183 void storePayload(ImmPayload imm, T address) {
184 /* Not for doubles. */
185 storePtr(imm, valueOf(address));
188 template <typename T>
189 void storeValue(RegisterID reg, T address) {
190 storePtr(reg, valueOf(address));
193 template <typename T>
194 void storeValue(const Value &v, T address) {
195 jsval_layout jv;
196 jv.asBits = JSVAL_BITS(Jsvalify(v));
198 storePtr(Imm64(jv.asBits), valueOf(address));
201 template <typename T>
202 void storeValue(const ValueRemat &vr, T address) {
203 if (vr.isConstant())
204 storeValue(vr.value(), address);
205 else if (vr.isTypeKnown())
206 storeValueFromComponents(ImmType(vr.knownType()), vr.dataReg(), address);
207 else
208 storeValueFromComponents(vr.typeReg(), vr.dataReg(), address);
211 void loadPrivate(Address privAddr, RegisterID to) {
212 loadPtr(privAddr, to);
213 lshiftPtr(Imm32(1), to);
216 void loadFunctionPrivate(RegisterID base, RegisterID to) {
217 Address priv(base, offsetof(JSObject, privateData));
218 loadPtr(priv, to);
221 Jump testNull(Condition cond, RegisterID reg) {
222 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_NULL));
225 Jump testNull(Condition cond, Address address) {
226 loadValue(address, Registers::ValueReg);
227 return testNull(cond, Registers::ValueReg);
230 Jump testUndefined(Condition cond, RegisterID reg) {
231 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_UNDEFINED));
234 Jump testUndefined(Condition cond, Address address) {
235 loadValue(address, Registers::ValueReg);
236 return testUndefined(cond, Registers::ValueReg);
239 Jump testInt32(Condition cond, RegisterID reg) {
240 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_INT32));
243 Jump testInt32(Condition cond, Address address) {
244 loadTypeTag(address, Registers::ValueReg);
245 return testInt32(cond, Registers::ValueReg);
248 Jump testNumber(Condition cond, RegisterID reg) {
249 cond = (cond == Equal) ? Below : AboveOrEqual;
250 return branchPtr(cond, reg,
251 ImmTag(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET));
254 Jump testNumber(Condition cond, Address address) {
255 loadValue(address, Registers::ValueReg);
256 return testNumber(cond, Registers::ValueReg);
259 Jump testPrimitive(Condition cond, RegisterID reg) {
260 cond = (cond == Equal) ? Below : AboveOrEqual;
261 return branchPtr(cond, reg,
262 ImmTag(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET));
265 Jump testPrimitive(Condition cond, Address address) {
266 loadValue(address, Registers::ValueReg);
267 return testPrimitive(cond, Registers::ValueReg);
270 Jump testObject(Condition cond, RegisterID reg) {
271 cond = (cond == Equal) ? AboveOrEqual : Below;
272 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_OBJECT));
275 Jump testObject(Condition cond, Address address) {
276 loadValue(address, Registers::ValueReg);
277 return testObject(cond, Registers::ValueReg);
280 Jump testDouble(Condition cond, RegisterID reg) {
281 cond = (cond == Equal) ? BelowOrEqual : Above;
282 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_MAX_DOUBLE));
285 Jump testDouble(Condition cond, Address address) {
286 loadValue(address, Registers::ValueReg);
287 return testDouble(cond, Registers::ValueReg);
290 Jump testBoolean(Condition cond, RegisterID reg) {
291 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_BOOLEAN));
294 Jump testBoolean(Condition cond, Address address) {
295 loadTypeTag(address, Registers::ValueReg);
296 return testBoolean(cond, Registers::ValueReg);
299 Jump testString(Condition cond, RegisterID reg) {
300 return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_STRING));
303 Jump testString(Condition cond, Address address) {
304 loadTypeTag(address, Registers::ValueReg);
305 return testString(cond, Registers::ValueReg);
308 template <typename T>
309 Jump fastArrayLoadSlot(T address, RegisterID typeReg, RegisterID dataReg) {
310 loadValueAsComponents(address, typeReg, dataReg);
311 return branchPtr(Equal, typeReg, ImmType(JSVAL_TYPE_MAGIC));
315 typedef PunboxAssembler ValueAssembler;
317 } /* namespace mjit */
318 } /* namespace js */
320 #endif