Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / methodjit / ICLabels.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  *   David Mandelin <dmandelin@mozilla.com>
25  *   David Anderson <danderson@mozilla.com>
26  *   Chris Leary <cdleary@mozilla.com>
27  *   Jacob Bramley <Jacob.Bramely@arm.com>
28  *
29  * Alternatively, the contents of this file may be used under the terms of
30  * either of the GNU General Public License Version 2 or later (the "GPL"),
31  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32  * in which case the provisions of the GPL or the LGPL are applicable instead
33  * of those above. If you wish to allow use of your version of this file only
34  * under the terms of either the GPL or the LGPL, and not to allow others to
35  * use your version of this file under the terms of the MPL, indicate your
36  * decision by deleting the provisions above and replace them with the notice
37  * and other provisions required by the GPL or the LGPL. If you do not delete
38  * the provisions above, a recipient may use your version of this file under
39  * the terms of any one of the MPL, the GPL or the LGPL.
40  *
41  * ***** END LICENSE BLOCK ***** */
42
43 #if !defined jsjaeger_ic_labels_h__ && defined JS_METHODJIT
44 #define jsjaeger_ic_labels_h__
45
46 #include "methodjit/BaseCompiler.h"
47
48 class ICOffsetInitializer {
49   public:
50     ICOffsetInitializer();
51 };
52
53 namespace js {
54 namespace mjit {
55 namespace ic {
56
57 /*
58  * On x64 and ARM, we record offsets into the labels data structures at runtime
59  * instead of using hardcoded offsets into the instruction stream, as we do on
60  * x86.
61  *
62  * This is done on x64 because of variable-width instruction encoding when
63  * using the extended register set. It is done on ARM for ease of
64  * implementation.
65  */
66
67 #if defined JS_CPU_X64 || defined JS_CPU_ARM
68 # define JS_HAS_IC_LABELS
69 #endif
70
71 /* GetPropCompiler */
72 struct GetPropLabels : MacroAssemblerTypedefs {
73     friend class ::ICOffsetInitializer;
74
75     void setValueLoad(MacroAssembler &masm, Label fastPathRejoin, Label fastValueLoad) {
76         int offset = masm.differenceBetween(fastPathRejoin, fastValueLoad);
77 #ifdef JS_HAS_IC_LABELS
78         inlineValueLoadOffset = offset;
79 #endif
80         /* 
81          * Note: the offset between the type and data loads for x86 is asserted
82          * in NunboxAssembler::loadValueWithAddressOffsetPatch.
83          */
84         JS_ASSERT(offset == inlineValueLoadOffset);
85         (void) offset;
86     }
87
88     CodeLocationLabel getValueLoad(CodeLocationLabel fastPathRejoin) {
89         return fastPathRejoin.labelAtOffset(inlineValueLoadOffset);
90     }
91
92     void setDslotsLoad(MacroAssembler &masm, Label fastPathRejoin, Label dslotsLoad) {
93         int offset = masm.differenceBetween(fastPathRejoin, dslotsLoad);
94         setDslotsLoadOffset(offset);
95     }
96
97     CodeLocationInstruction getDslotsLoad(CodeLocationLabel fastPathRejoin) {
98         return fastPathRejoin.instructionAtOffset(getDslotsLoadOffset());
99     }
100
101     void setInlineShapeData(MacroAssembler &masm, Label shapeGuard, DataLabel32 inlineShape) {
102         int offset = masm.differenceBetween(shapeGuard, inlineShape);
103         setInlineShapeOffset(offset);
104     }
105
106     CodeLocationDataLabel32 getInlineShapeData(CodeLocationLabel fastShapeGuard) {
107         return fastShapeGuard.dataLabel32AtOffset(getInlineShapeOffset());
108     }
109
110     /*
111      * Note: on x64, the base is the inlineShapeLabel DataLabel32, whereas on other
112      * platforms the base is the shapeGuard.
113      */
114     template <typename T>
115     void setInlineShapeJump(MacroAssembler &masm, T base, Label afterJump) {
116         setInlineShapeJumpOffset(masm.differenceBetween(base, afterJump));
117     }
118
119     CodeLocationJump getInlineShapeJump(CodeLocationLabel fastShapeGuard) {
120         return fastShapeGuard.jumpAtOffset(getInlineShapeJumpOffset());
121     }
122
123     void setInlineTypeJump(MacroAssembler &masm, Label fastPathStart, Label afterTypeJump) {
124         int offset = masm.differenceBetween(fastPathStart, afterTypeJump);
125         setInlineTypeJumpOffset(offset);
126     }
127
128     CodeLocationJump getInlineTypeJump(CodeLocationLabel fastPathStart) {
129         return fastPathStart.jumpAtOffset(getInlineTypeJumpOffset());
130     }
131
132     void setStubShapeJump(MacroAssembler &masm, Label stubStart, Label shapeJump) {
133         int offset = masm.differenceBetween(stubStart, shapeJump);
134         setStubShapeJumpOffset(offset);
135     }
136
137     /* Offset-based interface */
138
139     void setDslotsLoadOffset(int offset) {
140 #ifdef JS_HAS_IC_LABELS
141         dslotsLoadOffset = offset;
142 #endif
143         JS_ASSERT(offset == dslotsLoadOffset);
144     }
145
146     void setInlineShapeOffset(int offset) {
147 #ifdef JS_HAS_IC_LABELS
148         inlineShapeOffset = offset;
149 #endif
150         JS_ASSERT(offset == inlineShapeOffset);
151     }
152     
153     void setStubShapeJumpOffset(int offset) {
154 #ifdef JS_HAS_IC_LABELS
155         stubShapeJumpOffset = offset;
156 #endif
157         JS_ASSERT(offset == stubShapeJumpOffset);
158     }
159
160     int getInlineShapeJumpOffset() {
161 #if defined JS_CPU_X64
162         return getInlineShapeOffset() + INLINE_SHAPE_JUMP;
163 #else
164         return POST_INST_OFFSET(INLINE_SHAPE_JUMP);
165 #endif
166     }
167
168     void setInlineShapeJumpOffset(int offset) {
169         JS_ASSERT(INLINE_SHAPE_JUMP == offset);
170     }
171
172     int getInlineTypeJumpOffset() {
173 #if defined JS_CPU_X86 || defined JS_CPU_X64
174         return INLINE_TYPE_JUMP;
175 #elif defined JS_CPU_ARM
176         return POST_INST_OFFSET(inlineTypeJumpOffset);
177 #endif
178     }
179
180     void setInlineTypeJumpOffset(int offset) {
181 #if defined JS_CPU_X86 || defined JS_CPU_X64
182         JS_ASSERT(INLINE_TYPE_JUMP == offset);
183 #elif defined JS_CPU_ARM
184         inlineTypeJumpOffset = offset;
185         JS_ASSERT(offset == inlineTypeJumpOffset);
186 #endif
187      }
188
189     int getInlineShapeOffset() {
190         return inlineShapeOffset;
191     }
192     int getDslotsLoadOffset() {
193         return dslotsLoadOffset;
194     }
195     int getStubShapeJumpOffset() {
196         return POST_INST_OFFSET(stubShapeJumpOffset);
197     }
198
199   private:
200     /* Offset from storeBack to beginning of 'mov dslots, addr' */
201     int32 dslotsLoadOffset : 8;
202
203     /* Offset from shapeGuard to end of shape comparison. */
204     int32 inlineShapeOffset : 8;
205
206     /* Offset from storeBack to end of value load. */
207     int32 inlineValueLoadOffset : 8;
208
209     /* 
210      * Offset from lastStubStart to end of shape jump.
211      * TODO: We can redefine the location of lastStubStart to be
212      * after the jump -- at which point this is always 0.
213      */
214     int32 stubShapeJumpOffset : 8;
215
216 #if defined JS_CPU_X86 
217     static const int32 INLINE_SHAPE_JUMP = 12;
218     static const int32 INLINE_TYPE_JUMP = 12;
219 #elif defined JS_CPU_X64
220     static const int32 INLINE_SHAPE_JUMP = 6;
221     static const int32 INLINE_TYPE_JUMP = 19;
222 #elif defined JS_CPU_ARM
223     /* Offset from the shape guard start to the shape guard jump. */
224     static const int32 INLINE_SHAPE_JUMP = 12;
225
226     /* Offset from the fast path to the type guard jump. */
227     int32 inlineTypeJumpOffset : 8;
228 #endif
229 };
230
231 /* SetPropCompiler */
232 struct SetPropLabels : MacroAssemblerTypedefs {
233     friend class ::ICOffsetInitializer;
234
235     void setInlineValueStore(MacroAssembler &masm, Label fastPathRejoin, DataLabel32 inlineValueStore,
236                              const ValueRemat &vr) {
237         int offset = masm.differenceBetween(fastPathRejoin, inlineValueStore);
238         setInlineValueStoreOffset(offset, vr.isConstant(), vr.isTypeKnown());
239     }
240
241     CodeLocationLabel getInlineValueStore(CodeLocationLabel fastPathRejoin, const ValueRemat &vr) {
242         return fastPathRejoin.labelAtOffset(getInlineValueStoreOffset(vr.isConstant(),
243                                                                       vr.isTypeKnown()));
244     }
245
246     void setInlineShapeData(MacroAssembler &masm, Label shapeGuard, DataLabel32 inlineShapeData) {
247         int offset = masm.differenceBetween(shapeGuard, inlineShapeData);
248         setInlineShapeDataOffset(offset);
249     }
250
251     CodeLocationDataLabel32 getInlineShapeData(CodeLocationLabel fastPathStart, int shapeGuardOffset) {
252         return fastPathStart.dataLabel32AtOffset(shapeGuardOffset + getInlineShapeDataOffset());
253     }
254
255     void setDslotsLoad(MacroAssembler &masm, Label fastPathRejoin, Label beforeLoad,
256                        const ValueRemat &rhs) {
257         int offset = masm.differenceBetween(fastPathRejoin, beforeLoad);
258         setDslotsLoadOffset(offset, rhs.isConstant(), rhs.isTypeKnown());
259     }
260
261     CodeLocationInstruction getDslotsLoad(CodeLocationLabel fastPathRejoin, const ValueRemat &vr) {
262         return fastPathRejoin.instructionAtOffset(getDslotsLoadOffset(vr));
263     }
264
265     void setInlineShapeJump(MacroAssembler &masm, Label shapeGuard, Label afterJump) {
266         setInlineShapeJumpOffset(masm.differenceBetween(shapeGuard, afterJump));
267     }
268
269     CodeLocationJump getInlineShapeJump(CodeLocationLabel shapeGuard) {
270         return shapeGuard.jumpAtOffset(getInlineShapeJumpOffset());
271     }
272
273     void setStubShapeJump(MacroAssembler &masm, Label stubStart, Label afterShapeJump) {
274         int offset = masm.differenceBetween(stubStart, afterShapeJump);
275         setStubShapeJumpOffset(offset);
276     }
277
278     CodeLocationJump getStubShapeJump(CodeLocationLabel stubStart) {
279         return stubStart.jumpAtOffset(getStubShapeJumpOffset());
280     }
281
282   private:
283
284     /* Offset-based interface. */
285
286     void setDslotsLoadOffset(int offset, bool isConstant, bool isTypeKnown) {
287 #if defined JS_HAS_IC_LABELS
288         dslotsLoadOffset = offset;
289         JS_ASSERT(offset == dslotsLoadOffset);
290 #elif defined JS_CPU_X86
291         JS_ASSERT_IF(isConstant, offset == INLINE_DSLOTS_BEFORE_CONSTANT);
292         JS_ASSERT_IF(isTypeKnown && !isConstant, offset == INLINE_DSLOTS_BEFORE_KTYPE);
293         JS_ASSERT_IF(!isTypeKnown, offset == INLINE_DSLOTS_BEFORE_DYNAMIC);
294 #else
295 # error
296 #endif
297     }
298
299     int getDslotsLoadOffset(const ValueRemat &vr) {
300 #if defined JS_CPU_X86
301         if (vr.isConstant())
302             return INLINE_DSLOTS_BEFORE_CONSTANT;
303         if (vr.isTypeKnown())
304             return INLINE_DSLOTS_BEFORE_KTYPE;
305         return INLINE_DSLOTS_BEFORE_DYNAMIC;
306 #else
307         (void) vr;
308         return dslotsLoadOffset;
309 #endif
310     }
311
312     void setInlineShapeDataOffset(int offset) {
313 #ifdef JS_HAS_IC_LABELS
314         inlineShapeDataOffset = offset;
315 #endif
316         JS_ASSERT(offset == inlineShapeDataOffset);
317     }
318
319     void setStubShapeJumpOffset(int offset) {
320 #ifdef JS_HAS_IC_LABELS
321         stubShapeJumpOffset = offset;
322 #endif
323         JS_ASSERT(offset == stubShapeJumpOffset);
324     }
325
326     void setInlineValueStoreOffset(int offset, bool isConstant, bool isTypeKnown) {
327 #ifdef JS_HAS_IC_LABELS
328         inlineValueStoreOffset = offset;
329         JS_ASSERT(offset == inlineValueStoreOffset);
330 #elif defined JS_CPU_X86
331         JS_ASSERT_IF(isConstant, offset == INLINE_VALUE_STORE_CONSTANT);
332         JS_ASSERT_IF(isTypeKnown && !isConstant, offset == INLINE_VALUE_STORE_KTYPE);
333         JS_ASSERT_IF(!isTypeKnown && !isConstant, offset == INLINE_VALUE_STORE_DYNAMIC);
334 #endif
335     }
336
337     void setInlineShapeJumpOffset(int offset) {
338 #ifdef JS_HAS_IC_LABELS
339         inlineShapeJumpOffset = offset;
340 #endif
341         JS_ASSERT(offset == inlineShapeJumpOffset);
342     }
343
344     int getInlineShapeJumpOffset() {
345         return POST_INST_OFFSET(inlineShapeJumpOffset);
346     }
347
348     int getInlineShapeDataOffset() {
349         return inlineShapeDataOffset;
350     }
351
352     int getStubShapeJumpOffset() {
353         return POST_INST_OFFSET(stubShapeJumpOffset);
354     }
355
356     int getInlineValueStoreOffset(bool isConstant, bool isTypeKnown) {
357 #ifdef JS_HAS_IC_LABELS
358         return inlineValueStoreOffset;
359 #elif defined JS_CPU_X86
360         if (isConstant)
361             return INLINE_VALUE_STORE_CONSTANT;
362         else if (isTypeKnown)
363             return INLINE_VALUE_STORE_KTYPE;
364         else
365             return INLINE_VALUE_STORE_DYNAMIC;
366 #endif
367     }
368
369     /* Offset from storeBack to beginning of 'mov dslots, addr'. */
370 #if defined JS_CPU_X86
371     static const int INLINE_DSLOTS_BEFORE_CONSTANT = -23;
372     static const int INLINE_DSLOTS_BEFORE_KTYPE = -19;
373     static const int INLINE_DSLOTS_BEFORE_DYNAMIC = -15;
374 #else
375     int32 dslotsLoadOffset : 8;
376 #endif
377
378     /* Offset from shapeGuard to end of shape comparison. */
379     int32 inlineShapeDataOffset : 8;
380
381     /* 
382      * Offset from lastStubStart to end of shape jump.
383      * TODO: We can redefine the location of lastStubStart to be
384      * after the jump -- at which point this is always 0.
385      */
386     int32 stubShapeJumpOffset : 8;
387
388 #if defined JS_CPU_X86
389     static const int INLINE_VALUE_STORE_CONSTANT = -20;
390     static const int INLINE_VALUE_STORE_KTYPE = -16;
391     static const int INLINE_VALUE_STORE_DYNAMIC = -12;
392 #else
393     int32 inlineValueStoreOffset : 8;
394 #endif
395
396     /* Offset from shapeGuard to the end of the shape jump. */
397     int32 inlineShapeJumpOffset : 8;
398 };
399
400 /* BindNameCompiler */
401 struct BindNameLabels : MacroAssemblerTypedefs {
402     friend class ::ICOffsetInitializer;
403
404     void setInlineJumpOffset(int offset) {
405 #ifdef JS_HAS_IC_LABELS
406         inlineJumpOffset = offset;
407 #endif
408         JS_ASSERT(offset == inlineJumpOffset);
409     }
410
411     void setInlineJump(MacroAssembler &masm, Label shapeGuard, Jump inlineJump) {
412         int offset = masm.differenceBetween(shapeGuard, inlineJump);
413         setInlineJumpOffset(offset);
414     }
415
416     CodeLocationJump getInlineJump(CodeLocationLabel fastPathStart) {
417         return fastPathStart.jumpAtOffset(getInlineJumpOffset());
418     }
419
420     int getInlineJumpOffset() {
421         return inlineJumpOffset;
422     }
423
424     void setStubJumpOffset(int offset) {
425 #ifdef JS_HAS_IC_LABELS
426         stubJumpOffset = offset;
427 #endif
428         JS_ASSERT(offset == stubJumpOffset);
429     }
430
431     void setStubJump(MacroAssembler &masm, Label stubStart, Jump stubJump) {
432         int offset = masm.differenceBetween(stubStart, stubJump);
433         setStubJumpOffset(offset);
434     }
435
436     CodeLocationJump getStubJump(CodeLocationLabel lastStubStart) {
437         return lastStubStart.jumpAtOffset(getStubJumpOffset());
438     }
439
440     int getStubJumpOffset() {
441         return stubJumpOffset;
442     }
443
444   private:
445     /* Offset from shapeGuard to end of shape jump. */
446     int32 inlineJumpOffset : 8;
447
448     /* Offset from lastStubStart to end of the shape jump. */
449     int32 stubJumpOffset : 8;
450 };
451
452 /* ScopeNameCompiler */
453 struct ScopeNameLabels : MacroAssemblerTypedefs {
454     friend class ::ICOffsetInitializer;
455
456     void setInlineJumpOffset(int offset) {
457 #ifdef JS_HAS_IC_LABELS
458         inlineJumpOffset = offset;
459 #endif
460         JS_ASSERT(offset == inlineJumpOffset);
461     }
462
463     void setInlineJump(MacroAssembler &masm, Label fastPathStart, Jump inlineJump) {
464         int offset = masm.differenceBetween(fastPathStart, inlineJump);
465         setInlineJumpOffset(offset);
466     }
467
468     CodeLocationJump getInlineJump(CodeLocationLabel fastPathStart) {
469         return fastPathStart.jumpAtOffset(getInlineJumpOffset());
470     }
471
472     int getInlineJumpOffset() {
473         return inlineJumpOffset;
474     }
475
476     void setStubJumpOffset(int offset) {
477 #ifdef JS_HAS_IC_LABELS
478         stubJumpOffset = offset;
479 #endif
480         JS_ASSERT(offset == stubJumpOffset);
481     }
482
483     void setStubJump(MacroAssembler &masm, Label stubStart, Jump stubJump) {
484         int offset = masm.differenceBetween(stubStart, stubJump);
485         setStubJumpOffset(offset);
486     }
487
488     CodeLocationJump getStubJump(CodeLocationLabel lastStubStart) {
489         return lastStubStart.jumpAtOffset(getStubJumpOffset());
490     }
491
492     int getStubJumpOffset() {
493         return stubJumpOffset;
494     }
495
496   private:
497     /* Offset from fastPathStart to end of shape jump. */
498     int32 inlineJumpOffset : 8;
499
500     /* Offset from lastStubStart to end of the shape jump. */
501     int32 stubJumpOffset : 8;
502 };
503
504 } /* namespace ic */
505 } /* namespace mjit */
506 } /* namespace js */
507
508 #endif /* jsjaeger_ic_labels_h__ */