Backed out changeset de5d1b528b9a
[mozilla-central.git] / js / src / methodjit / PolyIC.h
blob0edbe26321c851a8903a6ca7da3e2e59d585a268
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>
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__
43 #include "jscntxt.h"
44 #include "jstl.h"
45 #include "jsvector.h"
46 #include "assembler/assembler/MacroAssembler.h"
47 #include "assembler/assembler/CodeLocation.h"
48 #include "methodjit/MethodJIT.h"
49 #include "RematInfo.h"
51 namespace js {
52 namespace mjit {
53 namespace ic {
55 /* Maximum number of stubs for a given callsite. */
56 static const uint32 MAX_PIC_STUBS = 16;
58 /* SetPropCompiler */
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
75 #endif
77 /* GetPropCompiler */
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
89 #endif
91 /* GetElemCompiler */
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)
106 #endif
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
113 #endif
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
121 #endif
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
130 union PICLabels {
131 /* SetPropCompiler */
132 struct {
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;
143 } setprop;
145 /* GetPropCompiler */
146 struct {
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;
160 } getprop;
162 /* GetElemCompiler */
163 struct {
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;
180 } getelem;
182 /* BindNameCompiler */
183 struct {
184 /* Offset from shapeGuard to end of shape jump. */
185 int32 inlineJumpOffset : 8;
186 } bindname;
188 #endif
190 struct PICInfo {
191 typedef JSC::MacroAssembler::RegisterID RegisterID;
193 // Operation this is a PIC for.
194 enum Kind
195 #ifdef _MSC_VER
196 : uint8_t
197 #endif
199 GET, // JSOP_GETPROP
200 CALL, // JSOP_CALLPROP
201 SET, // JSOP_SETPROP, JSOP_SETNAME
202 SETMETHOD, // JSOP_SETMETHOD
203 NAME, // JSOP_NAME
204 BIND, // JSOP_BINDNAME
205 GETELEM, // JSOP_GETELEM
206 XNAME // JSOP_GETXPROP
209 union {
210 // This struct comes out to 93 bits with GCC.
211 struct {
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.
222 uint32 idRemat : 20;
223 bool idNeedsRemat : 1;
224 } get;
225 ValueRemat vr;
226 } u;
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
230 // last stub.
231 int secondShapeGuard : 11;
233 Kind kind : 3;
235 // True if register R holds the base object shape along exits from the
236 // last stub.
237 bool shapeRegHasBaseShape : 1;
239 // State flags.
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.
250 uint32 shapeGuard;
252 // Return address of slow path call, as an offset from slowPathStart.
253 uint32 callReturn;
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() {
262 JS_ASSERT(isGet());
263 return u.get.typeReg;
265 inline bool hasTypeCheck() {
266 JS_ASSERT(isGet());
267 return u.get.hasTypeCheck;
269 inline uint32 objRemat() {
270 JS_ASSERT(isGet());
271 return u.get.objRemat;
273 inline uint32 idRemat() {
274 JS_ASSERT(isGet());
275 return u.get.idRemat;
277 inline bool objNeedsRemat() {
278 JS_ASSERT(isGet());
279 return u.get.objNeedsRemat;
281 inline bool idNeedsRemat() {
282 JS_ASSERT(isGet());
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.
295 PICLabels labels;
296 #endif
298 // Index into the script's atom table.
299 JSAtom *atom;
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();
332 ++pExecPool)
334 (*pExecPool)->release();
338 // Reset the data members to the state of a fresh PIC before any patching
339 // or stub generation was done.
340 void reset() {
341 hit = false;
342 inlinePathPatched = false;
343 if (kind == GET || kind == CALL || kind == GETELEM) {
344 u.get.objNeedsRemat = false;
346 secondShapeGuard = 0;
347 shapeRegHasBaseShape = true;
348 stubsGenerated = 0;
349 releasePools();
350 execPools.clear();
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);
364 } /* namespace ic */
365 } /* namespace mjit */
366 } /* namespace js */
368 #endif /* jsjaeger_poly_ic_h__ */