Refactor and improve GETELEM IC (bug 602641, r=dmandelin).
[mozilla-central.git] / js / src / methodjit / MethodJIT.h
blob1bcca198b9b2e78310b08b61856ce69e5b40d0be
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):
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #if !defined jsjaeger_h__ && defined JS_METHODJIT
40 #define jsjaeger_h__
42 #include "jscntxt.h"
44 #include "assembler/assembler/MacroAssemblerCodeRef.h"
46 #if !defined JS_CPU_X64 && \
47 !defined JS_CPU_X86 && \
48 !defined JS_CPU_ARM
49 # error "Oh no, you should define a platform so this compiles."
50 #endif
52 #if !defined(JS_NUNBOX32) && !defined(JS_PUNBOX64)
53 # error "No boxing format selected."
54 #endif
56 namespace js {
58 struct VMFrame
60 union Arguments {
61 struct {
62 void *ptr;
63 void *ptr2;
64 void *ptr3;
65 } x;
66 } u;
68 VMFrame *previous;
69 void *unused;
70 JSFrameRegs regs;
71 JSContext *cx;
72 Value *stackLimit;
73 JSStackFrame *entryFp;
75 #if defined(JS_CPU_X86)
76 void *savedEBX;
77 void *savedEDI;
78 void *savedESI;
79 void *savedEBP;
80 void *savedEIP;
82 # ifdef JS_NO_FASTCALL
83 inline void** returnAddressLocation() {
84 return reinterpret_cast<void**>(this) - 3;
86 # else
87 inline void** returnAddressLocation() {
88 return reinterpret_cast<void**>(this) - 1;
90 # endif
91 #elif defined(JS_CPU_X64)
92 void *savedRBX;
93 # ifdef _WIN64
94 void *savedRSI;
95 void *savedRDI;
96 # endif
97 void *savedR15;
98 void *savedR14;
99 void *savedR13;
100 void *savedR12;
101 void *savedRBP;
102 void *savedRIP;
104 # ifdef _WIN64
105 inline void** returnAddressLocation() {
106 return reinterpret_cast<void**>(this) - 5;
108 # else
109 inline void** returnAddressLocation() {
110 return reinterpret_cast<void**>(this) - 1;
112 # endif
114 #elif defined(JS_CPU_ARM)
115 void *savedR4;
116 void *savedR5;
117 void *savedR6;
118 void *savedR7;
119 void *savedR8;
120 void *savedR9;
121 void *savedR10;
122 void *savedR11;
123 void *savedLR;
125 inline void** returnAddressLocation() {
126 return reinterpret_cast<void**>(this) - 1;
128 #else
129 # error "The VMFrame layout isn't defined for your processor architecture!"
130 #endif
132 JSRuntime *runtime() { return cx->runtime; }
134 JSStackFrame *&fp() { return regs.fp; }
137 #ifdef JS_CPU_ARM
138 // WARNING: Do not call this function directly from C(++) code because it is not ABI-compliant.
139 extern "C" void JaegerStubVeneer(void);
140 #endif
142 namespace mjit {
143 namespace ic {
144 # if defined JS_POLYIC
145 struct PICInfo;
146 struct GetElementIC;
147 # endif
148 # if defined JS_MONOIC
149 struct MICInfo;
150 struct EqualityICInfo;
151 struct TraceICInfo;
152 struct CallICInfo;
153 # endif
157 typedef void (JS_FASTCALL *VoidStub)(VMFrame &);
158 typedef void (JS_FASTCALL *VoidVpStub)(VMFrame &, Value *);
159 typedef void (JS_FASTCALL *VoidStubUInt32)(VMFrame &, uint32);
160 typedef void (JS_FASTCALL *VoidStubInt32)(VMFrame &, int32);
161 typedef JSBool (JS_FASTCALL *BoolStub)(VMFrame &);
162 typedef void * (JS_FASTCALL *VoidPtrStub)(VMFrame &);
163 typedef void * (JS_FASTCALL *VoidPtrStubPC)(VMFrame &, jsbytecode *);
164 typedef void * (JS_FASTCALL *VoidPtrStubUInt32)(VMFrame &, uint32);
165 typedef JSObject * (JS_FASTCALL *JSObjStub)(VMFrame &);
166 typedef JSObject * (JS_FASTCALL *JSObjStubUInt32)(VMFrame &, uint32);
167 typedef JSObject * (JS_FASTCALL *JSObjStubFun)(VMFrame &, JSFunction *);
168 typedef void (JS_FASTCALL *VoidStubFun)(VMFrame &, JSFunction *);
169 typedef JSObject * (JS_FASTCALL *JSObjStubJSObj)(VMFrame &, JSObject *);
170 typedef void (JS_FASTCALL *VoidStubAtom)(VMFrame &, JSAtom *);
171 typedef JSString * (JS_FASTCALL *JSStrStub)(VMFrame &);
172 typedef JSString * (JS_FASTCALL *JSStrStubUInt32)(VMFrame &, uint32);
173 typedef void (JS_FASTCALL *VoidStubJSObj)(VMFrame &, JSObject *);
174 typedef void (JS_FASTCALL *VoidStubPC)(VMFrame &, jsbytecode *);
175 typedef JSBool (JS_FASTCALL *BoolStubUInt32)(VMFrame &f, uint32);
176 #ifdef JS_MONOIC
177 typedef void (JS_FASTCALL *VoidStubCallIC)(VMFrame &, js::mjit::ic::CallICInfo *);
178 typedef void * (JS_FASTCALL *VoidPtrStubCallIC)(VMFrame &, js::mjit::ic::CallICInfo *);
179 typedef void (JS_FASTCALL *VoidStubMIC)(VMFrame &, js::mjit::ic::MICInfo *);
180 typedef void * (JS_FASTCALL *VoidPtrStubMIC)(VMFrame &, js::mjit::ic::MICInfo *);
181 typedef JSBool (JS_FASTCALL *BoolStubEqualityIC)(VMFrame &, js::mjit::ic::EqualityICInfo *);
182 typedef void * (JS_FASTCALL *VoidPtrStubTraceIC)(VMFrame &, js::mjit::ic::TraceICInfo *);
183 #endif
184 #ifdef JS_POLYIC
185 typedef void (JS_FASTCALL *VoidStubPIC)(VMFrame &, js::mjit::ic::PICInfo *);
186 typedef void (JS_FASTCALL *VoidStubGetElemIC)(VMFrame &, js::mjit::ic::GetElementIC *);
187 #endif
189 namespace mjit {
191 struct CallSite;
193 struct JITScript {
194 typedef JSC::MacroAssemblerCodeRef CodeRef;
195 CodeRef code; /* pool & code addresses */
196 void **nmap; /* pc -> JIT code map, sparse */
198 js::mjit::CallSite *callSites;
199 uint32 nCallSites;
200 #ifdef JS_MONOIC
201 ic::MICInfo *mics; /* MICs in this script. */
202 uint32 nMICs; /* number of MonoICs */
203 ic::CallICInfo *callICs; /* CallICs in this script. */
204 uint32 nCallICs; /* number of call ICs */
205 ic::EqualityICInfo *equalityICs;
206 uint32 nEqualityICs;
207 ic::TraceICInfo *traceICs;
208 uint32 nTraceICs;
210 // Additional ExecutablePools that IC stubs were generated into.
211 typedef Vector<JSC::ExecutablePool *, 0, SystemAllocPolicy> ExecPoolVector;
212 ExecPoolVector execPools;
213 #endif
214 #ifdef JS_POLYIC
215 ic::PICInfo *pics; /* PICs in this script */
216 uint32 nPICs; /* number of PolyICs */
217 ic::GetElementIC *getElems;
218 uint32 nGetElems;
219 #endif
220 void *invokeEntry; /* invoke address */
221 void *fastEntry; /* cached entry, fastest */
222 void *arityCheckEntry; /* arity check address */
224 bool isValidCode(void *ptr) {
225 char *jitcode = (char *)code.m_code.executableAddress();
226 char *jcheck = (char *)ptr;
227 return jcheck >= jitcode && jcheck < jitcode + code.m_size;
230 void sweepCallICs();
231 void purgeMICs();
232 void purgePICs();
233 void release();
237 * Execute the given mjit code. This is a low-level call and callers must
238 * provide the same guarantees as JaegerShot/CheckStackAndEnterMethodJIT.
240 JSBool EnterMethodJIT(JSContext *cx, JSStackFrame *fp, void *code, Value *stackLimit);
242 /* Execute a method that has been JIT compiled. */
243 JSBool JaegerShot(JSContext *cx);
245 /* Drop into the middle of a method at an arbitrary point, and execute. */
246 JSBool JaegerShotAtSafePoint(JSContext *cx, void *safePoint);
248 enum CompileStatus
250 Compile_Okay,
251 Compile_Abort,
252 Compile_Error
255 void JS_FASTCALL
256 ProfileStubCall(VMFrame &f);
258 CompileStatus JS_NEVER_INLINE
259 TryCompile(JSContext *cx, JSStackFrame *fp);
261 void
262 ReleaseScriptCode(JSContext *cx, JSScript *script);
264 static inline CompileStatus
265 CanMethodJIT(JSContext *cx, JSScript *script, JSStackFrame *fp)
267 if (!cx->methodJitEnabled)
268 return Compile_Abort;
269 JITScriptStatus status = script->getJITStatus(fp->isConstructing());
270 if (status == JITScript_Invalid)
271 return Compile_Abort;
272 if (status == JITScript_None)
273 return TryCompile(cx, fp);
274 return Compile_Okay;
277 struct CallSite
279 uint32 codeOffset;
280 uint32 pcOffset;
281 uint32 id;
284 /* Re-enables a tracepoint in the method JIT. */
285 void
286 EnableTraceHint(JSScript *script, jsbytecode *pc, uint16_t index);
288 uintN
289 GetCallTargetCount(JSScript *script, jsbytecode *pc);
291 } /* namespace mjit */
293 } /* namespace js */
295 inline void *
296 JSScript::maybeNativeCodeForPC(bool constructing, jsbytecode *pc)
298 js::mjit::JITScript *jit = getJIT(constructing);
299 if (!jit)
300 return NULL;
301 JS_ASSERT(pc >= code && pc < code + length);
302 return jit->nmap[pc - code];
305 inline void **
306 JSScript::nativeMap(bool constructing)
308 return getJIT(constructing)->nmap;
311 inline void *
312 JSScript::nativeCodeForPC(bool constructing, jsbytecode *pc)
314 void **nmap = nativeMap(constructing);
315 JS_ASSERT(pc >= code && pc < code + length);
316 JS_ASSERT(nmap[pc - code]);
317 return nmap[pc - code];
320 #ifdef _MSC_VER
321 extern "C" void *JaegerThrowpoline(js::VMFrame *vmFrame);
322 #else
323 extern "C" void JaegerThrowpoline();
324 #endif
325 extern "C" void InjectJaegerReturn();
327 #endif /* jsjaeger_h__ */