1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=99:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
20 * The Initial Developer of the Original Code is
21 * Andreas Gal <gal@mozilla.com>
24 * Brendan Eich <brendan@mozilla.org>
25 * Mike Shaver <shaver@mozilla.org>
26 * David Anderson <danderson@mozilla.com>
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.
40 * ***** END LICENSE BLOCK ***** */
57 #include "nanojit/avmplus.h"
58 #include "nanojit/nanojit.h"
60 using namespace avmplus
;
61 using namespace nanojit
;
64 js_dmod(jsdouble a
, jsdouble b
)
68 u
.s
.hi
= JSDOUBLE_HI32_EXPMASK
| JSDOUBLE_HI32_MANTMASK
;
74 /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
75 if (JSDOUBLE_IS_FINITE(a
) && JSDOUBLE_IS_INFINITE(b
))
83 /* The following boxing/unboxing primitives we can't emit inline because
84 they either interact with the GC and depend on Spidermonkey's 32-bit
85 integer representation. */
88 js_BoxDouble(JSContext
* cx
, jsdouble d
)
91 if (JSDOUBLE_IS_INT(d
, i
))
92 return INT_TO_JSVAL(i
);
93 JS_ASSERT(cx
->executingTrace
);
94 jsval v
; /* not rooted but ok here because we know GC won't run */
95 if (!js_NewDoubleInRootedValue(cx
, d
, &v
))
96 return JSVAL_ERROR_COOKIE
;
101 js_BoxInt32(JSContext
* cx
, jsint i
)
103 if (JS_LIKELY(INT_FITS_IN_JSVAL(i
)))
104 return INT_TO_JSVAL(i
);
105 JS_ASSERT(cx
->executingTrace
);
106 jsval v
; /* not rooted but ok here because we know GC won't run */
107 jsdouble d
= (jsdouble
)i
;
108 if (!js_NewDoubleInRootedValue(cx
, d
, &v
))
109 return JSVAL_ERROR_COOKIE
;
114 js_UnboxDouble(jsval v
)
116 if (JS_LIKELY(JSVAL_IS_INT(v
)))
117 return (jsdouble
)JSVAL_TO_INT(v
);
118 return *JSVAL_TO_DOUBLE(v
);
122 js_UnboxInt32(jsval v
)
124 if (JS_LIKELY(JSVAL_IS_INT(v
)))
125 return JSVAL_TO_INT(v
);
126 return js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v
));
130 js_DoubleToInt32(jsdouble d
)
132 return js_DoubleToECMAInt32(d
);
136 js_DoubleToUint32(jsdouble d
)
138 return js_DoubleToECMAUint32(d
);
142 js_Math_sin(jsdouble d
)
148 js_Math_cos(jsdouble d
)
154 js_Math_floor(jsdouble d
)
160 js_Math_ceil(jsdouble d
)
166 js_Math_pow(jsdouble d
, jsdouble p
)
169 /* XXX Need to get a NaN here without parameterizing on context all the time. */
170 if (!JSDOUBLE_IS_FINITE(p
) && (d
== 1.0 || d
== -1.0))
179 js_Math_sqrt(jsdouble d
)
185 js_Array_dense_setelem(JSContext
* cx
, JSObject
* obj
, jsint i
, jsval v
)
187 JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx
, obj
));
189 jsuint length
= ARRAY_DENSE_LENGTH(obj
);
190 if ((jsuint
)i
< length
) {
191 if (obj
->dslots
[i
] == JSVAL_HOLE
) {
192 if (i
>= obj
->fslots
[JSSLOT_ARRAY_LENGTH
])
193 obj
->fslots
[JSSLOT_ARRAY_LENGTH
] = i
+ 1;
194 obj
->fslots
[JSSLOT_ARRAY_COUNT
]++;
199 return OBJ_SET_PROPERTY(cx
, obj
, INT_TO_JSID(i
), &v
) ? true : false;
203 js_Array_p_join(JSContext
* cx
, JSObject
* obj
, JSString
*str
)
206 if (!js_array_join_sub(cx
, obj
, TO_STRING
, str
, &v
))
208 JS_ASSERT(JSVAL_IS_STRING(v
));
209 return JSVAL_TO_STRING(v
);
213 js_String_p_substring(JSContext
* cx
, JSString
* str
, jsint begin
, jsint end
)
215 JS_ASSERT(end
>= begin
);
216 JS_ASSERT(cx
->executingTrace
);
217 return js_NewDependentString(cx
, str
, (size_t)begin
, (size_t)(end
- begin
));
221 js_String_p_substring_1(JSContext
* cx
, JSString
* str
, jsint begin
)
223 jsint end
= JSSTRING_LENGTH(str
);
224 JS_ASSERT(end
>= begin
);
225 JS_ASSERT(cx
->executingTrace
);
226 return js_NewDependentString(cx
, str
, (size_t)begin
, (size_t)(end
- begin
));
230 js_String_getelem(JSContext
* cx
, JSString
* str
, jsint i
)
232 if ((size_t)i
>= JSSTRING_LENGTH(str
))
234 return js_GetUnitString(cx
, str
, (size_t)i
);
238 js_String_fromCharCode(JSContext
* cx
, jsint i
)
240 JS_ASSERT(cx
->executingTrace
);
241 jschar c
= (jschar
)i
;
242 if (c
< UNIT_STRING_LIMIT
)
243 return js_GetUnitStringForChar(cx
, c
);
244 return js_NewStringCopyN(cx
, &c
, 1);
248 js_String_p_charCodeAt(JSString
* str
, jsint i
)
250 if (i
< 0 || (jsint
)JSSTRING_LENGTH(str
) <= i
)
252 return JSSTRING_CHARS(str
)[i
];
256 js_Math_random(JSRuntime
* rt
)
260 jsdouble z
= js_random_nextDouble(rt
);
261 JS_UNLOCK_RUNTIME(rt
);
266 js_String_p_concat_1int(JSContext
* cx
, JSString
* str
, jsint i
)
268 // FIXME: should be able to use stack buffer and avoid istr...
269 JSString
* istr
= js_NumberToString(cx
, i
);
272 return js_ConcatStrings(cx
, str
, istr
);
276 js_String_p_match(JSContext
* cx
, JSString
* str
, jsbytecode
*pc
, JSObject
* regexp
)
278 jsval vp
[3] = { JSVAL_NULL
, STRING_TO_JSVAL(str
), OBJECT_TO_JSVAL(regexp
) };
279 if (!js_StringMatchHelper(cx
, 1, vp
, pc
))
280 return (JSObject
*) JSVAL_TO_BOOLEAN(JSVAL_VOID
);
281 JS_ASSERT(JSVAL_IS_NULL(vp
[0]) ||
282 (!JSVAL_IS_PRIMITIVE(vp
[0]) && OBJ_IS_ARRAY(cx
, JSVAL_TO_OBJECT(vp
[0]))));
283 return JSVAL_TO_OBJECT(vp
[0]);
287 js_String_p_replace_str(JSContext
* cx
, JSString
* str
, JSObject
* regexp
, JSString
* repstr
)
290 JSVAL_NULL
, STRING_TO_JSVAL(str
), OBJECT_TO_JSVAL(regexp
), STRING_TO_JSVAL(repstr
)
292 if (!js_StringReplaceHelper(cx
, 2, NULL
, repstr
, vp
))
294 JS_ASSERT(JSVAL_IS_STRING(vp
[0]));
295 return JSVAL_TO_STRING(vp
[0]);
299 js_String_p_replace_str2(JSContext
* cx
, JSString
* str
, JSString
* patstr
, JSString
* repstr
)
302 JSVAL_NULL
, STRING_TO_JSVAL(str
), STRING_TO_JSVAL(patstr
), STRING_TO_JSVAL(repstr
)
304 if (!js_StringReplaceHelper(cx
, 2, NULL
, repstr
, vp
))
306 JS_ASSERT(JSVAL_IS_STRING(vp
[0]));
307 return JSVAL_TO_STRING(vp
[0]);
311 js_String_p_replace_str3(JSContext
* cx
, JSString
* str
, JSString
* patstr
, JSString
* repstr
,
315 JSVAL_NULL
, STRING_TO_JSVAL(str
), STRING_TO_JSVAL(patstr
), STRING_TO_JSVAL(repstr
),
316 STRING_TO_JSVAL(flagstr
)
318 if (!js_StringReplaceHelper(cx
, 3, NULL
, repstr
, vp
))
320 JS_ASSERT(JSVAL_IS_STRING(vp
[0]));
321 return JSVAL_TO_STRING(vp
[0]);
325 js_String_p_split(JSContext
* cx
, JSString
* str
, JSString
* sepstr
)
327 // FIXME: optimize by calling into a lower level exported from jsstr.cpp.
328 jsval vp
[4] = { JSVAL_NULL
, STRING_TO_JSVAL(str
), STRING_TO_JSVAL(sepstr
), JSVAL_VOID
};
329 if (!js_str_split(cx
, 2, vp
))
331 JS_ASSERT(JSVAL_IS_OBJECT(vp
[0]));
332 return JSVAL_TO_OBJECT(vp
[0]);
336 js_StringToNumber(JSContext
* cx
, JSString
* str
)
343 JSSTRING_CHARS_AND_END(str
, bp
, end
);
344 if ((!js_strtod(cx
, bp
, end
, &ep
, &d
) ||
345 js_SkipWhiteSpace(ep
, end
) != end
) &&
346 (!js_strtointeger(cx
, bp
, end
, &ep
, 0, &d
) ||
347 js_SkipWhiteSpace(ep
, end
) != end
)) {
348 return *cx
->runtime
->jsNaN
;
354 js_StringToInt32(JSContext
* cx
, JSString
* str
)
361 JSSTRING_CHARS_AND_END(str
, bp
, end
);
362 if (!js_strtod(cx
, bp
, end
, &ep
, &d
) || js_SkipWhiteSpace(ep
, end
) != end
)
368 js_ParseFloat(JSContext
* cx
, JSString
* str
)
375 JSSTRING_CHARS_AND_END(str
, bp
, end
);
376 if (!js_strtod(cx
, bp
, end
, &ep
, &d
) || ep
== bp
)
377 return *cx
->runtime
->jsNaN
;
382 js_ParseInt(JSContext
* cx
, JSString
* str
)
389 JSSTRING_CHARS_AND_END(str
, bp
, end
);
390 if (!js_strtointeger(cx
, bp
, end
, &ep
, 0, &d
) || ep
== bp
)
391 return *cx
->runtime
->jsNaN
;
396 js_Any_getelem(JSContext
* cx
, JSObject
* obj
, JSString
* idstr
)
401 if (!js_ValueToStringId(cx
, STRING_TO_JSVAL(idstr
), &id
))
402 return JSVAL_ERROR_COOKIE
;
403 if (!OBJ_GET_PROPERTY(cx
, obj
, id
, &v
))
404 return JSVAL_ERROR_COOKIE
;
409 js_Any_setelem(JSContext
* cx
, JSObject
* obj
, JSString
* idstr
, jsval v
)
412 if (!js_ValueToStringId(cx
, STRING_TO_JSVAL(idstr
), &id
))
414 return OBJ_SET_PROPERTY(cx
, obj
, id
, &v
);
418 js_FastValueToIterator(JSContext
* cx
, jsuint flags
, jsval v
)
420 if (!js_ValueToIterator(cx
, flags
, &v
))
422 return JSVAL_TO_OBJECT(v
);
426 js_FastCallIteratorNext(JSContext
* cx
, JSObject
* iterobj
)
429 if (!js_CallIteratorNext(cx
, iterobj
, &v
))
430 return JSVAL_ERROR_COOKIE
;
434 GuardRecord
* FASTCALL
435 js_CallTree(InterpState
* state
, Fragment
* f
)
438 union { NIns
*code
; GuardRecord
* (FASTCALL
*func
)(InterpState
*, Fragment
*); } u
;
443 #if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
444 SIMULATE_FASTCALL(lr
, state
, NULL
, u
.func
);
446 lr
= u
.func(state
, NULL
);
449 if (lr
->exit
->exitType
== NESTED_EXIT
)
450 lr
= state
->nestedExit
;
454 JS_STATIC_ASSERT(JSSLOT_PRIVATE
== JSSLOT_ARRAY_LENGTH
);
455 JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH
+ 1 == JSSLOT_ARRAY_COUNT
);
458 js_FastNewArray(JSContext
* cx
, JSObject
* proto
)
460 JS_ASSERT(OBJ_IS_ARRAY(cx
, proto
));
462 JS_ASSERT(cx
->executingTrace
);
463 JSObject
* obj
= (JSObject
*) js_NewGCThing(cx
, GCX_OBJECT
, sizeof(JSObject
));
467 obj
->fslots
[JSSLOT_PROTO
] = OBJECT_TO_JSVAL(proto
);
468 obj
->fslots
[JSSLOT_PARENT
] = proto
->fslots
[JSSLOT_PARENT
];
470 JSClass
* clasp
= &js_ArrayClass
;
471 obj
->fslots
[JSSLOT_CLASS
] = PRIVATE_TO_JSVAL(clasp
);
473 obj
->fslots
[JSSLOT_ARRAY_LENGTH
] = 0;
474 obj
->fslots
[JSSLOT_ARRAY_COUNT
] = 0;
475 for (unsigned i
= JSSLOT_ARRAY_COUNT
+ 1; i
!= JS_INITIAL_NSLOTS
; ++i
)
476 obj
->fslots
[i
] = JSVAL_VOID
;
478 JSObjectOps
* ops
= clasp
->getObjectOps(cx
, clasp
);
479 obj
->map
= ops
->newObjectMap(cx
, 1, ops
, clasp
, obj
);
487 js_FastNewObject(JSContext
* cx
, JSObject
* ctor
)
489 JS_ASSERT(HAS_FUNCTION_CLASS(ctor
));
490 JSFunction
* fun
= GET_FUNCTION_PRIVATE(cx
, ctor
);
491 JSClass
* clasp
= FUN_INTERPRETED(fun
) ? &js_ObjectClass
: fun
->u
.n
.clasp
;
492 JS_ASSERT(clasp
!= &js_ArrayClass
);
494 JS_ASSERT(cx
->executingTrace
);
495 JSObject
* obj
= (JSObject
*) js_NewGCThing(cx
, GCX_OBJECT
, sizeof(JSObject
));
499 JS_LOCK_OBJ(cx
, ctor
);
500 JSScope
*scope
= OBJ_SCOPE(ctor
);
501 JS_ASSERT(scope
->object
== ctor
);
502 JSAtom
* atom
= cx
->runtime
->atomState
.classPrototypeAtom
;
504 JSScopeProperty
*sprop
= SCOPE_GET_PROPERTY(scope
, ATOM_TO_JSID(atom
));
505 JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop
, scope
));
506 jsval v
= LOCKED_OBJ_GET_SLOT(ctor
, sprop
->slot
);
507 JS_UNLOCK_SCOPE(cx
, scope
);
509 JS_ASSERT(!JSVAL_IS_PRIMITIVE(v
));
510 JSObject
* proto
= JSVAL_TO_OBJECT(v
);
512 obj
->fslots
[JSSLOT_PROTO
] = OBJECT_TO_JSVAL(proto
);
513 obj
->fslots
[JSSLOT_PARENT
] = ctor
->fslots
[JSSLOT_PARENT
];
514 obj
->fslots
[JSSLOT_CLASS
] = PRIVATE_TO_JSVAL(clasp
);
515 for (unsigned i
= JSSLOT_PRIVATE
; i
!= JS_INITIAL_NSLOTS
; ++i
)
516 obj
->fslots
[i
] = JSVAL_VOID
;
518 obj
->map
= js_HoldObjectMap(cx
, proto
->map
);
524 js_AddProperty(JSContext
* cx
, JSObject
* obj
, JSScopeProperty
* sprop
)
526 JSScopeProperty
* sprop2
= NULL
; // initialize early to make MSVC happy
528 JS_ASSERT(OBJ_IS_NATIVE(obj
));
529 JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop
));
531 JS_LOCK_OBJ(cx
, obj
);
532 JSScope
* scope
= OBJ_SCOPE(obj
);
533 if (scope
->object
== obj
) {
534 JS_ASSERT(!SCOPE_HAS_PROPERTY(scope
, sprop
));
536 scope
= js_GetMutableScope(cx
, obj
);
538 JS_UNLOCK_OBJ(cx
, obj
);
543 uint32 slot
= sprop
->slot
;
544 if (!scope
->table
&& sprop
->parent
== scope
->lastProp
&& slot
== scope
->map
.freeslot
) {
545 if (slot
< STOBJ_NSLOTS(obj
) && !OBJ_GET_CLASS(cx
, obj
)->reserveSlots
) {
546 ++scope
->map
.freeslot
;
548 if (!js_AllocSlot(cx
, obj
, &slot
)) {
549 JS_UNLOCK_SCOPE(cx
, scope
);
553 if (slot
!= sprop
->slot
)
557 SCOPE_EXTEND_SHAPE(cx
, scope
, sprop
);
559 scope
->lastProp
= sprop
;
560 JS_UNLOCK_SCOPE(cx
, scope
);
564 sprop2
= js_AddScopeProperty(cx
, scope
, sprop
->id
,
565 sprop
->getter
, sprop
->setter
, SPROP_INVALID_SLOT
,
566 sprop
->attrs
, sprop
->flags
, sprop
->shortid
);
567 if (sprop2
== sprop
) {
568 JS_UNLOCK_SCOPE(cx
, scope
);
574 js_FreeSlot(cx
, obj
, slot
);
575 JS_UNLOCK_SCOPE(cx
, scope
);
580 js_HasNamedProperty(JSContext
* cx
, JSObject
* obj
, JSString
* idstr
)
583 if (!js_ValueToStringId(cx
, STRING_TO_JSVAL(idstr
), &id
))
584 return JSVAL_ERROR_COOKIE
;
588 if (!OBJ_LOOKUP_PROPERTY(cx
, obj
, id
, &obj2
, &prop
))
589 return JSVAL_TO_BOOLEAN(JSVAL_VOID
);
591 OBJ_DROP_PROPERTY(cx
, obj2
, prop
);
596 js_CallGetter(JSContext
* cx
, JSObject
* obj
, JSScopeProperty
* sprop
)
598 JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop
));
600 if (!SPROP_GET(cx
, sprop
, obj
, obj
, &v
))
601 return JSVAL_ERROR_COOKIE
;
606 js_TypeOfObject(JSContext
* cx
, JSObject
* obj
)
608 JSType type
= JS_TypeOfValue(cx
, OBJECT_TO_JSVAL(obj
));
609 return ATOM_TO_STRING(cx
->runtime
->atomState
.typeAtoms
[type
]);
613 js_TypeOfBoolean(JSContext
* cx
, jsint unboxed
)
615 jsval boxed
= BOOLEAN_TO_JSVAL(unboxed
);
616 JS_ASSERT(JSVAL_IS_VOID(boxed
) || JSVAL_IS_BOOLEAN(boxed
));
617 JSType type
= JS_TypeOfValue(cx
, boxed
);
618 return ATOM_TO_STRING(cx
->runtime
->atomState
.typeAtoms
[type
]);
622 js_Object_p_hasOwnProperty(JSContext
* cx
, JSObject
* obj
, JSString
*str
)
624 jsid id
= ATOM_TO_JSID(STRING_TO_JSVAL(str
));
626 if (!js_HasOwnProperty(cx
, obj
->map
->ops
->lookupProperty
, obj
, id
, &v
))
627 return JSVAL_TO_BOOLEAN(JSVAL_VOID
);
628 JS_ASSERT(JSVAL_IS_BOOLEAN(v
));
629 return JSVAL_TO_BOOLEAN(v
);
633 js_Object_p_propertyIsEnumerable(JSContext
* cx
, JSObject
* obj
, JSString
*str
)
635 jsid id
= ATOM_TO_JSID(STRING_TO_JSVAL(str
));
637 if (!js_PropertyIsEnumerable(cx
, obj
, id
, &v
))
638 return JSVAL_TO_BOOLEAN(JSVAL_VOID
);
639 JS_ASSERT(JSVAL_IS_BOOLEAN(v
));
640 return JSVAL_TO_BOOLEAN(v
);
644 js_BooleanToNumber(JSContext
* cx
, jsint unboxed
)
646 if (unboxed
== JSVAL_TO_BOOLEAN(JSVAL_VOID
))
647 return *cx
->runtime
->jsNaN
;
652 js_ObjectToString(JSContext
* cx
, JSObject
* obj
)
655 return ATOM_TO_STRING(cx
->runtime
->atomState
.nullAtom
);
657 if (!OBJ_DEFAULT_VALUE(cx
, obj
, JSTYPE_STRING
, &v
))
659 JS_ASSERT(JSVAL_IS_STRING(v
));
660 return JSVAL_TO_STRING(v
);
664 js_Array_1int(JSContext
* cx
, JSObject
* proto
, jsint i
)
666 JS_ASSERT(cx
->executingTrace
);
667 JSObject
* obj
= js_FastNewArray(cx
, proto
);
669 obj
->fslots
[JSSLOT_ARRAY_LENGTH
] = i
;
673 #define ARRAY_CTOR_GUTS(exact_len, newslots_code) \
674 JS_ASSERT(cx->executingTrace); \
675 JSObject* obj = js_FastNewArray(cx, proto); \
677 uint32 len = ARRAY_GROWBY; \
678 jsval* newslots = (jsval*) JS_malloc(cx, sizeof (jsval) * (len + 1)); \
680 obj->dslots = newslots + 1; \
681 ARRAY_SET_DENSE_LENGTH(obj, len); \
683 while (++newslots < obj->dslots + len) \
684 *newslots = JSVAL_HOLE; \
685 obj->fslots[JSSLOT_ARRAY_LENGTH] = (exact_len); \
692 js_Array_1str(JSContext
* cx
, JSObject
* proto
, JSString
*str
)
694 ARRAY_CTOR_GUTS(1, *++newslots
= STRING_TO_JSVAL(str
);)
698 js_Array_2obj(JSContext
* cx
, JSObject
* proto
, JSObject
*obj1
, JSObject
* obj2
)
701 *++newslots
= OBJECT_TO_JSVAL(obj1
);
702 *++newslots
= OBJECT_TO_JSVAL(obj2
);)
706 js_Array_3num(JSContext
* cx
, JSObject
* proto
, jsdouble n1
, jsdouble n2
, jsdouble n3
)
709 if (!js_NewDoubleInRootedValue(cx
, n1
, ++newslots
))
711 if (!js_NewDoubleInRootedValue(cx
, n2
, ++newslots
))
713 if (!js_NewDoubleInRootedValue(cx
, n3
, ++newslots
))
717 #define LO ARGSIZE_LO
721 #if defined AVMPLUS_64BIT
728 #define NAME(op) ,#op
733 #define BUILTIN1(op, at0, atr, tr, t0, cse, fold) \
734 { (intptr_t)&js_##op, (at0 << 2) | atr, cse, fold NAME(op) },
735 #define BUILTIN2(op, at0, at1, atr, tr, t0, t1, cse, fold) \
736 { (intptr_t)&js_##op, (at0 << 4) | (at1 << 2) | atr, cse, fold NAME(op) },
737 #define BUILTIN3(op, at0, at1, at2, atr, tr, t0, t1, t2, cse, fold) \
738 { (intptr_t)&js_##op, (at0 << 6) | (at1 << 4) | (at2 << 2) | atr, cse, fold NAME(op) },
739 #define BUILTIN4(op, at0, at1, at2, at3, atr, tr, t0, t1, t2, t3, cse, fold) \
740 { (intptr_t)&js_##op, (at0 << 8) | (at1 << 6) | (at2 << 4) | (at3 << 2) | atr, cse, fold NAME(op) },
741 #define BUILTIN5(op, at0, at1, at2, at3, at4, atr, tr, t0, t1, t2, t3, t4, cse, fold) \
742 { (intptr_t)&js_##op, (at0 << 10) | (at1 << 8) | (at2 << 6) | (at3 << 4) | (at4 << 2) | atr, cse, fold NAME(op) },
744 struct CallInfo builtins
[] = {
745 #include "builtins.tbl"