Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / methodjit / PunboxAssembler.h
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=4 sw=4 et tw=99:
3  *
4  * ***** BEGIN LICENSE BLOCK *****
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
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/
11  *
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.
16  *
17  * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18  * May 28, 2008.
19  *
20  * The Initial Developer of the Original Code is
21  *   Brendan Eich <brendan@mozilla.org>
22  *
23  * Contributor(s):
24  *   Sean Stangl <sstangl@mozilla.com>
25  *
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.
37  *
38  * ***** END LICENSE BLOCK ***** */
39
40 #if !defined jsjaeger_assembler64_h__ && defined JS_METHODJIT && defined JS_PUNBOX64
41 #define jsjaeger_assembler64_h__
42
43 #include "assembler/assembler/MacroAssembler.h"
44 #include "methodjit/MachineRegs.h"
45 #include "methodjit/RematInfo.h"
46 #include "jsnum.h"
47
48 namespace js {
49 namespace mjit {
50
51 struct Imm64 : JSC::MacroAssembler::ImmPtr
52 {
53     Imm64(uint64 u)
54       : ImmPtr((const void *)u)
55     { }
56 };
57
58 /* Tag stored in shifted format. */
59 struct ImmTag : JSC::MacroAssembler::ImmPtr
60 {
61     ImmTag(JSValueShiftedTag shtag)
62       : ImmPtr((const void *)shtag)
63     { }
64 };
65
66 struct ImmType : ImmTag
67 {
68     ImmType(JSValueType type)
69       : ImmTag(JSValueShiftedTag(JSVAL_TYPE_TO_SHIFTED_TAG(type)))
70     { }
71 };
72
73 struct ImmPayload : Imm64
74 {
75     ImmPayload(uint64 payload)
76       : Imm64(payload)
77     { }
78 };
79
80 class PunboxAssembler : public JSC::MacroAssembler
81 {
82     static const uint32 PAYLOAD_OFFSET = 0;
83
84   public:
85     static const JSC::MacroAssembler::Scale JSVAL_SCALE = JSC::MacroAssembler::TimesEight;
86
87     template <typename T>
88     T payloadOf(T address) {
89         return address;
90     }
91
92     template <typename T>
93     T valueOf(T address) {
94         return address;
95     }
96
97     void loadInlineSlot(RegisterID objReg, uint32 slot,
98                         RegisterID typeReg, RegisterID dataReg) {
99         Address address(objReg, JSObject::getFixedSlotOffset(slot));
100         loadValueAsComponents(address, typeReg, dataReg);
101     }
102
103     template <typename T>
104     void loadValue(T address, RegisterID dst) {
105         loadPtr(address, dst);
106     }
107
108     void convertValueToType(RegisterID val) {
109         andPtr(Registers::TypeMaskReg, val);
110     }
111
112     void convertValueToPayload(RegisterID val) {
113         andPtr(Registers::PayloadMaskReg, val);
114     }
115
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);
120         Label l = label();
121
122         move(Registers::PayloadMaskReg, payload);
123         andPtr(type, payload);
124         xorPtr(payload, type);
125
126         return l;
127     }
128
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);
132     }
133
134     /*
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.
138      */
139     Label loadValueWithAddressOffsetPatch(Address address, RegisterID type, RegisterID payload) {
140         return loadValueAsComponents(address, type, payload);
141     }
142
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);
148     }
149
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);
155     }
156
157     /*
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.
161      */
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);
166     }
167
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);
173     }
174
175     /* Overload for constant type and constant data. */
176     DataLabel32 storeValueWithAddressOffsetPatch(const Value &v, Address address) {
177         jsval_layout jv;
178         jv.asBits = JSVAL_BITS(Jsvalify(v));
179
180         move(ImmPtr(reinterpret_cast<void*>(jv.asBits)), Registers::ValueReg);
181         return storePtrWithAddressOffsetPatch(Registers::ValueReg, valueOf(address));
182     }
183
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);
192         } else {
193             RegisterID type(vr.typeReg());
194             RegisterID data(vr.dataReg());
195             return storeValueWithAddressOffsetPatch(type, data, address);
196         }
197     }
198
199     template <typename T>
200     void loadTypeTag(T address, RegisterID reg) {
201         loadValue(address, reg);
202         convertValueToType(reg);
203     }
204
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));
210     }
211
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));
218     }
219
220     template <typename T>
221     void loadPayload(T address, RegisterID reg) {
222         loadValue(address, reg);
223         convertValueToPayload(reg);
224     }
225
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));
232     }
233     
234     template <typename T>
235     void storePayload(ImmPayload imm, T address) {
236         /* Not for doubles. */
237         storePtr(imm, valueOf(address));
238     }
239
240     template <typename T>
241     void storeValue(RegisterID reg, T address) {
242         storePtr(reg, valueOf(address));
243     }
244
245     template <typename T>
246     void storeValue(const Value &v, T address) {
247         jsval_layout jv;
248         jv.asBits = JSVAL_BITS(Jsvalify(v));
249
250         storePtr(Imm64(jv.asBits), valueOf(address));
251     }
252
253     template <typename T>
254     void storeValue(const ValueRemat &vr, T address) {
255         if (vr.isConstant())
256             storeValue(vr.value(), address);
257         else if (vr.isTypeKnown())
258             storeValueFromComponents(ImmType(vr.knownType()), vr.dataReg(), address);
259         else
260             storeValueFromComponents(vr.typeReg(), vr.dataReg(), address);
261     }
262
263     template <typename T>
264     Jump guardNotHole(T address) {
265         loadTypeTag(address, Registers::ValueReg);
266         return branchPtr(Equal, Registers::ValueReg, ImmType(JSVAL_TYPE_MAGIC));
267     }
268
269     void loadPrivate(Address privAddr, RegisterID to) {
270         loadPtr(privAddr, to);
271         lshiftPtr(Imm32(1), to);
272     }
273
274     void loadObjPrivate(RegisterID base, RegisterID to) {
275         Address priv(base, offsetof(JSObject, privateData));
276         loadPtr(priv, to);
277     }
278
279     Jump testNull(Condition cond, RegisterID reg) {
280         return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_NULL));
281     }
282
283     Jump testNull(Condition cond, Address address) {
284         loadValue(address, Registers::ValueReg);
285         return testNull(cond, Registers::ValueReg);
286     }
287
288     Jump testUndefined(Condition cond, RegisterID reg) {
289         return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_UNDEFINED));
290     }
291
292     Jump testUndefined(Condition cond, Address address) {
293         loadValue(address, Registers::ValueReg);
294         return testUndefined(cond, Registers::ValueReg);
295     }
296
297     Jump testInt32(Condition cond, RegisterID reg) {
298         return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_INT32));
299     }
300
301     Jump testInt32(Condition cond, Address address) {
302         loadTypeTag(address, Registers::ValueReg);
303         return testInt32(cond, Registers::ValueReg);
304     }
305
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));
310     }
311
312     Jump testNumber(Condition cond, Address address) {
313         loadValue(address, Registers::ValueReg);
314         return testNumber(cond, Registers::ValueReg);
315     }
316
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));
321     }
322
323     Jump testPrimitive(Condition cond, Address address) {
324         loadValue(address, Registers::ValueReg);
325         return testPrimitive(cond, Registers::ValueReg);
326     }
327
328     Jump testObject(Condition cond, RegisterID reg) {
329         cond = (cond == Equal) ? AboveOrEqual : Below;
330         return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_OBJECT));
331     }
332
333     Jump testObject(Condition cond, Address address) {
334         loadValue(address, Registers::ValueReg);
335         return testObject(cond, Registers::ValueReg);
336     }
337
338     Jump testDouble(Condition cond, RegisterID reg) {
339         cond = (cond == Equal) ? BelowOrEqual : Above;
340         return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_MAX_DOUBLE));
341     }
342
343     Jump testDouble(Condition cond, Address address) {
344         loadValue(address, Registers::ValueReg);
345         return testDouble(cond, Registers::ValueReg);
346     }
347
348     Jump testBoolean(Condition cond, RegisterID reg) {
349         return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_BOOLEAN));
350     }
351
352     Jump testBoolean(Condition cond, Address address) {
353         loadTypeTag(address, Registers::ValueReg);
354         return testBoolean(cond, Registers::ValueReg);
355     }
356
357     Jump testString(Condition cond, RegisterID reg) {
358         return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_STRING));
359     }
360
361     Jump testString(Condition cond, Address address) {
362         loadTypeTag(address, Registers::ValueReg);
363         return testString(cond, Registers::ValueReg);
364     }
365
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);
371     }
372
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);
377     }
378
379     void loadStaticDouble(const double *dp, FPRegisterID dest, RegisterID scratch) {
380         jsdpun du;
381         du.d = *dp;
382         move(ImmPtr(reinterpret_cast<void*>(du.u64)), scratch);
383         m_assembler.movq_rr(scratch, dest);
384     }
385
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));
390     }
391 };
392
393 typedef PunboxAssembler ValueAssembler;
394
395 } /* namespace mjit */
396 } /* namespace js */
397
398 #endif
399