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 * David Mandelin <dmandelin@mozilla.com>
25 * David Anderson <danderson@mozilla.com>
26 * Chris Leary <cdleary@mozilla.com>
27 * Jacob Bramley <Jacob.Bramely@arm.com>
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.
41 * ***** END LICENSE BLOCK ***** */
43 #if !defined jsjaeger_ic_labels_h__ && defined JS_METHODJIT
44 #define jsjaeger_ic_labels_h__
46 #include "methodjit/BaseCompiler.h"
48 class ICOffsetInitializer
{
50 ICOffsetInitializer();
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
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
67 #if defined JS_CPU_X64 || defined JS_CPU_ARM
68 # define JS_HAS_IC_LABELS
72 struct GetPropLabels
: MacroAssemblerTypedefs
{
73 friend class ::ICOffsetInitializer
;
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
;
81 * Note: the offset between the type and data loads for x86 is asserted
82 * in NunboxAssembler::loadValueWithAddressOffsetPatch.
84 JS_ASSERT(offset
== inlineValueLoadOffset
);
88 CodeLocationLabel
getValueLoad(CodeLocationLabel fastPathRejoin
) {
89 return fastPathRejoin
.labelAtOffset(inlineValueLoadOffset
);
92 void setDslotsLoad(MacroAssembler
&masm
, Label fastPathRejoin
, Label dslotsLoad
) {
93 int offset
= masm
.differenceBetween(fastPathRejoin
, dslotsLoad
);
94 setDslotsLoadOffset(offset
);
97 CodeLocationInstruction
getDslotsLoad(CodeLocationLabel fastPathRejoin
) {
98 return fastPathRejoin
.instructionAtOffset(getDslotsLoadOffset());
101 void setInlineShapeData(MacroAssembler
&masm
, Label shapeGuard
, DataLabel32 inlineShape
) {
102 int offset
= masm
.differenceBetween(shapeGuard
, inlineShape
);
103 setInlineShapeOffset(offset
);
106 CodeLocationDataLabel32
getInlineShapeData(CodeLocationLabel fastShapeGuard
) {
107 return fastShapeGuard
.dataLabel32AtOffset(getInlineShapeOffset());
111 * Note: on x64, the base is the inlineShapeLabel DataLabel32, whereas on other
112 * platforms the base is the shapeGuard.
114 template <typename T
>
115 void setInlineShapeJump(MacroAssembler
&masm
, T base
, Label afterJump
) {
116 setInlineShapeJumpOffset(masm
.differenceBetween(base
, afterJump
));
119 CodeLocationJump
getInlineShapeJump(CodeLocationLabel fastShapeGuard
) {
120 return fastShapeGuard
.jumpAtOffset(getInlineShapeJumpOffset());
123 void setInlineTypeJump(MacroAssembler
&masm
, Label fastPathStart
, Label afterTypeJump
) {
124 int offset
= masm
.differenceBetween(fastPathStart
, afterTypeJump
);
125 setInlineTypeJumpOffset(offset
);
128 CodeLocationJump
getInlineTypeJump(CodeLocationLabel fastPathStart
) {
129 return fastPathStart
.jumpAtOffset(getInlineTypeJumpOffset());
132 void setStubShapeJump(MacroAssembler
&masm
, Label stubStart
, Label shapeJump
) {
133 int offset
= masm
.differenceBetween(stubStart
, shapeJump
);
134 setStubShapeJumpOffset(offset
);
137 /* Offset-based interface */
139 void setDslotsLoadOffset(int offset
) {
140 #ifdef JS_HAS_IC_LABELS
141 dslotsLoadOffset
= offset
;
143 JS_ASSERT(offset
== dslotsLoadOffset
);
146 void setInlineShapeOffset(int offset
) {
147 #ifdef JS_HAS_IC_LABELS
148 inlineShapeOffset
= offset
;
150 JS_ASSERT(offset
== inlineShapeOffset
);
153 void setStubShapeJumpOffset(int offset
) {
154 #ifdef JS_HAS_IC_LABELS
155 stubShapeJumpOffset
= offset
;
157 JS_ASSERT(offset
== stubShapeJumpOffset
);
160 int getInlineShapeJumpOffset() {
161 #if defined JS_CPU_X64
162 return getInlineShapeOffset() + INLINE_SHAPE_JUMP
;
164 return POST_INST_OFFSET(INLINE_SHAPE_JUMP
);
168 void setInlineShapeJumpOffset(int offset
) {
169 JS_ASSERT(INLINE_SHAPE_JUMP
== offset
);
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
);
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
);
189 int getInlineShapeOffset() {
190 return inlineShapeOffset
;
192 int getDslotsLoadOffset() {
193 return dslotsLoadOffset
;
195 int getStubShapeJumpOffset() {
196 return POST_INST_OFFSET(stubShapeJumpOffset
);
200 /* Offset from storeBack to beginning of 'mov dslots, addr' */
201 int32 dslotsLoadOffset
: 8;
203 /* Offset from shapeGuard to end of shape comparison. */
204 int32 inlineShapeOffset
: 8;
206 /* Offset from storeBack to end of value load. */
207 int32 inlineValueLoadOffset
: 8;
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.
214 int32 stubShapeJumpOffset
: 8;
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;
226 /* Offset from the fast path to the type guard jump. */
227 int32 inlineTypeJumpOffset
: 8;
231 /* SetPropCompiler */
232 struct SetPropLabels
: MacroAssemblerTypedefs
{
233 friend class ::ICOffsetInitializer
;
235 void setInlineValueStore(MacroAssembler
&masm
, Label fastPathRejoin
, Label inlineValueStore
,
236 const ValueRemat
&vr
) {
237 int offset
= masm
.differenceBetween(fastPathRejoin
, inlineValueStore
);
238 setInlineValueStoreOffset(offset
, vr
.isConstant(), vr
.isTypeKnown());
241 CodeLocationLabel
getInlineValueStore(CodeLocationLabel fastPathRejoin
, const ValueRemat
&vr
) {
242 return fastPathRejoin
.labelAtOffset(getInlineValueStoreOffset(vr
.isConstant(),
246 void setInlineShapeData(MacroAssembler
&masm
, Label shapeGuard
, DataLabel32 inlineShapeData
) {
247 int offset
= masm
.differenceBetween(shapeGuard
, inlineShapeData
);
248 setInlineShapeDataOffset(offset
);
251 CodeLocationDataLabel32
getInlineShapeData(CodeLocationLabel fastPathStart
, int shapeGuardOffset
) {
252 return fastPathStart
.dataLabel32AtOffset(shapeGuardOffset
+ getInlineShapeDataOffset());
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());
261 CodeLocationInstruction
getDslotsLoad(CodeLocationLabel fastPathRejoin
, const ValueRemat
&vr
) {
262 return fastPathRejoin
.instructionAtOffset(getDslotsLoadOffset(vr
));
265 void setInlineShapeJump(MacroAssembler
&masm
, Label shapeGuard
, Label afterJump
) {
266 setInlineShapeJumpOffset(masm
.differenceBetween(shapeGuard
, afterJump
));
269 CodeLocationJump
getInlineShapeJump(CodeLocationLabel shapeGuard
) {
270 return shapeGuard
.jumpAtOffset(getInlineShapeJumpOffset());
273 void setStubShapeJump(MacroAssembler
&masm
, Label stubStart
, Label afterShapeJump
) {
274 int offset
= masm
.differenceBetween(stubStart
, afterShapeJump
);
275 setStubShapeJumpOffset(offset
);
278 CodeLocationJump
getStubShapeJump(CodeLocationLabel stubStart
) {
279 return stubStart
.jumpAtOffset(getStubShapeJumpOffset());
284 /* Offset-based interface. */
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
);
299 int getDslotsLoadOffset(const ValueRemat
&vr
) {
300 #if defined JS_CPU_X86
302 return INLINE_DSLOTS_BEFORE_CONSTANT
;
303 if (vr
.isTypeKnown())
304 return INLINE_DSLOTS_BEFORE_KTYPE
;
305 return INLINE_DSLOTS_BEFORE_DYNAMIC
;
308 return dslotsLoadOffset
;
312 void setInlineShapeDataOffset(int offset
) {
313 #ifdef JS_HAS_IC_LABELS
314 inlineShapeDataOffset
= offset
;
316 JS_ASSERT(offset
== inlineShapeDataOffset
);
319 void setStubShapeJumpOffset(int offset
) {
320 #ifdef JS_HAS_IC_LABELS
321 stubShapeJumpOffset
= offset
;
323 JS_ASSERT(offset
== stubShapeJumpOffset
);
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
);
337 void setInlineShapeJumpOffset(int offset
) {
338 #ifdef JS_HAS_IC_LABELS
339 inlineShapeJumpOffset
= offset
;
341 JS_ASSERT(offset
== inlineShapeJumpOffset
);
344 int getInlineShapeJumpOffset() {
345 return POST_INST_OFFSET(inlineShapeJumpOffset
);
348 int getInlineShapeDataOffset() {
349 return inlineShapeDataOffset
;
352 int getStubShapeJumpOffset() {
353 return POST_INST_OFFSET(stubShapeJumpOffset
);
356 int getInlineValueStoreOffset(bool isConstant
, bool isTypeKnown
) {
357 #ifdef JS_HAS_IC_LABELS
358 return inlineValueStoreOffset
;
359 #elif defined JS_CPU_X86
361 return INLINE_VALUE_STORE_CONSTANT
;
362 else if (isTypeKnown
)
363 return INLINE_VALUE_STORE_KTYPE
;
365 return INLINE_VALUE_STORE_DYNAMIC
;
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;
375 int32 dslotsLoadOffset
: 8;
378 /* Offset from shapeGuard to end of shape comparison. */
379 int32 inlineShapeDataOffset
: 8;
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.
386 int32 stubShapeJumpOffset
: 8;
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;
393 int32 inlineValueStoreOffset
: 8;
396 /* Offset from shapeGuard to the end of the shape jump. */
397 int32 inlineShapeJumpOffset
: 8;
400 /* BindNameCompiler */
401 struct BindNameLabels
: MacroAssemblerTypedefs
{
402 friend class ::ICOffsetInitializer
;
404 void setInlineJumpOffset(int offset
) {
405 #ifdef JS_HAS_IC_LABELS
406 inlineJumpOffset
= offset
;
408 JS_ASSERT(offset
== inlineJumpOffset
);
411 void setInlineJump(MacroAssembler
&masm
, Label shapeGuard
, Jump inlineJump
) {
412 int offset
= masm
.differenceBetween(shapeGuard
, inlineJump
);
413 setInlineJumpOffset(offset
);
416 CodeLocationJump
getInlineJump(CodeLocationLabel fastPathStart
) {
417 return fastPathStart
.jumpAtOffset(getInlineJumpOffset());
420 int getInlineJumpOffset() {
421 return inlineJumpOffset
;
424 void setStubJumpOffset(int offset
) {
425 #ifdef JS_HAS_IC_LABELS
426 stubJumpOffset
= offset
;
428 JS_ASSERT(offset
== stubJumpOffset
);
431 void setStubJump(MacroAssembler
&masm
, Label stubStart
, Jump stubJump
) {
432 int offset
= masm
.differenceBetween(stubStart
, stubJump
);
433 setStubJumpOffset(offset
);
436 CodeLocationJump
getStubJump(CodeLocationLabel lastStubStart
) {
437 return lastStubStart
.jumpAtOffset(getStubJumpOffset());
440 int getStubJumpOffset() {
441 return stubJumpOffset
;
445 /* Offset from shapeGuard to end of shape jump. */
446 int32 inlineJumpOffset
: 8;
448 /* Offset from lastStubStart to end of the shape jump. */
449 int32 stubJumpOffset
: 8;
452 /* ScopeNameCompiler */
453 struct ScopeNameLabels
: MacroAssemblerTypedefs
{
454 friend class ::ICOffsetInitializer
;
456 void setInlineJumpOffset(int offset
) {
457 #ifdef JS_HAS_IC_LABELS
458 inlineJumpOffset
= offset
;
460 JS_ASSERT(offset
== inlineJumpOffset
);
463 void setInlineJump(MacroAssembler
&masm
, Label fastPathStart
, Jump inlineJump
) {
464 int offset
= masm
.differenceBetween(fastPathStart
, inlineJump
);
465 setInlineJumpOffset(offset
);
468 CodeLocationJump
getInlineJump(CodeLocationLabel fastPathStart
) {
469 return fastPathStart
.jumpAtOffset(getInlineJumpOffset());
472 int getInlineJumpOffset() {
473 return inlineJumpOffset
;
476 void setStubJumpOffset(int offset
) {
477 #ifdef JS_HAS_IC_LABELS
478 stubJumpOffset
= offset
;
480 JS_ASSERT(offset
== stubJumpOffset
);
483 void setStubJump(MacroAssembler
&masm
, Label stubStart
, Jump stubJump
) {
484 int offset
= masm
.differenceBetween(stubStart
, stubJump
);
485 setStubJumpOffset(offset
);
488 CodeLocationJump
getStubJump(CodeLocationLabel lastStubStart
) {
489 return lastStubStart
.jumpAtOffset(getStubJumpOffset());
492 int getStubJumpOffset() {
493 return stubJumpOffset
;
497 /* Offset from fastPathStart to end of shape jump. */
498 int32 inlineJumpOffset
: 8;
500 /* Offset from lastStubStart to end of the shape jump. */
501 int32 stubJumpOffset
: 8;
505 } /* namespace mjit */
508 #endif /* jsjaeger_ic_labels_h__ */