1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 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 * Mozilla Corporation.
24 * Jason Orendorff <jorendorff@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 jsbuiltins_h___
41 #define jsbuiltins_h___
45 #include "nanojit/nanojit.h"
52 enum JSTNErrType
{ INFALLIBLE
, FAIL_NULL
, FAIL_NEG
, FAIL_VOID
, FAIL_JSVAL
};
53 enum { JSTN_ERRTYPE_MASK
= 7, JSTN_MORE
= 8 };
55 #define JSTN_ERRTYPE(jstn) ((jstn)->flags & JSTN_ERRTYPE_MASK)
58 * |prefix| and |argtypes| declare what arguments should be passed to the
59 * native function. |prefix| can contain the following characters:
61 * 'C': a JSContext* argument
62 * 'T': |this| as a JSObject* argument (bails if |this| is not an object)
63 * 'S': |this| as a JSString* argument (bails if |this| is not a string)
64 * 'R': a JSRuntime* argument
65 * 'P': the pc as a jsbytecode*
66 * 'D': |this| as a number (jsdouble)
67 * 'f': the function being called, as a JSObject*
68 * 'p': the .prototype of the function, as a JSObject*
70 * The corresponding things will get passed as arguments to the builtin in
71 * reverse order (so TC means JSContext* as the first arg, and the
72 * JSObject* for |this| as the second arg).
74 * |argtypes| can contain the following characters:
75 * 'd': a number (double) argument
76 * 'i': an integer argument
77 * 's': a JSString* argument
78 * 'o': a JSObject* argument
79 * 'r': a JSObject* argument that is of class js_RegExpClass
80 * 'f': a JSObject* argument that is of class js_FunctionClass
81 * 'v': a jsval argument (boxing whatever value is actually being passed in)
83 struct JSTraceableNative
{
85 const nanojit::CallInfo
*builtin
;
88 uintN flags
; /* JSTN_MORE | JSTNErrType */
92 * We use a magic boxed pointer value to represent error conditions that
93 * trigger a side exit. The address is so low that it should never be actually
94 * in use. If it is, a performance regression occurs, not an actual runtime
97 #define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((void*)0x10)
99 /* Macros used by JS_DEFINE_CALLINFOn. */
101 #define _JS_CI_NAME(op) ,#op
103 #define _JS_CI_NAME(op)
106 #define _JS_I32_ARGSIZE nanojit::ARGSIZE_LO
107 #define _JS_I32_RETSIZE nanojit::ARGSIZE_LO
108 #define _JS_F64_ARGSIZE nanojit::ARGSIZE_F
109 #define _JS_F64_RETSIZE nanojit::ARGSIZE_F
110 #define _JS_PTR_ARGSIZE nanojit::ARGSIZE_LO
111 #if defined AVMPLUS_64BIT
112 # define _JS_PTR_RETSIZE nanojit::ARGSIZE_Q
114 # define _JS_PTR_RETSIZE nanojit::ARGSIZE_LO
118 * Supported types for builtin functions.
120 * Types with -- for the two string fields are not permitted as argument types
121 * in JS_DEFINE_TRCINFO.
123 * If a traceable native can fail, the values that indicate failure are part of
125 * JSVAL_FAIL: JSVAL_ERROR_COOKIE
126 * BOOL_FAIL: JSVAL_TO_BOOLEAN(JSVAL_VOID)
127 * INT32_FAIL: any negative value
129 * OBJECT_FAIL_NULL: NULL
130 * OBJECT_FAIL_VOID: JSVAL_TO_OBJECT(JSVAL_VOID)
131 * (NULL means the function successfully returned JS null.)
133 * Special builtins known to the tracer can have their own idiosyncratic
136 * When a traceable native returns a value indicating failure, we fall off
137 * trace. If an exception is pending, it is thrown; otherwise, we assume the
138 * builtin had no side effects and retry the current bytecode in the
141 * So a builtin must not return a value indicating failure after causing side
142 * effects (such as reporting an error), without setting an exception pending.
143 * The operation would be retried, despite the first attempt's observable
146 #define _JS_CTYPE(ctype, size, pch, ach, flags) (ctype, size, pch, ach, flags)
147 #define _JS_CTYPE_CONTEXT _JS_CTYPE(JSContext *, _JS_PTR,"C", "", INFALLIBLE)
148 #define _JS_CTYPE_RUNTIME _JS_CTYPE(JSRuntime *, _JS_PTR,"R", "", INFALLIBLE)
149 #define _JS_CTYPE_THIS _JS_CTYPE(JSObject *, _JS_PTR,"T", "", INFALLIBLE)
150 #define _JS_CTYPE_THIS_DOUBLE _JS_CTYPE(jsdouble, _JS_F64,"D", "", INFALLIBLE)
151 #define _JS_CTYPE_THIS_STRING _JS_CTYPE(JSString *, _JS_PTR,"S", "", INFALLIBLE)
152 #define _JS_CTYPE_PC _JS_CTYPE(jsbytecode *, _JS_PTR,"P", "", INFALLIBLE)
153 #define _JS_CTYPE_JSVAL _JS_CTYPE(jsval, _JS_PTR, "","v", INFALLIBLE)
154 #define _JS_CTYPE_JSVAL_FAIL _JS_CTYPE(jsval, _JS_PTR, --, --, FAIL_JSVAL)
155 #define _JS_CTYPE_BOOL _JS_CTYPE(JSBool, _JS_I32, "","i", INFALLIBLE)
156 #define _JS_CTYPE_BOOL_FAIL _JS_CTYPE(int32, _JS_I32, --, --, FAIL_VOID)
157 #define _JS_CTYPE_INT32 _JS_CTYPE(int32, _JS_I32, "","i", INFALLIBLE)
158 #define _JS_CTYPE_INT32_FAIL _JS_CTYPE(int32, _JS_I32, --, --, FAIL_NEG)
159 #define _JS_CTYPE_UINT32 _JS_CTYPE(uint32, _JS_I32, --, --, INFALLIBLE)
160 #define _JS_CTYPE_DOUBLE _JS_CTYPE(jsdouble, _JS_F64, "","d", INFALLIBLE)
161 #define _JS_CTYPE_STRING _JS_CTYPE(JSString *, _JS_PTR, "","s", INFALLIBLE)
162 #define _JS_CTYPE_STRING_FAIL _JS_CTYPE(JSString *, _JS_PTR, --, --, FAIL_NULL)
163 #define _JS_CTYPE_OBJECT _JS_CTYPE(JSObject *, _JS_PTR, "","o", INFALLIBLE)
164 #define _JS_CTYPE_OBJECT_FAIL_NULL _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_NULL)
165 #define _JS_CTYPE_OBJECT_FAIL_VOID _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_VOID)
166 #define _JS_CTYPE_REGEXP _JS_CTYPE(JSObject *, _JS_PTR, "","r", INFALLIBLE)
167 #define _JS_CTYPE_SCOPEPROP _JS_CTYPE(JSScopeProperty *, _JS_PTR, --, --, INFALLIBLE)
168 #define _JS_CTYPE_SIDEEXIT _JS_CTYPE(SideExit *, _JS_PTR, --, --, INFALLIBLE)
169 #define _JS_CTYPE_INTERPSTATE _JS_CTYPE(InterpState *, _JS_PTR, --, --, INFALLIBLE)
170 #define _JS_CTYPE_FRAGMENT _JS_CTYPE(nanojit::Fragment *, _JS_PTR, --, --, INFALLIBLE)
172 #define _JS_EXPAND(tokens) tokens
174 #define _JS_CTYPE_TYPE2(t,s,p,a,f) t
175 #define _JS_CTYPE_TYPE(tyname) _JS_EXPAND(_JS_CTYPE_TYPE2 _JS_CTYPE_##tyname)
176 #define _JS_CTYPE_RETSIZE2(t,s,p,a,f) s##_RETSIZE
177 #define _JS_CTYPE_RETSIZE(tyname) _JS_EXPAND(_JS_CTYPE_RETSIZE2 _JS_CTYPE_##tyname)
178 #define _JS_CTYPE_ARGSIZE2(t,s,p,a,f) s##_ARGSIZE
179 #define _JS_CTYPE_ARGSIZE(tyname) _JS_EXPAND(_JS_CTYPE_ARGSIZE2 _JS_CTYPE_##tyname)
180 #define _JS_CTYPE_PCH2(t,s,p,a,f) p
181 #define _JS_CTYPE_PCH(tyname) _JS_EXPAND(_JS_CTYPE_PCH2 _JS_CTYPE_##tyname)
182 #define _JS_CTYPE_ACH2(t,s,p,a,f) a
183 #define _JS_CTYPE_ACH(tyname) _JS_EXPAND(_JS_CTYPE_ACH2 _JS_CTYPE_##tyname)
184 #define _JS_CTYPE_FLAGS2(t,s,p,a,f) f
185 #define _JS_CTYPE_FLAGS(tyname) _JS_EXPAND(_JS_CTYPE_FLAGS2 _JS_CTYPE_##tyname)
187 #define _JS_static_TN(t) static t
188 #define _JS_static_CI static
189 #define _JS_extern_TN(t) extern t
190 #define _JS_extern_CI
191 #define _JS_FRIEND_TN(t) extern JS_FRIEND_API(t)
192 #define _JS_FRIEND_CI
193 #define _JS_TN_LINKAGE(linkage, t) _JS_##linkage##_TN(t)
194 #define _JS_CI_LINKAGE(linkage) _JS_##linkage##_CI
196 #define _JS_CALLINFO(name) name##_ci
198 #if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
199 #define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, cse, fold) \
200 _JS_TN_LINKAGE(linkage, crtype) name cargtypes; \
201 _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
202 { (intptr_t) &name, argtypes, cse, fold, nanojit::ABI_CDECL _JS_CI_NAME(name) };
204 #define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, cse, fold) \
205 _JS_TN_LINKAGE(linkage, crtype) FASTCALL name cargtypes; \
206 _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
207 { (intptr_t) &name, argtypes, cse, fold, nanojit::ABI_FASTCALL _JS_CI_NAME(name) };
211 * Declare a C function named <op> and a CallInfo struct named <op>_callinfo so the
212 * tracer can call it. |linkage| controls the visibility of both the function
213 * and the CallInfo global. It can be extern, static, or FRIEND, which
214 * specifies JS_FRIEND_API linkage for the function.
216 #define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold) \
217 _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), (_JS_CTYPE_TYPE(at0)), \
218 (_JS_CTYPE_ARGSIZE(at0) << 2) | _JS_CTYPE_RETSIZE(rt), cse, fold)
219 #define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, cse, fold) \
220 _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
221 (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1)), \
222 (_JS_CTYPE_ARGSIZE(at0) << 4) | (_JS_CTYPE_ARGSIZE(at1) << 2) | \
223 _JS_CTYPE_RETSIZE(rt), \
225 #define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, cse, fold) \
226 _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
227 (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2)), \
228 (_JS_CTYPE_ARGSIZE(at0) << 6) | (_JS_CTYPE_ARGSIZE(at1) << 4) | \
229 (_JS_CTYPE_ARGSIZE(at2) << 2) | _JS_CTYPE_RETSIZE(rt), \
231 #define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, cse, fold) \
232 _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
233 (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \
234 _JS_CTYPE_TYPE(at3)), \
235 (_JS_CTYPE_ARGSIZE(at0) << 8) | (_JS_CTYPE_ARGSIZE(at1) << 6) | \
236 (_JS_CTYPE_ARGSIZE(at2) << 4) | (_JS_CTYPE_ARGSIZE(at3) << 2) | \
237 _JS_CTYPE_RETSIZE(rt), \
239 #define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) \
240 _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
241 (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \
242 _JS_CTYPE_TYPE(at3), _JS_CTYPE_TYPE(at4)), \
243 (_JS_CTYPE_ARGSIZE(at0) << 10) | (_JS_CTYPE_ARGSIZE(at1) << 8) | \
244 (_JS_CTYPE_ARGSIZE(at2) << 6) | (_JS_CTYPE_ARGSIZE(at3) << 4) | \
245 (_JS_CTYPE_ARGSIZE(at4) << 2) | _JS_CTYPE_RETSIZE(rt), \
248 #define JS_DECLARE_CALLINFO(name) extern const nanojit::CallInfo _JS_CALLINFO(name);
250 #define _JS_TN_INIT_HELPER_n(n, args) _JS_TN_INIT_HELPER_##n args
252 #define _JS_TN_INIT_HELPER_1(linkage, rt, op, at0, cse, fold) \
254 _JS_CTYPE_PCH(at0), \
255 _JS_CTYPE_ACH(at0), \
258 #define _JS_TN_INIT_HELPER_2(linkage, rt, op, at0, at1, cse, fold) \
260 _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
261 _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1), \
264 #define _JS_TN_INIT_HELPER_3(linkage, rt, op, at0, at1, at2, cse, fold) \
266 _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
267 _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at2), \
270 #define _JS_TN_INIT_HELPER_4(linkage, rt, op, at0, at1, at2, at3, cse, fold) \
272 _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
273 _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at3), \
276 #define _JS_TN_INIT_HELPER_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) \
278 _JS_CTYPE_PCH(at4) _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) \
279 _JS_CTYPE_PCH(at0), \
280 _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at3) \
281 _JS_CTYPE_ACH(at4), \
284 #define JS_DEFINE_TRCINFO_1(name, tn0) \
285 _JS_DEFINE_CALLINFO_n tn0 \
286 JSTraceableNative name##_trcinfo[] = { \
287 { name, _JS_TN_INIT_HELPER_n tn0 } \
290 #define JS_DEFINE_TRCINFO_2(name, tn0, tn1) \
291 _JS_DEFINE_CALLINFO_n tn0 \
292 _JS_DEFINE_CALLINFO_n tn1 \
293 JSTraceableNative name##_trcinfo[] = { \
294 { name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
295 { name, _JS_TN_INIT_HELPER_n tn1 } \
298 #define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2) \
299 _JS_DEFINE_CALLINFO_n tn0 \
300 _JS_DEFINE_CALLINFO_n tn1 \
301 _JS_DEFINE_CALLINFO_n tn2 \
302 JSTraceableNative name##_trcinfo[] = { \
303 { name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
304 { name, _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \
305 { name, _JS_TN_INIT_HELPER_n tn2 } \
308 #define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3) \
309 _JS_DEFINE_CALLINFO_n tn0 \
310 _JS_DEFINE_CALLINFO_n tn1 \
311 _JS_DEFINE_CALLINFO_n tn2 \
312 _JS_DEFINE_CALLINFO_n tn3 \
313 JSTraceableNative name##_trcinfo[] = { \
314 { name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
315 { name, _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \
316 { name, _JS_TN_INIT_HELPER_n tn2 | JSTN_MORE }, \
317 { name, _JS_TN_INIT_HELPER_n tn3 } \
320 #define _JS_DEFINE_CALLINFO_n(n, args) JS_DEFINE_CALLINFO_##n args
323 js_StringToNumber(JSContext
* cx
, JSString
* str
);
326 js_BooleanOrUndefinedToNumber(JSContext
* cx
, int32 unboxed
);
330 #define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold)
331 #define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, cse, fold)
332 #define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, cse, fold)
333 #define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, cse, fold)
334 #define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold)
335 #define JS_DECLARE_CALLINFO(name)
336 #define JS_DEFINE_TRCINFO_1(name, tn0)
337 #define JS_DEFINE_TRCINFO_2(name, tn0, tn1)
338 #define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2)
339 #define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3)
341 #endif /* !JS_TRACER */
343 /* Defined in jsarray.cpp */
344 JS_DECLARE_CALLINFO(js_Array_dense_setelem
)
345 JS_DECLARE_CALLINFO(js_FastNewArray
)
346 JS_DECLARE_CALLINFO(js_NewUninitializedArray
)
347 JS_DECLARE_CALLINFO(js_FastNewArrayWithLength
)
348 JS_DECLARE_CALLINFO(js_Array_1str
)
350 /* Defined in jsdate.cpp */
351 JS_DECLARE_CALLINFO(js_FastNewDate
)
353 /* Defined in jsnum.cpp */
354 JS_DECLARE_CALLINFO(js_NumberToString
)
356 /* Defined in jsstr.cpp */
357 JS_DECLARE_CALLINFO(js_ConcatStrings
)
358 JS_DECLARE_CALLINFO(js_String_getelem
)
359 JS_DECLARE_CALLINFO(js_String_p_charCodeAt
)
360 JS_DECLARE_CALLINFO(js_EqualStrings
)
361 JS_DECLARE_CALLINFO(js_CompareStrings
)
363 /* Defined in jsbuiltins.cpp */
364 #define BUILTIN1(linkage, rt, op, at0, cse, fold) JS_DECLARE_CALLINFO(op)
365 #define BUILTIN2(linkage, rt, op, at0, at1, cse, fold) JS_DECLARE_CALLINFO(op)
366 #define BUILTIN3(linkage, rt, op, at0, at1, at2, cse, fold) JS_DECLARE_CALLINFO(op)
367 #define BUILTIN4(linkage, rt, op, at0, at1, at2, at3, cse, fold) JS_DECLARE_CALLINFO(op)
368 #define BUILTIN5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) JS_DECLARE_CALLINFO(op)
369 #include "builtins.tbl"
377 #endif /* jsbuiltins_h___ */