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

Annotation of /trunk/js/jsbuiltins.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 507 - (hide annotations)
Sun Jan 10 07:23:34 2010 UTC (10 years, 6 months ago) by siliconforks
File size: 13437 byte(s)
Update SpiderMonkey from Firefox 3.6rc1.

1 siliconforks 507 /* -*- 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 <math.h>
43    
44     #include "jsapi.h"
45 siliconforks 507 #include "jsstdint.h"
46 siliconforks 332 #include "jsarray.h"
47     #include "jsbool.h"
48     #include "jscntxt.h"
49     #include "jsgc.h"
50     #include "jsiter.h"
51 siliconforks 507 #include "jsnum.h"
52 siliconforks 332 #include "jslibmath.h"
53     #include "jsmath.h"
54     #include "jsnum.h"
55     #include "prmjtime.h"
56 siliconforks 399 #include "jsdate.h"
57 siliconforks 332 #include "jsscope.h"
58     #include "jsstr.h"
59 siliconforks 399 #include "jsbuiltins.h"
60 siliconforks 332 #include "jstracer.h"
61 siliconforks 507 #include "jsvector.h"
62 siliconforks 332
63 siliconforks 507 #include "jsatominlines.h"
64     #include "jsobjinlines.h"
65    
66 siliconforks 332 using namespace avmplus;
67     using namespace nanojit;
68    
69 siliconforks 399 extern jsdouble js_NaN;
70    
71 siliconforks 460 JS_FRIEND_API(void)
72     js_SetTraceableNativeFailed(JSContext *cx)
73     {
74     js_SetBuiltinError(cx);
75     }
76    
77 siliconforks 332 /*
78     * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
79     * Do not use bool FASTCALL, use JSBool only!
80     */
81    
82     jsdouble FASTCALL
83     js_dmod(jsdouble a, jsdouble b)
84     {
85     if (b == 0.0) {
86     jsdpun u;
87     u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
88     u.s.lo = 0xffffffff;
89     return u.d;
90     }
91 siliconforks 507 return js_fmod(a, b);
92 siliconforks 332 }
93 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_dmod, DOUBLE, DOUBLE, 1, 1)
94 siliconforks 332
95 siliconforks 399 int32 FASTCALL
96     js_imod(int32 a, int32 b)
97 siliconforks 332 {
98     if (a < 0 || b <= 0)
99     return -1;
100     int r = a % b;
101     return r;
102     }
103 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, INT32, js_imod, INT32, INT32, 1, 1)
104 siliconforks 332
105     /* The following boxing/unboxing primitives we can't emit inline because
106     they either interact with the GC and depend on Spidermonkey's 32-bit
107     integer representation. */
108    
109     jsval FASTCALL
110     js_BoxDouble(JSContext* cx, jsdouble d)
111     {
112 siliconforks 399 int32 i;
113     if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i))
114 siliconforks 332 return INT_TO_JSVAL(i);
115     JS_ASSERT(JS_ON_TRACE(cx));
116     jsval v; /* not rooted but ok here because we know GC won't run */
117     if (!js_NewDoubleInRootedValue(cx, d, &v))
118     return JSVAL_ERROR_COOKIE;
119     return v;
120     }
121 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxDouble, CONTEXT, DOUBLE, 1, 1)
122 siliconforks 332
123     jsval FASTCALL
124 siliconforks 399 js_BoxInt32(JSContext* cx, int32 i)
125 siliconforks 332 {
126     if (JS_LIKELY(INT_FITS_IN_JSVAL(i)))
127     return INT_TO_JSVAL(i);
128     JS_ASSERT(JS_ON_TRACE(cx));
129     jsval v; /* not rooted but ok here because we know GC won't run */
130     jsdouble d = (jsdouble)i;
131     if (!js_NewDoubleInRootedValue(cx, d, &v))
132     return JSVAL_ERROR_COOKIE;
133     return v;
134 siliconforks 507 }
135     JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxInt32, CONTEXT, INT32, 1, 1)
136 siliconforks 332
137     jsdouble FASTCALL
138     js_UnboxDouble(jsval v)
139     {
140     if (JS_LIKELY(JSVAL_IS_INT(v)))
141     return (jsdouble)JSVAL_TO_INT(v);
142     return *JSVAL_TO_DOUBLE(v);
143     }
144 siliconforks 507 JS_DEFINE_CALLINFO_1(extern, DOUBLE, js_UnboxDouble, JSVAL, 1, 1)
145 siliconforks 332
146 siliconforks 399 int32 FASTCALL
147 siliconforks 332 js_UnboxInt32(jsval v)
148     {
149     if (JS_LIKELY(JSVAL_IS_INT(v)))
150     return JSVAL_TO_INT(v);
151     return js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v));
152     }
153 siliconforks 507 JS_DEFINE_CALLINFO_1(extern, INT32, js_UnboxInt32, JSVAL, 1, 1)
154 siliconforks 332
155     int32 FASTCALL
156     js_DoubleToInt32(jsdouble d)
157     {
158     return js_DoubleToECMAInt32(d);
159     }
160 siliconforks 507 JS_DEFINE_CALLINFO_1(extern, INT32, js_DoubleToInt32, DOUBLE, 1, 1)
161 siliconforks 332
162 siliconforks 399 uint32 FASTCALL
163 siliconforks 332 js_DoubleToUint32(jsdouble d)
164     {
165     return js_DoubleToECMAUint32(d);
166     }
167 siliconforks 507 JS_DEFINE_CALLINFO_1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, 1)
168 siliconforks 332
169     jsdouble FASTCALL
170     js_StringToNumber(JSContext* cx, JSString* str)
171     {
172     const jschar* bp;
173     const jschar* end;
174     const jschar* ep;
175     jsdouble d;
176    
177 siliconforks 507 str->getCharsAndEnd(bp, end);
178 siliconforks 332 if ((!js_strtod(cx, bp, end, &ep, &d) ||
179     js_SkipWhiteSpace(ep, end) != end) &&
180     (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
181     js_SkipWhiteSpace(ep, end) != end)) {
182     return js_NaN;
183     }
184     return d;
185     }
186 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, 1, 1)
187 siliconforks 332
188 siliconforks 399 int32 FASTCALL
189 siliconforks 332 js_StringToInt32(JSContext* cx, JSString* str)
190     {
191     const jschar* bp;
192     const jschar* end;
193     const jschar* ep;
194     jsdouble d;
195 siliconforks 507
196     if (str->length() == 1) {
197     jschar c = str->chars()[0];
198     if ('0' <= c && c <= '9')
199     return c - '0';
200     return 0;
201     }
202 siliconforks 332
203 siliconforks 507 str->getCharsAndEnd(bp, end);
204 siliconforks 460 if ((!js_strtod(cx, bp, end, &ep, &d) ||
205     js_SkipWhiteSpace(ep, end) != end) &&
206     (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
207     js_SkipWhiteSpace(ep, end) != end)) {
208 siliconforks 332 return 0;
209 siliconforks 460 }
210 siliconforks 399 return js_DoubleToECMAInt32(d);
211 siliconforks 332 }
212 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, 1)
213 siliconforks 332
214 siliconforks 399 SideExit* FASTCALL
215 siliconforks 332 js_CallTree(InterpState* state, Fragment* f)
216     {
217     union { NIns *code; GuardRecord* (FASTCALL *func)(InterpState*, Fragment*); } u;
218    
219     u.code = f->code();
220     JS_ASSERT(u.code);
221    
222 siliconforks 399 GuardRecord* rec;
223 siliconforks 332 #if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
224 siliconforks 399 SIMULATE_FASTCALL(rec, state, NULL, u.func);
225 siliconforks 332 #else
226 siliconforks 399 rec = u.func(state, NULL);
227 siliconforks 332 #endif
228 siliconforks 399 VMSideExit* lr = (VMSideExit*)rec->exit;
229 siliconforks 332
230 siliconforks 399 if (lr->exitType == NESTED_EXIT) {
231 siliconforks 332 /* This only occurs once a tree call guard mismatches and we unwind the tree call stack.
232     We store the first (innermost) tree call guard in state and we will try to grow
233     the outer tree the failing call was in starting at that guard. */
234 siliconforks 399 if (!state->lastTreeCallGuard) {
235 siliconforks 332 state->lastTreeCallGuard = lr;
236 siliconforks 460 FrameInfo** rp = (FrameInfo**)state->rp;
237 siliconforks 399 state->rpAtLastTreeCall = rp + lr->calldepth;
238     }
239 siliconforks 332 } else {
240     /* If the tree exits on a regular (non-nested) guard, keep updating lastTreeExitGuard
241     with that guard. If we mismatch on a tree call guard, this will contain the last
242     non-nested guard we encountered, which is the innermost loop or branch guard. */
243     state->lastTreeExitGuard = lr;
244     }
245    
246     return lr;
247     }
248 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, SIDEEXIT, js_CallTree, INTERPSTATE, FRAGMENT, 0, 0)
249 siliconforks 332
250     JSBool FASTCALL
251     js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
252     {
253     JS_ASSERT(OBJ_IS_NATIVE(obj));
254     JS_LOCK_OBJ(cx, obj);
255 siliconforks 460
256 siliconforks 332 JSScope* scope = OBJ_SCOPE(obj);
257 siliconforks 460 uint32 slot;
258 siliconforks 507 if (scope->owned()) {
259     JS_ASSERT(!scope->has(sprop));
260 siliconforks 332 } else {
261     scope = js_GetMutableScope(cx, obj);
262 siliconforks 460 if (!scope)
263     goto exit_trace;
264 siliconforks 332 }
265    
266 siliconforks 460 slot = sprop->slot;
267     if (!scope->table && sprop->parent == scope->lastProp && slot == scope->freeslot) {
268 siliconforks 332 if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
269 siliconforks 460 JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->freeslot)));
270     ++scope->freeslot;
271 siliconforks 332 } else {
272 siliconforks 460 if (!js_AllocSlot(cx, obj, &slot))
273     goto exit_trace;
274    
275     if (slot != sprop->slot) {
276     js_FreeSlot(cx, obj, slot);
277     goto exit_trace;
278 siliconforks 332 }
279     }
280    
281 siliconforks 507 scope->extend(cx, sprop);
282 siliconforks 460 } else {
283 siliconforks 507 JSScopeProperty *sprop2 = scope->add(cx, sprop->id,
284     sprop->getter, sprop->setter,
285     SPROP_INVALID_SLOT, sprop->attrs,
286     sprop->flags, sprop->shortid);
287 siliconforks 460 if (sprop2 != sprop)
288     goto exit_trace;
289 siliconforks 332 }
290    
291 siliconforks 460 if (js_IsPropertyCacheDisabled(cx))
292     goto exit_trace;
293 siliconforks 332
294     JS_UNLOCK_SCOPE(cx, scope);
295 siliconforks 460 return JS_TRUE;
296    
297     exit_trace:
298     JS_UNLOCK_SCOPE(cx, scope);
299 siliconforks 332 return JS_FALSE;
300     }
301 siliconforks 507 JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SCOPEPROP, 0, 0)
302 siliconforks 332
303 siliconforks 460 static JSBool
304     HasProperty(JSContext* cx, JSObject* obj, jsid id)
305 siliconforks 332 {
306 siliconforks 460 // Check that we know how the lookup op will behave.
307     for (JSObject* pobj = obj; pobj; pobj = OBJ_GET_PROTO(cx, pobj)) {
308     if (pobj->map->ops->lookupProperty != js_LookupProperty)
309 siliconforks 507 return JSVAL_TO_SPECIAL(JSVAL_VOID);
310 siliconforks 460 JSClass* clasp = OBJ_GET_CLASS(cx, pobj);
311     if (clasp->resolve != JS_ResolveStub && clasp != &js_StringClass)
312 siliconforks 507 return JSVAL_TO_SPECIAL(JSVAL_VOID);
313 siliconforks 460 }
314 siliconforks 332
315     JSObject* obj2;
316     JSProperty* prop;
317 siliconforks 507 if (js_LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) < 0)
318     return JSVAL_TO_SPECIAL(JSVAL_VOID);
319 siliconforks 332 if (prop)
320 siliconforks 507 obj2->dropProperty(cx, prop);
321 siliconforks 332 return prop != NULL;
322     }
323    
324 siliconforks 399 JSBool FASTCALL
325 siliconforks 460 js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
326     {
327     jsid id;
328     if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
329     return JSVAL_TO_BOOLEAN(JSVAL_VOID);
330    
331     return HasProperty(cx, obj, id);
332     }
333 siliconforks 507 JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedProperty, CONTEXT, OBJECT, STRING, 0, 0)
334 siliconforks 460
335     JSBool FASTCALL
336 siliconforks 399 js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index)
337     {
338     jsid id;
339 siliconforks 460 if (!js_Int32ToId(cx, index, &id))
340 siliconforks 399 return JSVAL_TO_BOOLEAN(JSVAL_VOID);
341    
342 siliconforks 460 return HasProperty(cx, obj, id);
343 siliconforks 399 }
344 siliconforks 507 JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedPropertyInt32, CONTEXT, OBJECT, INT32, 0, 0)
345 siliconforks 399
346 siliconforks 332 JSString* FASTCALL
347     js_TypeOfObject(JSContext* cx, JSObject* obj)
348     {
349     JSType type = JS_TypeOfValue(cx, OBJECT_TO_JSVAL(obj));
350     return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
351     }
352 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfObject, CONTEXT, OBJECT, 1, 1)
353 siliconforks 332
354     JSString* FASTCALL
355 siliconforks 399 js_TypeOfBoolean(JSContext* cx, int32 unboxed)
356 siliconforks 332 {
357 siliconforks 460 /* Watch out for pseudo-booleans. */
358 siliconforks 507 jsval boxed = SPECIAL_TO_JSVAL(unboxed);
359 siliconforks 332 JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed));
360     JSType type = JS_TypeOfValue(cx, boxed);
361     return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
362     }
363 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfBoolean, CONTEXT, INT32, 1, 1)
364 siliconforks 332
365     jsdouble FASTCALL
366 siliconforks 399 js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed)
367 siliconforks 332 {
368 siliconforks 507 if (unboxed == JSVAL_TO_SPECIAL(JSVAL_VOID))
369 siliconforks 332 return js_NaN;
370 siliconforks 460 JS_ASSERT(unboxed == JS_TRUE || unboxed == JS_FALSE);
371 siliconforks 332 return unboxed;
372     }
373 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_BooleanOrUndefinedToNumber, CONTEXT, INT32, 1, 1)
374 siliconforks 332
375     JSString* FASTCALL
376 siliconforks 399 js_BooleanOrUndefinedToString(JSContext *cx, int32 unboxed)
377     {
378     JS_ASSERT(uint32(unboxed) <= 2);
379     return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]);
380     }
381 siliconforks 507 JS_DEFINE_CALLINFO_2(extern, STRING, js_BooleanOrUndefinedToString, CONTEXT, INT32, 1, 1)
382 siliconforks 399
383 siliconforks 460 JSObject* FASTCALL
384     js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* parent)
385 siliconforks 332 {
386 siliconforks 460 JS_ASSERT(HAS_FUNCTION_CLASS(funobj));
387     JS_ASSERT(HAS_FUNCTION_CLASS(proto));
388     JS_ASSERT(JS_ON_TRACE(cx));
389    
390     JSFunction *fun = (JSFunction*) funobj;
391     JS_ASSERT(GET_FUNCTION_PRIVATE(cx, funobj) == fun);
392    
393 siliconforks 507 JSObject* closure = js_NewGCObject(cx, GCX_OBJECT);
394 siliconforks 460 if (!closure)
395     return NULL;
396    
397 siliconforks 507 closure->initSharingEmptyScope(&js_FunctionClass, proto, parent,
398     reinterpret_cast<jsval>(fun));
399 siliconforks 460 return closure;
400 siliconforks 332 }
401 siliconforks 507 JS_DEFINE_CALLINFO_4(extern, OBJECT, js_NewNullClosure, CONTEXT, OBJECT, OBJECT, OBJECT, 0, 0)
402 siliconforks 332
403 siliconforks 507 JSString* FASTCALL
404     js_ConcatN(JSContext *cx, JSString **strArray, uint32 size)
405     {
406     /* Calculate total size. */
407     size_t numChar = 1;
408     for (uint32 i = 0; i < size; ++i) {
409     size_t before = numChar;
410     numChar += strArray[i]->length();
411     if (numChar < before)
412     return NULL;
413     }
414    
415    
416     /* Allocate buffer. */
417     if (numChar & js::tl::MulOverflowMask<sizeof(jschar)>::result)
418     return NULL;
419     jschar *buf = (jschar *)cx->malloc(numChar * sizeof(jschar));
420     if (!buf)
421     return NULL;
422    
423     /* Fill buffer. */
424     jschar *ptr = buf;
425     for (uint32 i = 0; i < size; ++i) {
426     const jschar *chars;
427     size_t length;
428     strArray[i]->getCharsAndLength(chars, length);
429     js_strncpy(ptr, chars, length);
430     ptr += length;
431     }
432     *ptr = '\0';
433    
434     /* Create string. */
435     JSString *str = js_NewString(cx, buf, numChar - 1);
436     if (!str)
437     cx->free(buf);
438     return str;
439     }
440     JS_DEFINE_CALLINFO_3(extern, STRING, js_ConcatN, CONTEXT, STRINGPTR, UINT32, 0, 0)

  ViewVC Help
Powered by ViewVC 1.1.24