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

Contents of /trunk/js/jsbuiltins.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 332 - (show annotations)
Thu Oct 23 19:03:33 2008 UTC (10 years, 10 months ago) by siliconforks
File size: 26154 byte(s)
Add SpiderMonkey from Firefox 3.1b1.

The following directories and files were removed:
correct/, correct.js
liveconnect/
nanojit/
t/
v8/
vprof/
xpconnect/
all JavaScript files (Y.js, call.js, if.js, math-partial-sums.js, md5.js, perfect.js, trace-test.js, trace.js)


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 "jsscope.h"
56 #include "jsstr.h"
57 #include "jstracer.h"
58
59 #include "nanojit/avmplus.h"
60 #include "nanojit/nanojit.h"
61
62 using namespace avmplus;
63 using namespace nanojit;
64
65 /*
66 * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
67 * Do not use bool FASTCALL, use JSBool only!
68 */
69
70 jsdouble FASTCALL
71 js_dmod(jsdouble a, jsdouble b)
72 {
73 if (b == 0.0) {
74 jsdpun u;
75 u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
76 u.s.lo = 0xffffffff;
77 return u.d;
78 }
79 jsdouble r;
80 #ifdef XP_WIN
81 /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
82 if (JSDOUBLE_IS_FINITE(a) && JSDOUBLE_IS_INFINITE(b))
83 r = a;
84 else
85 #endif
86 r = fmod(a, b);
87 return r;
88 }
89
90 jsint FASTCALL
91 js_imod(jsint a, jsint b)
92 {
93 if (a < 0 || b <= 0)
94 return -1;
95 int r = a % b;
96 return r;
97 }
98
99 /* The following boxing/unboxing primitives we can't emit inline because
100 they either interact with the GC and depend on Spidermonkey's 32-bit
101 integer representation. */
102
103 jsval FASTCALL
104 js_BoxDouble(JSContext* cx, jsdouble d)
105 {
106 jsint i;
107 if (JSDOUBLE_IS_INT(d, i))
108 return INT_TO_JSVAL(i);
109 JS_ASSERT(JS_ON_TRACE(cx));
110 jsval v; /* not rooted but ok here because we know GC won't run */
111 if (!js_NewDoubleInRootedValue(cx, d, &v))
112 return JSVAL_ERROR_COOKIE;
113 return v;
114 }
115
116 jsval FASTCALL
117 js_BoxInt32(JSContext* cx, jsint i)
118 {
119 if (JS_LIKELY(INT_FITS_IN_JSVAL(i)))
120 return INT_TO_JSVAL(i);
121 JS_ASSERT(JS_ON_TRACE(cx));
122 jsval v; /* not rooted but ok here because we know GC won't run */
123 jsdouble d = (jsdouble)i;
124 if (!js_NewDoubleInRootedValue(cx, d, &v))
125 return JSVAL_ERROR_COOKIE;
126 return v;
127 }
128
129 jsdouble FASTCALL
130 js_UnboxDouble(jsval v)
131 {
132 if (JS_LIKELY(JSVAL_IS_INT(v)))
133 return (jsdouble)JSVAL_TO_INT(v);
134 return *JSVAL_TO_DOUBLE(v);
135 }
136
137 jsint FASTCALL
138 js_UnboxInt32(jsval v)
139 {
140 if (JS_LIKELY(JSVAL_IS_INT(v)))
141 return JSVAL_TO_INT(v);
142 return js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v));
143 }
144
145 int32 FASTCALL
146 js_DoubleToInt32(jsdouble d)
147 {
148 return js_DoubleToECMAInt32(d);
149 }
150
151 int32 FASTCALL
152 js_DoubleToUint32(jsdouble d)
153 {
154 return js_DoubleToECMAUint32(d);
155 }
156
157 jsdouble FASTCALL
158 js_Math_sin(jsdouble d)
159 {
160 return sin(d);
161 }
162
163 jsdouble FASTCALL
164 js_Math_cos(jsdouble d)
165 {
166 return cos(d);
167 }
168
169 jsdouble FASTCALL
170 js_Math_floor(jsdouble d)
171 {
172 return floor(d);
173 }
174
175 jsdouble FASTCALL
176 js_Math_ceil(jsdouble d)
177 {
178 return ceil(d);
179 }
180
181 extern jsdouble js_NaN;
182
183 jsdouble FASTCALL
184 js_Math_pow(jsdouble d, jsdouble p)
185 {
186 if (!JSDOUBLE_IS_FINITE(p) && (d == 1.0 || d == -1.0))
187 return js_NaN;
188 if (p == 0)
189 return 1.0;
190 return pow(d, p);
191 }
192
193 jsdouble FASTCALL
194 js_Math_sqrt(jsdouble d)
195 {
196 return sqrt(d);
197 }
198
199 jsdouble FASTCALL
200 js_Math_log(jsdouble d)
201 {
202 #if !JS_USE_FDLIBM_MATH && defined(SOLARIS) && defined(__GNUC__)
203 if (d < 0)
204 return js_NaN;
205 #endif
206 return log(d);
207 }
208
209 jsdouble FASTCALL
210 js_Math_max(jsdouble d, jsdouble p)
211 {
212 if (JSDOUBLE_IS_NaN(d) || JSDOUBLE_IS_NaN(p))
213 return js_NaN;
214
215 if (p == 0 && p == d && fd_copysign(1.0, d) == -1)
216 return p;
217 return (d > p) ? d : p;
218 }
219
220 JSBool FASTCALL
221 js_Array_dense_setelem(JSContext* cx, JSObject* obj, jsint i, jsval v)
222 {
223 JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
224
225 jsuint length = ARRAY_DENSE_LENGTH(obj);
226 if ((jsuint)i < length) {
227 if (obj->dslots[i] == JSVAL_HOLE) {
228 if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])
229 obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
230 obj->fslots[JSSLOT_ARRAY_COUNT]++;
231 }
232 obj->dslots[i] = v;
233 return JS_TRUE;
234 }
235 return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(i), &v);
236 }
237
238 JSString* FASTCALL
239 js_Array_p_join(JSContext* cx, JSObject* obj, JSString *str)
240 {
241 jsval v;
242 if (!js_array_join_sub(cx, obj, TO_STRING, str, &v))
243 return NULL;
244 JS_ASSERT(JSVAL_IS_STRING(v));
245 return JSVAL_TO_STRING(v);
246 }
247
248 jsval FASTCALL
249 js_Array_p_push1(JSContext* cx, JSObject* obj, jsval v)
250 {
251 if (!(OBJ_IS_DENSE_ARRAY(cx, obj)
252 ? js_array_push1_dense(cx, obj, v, &v)
253 : js_array_push_slowly(cx, obj, 1, &v, &v))) {
254 return JSVAL_ERROR_COOKIE;
255 }
256 return v;
257 }
258
259 jsval FASTCALL
260 js_Array_p_pop(JSContext* cx, JSObject* obj)
261 {
262 jsval v;
263 if (!(OBJ_IS_DENSE_ARRAY(cx, obj)
264 ? js_array_pop_dense(cx, obj, &v)
265 : js_array_pop_slowly(cx, obj, &v))) {
266 return JSVAL_ERROR_COOKIE;
267 }
268 return v;
269 }
270
271 JSString* FASTCALL
272 js_String_p_substring(JSContext* cx, JSString* str, jsint begin, jsint end)
273 {
274 JS_ASSERT(end >= begin);
275 JS_ASSERT(JS_ON_TRACE(cx));
276 return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
277 }
278
279 JSString* FASTCALL
280 js_String_p_substring_1(JSContext* cx, JSString* str, jsint begin)
281 {
282 jsint end = JSSTRING_LENGTH(str);
283 JS_ASSERT(end >= begin);
284 JS_ASSERT(JS_ON_TRACE(cx));
285 return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
286 }
287
288 JSString* FASTCALL
289 js_String_getelem(JSContext* cx, JSString* str, jsint i)
290 {
291 if ((size_t)i >= JSSTRING_LENGTH(str))
292 return NULL;
293 return js_GetUnitString(cx, str, (size_t)i);
294 }
295
296 JSString* FASTCALL
297 js_String_fromCharCode(JSContext* cx, jsint i)
298 {
299 JS_ASSERT(JS_ON_TRACE(cx));
300 jschar c = (jschar)i;
301 if (c < UNIT_STRING_LIMIT)
302 return js_GetUnitStringForChar(cx, c);
303 return js_NewStringCopyN(cx, &c, 1);
304 }
305
306 jsint FASTCALL
307 js_String_p_charCodeAt(JSString* str, jsint i)
308 {
309 if (i < 0 || (jsint)JSSTRING_LENGTH(str) <= i)
310 return -1;
311 return JSSTRING_CHARS(str)[i];
312 }
313
314 jsdouble FASTCALL
315 js_Math_random(JSRuntime* rt)
316 {
317 JS_LOCK_RUNTIME(rt);
318 js_random_init(rt);
319 jsdouble z = js_random_nextDouble(rt);
320 JS_UNLOCK_RUNTIME(rt);
321 return z;
322 }
323
324 JSString* FASTCALL
325 js_String_p_concat_1int(JSContext* cx, JSString* str, jsint i)
326 {
327 // FIXME: should be able to use stack buffer and avoid istr...
328 JSString* istr = js_NumberToString(cx, i);
329 if (!istr)
330 return NULL;
331 return js_ConcatStrings(cx, str, istr);
332 }
333
334 JSString* FASTCALL
335 js_String_p_concat_2str(JSContext* cx, JSString* str, JSString* a, JSString* b)
336 {
337 str = js_ConcatStrings(cx, str, a);
338 if (str)
339 return js_ConcatStrings(cx, str, b);
340 return NULL;
341 }
342
343 JSString* FASTCALL
344 js_String_p_concat_3str(JSContext* cx, JSString* str, JSString* a, JSString* b, JSString* c)
345 {
346 str = js_ConcatStrings(cx, str, a);
347 if (str) {
348 str = js_ConcatStrings(cx, str, b);
349 if (str)
350 return js_ConcatStrings(cx, str, c);
351 }
352 return NULL;
353 }
354
355 JSObject* FASTCALL
356 js_String_p_match(JSContext* cx, JSString* str, jsbytecode *pc, JSObject* regexp)
357 {
358 jsval vp[3] = { JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
359 if (!js_StringMatchHelper(cx, 1, vp, pc))
360 return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
361 JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
362 (!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
363 return JSVAL_TO_OBJECT(vp[0]);
364 }
365
366 JSObject* FASTCALL
367 js_String_p_match_obj(JSContext* cx, JSObject* str, jsbytecode *pc, JSObject* regexp)
368 {
369 jsval vp[3] = { JSVAL_NULL, OBJECT_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
370 if (!js_StringMatchHelper(cx, 1, vp, pc))
371 return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
372 JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
373 (!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
374 return JSVAL_TO_OBJECT(vp[0]);
375 }
376
377 JSString* FASTCALL
378 js_String_p_replace_str(JSContext* cx, JSString* str, JSObject* regexp, JSString* repstr)
379 {
380 jsval vp[4] = {
381 JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp), STRING_TO_JSVAL(repstr)
382 };
383 if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
384 return NULL;
385 JS_ASSERT(JSVAL_IS_STRING(vp[0]));
386 return JSVAL_TO_STRING(vp[0]);
387 }
388
389 JSString* FASTCALL
390 js_String_p_replace_str2(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr)
391 {
392 jsval vp[4] = {
393 JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr)
394 };
395 if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
396 return NULL;
397 JS_ASSERT(JSVAL_IS_STRING(vp[0]));
398 return JSVAL_TO_STRING(vp[0]);
399 }
400
401 JSString* FASTCALL
402 js_String_p_replace_str3(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr,
403 JSString* flagstr)
404 {
405 jsval vp[5] = {
406 JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr),
407 STRING_TO_JSVAL(flagstr)
408 };
409 if (!js_StringReplaceHelper(cx, 3, NULL, repstr, vp))
410 return NULL;
411 JS_ASSERT(JSVAL_IS_STRING(vp[0]));
412 return JSVAL_TO_STRING(vp[0]);
413 }
414
415 JSObject* FASTCALL
416 js_String_p_split(JSContext* cx, JSString* str, JSString* sepstr)
417 {
418 // FIXME: optimize by calling into a lower level exported from jsstr.cpp.
419 jsval vp[4] = { JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(sepstr), JSVAL_VOID };
420 if (!js_str_split(cx, 2, vp))
421 return NULL;
422 JS_ASSERT(JSVAL_IS_OBJECT(vp[0]));
423 return JSVAL_TO_OBJECT(vp[0]);
424 }
425
426 jsdouble FASTCALL
427 js_StringToNumber(JSContext* cx, JSString* str)
428 {
429 const jschar* bp;
430 const jschar* end;
431 const jschar* ep;
432 jsdouble d;
433
434 JSSTRING_CHARS_AND_END(str, bp, end);
435 if ((!js_strtod(cx, bp, end, &ep, &d) ||
436 js_SkipWhiteSpace(ep, end) != end) &&
437 (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
438 js_SkipWhiteSpace(ep, end) != end)) {
439 return js_NaN;
440 }
441 return d;
442 }
443
444 jsint FASTCALL
445 js_StringToInt32(JSContext* cx, JSString* str)
446 {
447 const jschar* bp;
448 const jschar* end;
449 const jschar* ep;
450 jsdouble d;
451
452 JSSTRING_CHARS_AND_END(str, bp, end);
453 if (!js_strtod(cx, bp, end, &ep, &d) || js_SkipWhiteSpace(ep, end) != end)
454 return 0;
455 return (jsint)d;
456 }
457
458 jsdouble FASTCALL
459 js_ParseFloat(JSContext* cx, JSString* str)
460 {
461 const jschar* bp;
462 const jschar* end;
463 const jschar* ep;
464 jsdouble d;
465
466 JSSTRING_CHARS_AND_END(str, bp, end);
467 if (!js_strtod(cx, bp, end, &ep, &d) || ep == bp)
468 return js_NaN;
469 return d;
470 }
471
472 jsdouble FASTCALL
473 js_ParseInt(JSContext* cx, JSString* str)
474 {
475 const jschar* bp;
476 const jschar* end;
477 const jschar* ep;
478 jsdouble d;
479
480 JSSTRING_CHARS_AND_END(str, bp, end);
481 if (!js_strtointeger(cx, bp, end, &ep, 0, &d) || ep == bp)
482 return js_NaN;
483 return d;
484 }
485
486 jsdouble FASTCALL
487 js_ParseIntDouble(jsdouble d)
488 {
489 if (!JSDOUBLE_IS_FINITE(d))
490 return js_NaN;
491 return floor(d);
492 }
493
494 jsval FASTCALL
495 js_Any_getprop(JSContext* cx, JSObject* obj, JSString* idstr)
496 {
497 jsval v;
498 jsid id;
499
500 if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
501 return JSVAL_ERROR_COOKIE;
502 if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
503 return JSVAL_ERROR_COOKIE;
504 return v;
505 }
506
507 JSBool FASTCALL
508 js_Any_setprop(JSContext* cx, JSObject* obj, JSString* idstr, jsval v)
509 {
510 jsid id;
511 if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
512 return JS_FALSE;
513 return OBJ_SET_PROPERTY(cx, obj, id, &v);
514 }
515
516 jsval FASTCALL
517 js_Any_getelem(JSContext* cx, JSObject* obj, jsint index)
518 {
519 jsval v;
520 jsid id;
521 if (index < 0)
522 return JSVAL_ERROR_COOKIE;
523 if (!js_IndexToId(cx, index, &id))
524 return JSVAL_ERROR_COOKIE;
525 if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
526 return JSVAL_ERROR_COOKIE;
527 return v;
528 }
529
530 JSBool FASTCALL
531 js_Any_setelem(JSContext* cx, JSObject* obj, jsint index, jsval v)
532 {
533 jsid id;
534 if (index < 0)
535 return JSVAL_ERROR_COOKIE;
536 if (!js_IndexToId(cx, index, &id))
537 return JS_FALSE;
538 return OBJ_SET_PROPERTY(cx, obj, id, &v);
539 }
540
541 JSObject* FASTCALL
542 js_FastValueToIterator(JSContext* cx, jsuint flags, jsval v)
543 {
544 if (!js_ValueToIterator(cx, flags, &v))
545 return NULL;
546 return JSVAL_TO_OBJECT(v);
547 }
548
549 jsval FASTCALL
550 js_FastCallIteratorNext(JSContext* cx, JSObject* iterobj)
551 {
552 jsval v;
553 if (!js_CallIteratorNext(cx, iterobj, &v))
554 return JSVAL_ERROR_COOKIE;
555 return v;
556 }
557
558 GuardRecord* FASTCALL
559 js_CallTree(InterpState* state, Fragment* f)
560 {
561 GuardRecord* lr;
562 union { NIns *code; GuardRecord* (FASTCALL *func)(InterpState*, Fragment*); } u;
563
564 u.code = f->code();
565 JS_ASSERT(u.code);
566
567 #if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
568 SIMULATE_FASTCALL(lr, state, NULL, u.func);
569 #else
570 lr = u.func(state, NULL);
571 #endif
572
573 if (lr->exit->exitType == NESTED_EXIT) {
574 /* This only occurs once a tree call guard mismatches and we unwind the tree call stack.
575 We store the first (innermost) tree call guard in state and we will try to grow
576 the outer tree the failing call was in starting at that guard. */
577 if (!state->lastTreeCallGuard)
578 state->lastTreeCallGuard = lr;
579 } else {
580 /* If the tree exits on a regular (non-nested) guard, keep updating lastTreeExitGuard
581 with that guard. If we mismatch on a tree call guard, this will contain the last
582 non-nested guard we encountered, which is the innermost loop or branch guard. */
583 state->lastTreeExitGuard = lr;
584 }
585
586 return lr;
587 }
588
589 JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_ARRAY_LENGTH);
590 JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH + 1 == JSSLOT_ARRAY_COUNT);
591
592 JSObject* FASTCALL
593 js_FastNewArray(JSContext* cx, JSObject* proto)
594 {
595 JS_ASSERT(OBJ_IS_ARRAY(cx, proto));
596
597 JS_ASSERT(JS_ON_TRACE(cx));
598 JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
599 if (!obj)
600 return NULL;
601
602 JSClass* clasp = &js_ArrayClass;
603 obj->classword = jsuword(clasp);
604
605 obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
606 obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
607
608 obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
609 obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
610 for (unsigned i = JSSLOT_ARRAY_COUNT + 1; i != JS_INITIAL_NSLOTS; ++i)
611 obj->fslots[i] = JSVAL_VOID;
612
613 JSObjectOps* ops = clasp->getObjectOps(cx, clasp);
614 obj->map = ops->newObjectMap(cx, 1, ops, clasp, obj);
615 if (!obj->map)
616 return NULL;
617 obj->dslots = NULL;
618 return obj;
619 }
620
621 JSObject* FASTCALL
622 js_FastNewObject(JSContext* cx, JSObject* ctor)
623 {
624 JS_ASSERT(HAS_FUNCTION_CLASS(ctor));
625 JSFunction* fun = GET_FUNCTION_PRIVATE(cx, ctor);
626 JSClass* clasp = FUN_INTERPRETED(fun) ? &js_ObjectClass : fun->u.n.clasp;
627 JS_ASSERT(clasp != &js_ArrayClass);
628
629 JS_LOCK_OBJ(cx, ctor);
630 JSScope *scope = OBJ_SCOPE(ctor);
631 JS_ASSERT(scope->object == ctor);
632 JSAtom* atom = cx->runtime->atomState.classPrototypeAtom;
633
634 JSScopeProperty *sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));
635 JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, scope));
636 jsval v = LOCKED_OBJ_GET_SLOT(ctor, sprop->slot);
637 JS_UNLOCK_SCOPE(cx, scope);
638
639 JSObject* proto;
640 if (JSVAL_IS_PRIMITIVE(v)) {
641 if (!js_GetClassPrototype(cx, JSVAL_TO_OBJECT(ctor->fslots[JSSLOT_PARENT]),
642 INT_TO_JSID(JSProto_Object), &proto)) {
643 return NULL;
644 }
645 } else {
646 proto = JSVAL_TO_OBJECT(v);
647 }
648
649 JS_ASSERT(JS_ON_TRACE(cx));
650 JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
651 if (!obj)
652 return NULL;
653
654 obj->classword = jsuword(clasp);
655 obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
656 obj->fslots[JSSLOT_PARENT] = ctor->fslots[JSSLOT_PARENT];
657 for (unsigned i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
658 obj->fslots[i] = JSVAL_VOID;
659
660 obj->map = js_HoldObjectMap(cx, proto->map);
661 obj->dslots = NULL;
662 return obj;
663 }
664
665 JSBool FASTCALL
666 js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
667 {
668 JSScopeProperty* sprop2 = NULL; // initialize early to make MSVC happy
669
670 JS_ASSERT(OBJ_IS_NATIVE(obj));
671 JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop));
672
673 JS_LOCK_OBJ(cx, obj);
674 JSScope* scope = OBJ_SCOPE(obj);
675 if (scope->object == obj) {
676 JS_ASSERT(!SCOPE_HAS_PROPERTY(scope, sprop));
677 } else {
678 scope = js_GetMutableScope(cx, obj);
679 if (!scope) {
680 JS_UNLOCK_OBJ(cx, obj);
681 return JS_FALSE;
682 }
683 }
684
685 uint32 slot = sprop->slot;
686 if (!scope->table && sprop->parent == scope->lastProp && slot == scope->map.freeslot) {
687 if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
688 JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->map.freeslot)));
689 ++scope->map.freeslot;
690 } else {
691 if (!js_AllocSlot(cx, obj, &slot)) {
692 JS_UNLOCK_SCOPE(cx, scope);
693 return JS_FALSE;
694 }
695
696 if (slot != sprop->slot)
697 goto slot_changed;
698 }
699
700 SCOPE_EXTEND_SHAPE(cx, scope, sprop);
701 ++scope->entryCount;
702 scope->lastProp = sprop;
703 JS_UNLOCK_SCOPE(cx, scope);
704 return JS_TRUE;
705 }
706
707 sprop2 = js_AddScopeProperty(cx, scope, sprop->id,
708 sprop->getter, sprop->setter, SPROP_INVALID_SLOT,
709 sprop->attrs, sprop->flags, sprop->shortid);
710 if (sprop2 == sprop) {
711 JS_UNLOCK_SCOPE(cx, scope);
712 return JS_TRUE;
713 }
714 slot = sprop2->slot;
715
716 slot_changed:
717 js_FreeSlot(cx, obj, slot);
718 JS_UNLOCK_SCOPE(cx, scope);
719 return JS_FALSE;
720 }
721
722 JSBool FASTCALL
723 js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
724 {
725 jsid id;
726 if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
727 return JS_FALSE;
728
729 JSObject* obj2;
730 JSProperty* prop;
731 if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
732 return JSVAL_TO_BOOLEAN(JSVAL_VOID);
733 if (prop)
734 OBJ_DROP_PROPERTY(cx, obj2, prop);
735 return prop != NULL;
736 }
737
738 jsval FASTCALL
739 js_CallGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
740 {
741 JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop));
742 jsval v;
743 if (!SPROP_GET(cx, sprop, obj, obj, &v))
744 return JSVAL_ERROR_COOKIE;
745 return v;
746 }
747
748 JSString* FASTCALL
749 js_TypeOfObject(JSContext* cx, JSObject* obj)
750 {
751 JSType type = JS_TypeOfValue(cx, OBJECT_TO_JSVAL(obj));
752 return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
753 }
754
755 JSString* FASTCALL
756 js_TypeOfBoolean(JSContext* cx, jsint unboxed)
757 {
758 jsval boxed = BOOLEAN_TO_JSVAL(unboxed);
759 JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed));
760 JSType type = JS_TypeOfValue(cx, boxed);
761 return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
762 }
763
764 jsint FASTCALL
765 js_Object_p_hasOwnProperty(JSContext* cx, JSObject* obj, JSString *str)
766 {
767 jsid id = ATOM_TO_JSID(STRING_TO_JSVAL(str));
768 jsval v;
769 if (!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &v))
770 return JSVAL_TO_BOOLEAN(JSVAL_VOID);
771 JS_ASSERT(JSVAL_IS_BOOLEAN(v));
772 return JSVAL_TO_BOOLEAN(v);
773 }
774
775 jsint FASTCALL
776 js_Object_p_propertyIsEnumerable(JSContext* cx, JSObject* obj, JSString *str)
777 {
778 jsid id = ATOM_TO_JSID(STRING_TO_JSVAL(str));
779 jsval v;
780 if (!js_PropertyIsEnumerable(cx, obj, id, &v))
781 return JSVAL_TO_BOOLEAN(JSVAL_VOID);
782 JS_ASSERT(JSVAL_IS_BOOLEAN(v));
783 return JSVAL_TO_BOOLEAN(v);
784 }
785
786 jsdouble FASTCALL
787 js_BooleanToNumber(JSContext* cx, jsint unboxed)
788 {
789 if (unboxed == JSVAL_TO_BOOLEAN(JSVAL_VOID))
790 return js_NaN;
791 return unboxed;
792 }
793
794 JSString* FASTCALL
795 js_ObjectToString(JSContext* cx, JSObject* obj)
796 {
797 if (!obj)
798 return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
799 jsval v;
800 if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
801 return NULL;
802 JS_ASSERT(JSVAL_IS_STRING(v));
803 return JSVAL_TO_STRING(v);
804 }
805
806 JSObject* FASTCALL
807 js_Array_1int(JSContext* cx, JSObject* proto, jsint i)
808 {
809 JS_ASSERT(JS_ON_TRACE(cx));
810 JSObject* obj = js_FastNewArray(cx, proto);
811 if (obj)
812 obj->fslots[JSSLOT_ARRAY_LENGTH] = i;
813 return obj;
814 }
815
816 #define ARRAY_CTOR_GUTS(exact_len, newslots_code) \
817 JS_ASSERT(JS_ON_TRACE(cx)); \
818 JSObject* obj = js_FastNewArray(cx, proto); \
819 if (obj) { \
820 const uint32 len = ARRAY_GROWBY; \
821 jsval* newslots = (jsval*) JS_malloc(cx, sizeof (jsval) * (len + 1)); \
822 if (newslots) { \
823 obj->dslots = newslots + 1; \
824 ARRAY_SET_DENSE_LENGTH(obj, len); \
825 {newslots_code} \
826 while (++newslots < obj->dslots + len) \
827 *newslots = JSVAL_HOLE; \
828 obj->fslots[JSSLOT_ARRAY_LENGTH] = (exact_len); \
829 return obj; \
830 } \
831 } \
832 return NULL;
833
834 JSObject* FASTCALL
835 js_Array_1str(JSContext* cx, JSObject* proto, JSString *str)
836 {
837 ARRAY_CTOR_GUTS(1, *++newslots = STRING_TO_JSVAL(str);)
838 }
839
840 JSObject* FASTCALL
841 js_Array_2obj(JSContext* cx, JSObject* proto, JSObject *obj1, JSObject* obj2)
842 {
843 ARRAY_CTOR_GUTS(2,
844 *++newslots = OBJECT_TO_JSVAL(obj1);
845 *++newslots = OBJECT_TO_JSVAL(obj2);)
846 }
847
848 JSObject* FASTCALL
849 js_Array_3num(JSContext* cx, JSObject* proto, jsdouble n1, jsdouble n2, jsdouble n3)
850 {
851 ARRAY_CTOR_GUTS(3,
852 if (!js_NewDoubleInRootedValue(cx, n1, ++newslots))
853 return NULL;
854 if (!js_NewDoubleInRootedValue(cx, n2, ++newslots))
855 return NULL;
856 if (!js_NewDoubleInRootedValue(cx, n3, ++newslots))
857 return NULL;)
858 }
859
860 JSObject* FASTCALL
861 js_Arguments(JSContext* cx)
862 {
863 return NULL;
864 }
865
866 jsdouble FASTCALL
867 js_Date_now(JSContext*)
868 {
869 return PRMJ_Now() / PRMJ_USEC_PER_MSEC;
870 }
871
872 /* soft float */
873
874 jsdouble FASTCALL
875 js_fneg(jsdouble x)
876 {
877 return -x;
878 }
879
880 jsdouble FASTCALL
881 js_i2f(jsint i)
882 {
883 return i;
884 }
885
886 jsdouble FASTCALL
887 js_u2f(jsuint u)
888 {
889 return u;
890 }
891
892 jsint FASTCALL
893 js_fcmpeq(jsdouble x, jsdouble y)
894 {
895 return x==y;
896 }
897
898 jsint FASTCALL
899 js_fcmplt(jsdouble x, jsdouble y)
900 {
901 return x < y;
902 }
903
904 jsint FASTCALL
905 js_fcmple(jsdouble x, jsdouble y)
906 {
907 return x <= y;
908 }
909
910 jsint FASTCALL
911 js_fcmpgt(jsdouble x, jsdouble y)
912 {
913 return x > y;
914 }
915
916 jsint FASTCALL
917 js_fcmpge(jsdouble x, jsdouble y)
918 {
919 return x >= y;
920 }
921
922 jsdouble FASTCALL
923 js_fmul(jsdouble x, jsdouble y)
924 {
925 return x * y;
926 }
927 jsdouble FASTCALL
928 js_fadd(jsdouble x, jsdouble y)
929 {
930 return x + y;
931 }
932
933 jsdouble FASTCALL
934 js_fdiv(jsdouble x, jsdouble y)
935 {
936 return x / y;
937 }
938
939 jsdouble FASTCALL
940 js_fsub(jsdouble x, jsdouble y)
941 {
942 return x - y;
943 }
944
945 #define LO ARGSIZE_LO
946 #define F ARGSIZE_F
947 #define Q ARGSIZE_Q
948
949 #if defined AVMPLUS_64BIT
950 #define P ARGSIZE_Q
951 #else
952 #define P ARGSIZE_LO
953 #endif
954
955 #ifdef DEBUG
956 #define NAME(op) ,#op
957 #else
958 #define NAME(op)
959 #endif
960
961 #define BUILTIN1(op, at0, atr, tr, t0, cse, fold) \
962 { (intptr_t)&js_##op, (at0 << 2) | atr, cse, fold NAME(op) },
963 #define BUILTIN2(op, at0, at1, atr, tr, t0, t1, cse, fold) \
964 { (intptr_t)&js_##op, (at0 << 4) | (at1 << 2) | atr, cse, fold NAME(op) },
965 #define BUILTIN3(op, at0, at1, at2, atr, tr, t0, t1, t2, cse, fold) \
966 { (intptr_t)&js_##op, (at0 << 6) | (at1 << 4) | (at2 << 2) | atr, cse, fold NAME(op) },
967 #define BUILTIN4(op, at0, at1, at2, at3, atr, tr, t0, t1, t2, t3, cse, fold) \
968 { (intptr_t)&js_##op, (at0 << 8) | (at1 << 6) | (at2 << 4) | (at3 << 2) | atr, cse, fold NAME(op) },
969 #define BUILTIN5(op, at0, at1, at2, at3, at4, atr, tr, t0, t1, t2, t3, t4, cse, fold) \
970 { (intptr_t)&js_##op, (at0 << 10) | (at1 << 8) | (at2 << 6) | (at3 << 4) | (at4 << 2) | atr, cse, fold NAME(op) },
971
972 struct CallInfo builtins[] = {
973 #include "builtins.tbl"
974 };

  ViewVC Help
Powered by ViewVC 1.1.24