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>
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.
38 * ***** END LICENSE BLOCK ***** */
40 #if !defined jsjaeger_poly_ic_h__ && defined JS_METHODJIT && defined JS_POLYIC
41 #define jsjaeger_poly_ic_h__
46 #include "assembler/assembler/MacroAssembler.h"
47 #include "assembler/assembler/CodeLocation.h"
48 #include "methodjit/MethodJIT.h"
49 #include "RematInfo.h"
55 /* Maximum number of stubs for a given callsite. */
56 static const uint32 MAX_PIC_STUBS
= 16;
59 #if defined JS_CPU_X86
60 static const int32 SETPROP_INLINE_SHAPE_OFFSET
= 6; //asserted
61 static const int32 SETPROP_INLINE_SHAPE_JUMP
= 12; //asserted
62 static const int32 SETPROP_DSLOTS_BEFORE_CONSTANT
= -23; //asserted
63 static const int32 SETPROP_DSLOTS_BEFORE_KTYPE
= -19; //asserted
64 static const int32 SETPROP_DSLOTS_BEFORE_DYNAMIC
= -15; //asserted
65 static const int32 SETPROP_INLINE_STORE_DYN_TYPE
= -6; //asserted
66 static const int32 SETPROP_INLINE_STORE_DYN_DATA
= 0; //asserted
67 static const int32 SETPROP_INLINE_STORE_KTYPE_TYPE
= -10; //asserted
68 static const int32 SETPROP_INLINE_STORE_KTYPE_DATA
= 0; //asserted
69 static const int32 SETPROP_INLINE_STORE_CONST_TYPE
= -14; //asserted
70 static const int32 SETPROP_INLINE_STORE_CONST_DATA
= -4; //asserted
71 static const int32 SETPROP_STUB_SHAPE_JUMP
= 12; //asserted
72 #elif defined JS_CPU_X64
73 static const int32 SETPROP_INLINE_STORE_VALUE
= 0; //asserted
74 static const int32 SETPROP_INLINE_SHAPE_JUMP
= 6; //asserted
78 #if defined JS_CPU_X86
79 static const int32 GETPROP_DSLOTS_LOAD
= -15; //asserted
80 static const int32 GETPROP_TYPE_LOAD
= -6; //asserted
81 static const int32 GETPROP_DATA_LOAD
= 0; //asserted
82 static const int32 GETPROP_INLINE_TYPE_GUARD
= 12; //asserted
83 static const int32 GETPROP_INLINE_SHAPE_OFFSET
= 6; //asserted
84 static const int32 GETPROP_INLINE_SHAPE_JUMP
= 12; //asserted
85 static const int32 GETPROP_STUB_SHAPE_JUMP
= 12; //asserted
86 #elif defined JS_CPU_X64
87 static const int32 GETPROP_INLINE_TYPE_GUARD
= 19; //asserted
88 static const int32 GETPROP_INLINE_SHAPE_JUMP
= 6; //asserted
92 #if defined JS_CPU_X86
93 static const int32 GETELEM_DSLOTS_LOAD
= -15; //asserted
94 static const int32 GETELEM_TYPE_LOAD
= -6; //asserted
95 static const int32 GETELEM_DATA_LOAD
= 0; //asserted
96 static const int32 GETELEM_INLINE_SHAPE_OFFSET
= 6; //asserted
97 static const int32 GETELEM_INLINE_SHAPE_JUMP
= 12; //asserted
98 static const int32 GETELEM_INLINE_ATOM_OFFSET
= 18; //asserted
99 static const int32 GETELEM_INLINE_ATOM_JUMP
= 24; //asserted
100 static const int32 GETELEM_STUB_ATOM_JUMP
= 12; //asserted
101 static const int32 GETELEM_STUB_SHAPE_JUMP
= 24; //asserted
102 #elif defined JS_CPU_X64
103 static const int32 GETELEM_INLINE_SHAPE_JUMP
= 6; //asserted
104 static const int32 GETELEM_INLINE_ATOM_JUMP
= 9; //asserted
105 static const int32 GETELEM_STUB_ATOM_JUMP
= 19; //asserted (probably differs)
108 /* ScopeNameCompiler */
109 #if defined JS_CPU_X86
110 static const int32 SCOPENAME_JUMP_OFFSET
= 5; //asserted
111 #elif defined JS_CPU_X64
112 static const int32 SCOPENAME_JUMP_OFFSET
= 5; //asserted
115 /* BindNameCompiler */
116 #if defined JS_CPU_X86
117 static const int32 BINDNAME_INLINE_JUMP_OFFSET
= 10; //asserted
118 static const int32 BINDNAME_STUB_JUMP_OFFSET
= 5; //asserted
119 #elif defined JS_CPU_X64
120 static const int32 BINDNAME_STUB_JUMP_OFFSET
= 5; //asserted
123 void PurgePICs(JSContext
*cx
);
126 * x86_64 bytecode differs in length based on the involved registers.
127 * Since constants won't work, we need an array of labels.
129 #if defined JS_CPU_X64
131 /* SetPropCompiler */
133 /* Offset from storeBack to beginning of 'mov dslots, addr' */
134 int32 dslotsLoadOffset
: 8;
136 /* Offset from shapeGuard to end of shape comparison. */
137 int32 inlineShapeOffset
: 8;
139 /* Offset from lastStubStart to end of shape jump. */
140 // TODO: We can redefine the location of lastStubStart to be
141 // after the jump -- at which point this is always 0.
142 int32 stubShapeJump
: 8;
145 /* GetPropCompiler */
147 /* Offset from storeBack to beginning of 'mov dslots, addr' */
148 int32 dslotsLoadOffset
: 8;
150 /* Offset from shapeGuard to end of shape comparison. */
151 int32 inlineShapeOffset
: 8;
153 /* Offset from storeBack to end of value load. */
154 int32 inlineValueOffset
: 8;
156 /* Offset from lastStubStart to end of shape jump. */
157 // TODO: We can redefine the location of lastStubStart to be
158 // after the jump -- at which point this is always 0.
159 int32 stubShapeJump
: 8;
162 /* GetElemCompiler */
164 /* Offset from storeBack to beginning of 'mov dslots, addr' */
165 int32 dslotsLoadOffset
: 8;
167 /* Offset from shapeGuard to end of shape comparison. */
168 int32 inlineShapeOffset
: 8;
170 /* Offset from shapeGuard to end of atom comparison. */
171 int32 inlineAtomOffset
: 8;
173 /* Offset from storeBack to end of value load. */
174 int32 inlineValueOffset
: 8;
176 /* Offset from lastStubStart to end of shape jump. */
177 // TODO: We can redefine the location of lastStubStart to be
178 // after the jump -- at which point this is always 0.
179 int32 stubShapeJump
: 8;
182 /* BindNameCompiler */
184 /* Offset from shapeGuard to end of shape jump. */
185 int32 inlineJumpOffset
: 8;
191 typedef JSC::MacroAssembler::RegisterID RegisterID
;
193 // Operation this is a PIC for.
200 CALL
, // JSOP_CALLPROP
201 SET
, // JSOP_SETPROP, JSOP_SETNAME
202 SETMETHOD
, // JSOP_SETMETHOD
204 BIND
, // JSOP_BINDNAME
205 GETELEM
, // JSOP_GETELEM
206 XNAME
// JSOP_GETXPROP
210 // This struct comes out to 93 bits with GCC.
212 RegisterID typeReg
: 5; // reg used for checking type
213 bool hasTypeCheck
: 1; // type check and reg are present
215 // Reverse offset from slowPathStart to the type check slow path.
216 int32 typeCheckOffset
;
218 // Remat info for the object reg.
219 uint32 objRemat
: 20;
220 bool objNeedsRemat
: 1;
221 RegisterID idReg
: 5; // only used in GETELEM PICs.
223 bool idNeedsRemat
: 1;
228 // Offset from start of stub to jump target of second shape guard as Nitro
229 // asm data location. This is 0 if there is only one shape guard in the
231 int secondShapeGuard
: 11;
235 // True if register R holds the base object shape along exits from the
237 bool shapeRegHasBaseShape
: 1;
240 bool hit
: 1; // this PIC has been executed
241 bool inlinePathPatched
: 1; // inline path has been patched
243 RegisterID shapeReg
: 5; // also the out type reg
244 RegisterID objReg
: 5; // also the out data reg
246 // Number of stubs generated.
247 uint32 stubsGenerated
: 5;
249 // Offset from start of fast path to initial shape guard.
252 // Return address of slow path call, as an offset from slowPathStart.
255 inline bool isSet() {
256 return kind
== SET
|| kind
== SETMETHOD
;
258 inline bool isGet() {
259 return kind
== GET
|| kind
== CALL
|| kind
== GETELEM
;
261 inline RegisterID
typeReg() {
263 return u
.get
.typeReg
;
265 inline bool hasTypeCheck() {
267 return u
.get
.hasTypeCheck
;
269 inline uint32
objRemat() {
271 return u
.get
.objRemat
;
273 inline uint32
idRemat() {
275 return u
.get
.idRemat
;
277 inline bool objNeedsRemat() {
279 return u
.get
.objNeedsRemat
;
281 inline bool idNeedsRemat() {
283 return u
.get
.idNeedsRemat
;
285 inline bool shapeNeedsRemat() {
286 return !shapeRegHasBaseShape
;
288 inline bool isFastCall() {
289 JS_ASSERT(kind
== CALL
);
290 return !hasTypeCheck();
293 #if defined JS_CPU_X64
294 // Required labels for platform-specific patching.
298 // Index into the script's atom table.
301 // Address of inline fast-path.
302 JSC::CodeLocationLabel fastPathStart
;
304 // Address of store back at the end of the inline fast-path.
305 JSC::CodeLocationLabel storeBack
;
307 // Offset from callReturn to the start of the slow case.
308 JSC::CodeLocationLabel slowPathStart
;
310 // Address of the start of the last generated stub, if any.
311 JSC::CodeLocationLabel lastStubStart
;
313 typedef Vector
<JSC::ExecutablePool
*, 0, SystemAllocPolicy
> ExecPoolVector
;
315 // ExecutablePools that PIC stubs were generated into.
316 ExecPoolVector execPools
;
318 // Return the start address of the last path in this PIC, which is the
319 // inline path if no stubs have been generated yet.
320 JSC::CodeLocationLabel
lastPathStart() {
321 return stubsGenerated
> 0 ? lastStubStart
: fastPathStart
;
324 bool shouldGenerate() {
325 return stubsGenerated
< MAX_PIC_STUBS
|| !inlinePathPatched
;
328 // Release ExecutablePools referred to by this PIC.
329 void releasePools() {
330 for (JSC::ExecutablePool
**pExecPool
= execPools
.begin();
331 pExecPool
!= execPools
.end();
334 (*pExecPool
)->release();
338 // Reset the data members to the state of a fresh PIC before any patching
339 // or stub generation was done.
342 inlinePathPatched
= false;
343 if (kind
== GET
|| kind
== CALL
|| kind
== GETELEM
) {
344 u
.get
.objNeedsRemat
= false;
346 secondShapeGuard
= 0;
347 shapeRegHasBaseShape
= true;
354 void PurgePICs(JSContext
*cx
, JSScript
*script
);
355 void JS_FASTCALL
GetProp(VMFrame
&f
, uint32 index
);
356 void JS_FASTCALL
GetElem(VMFrame
&f
, uint32 index
);
357 void JS_FASTCALL
SetProp(VMFrame
&f
, uint32 index
);
358 void JS_FASTCALL
CallProp(VMFrame
&f
, uint32 index
);
359 void JS_FASTCALL
Name(VMFrame
&f
, uint32 index
);
360 void JS_FASTCALL
XName(VMFrame
&f
, uint32 index
);
361 void JS_FASTCALL
BindName(VMFrame
&f
, uint32 index
);
362 void JS_FASTCALL
SetPropDumb(VMFrame
&f
, uint32 index
);
365 } /* namespace mjit */
368 #endif /* jsjaeger_poly_ic_h__ */