1 /* -*- Mode: C++; tab-width: 8; 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
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
20 * The Initial Developer of the Original Code is
21 * Andreas Gal <gal@mozilla.com>
24 * Brendan Eich <brendan@mozilla.org>
25 * Mike Shaver <shaver@mozilla.org>
26 * David Anderson <danderson@mozilla.com>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either of the GNU General Public License Version 2 or later (the "GPL"),
30 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
52 #include "jslibmath.h"
59 #include "jsbuiltins.h"
63 #include "jsatominlines.h"
64 #include "jsobjinlines.h"
65 #include "jsscopeinlines.h"
66 #include "jscntxtinlines.h"
68 using namespace avmplus;
69 using namespace nanojit;
73 js_SetTraceableNativeFailed(JSContext *cx)
76 * We might not be on trace (we might have deep bailed) so we hope
77 * cx->compartment is correct.
79 SetBuiltinError(JS_TRACE_MONITOR_FROM_CONTEXT(cx));
83 * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
84 * Do not use bool FASTCALL, use JSBool only!
88 js_dmod(jsdouble a, jsdouble b)
92 u.s.hi = JSDOUBLE_HI32_NAN;
93 u.s.lo = JSDOUBLE_LO32_NAN;
98 JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_dmod, DOUBLE, DOUBLE, 1, ACCSET_NONE)
101 js_imod(int32 a, int32 b)
108 JS_DEFINE_CALLINFO_2(extern, INT32, js_imod, INT32, INT32, 1, ACCSET_NONE)
110 #if JS_BITS_PER_WORD == 32
113 js_UnboxDouble(uint32 tag, uint32 payload)
115 if (tag == JSVAL_TAG_INT32)
116 return (double)(int32)payload;
119 l.s.tag = (JSValueTag)tag;
120 l.s.payload.u32 = payload;
123 JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_UnboxDouble, UINT32, UINT32, 1, ACCSET_NONE)
126 js_UnboxInt32(uint32 tag, uint32 payload)
128 if (tag == JSVAL_TAG_INT32)
129 return (int32)payload;
132 l.s.tag = (JSValueTag)tag;
133 l.s.payload.u32 = payload;
134 return js_DoubleToECMAInt32(l.asDouble);
136 JS_DEFINE_CALLINFO_2(extern, INT32, js_UnboxInt32, UINT32, UINT32, 1, ACCSET_NONE)
138 #elif JS_BITS_PER_WORD == 64
141 js_UnboxDouble(Value v)
144 return (jsdouble)v.toInt32();
147 JS_DEFINE_CALLINFO_1(extern, DOUBLE, js_UnboxDouble, JSVAL, 1, ACCSET_NONE)
150 js_UnboxInt32(Value v)
154 return js_DoubleToECMAInt32(v.toDouble());
156 JS_DEFINE_CALLINFO_1(extern, INT32, js_UnboxInt32, VALUE, 1, ACCSET_NONE)
161 js_DoubleToInt32(jsdouble d)
163 return js_DoubleToECMAInt32(d);
165 JS_DEFINE_CALLINFO_1(extern, INT32, js_DoubleToInt32, DOUBLE, 1, ACCSET_NONE)
168 js_DoubleToUint32(jsdouble d)
170 return js_DoubleToECMAUint32(d);
172 JS_DEFINE_CALLINFO_1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, ACCSET_NONE)
175 * js_StringToNumber and js_StringToInt32 store into their second argument, so
176 * they need to be annotated accordingly. To be future-proof, we use
177 * ACCSET_STORE_ANY so that new callers don't have to remember to update the
181 js_StringToNumber(JSContext* cx, JSString* str, JSBool *ok)
183 double out = 0; /* silence warnings. */
184 *ok = StringToNumberType<jsdouble>(cx, str, &out);
187 JS_DEFINE_CALLINFO_3(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, BOOLPTR,
191 js_StringToInt32(JSContext* cx, JSString* str, JSBool *ok)
193 int32 out = 0; /* silence warnings. */
194 *ok = StringToNumberType<int32>(cx, str, &out);
197 JS_DEFINE_CALLINFO_3(extern, INT32, js_StringToInt32, CONTEXT, STRING, BOOLPTR,
200 /* Nb: it's always safe to set isDefinitelyAtom to false if you're unsure or don't know. */
202 AddPropertyHelper(JSContext* cx, JSObject* obj, Shape* shape, bool isDefinitelyAtom)
204 JS_ASSERT(shape->previous() == obj->lastProperty());
206 if (obj->nativeEmpty()) {
207 if (!obj->ensureClassReservedSlotsForEmptyObject(cx))
213 JS_ASSERT(slot == obj->slotSpan());
215 if (slot < obj->numSlots()) {
216 JS_ASSERT(obj->getSlot(slot).isUndefined());
218 if (!obj->allocSlot(cx, &slot))
220 JS_ASSERT(slot == shape->slot);
223 obj->extend(cx, shape, isDefinitelyAtom);
224 return !js_IsPropertyCacheDisabled(cx);
228 js_AddProperty(JSContext* cx, JSObject* obj, Shape* shape)
230 return AddPropertyHelper(cx, obj, shape, /* isDefinitelyAtom = */false);
232 JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SHAPE, 0, ACCSET_STORE_ANY)
235 js_AddAtomProperty(JSContext* cx, JSObject* obj, Shape* shape)
237 return AddPropertyHelper(cx, obj, shape, /* isDefinitelyAtom = */true);
239 JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddAtomProperty, CONTEXT, OBJECT, SHAPE, 0, ACCSET_STORE_ANY)
242 HasProperty(JSContext* cx, JSObject* obj, jsid id)
244 // Check that we know how the lookup op will behave.
245 for (JSObject* pobj = obj; pobj; pobj = pobj->getProto()) {
246 if (pobj->getOps()->lookupProperty)
248 Class* clasp = pobj->getClass();
249 if (clasp->resolve != JS_ResolveStub && clasp != &js_StringClass)
255 if (js_LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) < 0)
261 js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
263 JSAtom *atom = js_AtomizeString(cx, idstr, 0);
267 return HasProperty(cx, obj, ATOM_TO_JSID(atom));
269 JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedProperty, CONTEXT, OBJECT, STRING,
273 js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index)
276 if (!js_Int32ToId(cx, index, &id))
279 return HasProperty(cx, obj, id);
281 JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedPropertyInt32, CONTEXT, OBJECT, INT32,
285 js_TypeOfObject(JSContext* cx, JSObject* obj)
288 return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[obj->typeOf(cx)]);
290 JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfObject, CONTEXT, OBJECT, 1, ACCSET_NONE)
293 js_BooleanIntToString(JSContext *cx, int32 unboxed)
295 JS_ASSERT(uint32(unboxed) <= 1);
296 return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]);
298 JS_DEFINE_CALLINFO_2(extern, STRING, js_BooleanIntToString, CONTEXT, INT32, 1, ACCSET_NONE)
301 js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* parent)
303 JS_ASSERT(funobj->isFunction());
304 JS_ASSERT(proto->isFunction());
305 JS_ASSERT(JS_ON_TRACE(cx));
307 JSFunction *fun = (JSFunction*) funobj;
308 JS_ASSERT(GET_FUNCTION_PRIVATE(cx, funobj) == fun);
310 JSObject* closure = js_NewGCObject(cx, gc::FINALIZE_OBJECT2);
314 if (!closure->initSharingEmptyShape(cx, &js_FunctionClass, proto, parent,
315 fun, gc::FINALIZE_OBJECT2)) {
320 JS_DEFINE_CALLINFO_4(extern, OBJECT, js_NewNullClosure, CONTEXT, OBJECT, OBJECT, OBJECT,