/[jscoverage]/trunk/js/jsbuiltins.cpp
ViewVC logotype

Annotation of /trunk/js/jsbuiltins.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 399 - (hide annotations)
Tue Dec 9 03:37:47 2008 UTC (11 years, 1 month ago) by siliconforks
File size: 13959 byte(s)
Use SpiderMonkey from Firefox 3.1b2.

1 siliconforks 399 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; -*-
2 siliconforks 332 * 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 siliconforks 399 #include "jsdate.h"
56 siliconforks 332 #include "jsscope.h"
57     #include "jsstr.h"
58 siliconforks 399 #include "jsbuiltins.h"
59 siliconforks 332 #include "jstracer.h"
60    
61     using namespace avmplus;
62     using namespace nanojit;
63    
64 siliconforks 399 extern jsdouble js_NaN;
65    
66 siliconforks 332 /*
67     * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
68     * Do not use bool FASTCALL, use JSBool only!
69     */
70    
71     jsdouble FASTCALL
72     js_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    
91 siliconforks 399 int32 FASTCALL
92     js_imod(int32 a, int32 b)
93 siliconforks 332 {
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    
104     jsval FASTCALL
105     js_BoxDouble(JSContext* cx, jsdouble d)
106     {
107 siliconforks 399 int32 i;
108     if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i))
109 siliconforks 332 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    
117     jsval FASTCALL
118 siliconforks 399 js_BoxInt32(JSContext* cx, int32 i)
119 siliconforks 332 {
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    
130     jsdouble FASTCALL
131     js_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    
138 siliconforks 399 int32 FASTCALL
139 siliconforks 332 js_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    
146     int32 FASTCALL
147     js_DoubleToInt32(jsdouble d)
148     {
149     return js_DoubleToECMAInt32(d);
150     }
151    
152 siliconforks 399 uint32 FASTCALL
153 siliconforks 332 js_DoubleToUint32(jsdouble d)
154     {
155     return js_DoubleToECMAUint32(d);
156     }
157    
158     jsdouble FASTCALL
159     js_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    
176 siliconforks 399 int32 FASTCALL
177 siliconforks 332 js_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 siliconforks 399 return js_DoubleToECMAInt32(d);
188 siliconforks 332 }
189    
190 siliconforks 399 static inline JSBool
191     js_Int32ToId(JSContext* cx, int32 index, jsid* id)
192 siliconforks 332 {
193 siliconforks 399 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 siliconforks 332 }
202    
203     jsval FASTCALL
204     js_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    
216     JSBool FASTCALL
217     js_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    
225     jsval FASTCALL
226 siliconforks 399 js_Any_getelem(JSContext* cx, JSObject* obj, int32 index)
227 siliconforks 332 {
228     jsval v;
229     jsid id;
230 siliconforks 399 if (!js_Int32ToId(cx, index, &id))
231 siliconforks 332 return JSVAL_ERROR_COOKIE;
232     if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
233     return JSVAL_ERROR_COOKIE;
234     return v;
235     }
236    
237     JSBool FASTCALL
238 siliconforks 399 js_Any_setelem(JSContext* cx, JSObject* obj, int32 index, jsval v)
239 siliconforks 332 {
240     jsid id;
241 siliconforks 399 if (!js_Int32ToId(cx, index, &id))
242 siliconforks 332 return JSVAL_ERROR_COOKIE;
243     return OBJ_SET_PROPERTY(cx, obj, id, &v);
244     }
245    
246     JSObject* FASTCALL
247     js_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    
254     jsval FASTCALL
255     js_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    
263 siliconforks 399 SideExit* FASTCALL
264 siliconforks 332 js_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 siliconforks 399 GuardRecord* rec;
272 siliconforks 332 #if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
273 siliconforks 399 SIMULATE_FASTCALL(rec, state, NULL, u.func);
274 siliconforks 332 #else
275 siliconforks 399 rec = u.func(state, NULL);
276 siliconforks 332 #endif
277 siliconforks 399 VMSideExit* lr = (VMSideExit*)rec->exit;
278 siliconforks 332
279 siliconforks 399 if (lr->exitType == NESTED_EXIT) {
280 siliconforks 332 /* 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 siliconforks 399 if (!state->lastTreeCallGuard) {
284 siliconforks 332 state->lastTreeCallGuard = lr;
285 siliconforks 399 FrameInfo* rp = (FrameInfo*)state->rp;
286     state->rpAtLastTreeCall = rp + lr->calldepth;
287     }
288 siliconforks 332 } 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    
298     JSObject* FASTCALL
299     js_FastNewObject(JSContext* cx, JSObject* ctor)
300     {
301     JS_ASSERT(HAS_FUNCTION_CLASS(ctor));
302     JSFunction* fun = GET_FUNCTION_PRIVATE(cx, ctor);
303 siliconforks 399 JSClass* clasp = (FUN_INTERPRETED(fun) || (fun->flags & JSFUN_TRACEABLE))
304     ? &js_ObjectClass
305     : FUN_CLASP(fun);
306 siliconforks 332 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    
344     JSBool FASTCALL
345     js_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    
401     JSBool FASTCALL
402     js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
403     {
404     jsid id;
405 siliconforks 399 if (!obj || !js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
406     return JSVAL_TO_BOOLEAN(JSVAL_VOID);
407 siliconforks 332
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    
417 siliconforks 399 JSBool FASTCALL
418     js_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    
433 siliconforks 332 jsval FASTCALL
434     js_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    
443     JSString* FASTCALL
444     js_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    
450     JSString* FASTCALL
451 siliconforks 399 js_TypeOfBoolean(JSContext* cx, int32 unboxed)
452 siliconforks 332 {
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    
459     jsdouble FASTCALL
460 siliconforks 399 js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed)
461 siliconforks 332 {
462     if (unboxed == JSVAL_TO_BOOLEAN(JSVAL_VOID))
463     return js_NaN;
464     return unboxed;
465     }
466    
467     JSString* FASTCALL
468 siliconforks 399 js_BooleanOrUndefinedToString(JSContext *cx, int32 unboxed)
469     {
470     JS_ASSERT(uint32(unboxed) <= 2);
471     return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]);
472     }
473    
474     JSString* FASTCALL
475 siliconforks 332 js_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    
486     JSObject* FASTCALL
487     js_Arguments(JSContext* cx)
488     {
489     return NULL;
490     }
491    
492 siliconforks 399 #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 siliconforks 332 #include "builtins.tbl"

  ViewVC Help
Powered by ViewVC 1.1.24