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

Contents of /trunk/js/jsbuiltins.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

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
61 using namespace avmplus;
62 using namespace nanojit;
63
64 extern 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
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 int32 FASTCALL
92 js_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
104 jsval FASTCALL
105 js_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
117 jsval FASTCALL
118 js_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
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 int32 FASTCALL
139 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 uint32 FASTCALL
153 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 int32 FASTCALL
177 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 return js_DoubleToECMAInt32(d);
188 }
189
190 static inline JSBool
191 js_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
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 js_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
237 JSBool FASTCALL
238 js_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
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 SideExit* FASTCALL
264 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 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
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 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
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 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
417 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 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 js_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
459 jsdouble FASTCALL
460 js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed)
461 {
462 if (unboxed == JSVAL_TO_BOOLEAN(JSVAL_VOID))
463 return js_NaN;
464 return unboxed;
465 }
466
467 JSString* FASTCALL
468 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 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 #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"

  ViewVC Help
Powered by ViewVC 1.1.24