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
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 * 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 ***** */
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
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
63 #define INT32_ERROR_COOKIE 0xffffabcd
66 * Tracker is used to keep track of values being manipulated by the interpreter
67 * during trace recording.
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
);
85 T
get(const void* v
) const;
86 void set(const void* v
, T ins
);
90 struct VMFragmentInfo
{
91 unsigned entryNativeFrameSlots
;
92 unsigned maxNativeFrameSlots
;
93 size_t nativeStackBase
;
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
{
109 JSStackFrame
* global
;
110 Tracker
<nanojit::LIns
*> tracker
;
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
;
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
);
192 TraceRecorder(JSContext
* cx
, nanojit::Fragmento
*, nanojit::Fragment
*);
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
);
207 #define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
209 # include "jsopcode.tbl"
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)
234 js_LoopEdge(JSContext
* cx
);
237 js_AbortRecording(JSContext
* cx
, const char* reason
);
240 js_InitJIT(JSContext
* cx
);
242 #endif /* jstracer_h___ */