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, DataLabel32 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__ */