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

Contents of /trunk/js/jsbuiltins.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 460 - (show annotations)
Sat Sep 26 23:15:22 2009 UTC (11 years ago) by siliconforks
File size: 12133 byte(s)
Upgrade to SpiderMonkey from Firefox 3.5.3.

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 JS_FRIEND_API(void)
67 js_SetTraceableNativeFailed(JSContext *cx)
68 {
69 js_SetBuiltinError(cx);
70 }
71
72 /*
73 * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
74 * Do not use bool FASTCALL, use JSBool only!
75 */
76
77 jsdouble FASTCALL
78 js_dmod(jsdouble a, jsdouble b)
79 {
80 if (b == 0.0) {
81 jsdpun u;
82 u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
83 u.s.lo = 0xffffffff;
84 return u.d;
85 }
86 jsdouble r;
87 #ifdef XP_WIN
88 /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
89 if (JSDOUBLE_IS_FINITE(a) && JSDOUBLE_IS_INFINITE(b))
90 r = a;
91 else
92 #endif
93 r = fmod(a, b);
94 return r;
95 }
96
97 int32 FASTCALL
98 js_imod(int32 a, int32 b)
99 {
100 if (a < 0 || b <= 0)
101 return -1;
102 int r = a % b;
103 return r;
104 }
105
106 /* The following boxing/unboxing primitives we can't emit inline because
107 they either interact with the GC and depend on Spidermonkey's 32-bit
108 integer representation. */
109
110 jsval FASTCALL
111 js_BoxDouble(JSContext* cx, jsdouble d)
112 {
113 int32 i;
114 if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i))
115 return INT_TO_JSVAL(i);
116 JS_ASSERT(JS_ON_TRACE(cx));
117 jsval v; /* not rooted but ok here because we know GC won't run */
118 if (!js_NewDoubleInRootedValue(cx, d, &v))
119 return JSVAL_ERROR_COOKIE;
120 return v;
121 }
122
123 jsval FASTCALL
124 js_BoxInt32(JSContext* cx, int32 i)
125 {
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 }
135
136 jsdouble FASTCALL
137 js_UnboxDouble(jsval v)
138 {
139 if (JS_LIKELY(JSVAL_IS_INT(v)))
140 return (jsdouble)JSVAL_TO_INT(v);
141 return *JSVAL_TO_DOUBLE(v);
142 }
143
144 int32 FASTCALL
145 js_UnboxInt32(jsval v)
146 {
147 if (JS_LIKELY(JSVAL_IS_INT(v)))
148 return JSVAL_TO_INT(v);
149 return js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v));
150 }
151
152 int32 FASTCALL
153 js_DoubleToInt32(jsdouble d)
154 {
155 return js_DoubleToECMAInt32(d);
156 }
157
158 uint32 FASTCALL
159 js_DoubleToUint32(jsdouble d)
160 {
161 return js_DoubleToECMAUint32(d);
162 }
163
164 jsdouble FASTCALL
165 js_StringToNumber(JSContext* cx, JSString* str)
166 {
167 const jschar* bp;
168 const jschar* end;
169 const jschar* ep;
170 jsdouble d;
171
172 JSSTRING_CHARS_AND_END(str, bp, end);
173 if ((!js_strtod(cx, bp, end, &ep, &d) ||
174 js_SkipWhiteSpace(ep, end) != end) &&
175 (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
176 js_SkipWhiteSpace(ep, end) != end)) {
177 return js_NaN;
178 }
179 return d;
180 }
181
182 int32 FASTCALL
183 js_StringToInt32(JSContext* cx, JSString* str)
184 {
185 const jschar* bp;
186 const jschar* end;
187 const jschar* ep;
188 jsdouble d;
189
190 JSSTRING_CHARS_AND_END(str, bp, end);
191 if ((!js_strtod(cx, bp, end, &ep, &d) ||
192 js_SkipWhiteSpace(ep, end) != end) &&
193 (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
194 js_SkipWhiteSpace(ep, end) != end)) {
195 return 0;
196 }
197 return js_DoubleToECMAInt32(d);
198 }
199
200 SideExit* FASTCALL
201 js_CallTree(InterpState* state, Fragment* f)
202 {
203 union { NIns *code; GuardRecord* (FASTCALL *func)(InterpState*, Fragment*); } u;
204
205 u.code = f->code();
206 JS_ASSERT(u.code);
207
208 GuardRecord* rec;
209 #if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
210 SIMULATE_FASTCALL(rec, state, NULL, u.func);
211 #else
212 rec = u.func(state, NULL);
213 #endif
214 VMSideExit* lr = (VMSideExit*)rec->exit;
215
216 if (lr->exitType == NESTED_EXIT) {
217 /* This only occurs once a tree call guard mismatches and we unwind the tree call stack.
218 We store the first (innermost) tree call guard in state and we will try to grow
219 the outer tree the failing call was in starting at that guard. */
220 if (!state->lastTreeCallGuard) {
221 state->lastTreeCallGuard = lr;
222 FrameInfo** rp = (FrameInfo**)state->rp;
223 state->rpAtLastTreeCall = rp + lr->calldepth;
224 }
225 } else {
226 /* If the tree exits on a regular (non-nested) guard, keep updating lastTreeExitGuard
227 with that guard. If we mismatch on a tree call guard, this will contain the last
228 non-nested guard we encountered, which is the innermost loop or branch guard. */
229 state->lastTreeExitGuard = lr;
230 }
231
232 return lr;
233 }
234
235 JSBool FASTCALL
236 js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
237 {
238 JS_ASSERT(OBJ_IS_NATIVE(obj));
239 JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop));
240
241 JS_LOCK_OBJ(cx, obj);
242
243 JSScope* scope = OBJ_SCOPE(obj);
244 uint32 slot;
245 if (scope->object == obj) {
246 JS_ASSERT(!SCOPE_HAS_PROPERTY(scope, sprop));
247 } else {
248 scope = js_GetMutableScope(cx, obj);
249 if (!scope)
250 goto exit_trace;
251 }
252
253 slot = sprop->slot;
254 if (!scope->table && sprop->parent == scope->lastProp && slot == scope->freeslot) {
255 if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
256 JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->freeslot)));
257 ++scope->freeslot;
258 } else {
259 if (!js_AllocSlot(cx, obj, &slot))
260 goto exit_trace;
261
262 if (slot != sprop->slot) {
263 js_FreeSlot(cx, obj, slot);
264 goto exit_trace;
265 }
266 }
267
268 js_ExtendScopeShape(cx, scope, sprop);
269 ++scope->entryCount;
270 scope->lastProp = sprop;
271 } else {
272 JSScopeProperty *sprop2 = js_AddScopeProperty(cx, scope, sprop->id,
273 sprop->getter,
274 sprop->setter,
275 SPROP_INVALID_SLOT,
276 sprop->attrs,
277 sprop->flags,
278 sprop->shortid);
279 if (sprop2 != sprop)
280 goto exit_trace;
281 }
282
283 if (js_IsPropertyCacheDisabled(cx))
284 goto exit_trace;
285
286 JS_UNLOCK_SCOPE(cx, scope);
287 return JS_TRUE;
288
289 exit_trace:
290 JS_UNLOCK_SCOPE(cx, scope);
291 return JS_FALSE;
292 }
293
294 static JSBool
295 HasProperty(JSContext* cx, JSObject* obj, jsid id)
296 {
297 // Check that we know how the lookup op will behave.
298 for (JSObject* pobj = obj; pobj; pobj = OBJ_GET_PROTO(cx, pobj)) {
299 if (pobj->map->ops->lookupProperty != js_LookupProperty)
300 return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID);
301 JSClass* clasp = OBJ_GET_CLASS(cx, pobj);
302 if (clasp->resolve != JS_ResolveStub && clasp != &js_StringClass)
303 return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID);
304 }
305
306 JSObject* obj2;
307 JSProperty* prop;
308 if (!js_LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
309 return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID);
310 if (prop)
311 OBJ_DROP_PROPERTY(cx, obj2, prop);
312 return prop != NULL;
313 }
314
315 JSBool FASTCALL
316 js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
317 {
318 jsid id;
319 if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
320 return JSVAL_TO_BOOLEAN(JSVAL_VOID);
321
322 return HasProperty(cx, obj, id);
323 }
324
325 JSBool FASTCALL
326 js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index)
327 {
328 jsid id;
329 if (!js_Int32ToId(cx, index, &id))
330 return JSVAL_TO_BOOLEAN(JSVAL_VOID);
331
332 return HasProperty(cx, obj, id);
333 }
334
335 jsval FASTCALL
336 js_CallGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
337 {
338 JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop));
339 jsval v;
340 if (!js_GetSprop(cx, sprop, obj, &v))
341 return JSVAL_ERROR_COOKIE;
342 return v;
343 }
344
345 JSString* FASTCALL
346 js_TypeOfObject(JSContext* cx, JSObject* obj)
347 {
348 JSType type = JS_TypeOfValue(cx, OBJECT_TO_JSVAL(obj));
349 return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
350 }
351
352 JSString* FASTCALL
353 js_TypeOfBoolean(JSContext* cx, int32 unboxed)
354 {
355 /* Watch out for pseudo-booleans. */
356 jsval boxed = PSEUDO_BOOLEAN_TO_JSVAL(unboxed);
357 JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed));
358 JSType type = JS_TypeOfValue(cx, boxed);
359 return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
360 }
361
362 jsdouble FASTCALL
363 js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed)
364 {
365 if (unboxed == JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID))
366 return js_NaN;
367 JS_ASSERT(unboxed == JS_TRUE || unboxed == JS_FALSE);
368 return unboxed;
369 }
370
371 JSString* FASTCALL
372 js_BooleanOrUndefinedToString(JSContext *cx, int32 unboxed)
373 {
374 JS_ASSERT(uint32(unboxed) <= 2);
375 return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]);
376 }
377
378 JSObject* FASTCALL
379 js_Arguments(JSContext* cx)
380 {
381 return NULL;
382 }
383
384 JSObject* FASTCALL
385 js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* parent)
386 {
387 JS_ASSERT(HAS_FUNCTION_CLASS(funobj));
388 JS_ASSERT(HAS_FUNCTION_CLASS(proto));
389 JS_ASSERT(JS_ON_TRACE(cx));
390
391 JSFunction *fun = (JSFunction*) funobj;
392 JS_ASSERT(GET_FUNCTION_PRIVATE(cx, funobj) == fun);
393
394 JSObject* closure = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
395 if (!closure)
396 return NULL;
397
398 js_HoldScope(OBJ_SCOPE(proto));
399 closure->map = proto->map;
400 closure->classword = jsuword(&js_FunctionClass);
401 closure->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
402 closure->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent);
403 closure->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
404 for (unsigned i = JSSLOT_PRIVATE + 1; i != JS_INITIAL_NSLOTS; ++i)
405 closure->fslots[i] = JSVAL_VOID;
406 closure->dslots = NULL;
407 return closure;
408 }
409
410 #define BUILTIN1 JS_DEFINE_CALLINFO_1
411 #define BUILTIN2 JS_DEFINE_CALLINFO_2
412 #define BUILTIN3 JS_DEFINE_CALLINFO_3
413 #define BUILTIN4 JS_DEFINE_CALLINFO_4
414 #define BUILTIN5 JS_DEFINE_CALLINFO_5
415 #include "builtins.tbl"

  ViewVC Help
Powered by ViewVC 1.1.24