Bug 625718: Correct SETPROP label offsets. (r=jbramley)
[mozilla-central.git] / js / src / methodjit / ICLabels.h
blobab3b15cede3e543205844df99652fb470df553c5
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 * 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 {
49 public:
50 ICOffsetInitializer();
53 namespace js {
54 namespace mjit {
55 namespace ic {
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.
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.
67 #if defined JS_CPU_X64 || defined JS_CPU_ARM
68 # define JS_HAS_IC_LABELS
69 #endif
71 /* GetPropCompiler */
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;
79 #endif
80 /*
81 * Note: the offset between the type and data loads for x86 is asserted
82 * in NunboxAssembler::loadValueWithAddressOffsetPatch.
84 JS_ASSERT(offset == inlineValueLoadOffset);
85 (void) offset;
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;
142 #endif
143 JS_ASSERT(offset == dslotsLoadOffset);
146 void setInlineShapeOffset(int offset) {
147 #ifdef JS_HAS_IC_LABELS
148 inlineShapeOffset = offset;
149 #endif
150 JS_ASSERT(offset == inlineShapeOffset);
153 void setStubShapeJumpOffset(int offset) {
154 #ifdef JS_HAS_IC_LABELS
155 stubShapeJumpOffset = offset;
156 #endif
157 JS_ASSERT(offset == stubShapeJumpOffset);
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
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);
177 #endif
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
189 int getInlineShapeOffset() {
190 return inlineShapeOffset;
192 int getDslotsLoadOffset() {
193 return dslotsLoadOffset;
195 int getStubShapeJumpOffset() {
196 return POST_INST_OFFSET(stubShapeJumpOffset);
199 private:
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;
228 #endif
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(),
243 vr.isTypeKnown()));
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());
282 private:
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);
294 #else
295 # error
296 #endif
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
312 void setInlineShapeDataOffset(int offset) {
313 #ifdef JS_HAS_IC_LABELS
314 inlineShapeDataOffset = offset;
315 #endif
316 JS_ASSERT(offset == inlineShapeDataOffset);
319 void setStubShapeJumpOffset(int offset) {
320 #ifdef JS_HAS_IC_LABELS
321 stubShapeJumpOffset = offset;
322 #endif
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);
334 #endif
337 void setInlineShapeJumpOffset(int offset) {
338 #ifdef JS_HAS_IC_LABELS
339 inlineShapeJumpOffset = offset;
340 #endif
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
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
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
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;
392 #else
393 int32 inlineValueStoreOffset : 8;
394 #endif
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;
407 #endif
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;
427 #endif
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;
444 private:
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;
459 #endif
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;
479 #endif
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;
496 private:
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;
504 } /* namespace ic */
505 } /* namespace mjit */
506 } /* namespace js */
508 #endif /* jsjaeger_ic_labels_h__ */