Builds against latest nanojit; merged VMSideExitInfo into SideExit
[mozilla-central.git] / js / src / jstracer.h
blob1de0f08ac0daf414a9d6d02df4e1c2e404f4bb8e
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=99 ft=cpp:
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 * Andreas Gal <gal@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 #ifndef jstracer_h___
41 #define jstracer_h___
43 #include "jsstddef.h"
44 #include "jslock.h"
45 #include "jsnum.h"
46 #include "jsinterp.h"
48 #include "nanojit/nanojit.h"
51 * We use a magic boxed pointer value to represent error conditions that
52 * trigger a side exit. The address is so low that it should never be actually
53 * in use. If it is, a performance regression occurs, not an actual runtime
54 * error.
56 #define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((void*)0x10)
59 * We also need a magic unboxed 32-bit integer that signals an error. Again if
60 * this number is hit we experience a performance regression, not a runtime
61 * error.
63 #define INT32_ERROR_COOKIE 0xffffabcd
66 * Tracker is used to keep track of values being manipulated by the interpreter
67 * during trace recording.
69 template <typename T>
70 class Tracker {
71 struct Page {
72 struct Page* next;
73 jsuword base;
74 T map[0];
76 struct Page* pagelist;
78 jsuword getPageBase(const void* v) const;
79 struct Page* findPage(const void* v) const;
80 struct Page* addPage(const void* v);
81 public:
82 Tracker();
83 ~Tracker();
85 T get(const void* v) const;
86 void set(const void* v, T ins);
87 void clear();
90 struct VMFragmentInfo {
91 unsigned entryNativeFrameSlots;
92 unsigned maxNativeFrameSlots;
93 size_t nativeStackBase;
94 uint8 typeMap[0];
97 #define TYPEMAP_GET_TYPE(x) ((x) & JSVAL_TAGMASK)
98 #define TYPEMAP_SET_TYPE(x, t) (x = (x & 0xf0) | t)
99 #define TYPEMAP_GET_FLAG(x, flag) ((x) & flag)
100 #define TYPEMAP_SET_FLAG(x, flag) do { (x) |= flag; } while (0)
102 #define TYPEMAP_TYPE_ANY 7
104 #define TYPEMAP_FLAG_DEMOTE 0x10 /* try to record as int */
105 #define TYPEMAP_FLAG_DONT_DEMOTE 0x20 /* do not try to record as int */
107 class TraceRecorder {
108 JSContext* cx;
109 JSStackFrame* global;
110 Tracker<nanojit::LIns*> tracker;
111 char* entryTypeMap;
112 struct JSStackFrame* entryFrame;
113 struct JSFrameRegs entryRegs;
114 nanojit::Fragment* fragment;
115 VMFragmentInfo* fragmentInfo;
116 nanojit::LirBuffer* lirbuf;
117 nanojit::LirWriter* lir;
118 nanojit::LirBufWriter* lir_buf_writer;
119 nanojit::LirWriter* verbose_filter;
120 nanojit::LirWriter* cse_filter;
121 nanojit::LirWriter* expr_filter;
122 nanojit::LirWriter* exit_filter;
123 nanojit::LirWriter* func_filter;
124 nanojit::LIns* cx_ins;
125 nanojit::SideExit exit;
126 bool recompileFlag;
128 JSStackFrame* findFrame(void* p) const;
129 bool onFrame(void* p) const;
130 bool isGlobal(void* p) const;
131 unsigned nativeFrameSlots(JSStackFrame* fp, JSFrameRegs& regs) const;
132 size_t nativeFrameOffset(void* p) const;
133 void import(jsval* p, uint8& t, char *prefix, int index);
134 void trackNativeFrameUse(unsigned slots);
136 unsigned getCallDepth() const;
137 void guard(bool expected, nanojit::LIns* cond);
139 void set(void* p, nanojit::LIns* l);
141 bool checkType(jsval& v, uint8& type);
142 bool verifyTypeStability(JSStackFrame* entryFrame, JSStackFrame* currentFrame, uint8* m);
143 void closeLoop(nanojit::Fragmento* fragmento);
145 jsval& gvarval(unsigned n) const;
146 jsval& argval(unsigned n) const;
147 jsval& varval(unsigned n) const;
148 jsval& stackval(int n) const;
150 nanojit::LIns* gvar(unsigned n);
151 void gvar(unsigned n, nanojit::LIns* i);
152 nanojit::LIns* arg(unsigned n);
153 void arg(unsigned n, nanojit::LIns* i);
154 nanojit::LIns* var(unsigned n);
155 void var(unsigned n, nanojit::LIns* i);
156 nanojit::LIns* stack(int n);
157 void stack(int n, nanojit::LIns* i);
159 nanojit::LIns* f2i(nanojit::LIns* f);
161 bool ifop(bool sense);
162 bool inc(jsval& v, jsint incr, bool pre);
163 bool cmp(nanojit::LOpcode op, bool negate = false);
165 bool unary(nanojit::LOpcode op);
166 bool binary(nanojit::LOpcode op);
168 bool ibinary(nanojit::LOpcode op);
169 bool iunary(nanojit::LOpcode op);
170 bool bbinary(nanojit::LOpcode op);
171 void demote(jsval& v, jsdouble result);
173 bool map_is_native(JSObjectMap* map, nanojit::LIns* map_ins);
174 bool test_property_cache(JSObject* obj, nanojit::LIns* obj_ins, JSObject*& obj2,
175 JSPropCacheEntry*& entry);
176 void stobj_set_slot(nanojit::LIns* obj_ins, unsigned slot,
177 nanojit::LIns*& dslots_ins, nanojit::LIns* v_ins);
178 nanojit::LIns* stobj_get_slot(nanojit::LIns* obj_ins, unsigned slot,
179 nanojit::LIns*& dslots_ins);
180 bool native_set(nanojit::LIns* obj_ins, JSScopeProperty* sprop,
181 nanojit::LIns*& dslots_ins, nanojit::LIns* v_ins);
182 bool native_get(nanojit::LIns* obj_ins, nanojit::LIns* pobj_ins, JSScopeProperty* sprop,
183 nanojit::LIns*& dslots_ins, nanojit::LIns*& v_ins);
185 bool box_jsval(jsval v, nanojit::LIns*& v_ins);
186 bool unbox_jsval(jsval v, nanojit::LIns*& v_ins);
187 bool guardThatObjectIsDenseArray(JSObject* obj, nanojit::LIns* obj_ins,
188 nanojit::LIns*& dslots_ins);
189 bool guardDenseArrayIndexWithinBounds(JSObject* obj, jsint idx, nanojit::LIns* obj_ins,
190 nanojit::LIns*& dslots_ins, nanojit::LIns* idx_ins);
191 public:
192 TraceRecorder(JSContext* cx, nanojit::Fragmento*, nanojit::Fragment*);
193 ~TraceRecorder();
195 JSStackFrame* getGlobalFrame() const;
196 JSStackFrame* getEntryFrame() const;
197 JSStackFrame* getFp() const;
198 JSFrameRegs& getRegs() const;
199 nanojit::Fragment* getFragment() const;
200 nanojit::SideExit* snapshot();
202 nanojit::LIns* get(void* p);
204 bool loopEdge();
205 void stop();
207 #define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
208 bool op();
209 # include "jsopcode.tbl"
210 #undef OPDEF
213 FASTCALL jsdouble builtin_dmod(jsdouble a, jsdouble b);
214 FASTCALL jsval builtin_BoxDouble(JSContext* cx, jsdouble d);
215 FASTCALL jsval builtin_BoxInt32(JSContext* cx, jsint i);
216 FASTCALL jsdouble builtin_UnboxDouble(jsval v);
217 FASTCALL jsint builtin_UnboxInt32(jsval v);
218 FASTCALL int32 builtin_doubleToInt32(jsdouble d);
219 FASTCALL int32 builtin_doubleToUint32(jsdouble d);
222 * Trace monitor. Every JSThread (if JS_THREADSAFE) or JSRuntime (if not
223 * JS_THREADSAFE) has an associated trace monitor that keeps track of loop
224 * frequencies for all JavaScript code loaded into that runtime.
226 struct JSTraceMonitor {
227 nanojit::Fragmento* fragmento;
228 TraceRecorder* recorder;
231 #define TRACING_ENABLED(cx) JS_HAS_OPTION(cx, JSOPTION_JIT)
233 extern bool
234 js_LoopEdge(JSContext* cx);
236 extern void
237 js_AbortRecording(JSContext* cx, const char* reason);
239 extern void
240 js_InitJIT(JSContext* cx);
242 #endif /* jstracer_h___ */