PageRenderTime 37ms CodeModel.GetById 2ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/js/jsbuiltins.cpp

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
C++ | 497 lines | 385 code | 58 blank | 54 comment | 76 complexity | 4967552c23efce3e90821ec1020bc059 MD5 | raw file
  1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; -*-
  2 * vim: set ts=8 sw=4 et tw=99:
  3 *
  4 * ***** BEGIN LICENSE BLOCK *****
  5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6 *
  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/
 11 *
 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.
 16 *
 17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
 18 * May 28, 2008.
 19 *
 20 * The Initial Developer of the Original Code is
 21 *   Andreas Gal <gal@mozilla.com>
 22 *
 23 * Contributor(s):
 24 *   Brendan Eich <brendan@mozilla.org>
 25 *   Mike Shaver <shaver@mozilla.org>
 26 *   David Anderson <danderson@mozilla.com>
 27 *
 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.
 39 *
 40 * ***** END LICENSE BLOCK ***** */
 41
 42#include "jsstddef.h"
 43#include <math.h>
 44
 45#include "jsapi.h"
 46#include "jsarray.h"
 47#include "jsbool.h"
 48#include "jscntxt.h"
 49#include "jsgc.h"
 50#include "jsiter.h"
 51#include "jslibmath.h"
 52#include "jsmath.h"
 53#include "jsnum.h"
 54#include "prmjtime.h"
 55#include "jsdate.h"
 56#include "jsscope.h"
 57#include "jsstr.h"
 58#include "jsbuiltins.h"
 59#include "jstracer.h"
 60
 61using namespace avmplus;
 62using namespace nanojit;
 63
 64extern jsdouble js_NaN;
 65
 66/*
 67 * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
 68 * Do not use bool FASTCALL, use JSBool only!
 69 */
 70
 71jsdouble FASTCALL
 72js_dmod(jsdouble a, jsdouble b)
 73{
 74    if (b == 0.0) {
 75        jsdpun u;
 76        u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
 77        u.s.lo = 0xffffffff;
 78        return u.d;
 79    }
 80    jsdouble r;
 81#ifdef XP_WIN
 82    /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
 83    if (JSDOUBLE_IS_FINITE(a) && JSDOUBLE_IS_INFINITE(b))
 84        r = a;
 85    else
 86#endif
 87        r = fmod(a, b);
 88    return r;
 89}
 90
 91int32 FASTCALL
 92js_imod(int32 a, int32 b)
 93{
 94    if (a < 0 || b <= 0)
 95        return -1;
 96    int r = a % b;
 97    return r;
 98}
 99
100/* The following boxing/unboxing primitives we can't emit inline because
101   they either interact with the GC and depend on Spidermonkey's 32-bit
102   integer representation. */
103
104jsval FASTCALL
105js_BoxDouble(JSContext* cx, jsdouble d)
106{
107    int32 i;
108    if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i))
109        return INT_TO_JSVAL(i);
110    JS_ASSERT(JS_ON_TRACE(cx));
111    jsval v; /* not rooted but ok here because we know GC won't run */
112    if (!js_NewDoubleInRootedValue(cx, d, &v))
113        return JSVAL_ERROR_COOKIE;
114    return v;
115}
116
117jsval FASTCALL
118js_BoxInt32(JSContext* cx, int32 i)
119{
120    if (JS_LIKELY(INT_FITS_IN_JSVAL(i)))
121        return INT_TO_JSVAL(i);
122    JS_ASSERT(JS_ON_TRACE(cx));
123    jsval v; /* not rooted but ok here because we know GC won't run */
124    jsdouble d = (jsdouble)i;
125    if (!js_NewDoubleInRootedValue(cx, d, &v))
126        return JSVAL_ERROR_COOKIE;
127    return v;
128} 
129
130jsdouble FASTCALL
131js_UnboxDouble(jsval v)
132{
133    if (JS_LIKELY(JSVAL_IS_INT(v)))
134        return (jsdouble)JSVAL_TO_INT(v);
135    return *JSVAL_TO_DOUBLE(v);
136}
137
138int32 FASTCALL
139js_UnboxInt32(jsval v)
140{
141    if (JS_LIKELY(JSVAL_IS_INT(v)))
142        return JSVAL_TO_INT(v);
143    return js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v));
144}
145
146int32 FASTCALL
147js_DoubleToInt32(jsdouble d)
148{
149    return js_DoubleToECMAInt32(d);
150}
151
152uint32 FASTCALL
153js_DoubleToUint32(jsdouble d)
154{
155    return js_DoubleToECMAUint32(d);
156}
157
158jsdouble FASTCALL
159js_StringToNumber(JSContext* cx, JSString* str)
160{
161    const jschar* bp;
162    const jschar* end;
163    const jschar* ep;
164    jsdouble d;
165
166    JSSTRING_CHARS_AND_END(str, bp, end);
167    if ((!js_strtod(cx, bp, end, &ep, &d) ||
168         js_SkipWhiteSpace(ep, end) != end) &&
169        (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
170         js_SkipWhiteSpace(ep, end) != end)) {
171        return js_NaN;
172    }
173    return d;
174}
175
176int32 FASTCALL
177js_StringToInt32(JSContext* cx, JSString* str)
178{
179    const jschar* bp;
180    const jschar* end;
181    const jschar* ep;
182    jsdouble d;
183
184    JSSTRING_CHARS_AND_END(str, bp, end);
185    if (!js_strtod(cx, bp, end, &ep, &d) || js_SkipWhiteSpace(ep, end) != end)
186        return 0;
187    return js_DoubleToECMAInt32(d);
188}
189
190static inline JSBool
191js_Int32ToId(JSContext* cx, int32 index, jsid* id)
192{
193    if (index <= JSVAL_INT_MAX) {
194        *id = INT_TO_JSID(index);
195        return JS_TRUE;
196    }
197    JSString* str = js_NumberToString(cx, index);
198    if (!str)
199        return JS_FALSE;
200    return js_ValueToStringId(cx, STRING_TO_JSVAL(str), id);
201}
202
203jsval FASTCALL
204js_Any_getprop(JSContext* cx, JSObject* obj, JSString* idstr)
205{
206    jsval v;
207    jsid id;
208
209    if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
210        return JSVAL_ERROR_COOKIE;
211    if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
212        return JSVAL_ERROR_COOKIE;
213    return v;
214}
215
216JSBool FASTCALL
217js_Any_setprop(JSContext* cx, JSObject* obj, JSString* idstr, jsval v)
218{
219    jsid id;
220    if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
221        return JS_FALSE;
222    return OBJ_SET_PROPERTY(cx, obj, id, &v);
223}
224
225jsval FASTCALL
226js_Any_getelem(JSContext* cx, JSObject* obj, int32 index)
227{
228    jsval v;
229    jsid id;
230    if (!js_Int32ToId(cx, index, &id))
231        return JSVAL_ERROR_COOKIE;
232    if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
233        return JSVAL_ERROR_COOKIE;
234    return v;
235}
236
237JSBool FASTCALL
238js_Any_setelem(JSContext* cx, JSObject* obj, int32 index, jsval v)
239{
240    jsid id;
241    if (!js_Int32ToId(cx, index, &id))
242        return JSVAL_ERROR_COOKIE;
243    return OBJ_SET_PROPERTY(cx, obj, id, &v);
244}
245
246JSObject* FASTCALL
247js_FastValueToIterator(JSContext* cx, jsuint flags, jsval v)
248{
249    if (!js_ValueToIterator(cx, flags, &v))
250        return NULL;
251    return JSVAL_TO_OBJECT(v);
252}
253
254jsval FASTCALL
255js_FastCallIteratorNext(JSContext* cx, JSObject* iterobj)
256{
257    jsval v;
258    if (!js_CallIteratorNext(cx, iterobj, &v))
259        return JSVAL_ERROR_COOKIE;
260    return v;
261}
262
263SideExit* FASTCALL
264js_CallTree(InterpState* state, Fragment* f)
265{
266    union { NIns *code; GuardRecord* (FASTCALL *func)(InterpState*, Fragment*); } u;
267
268    u.code = f->code();
269    JS_ASSERT(u.code);
270
271    GuardRecord* rec;
272#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
273    SIMULATE_FASTCALL(rec, state, NULL, u.func);
274#else
275    rec = u.func(state, NULL);
276#endif
277    VMSideExit* lr = (VMSideExit*)rec->exit;
278
279    if (lr->exitType == NESTED_EXIT) {
280        /* This only occurs once a tree call guard mismatches and we unwind the tree call stack.
281           We store the first (innermost) tree call guard in state and we will try to grow
282           the outer tree the failing call was in starting at that guard. */
283        if (!state->lastTreeCallGuard) {
284            state->lastTreeCallGuard = lr;
285            FrameInfo* rp = (FrameInfo*)state->rp;
286            state->rpAtLastTreeCall = rp + lr->calldepth;
287        }
288    } else {
289        /* If the tree exits on a regular (non-nested) guard, keep updating lastTreeExitGuard
290           with that guard. If we mismatch on a tree call guard, this will contain the last
291           non-nested guard we encountered, which is the innermost loop or branch guard. */
292        state->lastTreeExitGuard = lr;
293    }
294
295    return lr;
296}
297
298JSObject* FASTCALL
299js_FastNewObject(JSContext* cx, JSObject* ctor)
300{
301    JS_ASSERT(HAS_FUNCTION_CLASS(ctor));
302    JSFunction* fun = GET_FUNCTION_PRIVATE(cx, ctor);
303    JSClass* clasp = (FUN_INTERPRETED(fun) || (fun->flags & JSFUN_TRACEABLE))
304                     ? &js_ObjectClass
305                     : FUN_CLASP(fun);
306    JS_ASSERT(clasp != &js_ArrayClass);
307
308    JS_LOCK_OBJ(cx, ctor);
309    JSScope *scope = OBJ_SCOPE(ctor);
310    JS_ASSERT(scope->object == ctor);
311    JSAtom* atom = cx->runtime->atomState.classPrototypeAtom;
312
313    JSScopeProperty *sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));
314    JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, scope));
315    jsval v = LOCKED_OBJ_GET_SLOT(ctor, sprop->slot);
316    JS_UNLOCK_SCOPE(cx, scope);
317
318    JSObject* proto;
319    if (JSVAL_IS_PRIMITIVE(v)) {
320        if (!js_GetClassPrototype(cx, JSVAL_TO_OBJECT(ctor->fslots[JSSLOT_PARENT]), 
321                                  INT_TO_JSID(JSProto_Object), &proto)) {
322            return NULL;
323        }
324    } else {
325        proto = JSVAL_TO_OBJECT(v);
326    }
327
328    JS_ASSERT(JS_ON_TRACE(cx));
329    JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
330    if (!obj)
331        return NULL;
332
333    obj->classword = jsuword(clasp);
334    obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
335    obj->fslots[JSSLOT_PARENT] = ctor->fslots[JSSLOT_PARENT];
336    for (unsigned i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
337        obj->fslots[i] = JSVAL_VOID;
338
339    obj->map = js_HoldObjectMap(cx, proto->map);
340    obj->dslots = NULL;
341    return obj;
342}
343
344JSBool FASTCALL
345js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
346{
347    JSScopeProperty* sprop2 = NULL; // initialize early to make MSVC happy
348
349    JS_ASSERT(OBJ_IS_NATIVE(obj));
350    JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop));
351
352    JS_LOCK_OBJ(cx, obj);
353    JSScope* scope = OBJ_SCOPE(obj);
354    if (scope->object == obj) {
355        JS_ASSERT(!SCOPE_HAS_PROPERTY(scope, sprop));
356    } else {
357        scope = js_GetMutableScope(cx, obj);
358        if (!scope) {
359            JS_UNLOCK_OBJ(cx, obj);
360            return JS_FALSE;
361        }
362    }
363
364    uint32 slot = sprop->slot;
365    if (!scope->table && sprop->parent == scope->lastProp && slot == scope->map.freeslot) {
366        if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
367            JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->map.freeslot)));
368            ++scope->map.freeslot;
369        } else {
370            if (!js_AllocSlot(cx, obj, &slot)) {
371                JS_UNLOCK_SCOPE(cx, scope);
372                return JS_FALSE;
373            }
374
375            if (slot != sprop->slot)
376                goto slot_changed;
377        }
378
379        SCOPE_EXTEND_SHAPE(cx, scope, sprop);
380        ++scope->entryCount;
381        scope->lastProp = sprop;
382        JS_UNLOCK_SCOPE(cx, scope);
383        return JS_TRUE;
384    }
385
386    sprop2 = js_AddScopeProperty(cx, scope, sprop->id,
387                                 sprop->getter, sprop->setter, SPROP_INVALID_SLOT,
388                                 sprop->attrs, sprop->flags, sprop->shortid);
389    if (sprop2 == sprop) {
390        JS_UNLOCK_SCOPE(cx, scope);
391        return JS_TRUE;
392    }
393    slot = sprop2->slot;
394
395  slot_changed:
396    js_FreeSlot(cx, obj, slot);
397    JS_UNLOCK_SCOPE(cx, scope);
398    return JS_FALSE;
399}
400
401JSBool FASTCALL
402js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
403{
404    jsid id;
405    if (!obj || !js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
406        return JSVAL_TO_BOOLEAN(JSVAL_VOID);
407
408    JSObject* obj2;
409    JSProperty* prop;
410    if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
411        return JSVAL_TO_BOOLEAN(JSVAL_VOID);
412    if (prop)
413        OBJ_DROP_PROPERTY(cx, obj2, prop);
414    return prop != NULL;
415}
416
417JSBool FASTCALL
418js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index)
419{
420    jsid id;
421    if (!obj || !js_Int32ToId(cx, index, &id))
422        return JSVAL_TO_BOOLEAN(JSVAL_VOID);
423
424    JSObject* obj2;
425    JSProperty* prop;
426    if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
427        return JSVAL_TO_BOOLEAN(JSVAL_VOID);
428    if (prop)
429        OBJ_DROP_PROPERTY(cx, obj2, prop);
430    return prop != NULL;
431}
432
433jsval FASTCALL
434js_CallGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
435{
436    JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop));
437    jsval v;
438    if (!SPROP_GET(cx, sprop, obj, obj, &v))
439        return JSVAL_ERROR_COOKIE;
440    return v;
441}
442
443JSString* FASTCALL
444js_TypeOfObject(JSContext* cx, JSObject* obj)
445{
446    JSType type = JS_TypeOfValue(cx, OBJECT_TO_JSVAL(obj));
447    return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
448}
449
450JSString* FASTCALL
451js_TypeOfBoolean(JSContext* cx, int32 unboxed)
452{
453    jsval boxed = BOOLEAN_TO_JSVAL(unboxed);
454    JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed));
455    JSType type = JS_TypeOfValue(cx, boxed);
456    return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
457}
458
459jsdouble FASTCALL
460js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed)
461{
462    if (unboxed == JSVAL_TO_BOOLEAN(JSVAL_VOID))
463        return js_NaN;
464    return unboxed;
465}
466
467JSString* FASTCALL
468js_BooleanOrUndefinedToString(JSContext *cx, int32 unboxed)
469{
470    JS_ASSERT(uint32(unboxed) <= 2);
471    return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]);
472}
473
474JSString* FASTCALL
475js_ObjectToString(JSContext* cx, JSObject* obj)
476{
477    if (!obj)
478        return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
479    jsval v;
480    if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
481        return NULL;
482    JS_ASSERT(JSVAL_IS_STRING(v));
483    return JSVAL_TO_STRING(v);
484}
485
486JSObject* FASTCALL
487js_Arguments(JSContext* cx)
488{
489    return NULL;
490}
491
492#define BUILTIN1 JS_DEFINE_CALLINFO_1
493#define BUILTIN2 JS_DEFINE_CALLINFO_2
494#define BUILTIN3 JS_DEFINE_CALLINFO_3
495#define BUILTIN4 JS_DEFINE_CALLINFO_4
496#define BUILTIN5 JS_DEFINE_CALLINFO_5
497#include "builtins.tbl"