зеркало из https://github.com/mozilla/gecko-dev.git
Bug 458735 - Improve internal API for traceable natives (r=brendan, nanojit r=edwsmith)
This commit is contained in:
Родитель
90b150b28d
Коммит
c6bca4ae17
|
@ -215,16 +215,17 @@ ifdef ENABLE_JIT
|
|||
VPATH += $(srcdir)/nanojit
|
||||
|
||||
EXPORTS += \
|
||||
builtins.tbl \
|
||||
jsbuiltins.h \
|
||||
Assembler.h \
|
||||
LIR.h \
|
||||
avmplus.h \
|
||||
vm_fops.h \
|
||||
Fragmento.h \
|
||||
Native.h \
|
||||
Native$(NANOJIT_ARCH).h \
|
||||
RegAlloc.h \
|
||||
nanojit.h \
|
||||
builtins.tbl \
|
||||
TraceTreeDrawer.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += \
|
||||
|
@ -239,7 +240,6 @@ CPPSRCS += \
|
|||
$(NULL)
|
||||
|
||||
ifdef DEBUG
|
||||
EXPORTS += TraceTreeDrawer.h
|
||||
CPPSRCS += TraceTreeDrawer.cpp
|
||||
endif
|
||||
|
||||
|
|
|
@ -37,30 +37,25 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* This file declares the various builtins we recognize, and is
|
||||
* included in various places in interesting ways. Each line starts
|
||||
* with "BUILTIN" then an integer indicating the number of arguments
|
||||
* the builtin takes. Builtins with no arguments are not supported at
|
||||
* the moment.
|
||||
* This file declares builtin functions that can be called from JITted code.
|
||||
* Each line starts with "BUILTIN" and an integer, the number of arguments the
|
||||
* builtin takes. Builtins with no arguments are not supported.
|
||||
*
|
||||
* This is followed, in parentheses, by the following things, in order:
|
||||
* - A name for the builtin. Prefixed with "F_" this is the opcode name to
|
||||
* pass to insCall. Prefixed with "js_" this is the name of the actual
|
||||
* native method to call.
|
||||
* - The sizes of the arguments to the native, in order. These can be "LO" for
|
||||
* integers (any size), pointers, or jsvals and "F" for doubles.
|
||||
* - The size of the return value. This can be "LO" for 32-bit integers, "P"
|
||||
* for pointers or jsvals, "F" for doubles, "Q" for 64-bit integers.
|
||||
* - The actual C++ type of the return value
|
||||
* - The C++ types of the arguments, in order
|
||||
* - A boolean value (0 = false, 1 = true) indicating whether the builtin call
|
||||
* can be optimized away during common subexpression elimination. This
|
||||
* should only be true if the the builtin is idempotent and the return value
|
||||
* is uniquely determined by the values of the arguments.
|
||||
* - A boolean value (0 = false, 1 = true) indicating whether the builtin call
|
||||
* can be optimized away during constant folding. This should only be true
|
||||
* if the builtin is idempotent and if the return value can be determined at
|
||||
* compile time if the input values are known at compile time.
|
||||
* The macro arguments are:
|
||||
*
|
||||
* - The return type. This identifier must name one of the _JS_TYPEINFO_*
|
||||
* macros defined in jsbuiltins.h.
|
||||
*
|
||||
* - The builtin name. Prefixed with "js_" this gives the native function name.
|
||||
*
|
||||
* - The parameter types.
|
||||
*
|
||||
* - The cse flag. 1 if the builtin call can be optimized away by common
|
||||
* subexpression elimination; otherwise 0. This should be 1 only if the
|
||||
* function is idempotent and the return value is determined solely by the
|
||||
* arguments.
|
||||
*
|
||||
* - The fold flag. Reserved. The same as cse for now.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -68,93 +63,45 @@
|
|||
* Do not use bool FASTCALL, use JSBool only!
|
||||
*/
|
||||
|
||||
BUILTIN2(BoxDouble, LO, F, P, jsval, JSContext*, jsdouble, 1, 1)
|
||||
BUILTIN2(BoxInt32, LO, LO, P, jsval, JSContext*, jsint, 1, 1)
|
||||
BUILTIN1(UnboxDouble, LO, F, jsdouble, jsval, 1, 1)
|
||||
BUILTIN1(UnboxInt32, LO, LO, int32, jsval, 1, 1)
|
||||
BUILTIN2(dmod, F, F, F, jsdouble, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(imod, LO, LO, LO, jsint, jsint, jsint, 1, 1)
|
||||
BUILTIN1(DoubleToInt32, F, LO, int32, jsdouble, 1, 1)
|
||||
BUILTIN1(DoubleToUint32, F, LO, int32, jsdouble, 1, 1)
|
||||
BUILTIN1(Math_sin, F, F, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN1(Math_cos, F, F, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(Math_pow, F, F, F, jsdouble, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN1(Math_sqrt, F, F, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN1(Math_floor, F, F, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN1(Math_ceil, F, F, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN1(Math_log, F, F, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(Math_max, F, F, F, jsdouble, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN4(Array_dense_setelem, LO, LO, LO, LO, LO, bool, JSContext*, JSObject*, jsint, jsval, 0, 0)
|
||||
BUILTIN3(Array_p_join, LO, LO, LO, P, JSString*, JSContext*, JSObject*, JSString*, 0, 0)
|
||||
BUILTIN3(Array_p_push1, LO, LO, LO, LO, jsval, JSContext*, JSObject*, jsval, 0, 0)
|
||||
BUILTIN2(Array_p_pop, LO, LO, LO, jsval, JSContext*, JSObject*, 0, 0)
|
||||
BUILTIN4(String_p_substring, LO, LO, LO, LO, P, JSString*, JSContext*, JSString*, jsint, jsint, 1, 1)
|
||||
BUILTIN3(String_p_substring_1, LO, LO, LO, P, JSString*, JSContext*, JSString*, jsint, 1, 1)
|
||||
BUILTIN3(ConcatStrings, LO, LO, LO, P, JSString*, JSContext*, JSString*, JSString*, 1, 1)
|
||||
BUILTIN3(String_getelem, LO, LO, LO, P, JSString*, JSContext*, JSString*, jsint, 1, 1)
|
||||
BUILTIN2(String_fromCharCode, LO, LO, P, JSString*, JSContext*, jsint, 1, 1)
|
||||
BUILTIN2(String_p_charCodeAt, LO, LO, LO, jsint, JSString*, jsint, 1, 1)
|
||||
BUILTIN3(String_p_concat_1int, LO, LO, LO, P, JSString*, JSContext*, JSString*, jsint, 1, 1)
|
||||
BUILTIN4(String_p_concat_2str, LO, LO, LO, LO, P, JSString*, JSContext*, JSString*, JSString*, JSString*, 1, 1)
|
||||
BUILTIN5(String_p_concat_3str, LO, LO, LO, LO, LO, P, JSString*, JSContext*, JSString*, JSString*, JSString*, JSString*, 1, 1)
|
||||
BUILTIN4(String_p_match, LO, LO, LO, LO, P, JSObject*, JSContext*, JSString*, jsbytecode*, JSObject*, 1, 1)
|
||||
BUILTIN4(String_p_match_obj, LO, LO, LO, LO, P, JSObject*, JSContext*, JSObject*, jsbytecode*, JSObject*, 1, 1)
|
||||
BUILTIN4(String_p_replace_str, LO, LO, LO, LO, P, JSString*, JSContext*, JSString*, JSObject*, JSString*, 1, 1)
|
||||
BUILTIN4(String_p_replace_str2, LO, LO, LO, LO, P, JSString*, JSContext*, JSString*, JSString*, JSString*, 1, 1)
|
||||
BUILTIN5(String_p_replace_str3, LO, LO, LO, LO, LO, P, JSString*, JSContext*, JSString*, JSString*, JSString*, JSString*, 1, 1)
|
||||
BUILTIN3(String_p_split, LO, LO, LO, P, JSObject*, JSContext*, JSString*, JSString*, 0, 0)
|
||||
BUILTIN2(toLowerCase, LO, LO, P, JSString*, JSContext*, JSString*, 1, 1)
|
||||
BUILTIN2(toUpperCase, LO, LO, P, JSString*, JSContext*, JSString*, 1, 1)
|
||||
BUILTIN1(Math_random, LO, F, jsdouble, JSRuntime*, 0, 0)
|
||||
BUILTIN2(EqualStrings, LO, LO, LO, bool, JSString*, JSString*, 1, 1)
|
||||
BUILTIN2(CompareStrings, LO, LO, LO, bool, JSString*, JSString*, 1, 1)
|
||||
BUILTIN2(StringToNumber, LO, LO, F, jsdouble, JSContext*, JSString*, 1, 1)
|
||||
BUILTIN2(StringToInt32, LO, LO, LO, jsint, JSContext*, JSString*, 1, 1)
|
||||
BUILTIN2(ParseInt, LO, LO, F, jsdouble, JSContext*, JSString*, 1, 1)
|
||||
BUILTIN1(ParseIntDouble, F, F, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(ParseFloat, LO, LO, F, jsdouble, JSContext*, JSString*, 1, 1)
|
||||
BUILTIN3(Any_getprop, LO, LO, LO, P, jsval, JSContext*, JSObject*, JSString*, 0, 0)
|
||||
BUILTIN4(Any_setprop, LO, LO, LO, LO, LO, bool, JSContext*, JSObject*, JSString*, jsval, 0, 0)
|
||||
BUILTIN3(Any_getelem, LO, LO, LO, P, jsval, JSContext*, JSObject*, jsuint, 0, 0)
|
||||
BUILTIN4(Any_setelem, LO, LO, LO, LO, LO, bool, JSContext*, JSObject*, jsuint, jsval, 0, 0)
|
||||
BUILTIN3(FastValueToIterator, LO, LO, LO, P, JSObject*, JSContext*, jsuint, jsval, 0, 0)
|
||||
BUILTIN2(FastCallIteratorNext, LO, LO, P, JSObject*, JSContext*, JSObject*, 0, 0)
|
||||
BUILTIN2(CloseIterator, LO, LO, LO, bool, JSContext*, jsval, 0, 0)
|
||||
BUILTIN2(CallTree, LO, LO, P, nanojit::GuardRecord*, avmplus::InterpState*, nanojit::Fragment*, 0, 0)
|
||||
BUILTIN2(FastNewArray, LO, LO, P, JSObject*, JSContext*, JSObject*, 0, 0)
|
||||
BUILTIN2(FastNewObject, LO, LO, P, JSObject*, JSContext*, JSObject*, 0, 0)
|
||||
BUILTIN3(AddProperty, LO, LO, LO, LO, bool, JSContext*, JSObject*, JSScopeProperty*, 0, 0)
|
||||
BUILTIN3(HasNamedProperty, LO, LO, LO, LO, bool, JSContext*, JSObject*, JSString*, 0, 0)
|
||||
BUILTIN3(CallGetter, LO, LO, LO, P, jsval, JSContext*, JSObject*, JSScopeProperty*, 0, 0)
|
||||
BUILTIN2(TypeOfObject, LO, LO, P, JSString*, JSContext*, JSObject*, 1, 1)
|
||||
BUILTIN2(TypeOfBoolean, LO, LO, P, JSString*, JSContext*, jsint, 1, 1)
|
||||
BUILTIN2(NumberToString, LO, F, P, JSString*, JSContext*, jsdouble, 1, 1)
|
||||
BUILTIN3(Object_p_hasOwnProperty,
|
||||
LO, LO, LO, LO, jsint, JSContext*, JSObject*, JSString*, 0, 0)
|
||||
BUILTIN3(Object_p_propertyIsEnumerable,
|
||||
LO, LO, LO, LO, jsint, JSContext*, JSObject*, JSString*, 0, 0)
|
||||
BUILTIN2(BooleanToNumber, LO, LO, F, jsdouble, JSContext*, jsint, 1, 1)
|
||||
BUILTIN2(ObjectToString, LO, LO, P, JSString*, JSContext*, JSObject*, 0, 0)
|
||||
BUILTIN3(Array_1int, LO, LO, LO, P, JSObject*, JSContext*, JSObject*, jsint, 0, 0)
|
||||
BUILTIN3(Array_1str, LO, LO, LO, P, JSObject*, JSContext*, JSObject*, JSString*, 0, 0)
|
||||
BUILTIN4(Array_2obj, LO, LO, LO, LO, P, JSObject*, JSContext*, JSObject*, JSObject*, JSObject**, 0, 0)
|
||||
BUILTIN5(Array_3num, LO, LO, F, F, F, P, JSObject*, JSContext*, JSObject*, jsdouble, jsdouble, jsdouble, 0, 0)
|
||||
BUILTIN1(Arguments, LO, P, JSObject*, JSContext*, 0, 0)
|
||||
BUILTIN2(JSVAL, BoxDouble, CONTEXT, DOUBLE, 1, 1)
|
||||
BUILTIN2(JSVAL, BoxInt32, CONTEXT, INT32, 1, 1)
|
||||
BUILTIN1(DOUBLE, UnboxDouble, JSVAL, 1, 1)
|
||||
BUILTIN1(INT32, UnboxInt32, JSVAL, 1, 1)
|
||||
BUILTIN2(DOUBLE, dmod, DOUBLE, DOUBLE, 1, 1)
|
||||
BUILTIN2(INT32, imod, INT32, INT32, 1, 1)
|
||||
BUILTIN1(INT32, DoubleToInt32, DOUBLE, 1, 1)
|
||||
BUILTIN1(UINT32, DoubleToUint32, DOUBLE, 1, 1)
|
||||
|
||||
// Don't really need an argument here, but we don't support arg-less builtins
|
||||
BUILTIN1(Date_now, LO, F, jsdouble, JSContext*, 0, 0)
|
||||
BUILTIN2(FastNewDate, LO, LO, P, JSObject*, JSContext*, JSObject*, 0, 0)
|
||||
BUILTIN2(DOUBLE, StringToNumber, CONTEXT, STRING, 1, 1)
|
||||
BUILTIN2(INT32, StringToInt32, CONTEXT, STRING, 1, 1)
|
||||
BUILTIN3(JSVAL, Any_getprop, CONTEXT, OBJECT, STRING, 0, 0)
|
||||
BUILTIN4(BOOL, Any_setprop, CONTEXT, OBJECT, STRING, JSVAL, 0, 0)
|
||||
BUILTIN3(JSVAL, Any_getelem, CONTEXT, OBJECT, UINT32, 0, 0)
|
||||
BUILTIN4(BOOL, Any_setelem, CONTEXT, OBJECT, UINT32, JSVAL, 0, 0)
|
||||
BUILTIN3(OBJECT, FastValueToIterator, CONTEXT, UINT32, JSVAL, 0, 0)
|
||||
BUILTIN2(JSVAL, FastCallIteratorNext, CONTEXT, OBJECT, 0, 0)
|
||||
BUILTIN2(BOOL, CloseIterator, CONTEXT, JSVAL, 0, 0)
|
||||
BUILTIN2(GUARDRECORD, CallTree, INTERPSTATE, FRAGMENT, 0, 0)
|
||||
BUILTIN2(OBJECT, FastNewObject, CONTEXT, OBJECT, 0, 0)
|
||||
BUILTIN3(BOOL, AddProperty, CONTEXT, OBJECT, SCOPEPROP, 0, 0)
|
||||
BUILTIN3(BOOL, HasNamedProperty, CONTEXT, OBJECT, STRING, 0, 0)
|
||||
BUILTIN3(JSVAL, CallGetter, CONTEXT, OBJECT, SCOPEPROP, 0, 0)
|
||||
BUILTIN2(STRING, TypeOfObject, CONTEXT, OBJECT, 1, 1)
|
||||
BUILTIN2(STRING, TypeOfBoolean, CONTEXT, INT32, 1, 1)
|
||||
BUILTIN2(DOUBLE, BooleanToNumber, CONTEXT, INT32, 1, 1)
|
||||
BUILTIN2(STRING, ObjectToString, CONTEXT, OBJECT, 0, 0)
|
||||
BUILTIN1(OBJECT, Arguments, CONTEXT, 0, 0)
|
||||
|
||||
// soft float
|
||||
BUILTIN1(fneg, F, F, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN1(i2f, LO, F, jsdouble, jsint, 1, 1)
|
||||
BUILTIN1(u2f, LO, F, jsdouble, jsuint, 1, 1)
|
||||
BUILTIN2(fcmpeq, F, F, LO, jsint, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(fcmplt, F, F, LO, jsint, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(fcmple, F, F, LO, jsint, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(fcmpgt, F, F, LO, jsint, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(fcmpge, F, F, LO, jsint, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(fmul, F, F, F, jsdouble, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(fadd, F, F, F, jsdouble, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(fdiv, F, F, F, jsdouble, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(fsub, F, F, F, jsdouble, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN1(DOUBLE, fneg, DOUBLE, 1, 1)
|
||||
BUILTIN1(DOUBLE, i2f, INT32, 1, 1)
|
||||
BUILTIN1(DOUBLE, u2f, UINT32, 1, 1)
|
||||
BUILTIN2(INT32, fcmpeq, DOUBLE, DOUBLE, 1, 1)
|
||||
BUILTIN2(INT32, fcmplt, DOUBLE, DOUBLE, 1, 1)
|
||||
BUILTIN2(INT32, fcmple, DOUBLE, DOUBLE, 1, 1)
|
||||
BUILTIN2(INT32, fcmpgt, DOUBLE, DOUBLE, 1, 1)
|
||||
BUILTIN2(INT32, fcmpge, DOUBLE, DOUBLE, 1, 1)
|
||||
BUILTIN2(DOUBLE, fmul, DOUBLE, DOUBLE, 1, 1)
|
||||
BUILTIN2(DOUBLE, fadd, DOUBLE, DOUBLE, 1, 1)
|
||||
BUILTIN2(DOUBLE, fdiv, DOUBLE, DOUBLE, 1, 1)
|
||||
BUILTIN2(DOUBLE, fsub, DOUBLE, DOUBLE, 1, 1)
|
||||
|
|
|
@ -8,7 +8,7 @@ for i in correct/*.js; do
|
|||
echo -n jit:' '
|
||||
JIT=`Darwin_OPT.OBJ/js -j -f $i`
|
||||
echo $JIT' '
|
||||
if [ $INTERP != "true" -o $JIT != "true" ]
|
||||
if [ "$INTERP" != "true" -o "$JIT" != "true" ]
|
||||
then
|
||||
FAILURES=${FAILURES}" "${i}
|
||||
fi
|
||||
|
@ -20,4 +20,4 @@ then
|
|||
echo ${FAILURES}
|
||||
else
|
||||
echo "PASSED"
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "jsarray.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbool.h"
|
||||
#include "jsbuiltins.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsversion.h"
|
||||
#include "jsdate.h"
|
||||
|
@ -2784,7 +2785,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
|||
* we know to create an object of this class when we call the
|
||||
* constructor.
|
||||
*/
|
||||
fun->u.n.clasp = clasp;
|
||||
FUN_CLASP(fun) = clasp;
|
||||
|
||||
/*
|
||||
* Optionally construct the prototype object, before the class has
|
||||
|
@ -4380,6 +4381,7 @@ js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, jsval *vp)
|
|||
jsval fsv;
|
||||
JSFunctionSpec *fs;
|
||||
JSObject *tmp;
|
||||
JSFastNative native;
|
||||
|
||||
if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(*vp), 0, &fsv))
|
||||
return JS_FALSE;
|
||||
|
@ -4424,7 +4426,14 @@ js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (argc != 0)
|
||||
--argc;
|
||||
|
||||
return ((JSFastNative) fs->call)(cx, argc, vp);
|
||||
native =
|
||||
#ifdef JS_TRACER
|
||||
(fs->flags & JSFUN_TRACEABLE)
|
||||
? ((JSTraceableNative *) fs->call)->native
|
||||
:
|
||||
#endif
|
||||
(JSFastNative) fs->call;
|
||||
return native(cx, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -4515,7 +4524,8 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
|
|||
? (JSNative)
|
||||
js_generic_fast_native_method_dispatcher
|
||||
: js_generic_native_method_dispatcher,
|
||||
fs->nargs + 1, flags);
|
||||
fs->nargs + 1,
|
||||
flags & ~JSFUN_TRACEABLE);
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
fun->u.n.extra = (uint16)fs->extra;
|
||||
|
|
|
@ -1447,8 +1447,7 @@ struct JSFunctionSpec {
|
|||
/*
|
||||
* extra & 0xFFFF: Number of extra argument slots for local GC roots.
|
||||
* If fast native, must be zero.
|
||||
* extra >> 16: If slow native, reserved for future use (must be 0).
|
||||
* If fast native, minimum required argc.
|
||||
* extra >> 16: Reserved for future use (must be 0).
|
||||
*/
|
||||
uint32 extra;
|
||||
};
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "jsatom.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsbool.h"
|
||||
#include "jsbuiltins.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsversion.h"
|
||||
#include "jsdbgapi.h" /* for js_TraceWatchPoints */
|
||||
|
@ -791,6 +792,30 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSBool FASTCALL
|
||||
js_Array_dense_setelem(JSContext* cx, JSObject* obj, jsint i, jsval v)
|
||||
{
|
||||
JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
|
||||
|
||||
do {
|
||||
jsuint length = ARRAY_DENSE_LENGTH(obj);
|
||||
if ((jsuint)i < length) {
|
||||
if (obj->dslots[i] == JSVAL_HOLE) {
|
||||
if (cx->runtime->anyArrayProtoHasElement)
|
||||
break;
|
||||
if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
}
|
||||
obj->dslots[i] = v;
|
||||
return JS_TRUE;
|
||||
}
|
||||
} while (0);
|
||||
return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(i), &v);
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
array_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
|
||||
|
@ -1193,14 +1218,20 @@ out_bad:
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
enum ArrayToStringOp {
|
||||
TO_STRING,
|
||||
TO_LOCALE_STRING,
|
||||
TO_SOURCE
|
||||
};
|
||||
|
||||
/*
|
||||
* When op is TO_STRING or TO_LOCALE_STRING sep indicates a separator to use
|
||||
* or "," when sep is NULL.
|
||||
* When op is TO_SOURCE sep must be NULL.
|
||||
*/
|
||||
JSBool
|
||||
js_array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op,
|
||||
JSString *sep, jsval *rval)
|
||||
static JSBool
|
||||
array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op,
|
||||
JSString *sep, jsval *rval)
|
||||
{
|
||||
JSBool ok, hole;
|
||||
jsuint length, index;
|
||||
|
@ -1418,7 +1449,7 @@ array_toSource(JSContext *cx, uintN argc, jsval *vp)
|
|||
!JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
return js_array_join_sub(cx, obj, TO_SOURCE, NULL, vp);
|
||||
return array_join_sub(cx, obj, TO_SOURCE, NULL, vp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1432,7 +1463,7 @@ array_toString(JSContext *cx, uintN argc, jsval *vp)
|
|||
!JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
return js_array_join_sub(cx, obj, TO_STRING, NULL, vp);
|
||||
return array_join_sub(cx, obj, TO_STRING, NULL, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -1450,7 +1481,7 @@ array_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
|
|||
* Passing comma here as the separator. Need a way to get a
|
||||
* locale-specific version.
|
||||
*/
|
||||
return js_array_join_sub(cx, obj, TO_LOCALE_STRING, NULL, vp);
|
||||
return array_join_sub(cx, obj, TO_LOCALE_STRING, NULL, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -1506,11 +1537,23 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, jsval *vector,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSString* FASTCALL
|
||||
js_Array_p_join(JSContext* cx, JSObject* obj, JSString *str)
|
||||
{
|
||||
jsval v;
|
||||
if (!array_join_sub(cx, obj, TO_STRING, str, &v))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_STRING(v));
|
||||
return JSVAL_TO_STRING(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Perl-inspired join, reverse, and sort.
|
||||
*/
|
||||
JSBool
|
||||
js_array_join(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
array_join(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
JSObject *obj;
|
||||
|
@ -1524,7 +1567,7 @@ js_array_join(JSContext *cx, uintN argc, jsval *vp)
|
|||
vp[2] = STRING_TO_JSVAL(str);
|
||||
}
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
return obj && js_array_join_sub(cx, obj, TO_STRING, str, vp);
|
||||
return obj && array_join_sub(cx, obj, TO_STRING, str, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -2045,8 +2088,8 @@ array_sort(JSContext *cx, uintN argc, jsval *vp)
|
|||
/*
|
||||
* Perl-inspired push, pop, shift, unshift, and splice methods.
|
||||
*/
|
||||
JSBool
|
||||
js_array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool
|
||||
array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsuint length, newlength;
|
||||
|
||||
|
@ -2062,14 +2105,14 @@ js_array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsva
|
|||
return js_SetLengthProperty(cx, obj, newlength);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
|
||||
static JSBool
|
||||
array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
|
||||
{
|
||||
uint32 length = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
if (INDEX_TOO_SPARSE(obj, length)) {
|
||||
if (!js_MakeArraySlow(cx, obj))
|
||||
return JS_FALSE;
|
||||
return js_array_push_slowly(cx, obj, 1, &v, rval);
|
||||
return array_push_slowly(cx, obj, 1, &v, rval);
|
||||
}
|
||||
|
||||
if (!EnsureLength(cx, obj, length + 1))
|
||||
|
@ -2082,8 +2125,21 @@ js_array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
|
|||
return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], rval);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_array_push(JSContext *cx, uintN argc, jsval *vp)
|
||||
#ifdef JS_TRACER
|
||||
jsval FASTCALL
|
||||
js_Array_p_push1(JSContext* cx, JSObject* obj, jsval v)
|
||||
{
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj)
|
||||
? array_push1_dense(cx, obj, v, &v)
|
||||
: array_push_slowly(cx, obj, 1, &v, &v)) {
|
||||
return v;
|
||||
}
|
||||
return JSVAL_ERROR_COOKIE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
array_push(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
|
@ -2092,13 +2148,13 @@ js_array_push(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (argc != 1 || !OBJ_IS_DENSE_ARRAY(cx, obj))
|
||||
return js_array_push_slowly(cx, obj, argc, vp + 2, vp);
|
||||
return array_push_slowly(cx, obj, argc, vp + 2, vp);
|
||||
|
||||
return js_array_push1_dense(cx, obj, vp[2], vp);
|
||||
return array_push1_dense(cx, obj, vp[2], vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_array_pop_slowly(JSContext *cx, JSObject* obj, jsval *vp)
|
||||
static JSBool
|
||||
array_pop_slowly(JSContext *cx, JSObject* obj, jsval *vp)
|
||||
{
|
||||
jsuint index;
|
||||
JSBool hole;
|
||||
|
@ -2119,8 +2175,8 @@ js_array_pop_slowly(JSContext *cx, JSObject* obj, jsval *vp)
|
|||
return js_SetLengthProperty(cx, obj, index);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
|
||||
static JSBool
|
||||
array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
|
||||
{
|
||||
jsuint index;
|
||||
JSBool hole;
|
||||
|
@ -2140,8 +2196,22 @@ js_array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
|
|||
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_array_pop(JSContext *cx, uintN argc, jsval *vp)
|
||||
#ifdef JS_TRACER
|
||||
jsval FASTCALL
|
||||
js_Array_p_pop(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
jsval v;
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj)
|
||||
? array_pop_dense(cx, obj, &v)
|
||||
: array_pop_slowly(cx, obj, &v)) {
|
||||
return v;
|
||||
}
|
||||
return JSVAL_ERROR_COOKIE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
array_pop(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
|
@ -2149,8 +2219,8 @@ js_array_pop(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj))
|
||||
return js_array_pop_dense(cx, obj, vp);
|
||||
return js_array_pop_slowly(cx, obj, vp);
|
||||
return array_pop_dense(cx, obj, vp);
|
||||
return array_pop_slowly(cx, obj, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -2897,6 +2967,24 @@ static JSPropertySpec array_props[] = {
|
|||
{0,0,0,0,0}
|
||||
};
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
JS_DEFINE_CALLINFO_3(STRING, Array_p_join, CONTEXT, OBJECT, STRING, 0, 0)
|
||||
JS_DEFINE_CALLINFO_3(JSVAL, Array_p_push1, CONTEXT, OBJECT, JSVAL, 0, 0)
|
||||
JS_DEFINE_CALLINFO_2(JSVAL, Array_p_pop, CONTEXT, OBJECT, 0, 0)
|
||||
|
||||
static JSTraceableNative array_join_trcinfo[] = {
|
||||
{ array_join, &ci_Array_p_join, "TC", "s", FAIL_NULL }
|
||||
};
|
||||
static JSTraceableNative array_push_trcinfo[] = {
|
||||
{ array_push, &ci_Array_p_push1, "TC", "v", FAIL_JSVAL }
|
||||
};
|
||||
static JSTraceableNative array_pop_trcinfo[] = {
|
||||
{ array_pop, &ci_Array_p_pop, "TC", "", FAIL_JSVAL }
|
||||
};
|
||||
|
||||
#endif /* JS_TRACER */
|
||||
|
||||
static JSFunctionSpec array_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
JS_FN(js_toSource_str, array_toSource, 0,0),
|
||||
|
@ -2905,11 +2993,11 @@ static JSFunctionSpec array_methods[] = {
|
|||
JS_FN(js_toLocaleString_str,array_toLocaleString,0,0),
|
||||
|
||||
/* Perl-ish methods. */
|
||||
JS_FN("join", js_array_join, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_TN("join", array_join, 1,JSFUN_GENERIC_NATIVE, array_join_trcinfo),
|
||||
JS_FN("reverse", array_reverse, 0,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("sort", array_sort, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("push", js_array_push, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("pop", js_array_pop, 0,JSFUN_GENERIC_NATIVE),
|
||||
JS_TN("push", array_push, 1,JSFUN_GENERIC_NATIVE, array_push_trcinfo),
|
||||
JS_TN("pop", array_pop, 0,JSFUN_GENERIC_NATIVE, array_pop_trcinfo),
|
||||
JS_FN("shift", array_shift, 0,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("unshift", array_unshift, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("splice", array_splice, 2,JSFUN_GENERIC_NATIVE),
|
||||
|
@ -2965,6 +3053,96 @@ js_Array(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return InitArrayObject(cx, obj, length, vector);
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_ARRAY_LENGTH);
|
||||
JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH + 1 == JSSLOT_ARRAY_COUNT);
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_FastNewArray(JSContext* cx, JSObject* proto)
|
||||
{
|
||||
JS_ASSERT(OBJ_IS_ARRAY(cx, proto));
|
||||
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
JSClass* clasp = &js_ArrayClass;
|
||||
obj->classword = jsuword(clasp);
|
||||
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
|
||||
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
|
||||
for (unsigned i = JSSLOT_ARRAY_COUNT + 1; i != JS_INITIAL_NSLOTS; ++i)
|
||||
obj->fslots[i] = JSVAL_VOID;
|
||||
|
||||
JSObjectOps* ops = clasp->getObjectOps(cx, clasp);
|
||||
obj->map = ops->newObjectMap(cx, 1, ops, clasp, obj);
|
||||
if (!obj->map)
|
||||
return NULL;
|
||||
obj->dslots = NULL;
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_Array_1int(JSContext* cx, JSObject* proto, int32 i)
|
||||
{
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
JSObject* obj = js_FastNewArray(cx, proto);
|
||||
if (obj)
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = i;
|
||||
return obj;
|
||||
}
|
||||
|
||||
#define ARRAY_CTOR_GUTS(exact_len, newslots_code) \
|
||||
JS_ASSERT(JS_ON_TRACE(cx)); \
|
||||
JSObject* obj = js_FastNewArray(cx, proto); \
|
||||
if (obj) { \
|
||||
const uint32 len = ARRAY_GROWBY; \
|
||||
jsval* newslots = (jsval*) JS_malloc(cx, sizeof (jsval) * (len + 1)); \
|
||||
if (newslots) { \
|
||||
obj->dslots = newslots + 1; \
|
||||
ARRAY_SET_DENSE_LENGTH(obj, len); \
|
||||
{newslots_code} \
|
||||
while (++newslots < obj->dslots + len) \
|
||||
*newslots = JSVAL_HOLE; \
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = (exact_len); \
|
||||
return obj; \
|
||||
} \
|
||||
} \
|
||||
return NULL;
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_Array_1str(JSContext* cx, JSObject* proto, JSString *str)
|
||||
{
|
||||
ARRAY_CTOR_GUTS(1, *++newslots = STRING_TO_JSVAL(str);)
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_Array_2obj(JSContext* cx, JSObject* proto, JSObject *obj1, JSObject* obj2)
|
||||
{
|
||||
ARRAY_CTOR_GUTS(2,
|
||||
*++newslots = OBJECT_TO_JSVAL(obj1);
|
||||
*++newslots = OBJECT_TO_JSVAL(obj2);)
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_Array_3num(JSContext* cx, JSObject* proto, jsdouble n1, jsdouble n2, jsdouble n3)
|
||||
{
|
||||
ARRAY_CTOR_GUTS(3,
|
||||
if (!js_NewDoubleInRootedValue(cx, n1, ++newslots))
|
||||
return NULL;
|
||||
if (!js_NewDoubleInRootedValue(cx, n2, ++newslots))
|
||||
return NULL;
|
||||
if (!js_NewDoubleInRootedValue(cx, n3, ++newslots))
|
||||
return NULL;)
|
||||
}
|
||||
|
||||
#endif /* JS_TRACER */
|
||||
|
||||
JSObject *
|
||||
js_InitArrayClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
|
@ -3238,3 +3416,10 @@ js_ArrayToJSDoubleBuffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint cou
|
|||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_DEFINE_CALLINFO_4(BOOL, Array_dense_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, 0)
|
||||
JS_DEFINE_CALLINFO_2(OBJECT, FastNewArray, CONTEXT, OBJECT, 0, 0)
|
||||
JS_DEFINE_CALLINFO_3(OBJECT, Array_1int, CONTEXT, OBJECT, INT32, 0, 0)
|
||||
JS_DEFINE_CALLINFO_3(OBJECT, Array_1str, CONTEXT, OBJECT, STRING, 0, 0)
|
||||
JS_DEFINE_CALLINFO_4(OBJECT, Array_2obj, CONTEXT, OBJECT, OBJECT, OBJECT, 0, 0)
|
||||
JS_DEFINE_CALLINFO_5(OBJECT, Array_3num, CONTEXT, OBJECT, DOUBLE, DOUBLE, DOUBLE, 0, 0)
|
||||
|
|
|
@ -131,37 +131,6 @@ extern JSBool
|
|||
js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
#endif
|
||||
|
||||
extern JSBool
|
||||
js_array_join(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_array_push1_dense(JSContext *cx, JSObject *obj, jsval v, jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_array_push(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_array_pop_slowly(JSContext *cx, JSObject* obj, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_array_pop(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
enum ArrayToStringOp {
|
||||
TO_STRING,
|
||||
TO_LOCALE_STRING,
|
||||
TO_SOURCE
|
||||
};
|
||||
|
||||
extern JSBool
|
||||
js_array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op,
|
||||
JSString *sep, jsval *rval);
|
||||
|
||||
/*
|
||||
* Fast dense-array-to-buffer conversions.
|
||||
*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; -*-
|
||||
* vim: set ts=8 sw=4 et tw=99:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
|
@ -55,14 +55,15 @@
|
|||
#include "jsdate.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsstr.h"
|
||||
#include "jstracer.h"
|
||||
#include "jsbuiltins.h"
|
||||
|
||||
#include "nanojit/avmplus.h"
|
||||
#include "nanojit/nanojit.h"
|
||||
#include "nanojit.h"
|
||||
|
||||
using namespace avmplus;
|
||||
using namespace nanojit;
|
||||
|
||||
extern jsdouble js_NaN;
|
||||
|
||||
/*
|
||||
* NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
|
||||
* Do not use bool FASTCALL, use JSBool only!
|
||||
|
@ -88,8 +89,8 @@ js_dmod(jsdouble a, jsdouble b)
|
|||
return r;
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
js_imod(jsint a, jsint b)
|
||||
int32 FASTCALL
|
||||
js_imod(int32 a, int32 b)
|
||||
{
|
||||
if (a < 0 || b <= 0)
|
||||
return -1;
|
||||
|
@ -104,7 +105,7 @@ js_imod(jsint a, jsint b)
|
|||
jsval FASTCALL
|
||||
js_BoxDouble(JSContext* cx, jsdouble d)
|
||||
{
|
||||
jsint i;
|
||||
int32 i;
|
||||
if (JSDOUBLE_IS_INT(d, i))
|
||||
return INT_TO_JSVAL(i);
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
|
@ -115,7 +116,7 @@ js_BoxDouble(JSContext* cx, jsdouble d)
|
|||
}
|
||||
|
||||
jsval FASTCALL
|
||||
js_BoxInt32(JSContext* cx, jsint i)
|
||||
js_BoxInt32(JSContext* cx, int32 i)
|
||||
{
|
||||
if (JS_LIKELY(INT_FITS_IN_JSVAL(i)))
|
||||
return INT_TO_JSVAL(i);
|
||||
|
@ -135,7 +136,7 @@ js_UnboxDouble(jsval v)
|
|||
return *JSVAL_TO_DOUBLE(v);
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
int32 FASTCALL
|
||||
js_UnboxInt32(jsval v)
|
||||
{
|
||||
if (JS_LIKELY(JSVAL_IS_INT(v)))
|
||||
|
@ -149,291 +150,12 @@ js_DoubleToInt32(jsdouble d)
|
|||
return js_DoubleToECMAInt32(d);
|
||||
}
|
||||
|
||||
int32 FASTCALL
|
||||
uint32 FASTCALL
|
||||
js_DoubleToUint32(jsdouble d)
|
||||
{
|
||||
return js_DoubleToECMAUint32(d);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_sin(jsdouble d)
|
||||
{
|
||||
return sin(d);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_cos(jsdouble d)
|
||||
{
|
||||
return cos(d);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_floor(jsdouble d)
|
||||
{
|
||||
return floor(d);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_ceil(jsdouble d)
|
||||
{
|
||||
return ceil(d);
|
||||
}
|
||||
|
||||
extern jsdouble js_NaN;
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_pow(jsdouble d, jsdouble p)
|
||||
{
|
||||
if (!JSDOUBLE_IS_FINITE(p) && (d == 1.0 || d == -1.0))
|
||||
return js_NaN;
|
||||
if (p == 0)
|
||||
return 1.0;
|
||||
return pow(d, p);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_sqrt(jsdouble d)
|
||||
{
|
||||
return sqrt(d);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_log(jsdouble d)
|
||||
{
|
||||
#if !JS_USE_FDLIBM_MATH && defined(SOLARIS) && defined(__GNUC__)
|
||||
if (d < 0)
|
||||
return js_NaN;
|
||||
#endif
|
||||
return log(d);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_max(jsdouble d, jsdouble p)
|
||||
{
|
||||
if (JSDOUBLE_IS_NaN(d) || JSDOUBLE_IS_NaN(p))
|
||||
return js_NaN;
|
||||
|
||||
if (p == 0 && p == d && fd_copysign(1.0, d) == -1)
|
||||
return p;
|
||||
/*
|
||||
* Note: it is essential that you write the ternary expression here such
|
||||
* that the false branch produces d not p, as the case of p=-0, d=0, for
|
||||
* which we wind up in this expression but evaluate either > order as
|
||||
* false, whether we do p>d *or* d>p.
|
||||
*/
|
||||
return (p > d) ? p : d;
|
||||
}
|
||||
|
||||
JSBool FASTCALL
|
||||
js_Array_dense_setelem(JSContext* cx, JSObject* obj, jsint i, jsval v)
|
||||
{
|
||||
JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
|
||||
|
||||
do {
|
||||
jsuint length = ARRAY_DENSE_LENGTH(obj);
|
||||
if ((jsuint)i < length) {
|
||||
if (obj->dslots[i] == JSVAL_HOLE) {
|
||||
if (cx->runtime->anyArrayProtoHasElement)
|
||||
break;
|
||||
if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
}
|
||||
obj->dslots[i] = v;
|
||||
return JS_TRUE;
|
||||
}
|
||||
} while (0);
|
||||
return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(i), &v);
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_Array_p_join(JSContext* cx, JSObject* obj, JSString *str)
|
||||
{
|
||||
jsval v;
|
||||
if (!js_array_join_sub(cx, obj, TO_STRING, str, &v))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_STRING(v));
|
||||
return JSVAL_TO_STRING(v);
|
||||
}
|
||||
|
||||
jsval FASTCALL
|
||||
js_Array_p_push1(JSContext* cx, JSObject* obj, jsval v)
|
||||
{
|
||||
if (!(OBJ_IS_DENSE_ARRAY(cx, obj)
|
||||
? js_array_push1_dense(cx, obj, v, &v)
|
||||
: js_array_push_slowly(cx, obj, 1, &v, &v))) {
|
||||
return JSVAL_ERROR_COOKIE;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
jsval FASTCALL
|
||||
js_Array_p_pop(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
jsval v;
|
||||
if (!(OBJ_IS_DENSE_ARRAY(cx, obj)
|
||||
? js_array_pop_dense(cx, obj, &v)
|
||||
: js_array_pop_slowly(cx, obj, &v))) {
|
||||
return JSVAL_ERROR_COOKIE;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_substring(JSContext* cx, JSString* str, jsint begin, jsint end)
|
||||
{
|
||||
JS_ASSERT(end >= begin);
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_substring_1(JSContext* cx, JSString* str, jsint begin)
|
||||
{
|
||||
jsint end = JSSTRING_LENGTH(str);
|
||||
JS_ASSERT(end >= begin);
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_getelem(JSContext* cx, JSString* str, jsint i)
|
||||
{
|
||||
if ((size_t)i >= JSSTRING_LENGTH(str))
|
||||
return NULL;
|
||||
return js_GetUnitString(cx, str, (size_t)i);
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_fromCharCode(JSContext* cx, jsint i)
|
||||
{
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
jschar c = (jschar)i;
|
||||
if (c < UNIT_STRING_LIMIT)
|
||||
return js_GetUnitStringForChar(cx, c);
|
||||
return js_NewStringCopyN(cx, &c, 1);
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
js_String_p_charCodeAt(JSString* str, jsint i)
|
||||
{
|
||||
if (i < 0 || (jsint)JSSTRING_LENGTH(str) <= i)
|
||||
return -1;
|
||||
return JSSTRING_CHARS(str)[i];
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_random(JSRuntime* rt)
|
||||
{
|
||||
JS_LOCK_RUNTIME(rt);
|
||||
js_random_init(rt);
|
||||
jsdouble z = js_random_nextDouble(rt);
|
||||
JS_UNLOCK_RUNTIME(rt);
|
||||
return z;
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_concat_1int(JSContext* cx, JSString* str, jsint i)
|
||||
{
|
||||
// FIXME: should be able to use stack buffer and avoid istr...
|
||||
JSString* istr = js_NumberToString(cx, i);
|
||||
if (!istr)
|
||||
return NULL;
|
||||
return js_ConcatStrings(cx, str, istr);
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_concat_2str(JSContext* cx, JSString* str, JSString* a, JSString* b)
|
||||
{
|
||||
str = js_ConcatStrings(cx, str, a);
|
||||
if (str)
|
||||
return js_ConcatStrings(cx, str, b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_concat_3str(JSContext* cx, JSString* str, JSString* a, JSString* b, JSString* c)
|
||||
{
|
||||
str = js_ConcatStrings(cx, str, a);
|
||||
if (str) {
|
||||
str = js_ConcatStrings(cx, str, b);
|
||||
if (str)
|
||||
return js_ConcatStrings(cx, str, c);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_String_p_match(JSContext* cx, JSString* str, jsbytecode *pc, JSObject* regexp)
|
||||
{
|
||||
jsval vp[3] = { JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
|
||||
if (!js_StringMatchHelper(cx, 1, vp, pc))
|
||||
return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
|
||||
(!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
|
||||
return JSVAL_TO_OBJECT(vp[0]);
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_String_p_match_obj(JSContext* cx, JSObject* str, jsbytecode *pc, JSObject* regexp)
|
||||
{
|
||||
jsval vp[3] = { JSVAL_NULL, OBJECT_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
|
||||
if (!js_StringMatchHelper(cx, 1, vp, pc))
|
||||
return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
|
||||
(!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
|
||||
return JSVAL_TO_OBJECT(vp[0]);
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_replace_str(JSContext* cx, JSString* str, JSObject* regexp, JSString* repstr)
|
||||
{
|
||||
jsval vp[4] = {
|
||||
JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp), STRING_TO_JSVAL(repstr)
|
||||
};
|
||||
if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_STRING(vp[0]));
|
||||
return JSVAL_TO_STRING(vp[0]);
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_replace_str2(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr)
|
||||
{
|
||||
jsval vp[4] = {
|
||||
JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr)
|
||||
};
|
||||
if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_STRING(vp[0]));
|
||||
return JSVAL_TO_STRING(vp[0]);
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_replace_str3(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr,
|
||||
JSString* flagstr)
|
||||
{
|
||||
jsval vp[5] = {
|
||||
JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr),
|
||||
STRING_TO_JSVAL(flagstr)
|
||||
};
|
||||
if (!js_StringReplaceHelper(cx, 3, NULL, repstr, vp))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_STRING(vp[0]));
|
||||
return JSVAL_TO_STRING(vp[0]);
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_String_p_split(JSContext* cx, JSString* str, JSString* sepstr)
|
||||
{
|
||||
// FIXME: optimize by calling into a lower level exported from jsstr.cpp.
|
||||
jsval vp[4] = { JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(sepstr), JSVAL_VOID };
|
||||
if (!js_str_split(cx, 2, vp))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(vp[0]));
|
||||
return JSVAL_TO_OBJECT(vp[0]);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_StringToNumber(JSContext* cx, JSString* str)
|
||||
{
|
||||
|
@ -452,7 +174,7 @@ js_StringToNumber(JSContext* cx, JSString* str)
|
|||
return d;
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
int32 FASTCALL
|
||||
js_StringToInt32(JSContext* cx, JSString* str)
|
||||
{
|
||||
const jschar* bp;
|
||||
|
@ -463,43 +185,7 @@ js_StringToInt32(JSContext* cx, JSString* str)
|
|||
JSSTRING_CHARS_AND_END(str, bp, end);
|
||||
if (!js_strtod(cx, bp, end, &ep, &d) || js_SkipWhiteSpace(ep, end) != end)
|
||||
return 0;
|
||||
return (jsint)d;
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_ParseFloat(JSContext* cx, JSString* str)
|
||||
{
|
||||
const jschar* bp;
|
||||
const jschar* end;
|
||||
const jschar* ep;
|
||||
jsdouble d;
|
||||
|
||||
JSSTRING_CHARS_AND_END(str, bp, end);
|
||||
if (!js_strtod(cx, bp, end, &ep, &d) || ep == bp)
|
||||
return js_NaN;
|
||||
return d;
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_ParseInt(JSContext* cx, JSString* str)
|
||||
{
|
||||
const jschar* bp;
|
||||
const jschar* end;
|
||||
const jschar* ep;
|
||||
jsdouble d;
|
||||
|
||||
JSSTRING_CHARS_AND_END(str, bp, end);
|
||||
if (!js_strtointeger(cx, bp, end, &ep, 0, &d) || ep == bp)
|
||||
return js_NaN;
|
||||
return d;
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_ParseIntDouble(jsdouble d)
|
||||
{
|
||||
if (!JSDOUBLE_IS_FINITE(d))
|
||||
return js_NaN;
|
||||
return floor(d);
|
||||
return (int32)d;
|
||||
}
|
||||
|
||||
jsval FASTCALL
|
||||
|
@ -525,7 +211,7 @@ js_Any_setprop(JSContext* cx, JSObject* obj, JSString* idstr, jsval v)
|
|||
}
|
||||
|
||||
jsval FASTCALL
|
||||
js_Any_getelem(JSContext* cx, JSObject* obj, jsint index)
|
||||
js_Any_getelem(JSContext* cx, JSObject* obj, uint32 index)
|
||||
{
|
||||
jsval v;
|
||||
jsid id;
|
||||
|
@ -539,7 +225,7 @@ js_Any_getelem(JSContext* cx, JSObject* obj, jsint index)
|
|||
}
|
||||
|
||||
JSBool FASTCALL
|
||||
js_Any_setelem(JSContext* cx, JSObject* obj, jsint index, jsval v)
|
||||
js_Any_setelem(JSContext* cx, JSObject* obj, uint32 index, jsval v)
|
||||
{
|
||||
jsid id;
|
||||
if (index < 0)
|
||||
|
@ -597,44 +283,14 @@ js_CallTree(InterpState* state, Fragment* f)
|
|||
return lr;
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_ARRAY_LENGTH);
|
||||
JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH + 1 == JSSLOT_ARRAY_COUNT);
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_FastNewArray(JSContext* cx, JSObject* proto)
|
||||
{
|
||||
JS_ASSERT(OBJ_IS_ARRAY(cx, proto));
|
||||
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
JSClass* clasp = &js_ArrayClass;
|
||||
obj->classword = jsuword(clasp);
|
||||
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
|
||||
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
|
||||
for (unsigned i = JSSLOT_ARRAY_COUNT + 1; i != JS_INITIAL_NSLOTS; ++i)
|
||||
obj->fslots[i] = JSVAL_VOID;
|
||||
|
||||
JSObjectOps* ops = clasp->getObjectOps(cx, clasp);
|
||||
obj->map = ops->newObjectMap(cx, 1, ops, clasp, obj);
|
||||
if (!obj->map)
|
||||
return NULL;
|
||||
obj->dslots = NULL;
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_FastNewObject(JSContext* cx, JSObject* ctor)
|
||||
{
|
||||
JS_ASSERT(HAS_FUNCTION_CLASS(ctor));
|
||||
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, ctor);
|
||||
JSClass* clasp = FUN_INTERPRETED(fun) ? &js_ObjectClass : fun->u.n.clasp;
|
||||
JSClass* clasp = (FUN_INTERPRETED(fun) || (fun->flags & JSFUN_TRACEABLE))
|
||||
? &js_ObjectClass
|
||||
: FUN_CLASP(fun);
|
||||
JS_ASSERT(clasp != &js_ArrayClass);
|
||||
|
||||
JS_LOCK_OBJ(cx, ctor);
|
||||
|
@ -764,7 +420,7 @@ js_TypeOfObject(JSContext* cx, JSObject* obj)
|
|||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_TypeOfBoolean(JSContext* cx, jsint unboxed)
|
||||
js_TypeOfBoolean(JSContext* cx, int32 unboxed)
|
||||
{
|
||||
jsval boxed = BOOLEAN_TO_JSVAL(unboxed);
|
||||
JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed));
|
||||
|
@ -772,30 +428,8 @@ js_TypeOfBoolean(JSContext* cx, jsint unboxed)
|
|||
return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
js_Object_p_hasOwnProperty(JSContext* cx, JSObject* obj, JSString *str)
|
||||
{
|
||||
jsid id = ATOM_TO_JSID(STRING_TO_JSVAL(str));
|
||||
jsval v;
|
||||
if (!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &v))
|
||||
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
|
||||
return JSVAL_TO_BOOLEAN(v);
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
js_Object_p_propertyIsEnumerable(JSContext* cx, JSObject* obj, JSString *str)
|
||||
{
|
||||
jsid id = ATOM_TO_JSID(STRING_TO_JSVAL(str));
|
||||
jsval v;
|
||||
if (!js_PropertyIsEnumerable(cx, obj, id, &v))
|
||||
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
|
||||
return JSVAL_TO_BOOLEAN(v);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_BooleanToNumber(JSContext* cx, jsint unboxed)
|
||||
js_BooleanToNumber(JSContext* cx, int32 unboxed)
|
||||
{
|
||||
if (unboxed == JSVAL_TO_BOOLEAN(JSVAL_VOID))
|
||||
return js_NaN;
|
||||
|
@ -814,103 +448,12 @@ js_ObjectToString(JSContext* cx, JSObject* obj)
|
|||
return JSVAL_TO_STRING(v);
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_Array_1int(JSContext* cx, JSObject* proto, jsint i)
|
||||
{
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
JSObject* obj = js_FastNewArray(cx, proto);
|
||||
if (obj)
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = i;
|
||||
return obj;
|
||||
}
|
||||
|
||||
#define ARRAY_CTOR_GUTS(exact_len, newslots_code) \
|
||||
JS_ASSERT(JS_ON_TRACE(cx)); \
|
||||
JSObject* obj = js_FastNewArray(cx, proto); \
|
||||
if (obj) { \
|
||||
const uint32 len = ARRAY_GROWBY; \
|
||||
jsval* newslots = (jsval*) JS_malloc(cx, sizeof (jsval) * (len + 1)); \
|
||||
if (newslots) { \
|
||||
obj->dslots = newslots + 1; \
|
||||
ARRAY_SET_DENSE_LENGTH(obj, len); \
|
||||
{newslots_code} \
|
||||
while (++newslots < obj->dslots + len) \
|
||||
*newslots = JSVAL_HOLE; \
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = (exact_len); \
|
||||
return obj; \
|
||||
} \
|
||||
} \
|
||||
return NULL;
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_Array_1str(JSContext* cx, JSObject* proto, JSString *str)
|
||||
{
|
||||
ARRAY_CTOR_GUTS(1, *++newslots = STRING_TO_JSVAL(str);)
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_Array_2obj(JSContext* cx, JSObject* proto, JSObject *obj1, JSObject* obj2)
|
||||
{
|
||||
ARRAY_CTOR_GUTS(2,
|
||||
*++newslots = OBJECT_TO_JSVAL(obj1);
|
||||
*++newslots = OBJECT_TO_JSVAL(obj2);)
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_Array_3num(JSContext* cx, JSObject* proto, jsdouble n1, jsdouble n2, jsdouble n3)
|
||||
{
|
||||
ARRAY_CTOR_GUTS(3,
|
||||
if (!js_NewDoubleInRootedValue(cx, n1, ++newslots))
|
||||
return NULL;
|
||||
if (!js_NewDoubleInRootedValue(cx, n2, ++newslots))
|
||||
return NULL;
|
||||
if (!js_NewDoubleInRootedValue(cx, n3, ++newslots))
|
||||
return NULL;)
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_Arguments(JSContext* cx)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Date_now(JSContext*)
|
||||
{
|
||||
return PRMJ_Now() / PRMJ_USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_UTC_TIME);
|
||||
JS_STATIC_ASSERT(JSSLOT_UTC_TIME + 1 == JSSLOT_LOCAL_TIME);
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_FastNewDate(JSContext* cx, JSObject* proto)
|
||||
{
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
JSClass* clasp = &js_DateClass;
|
||||
obj->classword = jsuword(clasp);
|
||||
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
|
||||
|
||||
jsdouble* date = js_NewWeaklyRootedDouble(cx, 0.0);
|
||||
if (!date)
|
||||
return NULL;
|
||||
*date = js_Date_now(cx);
|
||||
obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(date);
|
||||
obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);;
|
||||
|
||||
JS_ASSERT(!clasp->getObjectOps);
|
||||
JS_ASSERT(proto->map->ops == &js_ObjectOps);
|
||||
obj->map = js_HoldObjectMap(cx, proto->map);
|
||||
obj->dslots = NULL;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* soft float */
|
||||
|
||||
jsdouble FASTCALL
|
||||
|
@ -920,7 +463,7 @@ js_fneg(jsdouble x)
|
|||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_i2f(jsint i)
|
||||
js_i2f(int32 i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
@ -931,31 +474,31 @@ js_u2f(jsuint u)
|
|||
return u;
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
int32 FASTCALL
|
||||
js_fcmpeq(jsdouble x, jsdouble y)
|
||||
{
|
||||
return x==y;
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
int32 FASTCALL
|
||||
js_fcmplt(jsdouble x, jsdouble y)
|
||||
{
|
||||
return x < y;
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
int32 FASTCALL
|
||||
js_fcmple(jsdouble x, jsdouble y)
|
||||
{
|
||||
return x <= y;
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
int32 FASTCALL
|
||||
js_fcmpgt(jsdouble x, jsdouble y)
|
||||
{
|
||||
return x > y;
|
||||
}
|
||||
|
||||
jsint FASTCALL
|
||||
int32 FASTCALL
|
||||
js_fcmpge(jsdouble x, jsdouble y)
|
||||
{
|
||||
return x >= y;
|
||||
|
@ -984,33 +527,9 @@ js_fsub(jsdouble x, jsdouble y)
|
|||
return x - y;
|
||||
}
|
||||
|
||||
#define LO ARGSIZE_LO
|
||||
#define F ARGSIZE_F
|
||||
#define Q ARGSIZE_Q
|
||||
|
||||
#if defined AVMPLUS_64BIT
|
||||
#define P ARGSIZE_Q
|
||||
#else
|
||||
#define P ARGSIZE_LO
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define NAME(op) ,#op
|
||||
#else
|
||||
#define NAME(op)
|
||||
#endif
|
||||
|
||||
#define BUILTIN1(op, at0, atr, tr, t0, cse, fold) \
|
||||
{ (intptr_t)&js_##op, (at0 << 2) | atr, cse, fold NAME(op) },
|
||||
#define BUILTIN2(op, at0, at1, atr, tr, t0, t1, cse, fold) \
|
||||
{ (intptr_t)&js_##op, (at0 << 4) | (at1 << 2) | atr, cse, fold NAME(op) },
|
||||
#define BUILTIN3(op, at0, at1, at2, atr, tr, t0, t1, t2, cse, fold) \
|
||||
{ (intptr_t)&js_##op, (at0 << 6) | (at1 << 4) | (at2 << 2) | atr, cse, fold NAME(op) },
|
||||
#define BUILTIN4(op, at0, at1, at2, at3, atr, tr, t0, t1, t2, t3, cse, fold) \
|
||||
{ (intptr_t)&js_##op, (at0 << 8) | (at1 << 6) | (at2 << 4) | (at3 << 2) | atr, cse, fold NAME(op) },
|
||||
#define BUILTIN5(op, at0, at1, at2, at3, at4, atr, tr, t0, t1, t2, t3, t4, cse, fold) \
|
||||
{ (intptr_t)&js_##op, (at0 << 10) | (at1 << 8) | (at2 << 6) | (at3 << 4) | (at4 << 2) | atr, cse, fold NAME(op) },
|
||||
|
||||
struct CallInfo builtins[] = {
|
||||
#define BUILTIN1 JS_DEFINE_CALLINFO_1
|
||||
#define BUILTIN2 JS_DEFINE_CALLINFO_2
|
||||
#define BUILTIN3 JS_DEFINE_CALLINFO_3
|
||||
#define BUILTIN4 JS_DEFINE_CALLINFO_4
|
||||
#define BUILTIN5 JS_DEFINE_CALLINFO_5
|
||||
#include "builtins.tbl"
|
||||
};
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* May 28, 2008.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Orendorff <jorendorff@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef jsbuiltins_h___
|
||||
#define jsbuiltins_h___
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
#include "nanojit.h"
|
||||
|
||||
enum JSTNErrType { INFALLIBLE, FAIL_NULL, FAIL_NEG, FAIL_VOID, FAIL_JSVAL };
|
||||
enum { JSTN_ERRTYPE_MASK = 7, JSTN_MORE = 8 };
|
||||
|
||||
#define JSTN_ERRTYPE(jstn) ((jstn)->flags & JSTN_ERRTYPE_MASK)
|
||||
|
||||
struct JSTraceableNative {
|
||||
JSFastNative native;
|
||||
const nanojit::CallInfo *builtin;
|
||||
const char *prefix;
|
||||
const char *argtypes;
|
||||
uintN flags; /* JSTN_MORE | JSTNErrType */
|
||||
};
|
||||
|
||||
/*
|
||||
* We use a magic boxed pointer value to represent error conditions that
|
||||
* trigger a side exit. The address is so low that it should never be actually
|
||||
* in use. If it is, a performance regression occurs, not an actual runtime
|
||||
* error.
|
||||
*/
|
||||
#define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((void*)0x10)
|
||||
|
||||
/*
|
||||
* We also need a magic unboxed 32-bit integer that signals an error. Again if
|
||||
* this number is hit we experience a performance regression, not a runtime
|
||||
* error.
|
||||
*/
|
||||
#define INT32_ERROR_COOKIE 0xffffabcd
|
||||
|
||||
/* Macros used by JS_DEFINE_CALLINFOn. */
|
||||
#ifdef DEBUG
|
||||
#define _JS_CI_NAME(op) ,#op
|
||||
#else
|
||||
#define _JS_CI_NAME(op)
|
||||
#endif
|
||||
|
||||
#define _JS_I32_ARGSIZE nanojit::ARGSIZE_LO
|
||||
#define _JS_I32_RETSIZE nanojit::ARGSIZE_LO
|
||||
#define _JS_F64_ARGSIZE nanojit::ARGSIZE_F
|
||||
#define _JS_F64_RETSIZE nanojit::ARGSIZE_F
|
||||
#define _JS_PTR_ARGSIZE nanojit::ARGSIZE_LO
|
||||
#if defined AVMPLUS_64BIT
|
||||
# define _JS_PTR_RETSIZE nanojit::ARGSIZE_Q
|
||||
#else
|
||||
# define _JS_PTR_RETSIZE nanojit::ARGSIZE_LO
|
||||
#endif
|
||||
|
||||
/* Supported types for builtin functions. */
|
||||
#define _JS_TYPEINFO(ctype, size) (ctype, size)
|
||||
#define _JS_TYPEINFO_CONTEXT _JS_TYPEINFO(JSContext *, _JS_PTR)
|
||||
#define _JS_TYPEINFO_RUNTIME _JS_TYPEINFO(JSRuntime *, _JS_PTR)
|
||||
#define _JS_TYPEINFO_JSVAL _JS_TYPEINFO(jsval, _JS_I32)
|
||||
#define _JS_TYPEINFO_BOOL _JS_TYPEINFO(JSBool, _JS_I32)
|
||||
#define _JS_TYPEINFO_INT32 _JS_TYPEINFO(int32, _JS_I32)
|
||||
#define _JS_TYPEINFO_UINT32 _JS_TYPEINFO(uint32, _JS_I32)
|
||||
#define _JS_TYPEINFO_DOUBLE _JS_TYPEINFO(jsdouble, _JS_F64)
|
||||
#define _JS_TYPEINFO_STRING _JS_TYPEINFO(JSString *, _JS_PTR)
|
||||
#define _JS_TYPEINFO_OBJECT _JS_TYPEINFO(JSObject *, _JS_PTR)
|
||||
#define _JS_TYPEINFO_SCOPEPROP _JS_TYPEINFO(JSScopeProperty *, _JS_PTR)
|
||||
#define _JS_TYPEINFO_PC _JS_TYPEINFO(jsbytecode *, _JS_PTR)
|
||||
#define _JS_TYPEINFO_GUARDRECORD _JS_TYPEINFO(nanojit::GuardRecord *, _JS_PTR)
|
||||
#define _JS_TYPEINFO_INTERPSTATE _JS_TYPEINFO(avmplus::InterpState *, _JS_PTR)
|
||||
#define _JS_TYPEINFO_FRAGMENT _JS_TYPEINFO(nanojit::Fragment *, _JS_PTR)
|
||||
|
||||
#define _JS_EXPAND(tokens) tokens
|
||||
|
||||
#define _JS_CTYPE2(ctype, size) ctype
|
||||
#define _JS_CTYPE(tyname) _JS_EXPAND(_JS_CTYPE2 _JS_TYPEINFO_##tyname)
|
||||
#define _JS_RETSIZE2(ctype, size) size##_ARGSIZE
|
||||
#define _JS_RETSIZE(tyname) _JS_EXPAND(_JS_RETSIZE2 _JS_TYPEINFO_##tyname)
|
||||
#define _JS_ARGSIZE2(ctype, size) size##_RETSIZE
|
||||
#define _JS_ARGSIZE(tyname) _JS_EXPAND(_JS_ARGSIZE2 _JS_TYPEINFO_##tyname)
|
||||
|
||||
#define _JS_DEFINE_CALLINFO(name, crtype, cargtypes, argtypes, cse, fold) \
|
||||
crtype FASTCALL js_##name cargtypes; \
|
||||
const nanojit::CallInfo ci_##name = \
|
||||
{ (intptr_t) &js_##name, argtypes, cse, fold _JS_CI_NAME(name) };
|
||||
|
||||
/*
|
||||
* Declare a C function named js_<op> and a CallInfo struct named ci_<op> so
|
||||
* the tracer can call it.
|
||||
*/
|
||||
#define JS_DEFINE_CALLINFO_1(rt, op, at0, cse, fold) \
|
||||
_JS_DEFINE_CALLINFO(op, _JS_CTYPE(rt), (_JS_CTYPE(at0)), \
|
||||
(_JS_ARGSIZE(at0) << 2) | _JS_RETSIZE(rt), cse, fold)
|
||||
#define JS_DEFINE_CALLINFO_2(rt, op, at0, at1, cse, fold) \
|
||||
_JS_DEFINE_CALLINFO(op, _JS_CTYPE(rt), (_JS_CTYPE(at0), _JS_CTYPE(at1)), \
|
||||
(_JS_ARGSIZE(at0) << 4) | (_JS_ARGSIZE(at1) << 2) | _JS_RETSIZE(rt), \
|
||||
cse, fold)
|
||||
#define JS_DEFINE_CALLINFO_3(rt, op, at0, at1, at2, cse, fold) \
|
||||
_JS_DEFINE_CALLINFO(op, _JS_CTYPE(rt), (_JS_CTYPE(at0), _JS_CTYPE(at1), _JS_CTYPE(at2)), \
|
||||
(_JS_ARGSIZE(at0) << 6) | (_JS_ARGSIZE(at1) << 4) | \
|
||||
(_JS_ARGSIZE(at2) << 2) | _JS_RETSIZE(rt), \
|
||||
cse, fold)
|
||||
#define JS_DEFINE_CALLINFO_4(rt, op, at0, at1, at2, at3, cse, fold) \
|
||||
_JS_DEFINE_CALLINFO(op, _JS_CTYPE(rt), (_JS_CTYPE(at0), _JS_CTYPE(at1), _JS_CTYPE(at2), \
|
||||
_JS_CTYPE(at3)), \
|
||||
(_JS_ARGSIZE(at0) << 8) | (_JS_ARGSIZE(at1) << 6) | \
|
||||
(_JS_ARGSIZE(at2) << 4) | (_JS_ARGSIZE(at3) << 2) | _JS_RETSIZE(rt), \
|
||||
cse, fold)
|
||||
#define JS_DEFINE_CALLINFO_5(rt, op, at0, at1, at2, at3, at4, cse, fold) \
|
||||
_JS_DEFINE_CALLINFO(op, _JS_CTYPE(rt), (_JS_CTYPE(at0), _JS_CTYPE(at1), _JS_CTYPE(at2), \
|
||||
_JS_CTYPE(at3), _JS_CTYPE(at4)), \
|
||||
(_JS_ARGSIZE(at0) << 10) | (_JS_ARGSIZE(at1) << 8) | \
|
||||
(_JS_ARGSIZE(at2) << 6) | (_JS_ARGSIZE(at3) << 4) | \
|
||||
(_JS_ARGSIZE(at4) << 2) | _JS_RETSIZE(rt), \
|
||||
cse, fold)
|
||||
|
||||
#define JS_DECLARE_CALLINFO(name) extern const nanojit::CallInfo ci_##name;
|
||||
|
||||
#else
|
||||
|
||||
#define JS_DEFINE_CALLINFO_1(rt, op, at0, cse, fold)
|
||||
#define JS_DEFINE_CALLINFO_2(rt, op, at0, at1, cse, fold)
|
||||
#define JS_DEFINE_CALLINFO_3(rt, op, at0, at1, at2, cse, fold)
|
||||
#define JS_DEFINE_CALLINFO_4(rt, op, at0, at1, at2, at3, cse, fold)
|
||||
#define JS_DEFINE_CALLINFO_5(rt, op, at0, at1, at2, at3, at4, cse, fold)
|
||||
#define JS_DECLARE_CALLINFO(name)
|
||||
|
||||
#endif /* !JS_TRACER */
|
||||
|
||||
/* Defined in jsarray.cpp */
|
||||
JS_DECLARE_CALLINFO(Array_dense_setelem)
|
||||
JS_DECLARE_CALLINFO(FastNewArray)
|
||||
JS_DECLARE_CALLINFO(Array_1int)
|
||||
JS_DECLARE_CALLINFO(Array_1str)
|
||||
JS_DECLARE_CALLINFO(Array_2obj)
|
||||
JS_DECLARE_CALLINFO(Array_3num)
|
||||
|
||||
/* Defined in jsdate.cpp */
|
||||
JS_DECLARE_CALLINFO(FastNewDate)
|
||||
|
||||
/* Defined in jsnum.cpp */
|
||||
JS_DECLARE_CALLINFO(NumberToString)
|
||||
|
||||
/* Defined in jsstr.cpp */
|
||||
JS_DECLARE_CALLINFO(ConcatStrings)
|
||||
JS_DECLARE_CALLINFO(String_getelem)
|
||||
JS_DECLARE_CALLINFO(String_p_charCodeAt)
|
||||
JS_DECLARE_CALLINFO(EqualStrings)
|
||||
JS_DECLARE_CALLINFO(CompareStrings)
|
||||
|
||||
/* Defined in jsbuiltins.cpp */
|
||||
#define BUILTIN1(rt, op, at0, cse, fold) JS_DECLARE_CALLINFO(op)
|
||||
#define BUILTIN2(rt, op, at0, at1, cse, fold) JS_DECLARE_CALLINFO(op)
|
||||
#define BUILTIN3(rt, op, at0, at1, at2, cse, fold) JS_DECLARE_CALLINFO(op)
|
||||
#define BUILTIN4(rt, op, at0, at1, at2, at3, cse, fold) JS_DECLARE_CALLINFO(op)
|
||||
#define BUILTIN5(rt, op, at0, at1, at2, at3, at4, cse, fold) JS_DECLARE_CALLINFO(op)
|
||||
#include "builtins.tbl"
|
||||
#undef BUILTIN
|
||||
#undef BUILTIN1
|
||||
#undef BUILTIN2
|
||||
#undef BUILTIN3
|
||||
#undef BUILTIN4
|
||||
#undef BUILTIN5
|
||||
|
||||
#endif /* jsbuiltins_h___ */
|
|
@ -63,6 +63,7 @@
|
|||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsapi.h"
|
||||
#include "jsversion.h"
|
||||
#include "jsbuiltins.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsdate.h"
|
||||
#include "jsinterp.h"
|
||||
|
@ -478,6 +479,9 @@ msFromTime(jsdouble t)
|
|||
* We use the first reseved slot to store UTC time, and the second for caching
|
||||
* the local time. The initial value of the cache entry is NaN.
|
||||
*/
|
||||
const uint32 JSSLOT_UTC_TIME = JSSLOT_PRIVATE;
|
||||
const uint32 JSSLOT_LOCAL_TIME = JSSLOT_PRIVATE + 1;
|
||||
|
||||
const uint32 DATE_RESERVED_SLOTS = 2;
|
||||
|
||||
JSClass js_DateClass = {
|
||||
|
@ -909,12 +913,20 @@ date_parse(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_date_now(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
date_now(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return js_NewDoubleInRootedValue(cx, PRMJ_Now() / PRMJ_USEC_PER_MSEC, vp);
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
jsdouble FASTCALL
|
||||
js_Date_now(JSContext*)
|
||||
{
|
||||
return PRMJ_Now() / PRMJ_USEC_PER_MSEC;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get UTC time from the date object. Returns false if the object is not
|
||||
* Date type.
|
||||
|
@ -1952,10 +1964,23 @@ date_valueOf(JSContext *cx, uintN argc, jsval *vp)
|
|||
* creation and destruction
|
||||
*/
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
// Don't really need an argument here, but we don't support arg-less builtins
|
||||
JS_DEFINE_CALLINFO_1(DOUBLE, Date_now, CONTEXT, 0, 0)
|
||||
|
||||
JS_DEFINE_CALLINFO_2(OBJECT, FastNewDate, CONTEXT, OBJECT, 0, 0)
|
||||
|
||||
static JSTraceableNative date_now_trcinfo[] = {
|
||||
{ date_now, &ci_Date_now, "C", "", INFALLIBLE }
|
||||
};
|
||||
|
||||
#endif /* JS_TRACER */
|
||||
|
||||
static JSFunctionSpec date_static_methods[] = {
|
||||
JS_FN("UTC", date_UTC, MAXARGS,0),
|
||||
JS_FN("parse", date_parse, 1,0),
|
||||
JS_FN("now", js_date_now, 0,0),
|
||||
JS_TN("now", date_now, 0,0, date_now_trcinfo),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -2088,6 +2113,39 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_UTC_TIME);
|
||||
JS_STATIC_ASSERT(JSSLOT_UTC_TIME + 1 == JSSLOT_LOCAL_TIME);
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSObject* FASTCALL
|
||||
js_FastNewDate(JSContext* cx, JSObject* proto)
|
||||
{
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
JSClass* clasp = &js_DateClass;
|
||||
obj->classword = jsuword(clasp);
|
||||
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
|
||||
|
||||
jsdouble* date = js_NewWeaklyRootedDouble(cx, 0.0);
|
||||
if (!date)
|
||||
return NULL;
|
||||
*date = js_Date_now(cx);
|
||||
obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(date);
|
||||
obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);;
|
||||
|
||||
JS_ASSERT(!clasp->getObjectOps);
|
||||
JS_ASSERT(proto->map->ops == &js_ObjectOps);
|
||||
obj->map = js_HoldObjectMap(cx, proto->map);
|
||||
obj->dslots = NULL;
|
||||
return obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
JSObject *
|
||||
js_InitDateClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
|
|
|
@ -51,18 +51,6 @@ extern JSClass js_DateClass;
|
|||
extern JSObject *
|
||||
js_InitDateClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
js_date_now(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
extern JSClass js_DateClass;
|
||||
|
||||
/*
|
||||
* We use the first reseved slot to store UTC time, and the second for caching
|
||||
* the local time. The initial value of the cache entry is NaN.
|
||||
*/
|
||||
#define JSSLOT_UTC_TIME JSSLOT_PRIVATE
|
||||
#define JSSLOT_LOCAL_TIME (JSSLOT_PRIVATE + 1)
|
||||
|
||||
/*
|
||||
* These functions provide a C interface to the date/time object
|
||||
*/
|
||||
|
|
|
@ -54,8 +54,10 @@ static char dempty[] = "<null>";
|
|||
char *
|
||||
jsdtrace_funcclass_name(JSFunction *fun)
|
||||
{
|
||||
return (!FUN_INTERPRETED(fun) && fun->u.n.clasp)
|
||||
? (char *)fun->u.n.clasp->name
|
||||
return (!FUN_INTERPRETED(fun) &&
|
||||
!(fun->flags & JSFUN_TRACEABLE) &&
|
||||
FUN_CLASP(fun))
|
||||
? (char *)FUN_CLASP(fun)->name
|
||||
: dempty;
|
||||
}
|
||||
|
||||
|
|
|
@ -1074,7 +1074,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
|||
break;
|
||||
|
||||
/* Make this constructor make objects of class Exception. */
|
||||
fun->u.n.clasp = &js_ErrorClass;
|
||||
FUN_CLASP(fun) = &js_ErrorClass;
|
||||
|
||||
/* Make the prototype and constructor links. */
|
||||
if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), protos[i],
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "jsapi.h"
|
||||
#include "jsarray.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbuiltins.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsversion.h"
|
||||
#include "jsdbgapi.h"
|
||||
|
@ -2089,7 +2090,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
|||
|
||||
/* Initialize all function members. */
|
||||
fun->nargs = nargs;
|
||||
fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED);
|
||||
fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED | JSFUN_TRACEABLE);
|
||||
if (flags & JSFUN_INTERPRETED) {
|
||||
JS_ASSERT(!native);
|
||||
JS_ASSERT(nargs == 0);
|
||||
|
@ -2100,10 +2101,20 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
|||
fun->u.i.names.taggedAtom = 0;
|
||||
#endif
|
||||
} else {
|
||||
fun->u.n.native = native;
|
||||
fun->u.n.extra = 0;
|
||||
fun->u.n.spare = 0;
|
||||
fun->u.n.clasp = NULL;
|
||||
if (flags & JSFUN_TRACEABLE) {
|
||||
#ifdef JS_TRACER
|
||||
JSTraceableNative *trcinfo = (JSTraceableNative *) native;
|
||||
fun->u.n.native = (JSNative) trcinfo->native;
|
||||
FUN_TRCINFO(fun) = trcinfo;
|
||||
#else
|
||||
JS_ASSERT(0);
|
||||
#endif
|
||||
} else {
|
||||
fun->u.n.native = native;
|
||||
FUN_CLASP(fun) = NULL;
|
||||
}
|
||||
}
|
||||
fun->atom = atom;
|
||||
|
||||
|
|
|
@ -73,7 +73,12 @@ struct JSFunction {
|
|||
uint16 extra; /* number of arg slots for local GC roots */
|
||||
uint16 spare; /* reserved for future use */
|
||||
JSNative native; /* native method pointer or null */
|
||||
JSClass *clasp; /* if non-null, constructor for this class */
|
||||
union {
|
||||
JSClass *clasp; /* class of objects constructed
|
||||
by this function */
|
||||
JSTraceableNative *trcinfo; /* tracer metadata; can be first
|
||||
element of array */
|
||||
} u;
|
||||
} n;
|
||||
struct {
|
||||
uint16 nvars; /* number of local variables */
|
||||
|
@ -86,6 +91,9 @@ struct JSFunction {
|
|||
JSAtom *atom; /* name for diagnostics and decompiling */
|
||||
};
|
||||
|
||||
#define JSFUN_TRACEABLE 0x2000 /* can trace across calls to this native
|
||||
function; use FUN_TRCINFO if set,
|
||||
FUN_CLASP if unset */
|
||||
#define JSFUN_EXPR_CLOSURE 0x4000 /* expression closure: function(x)x*x */
|
||||
#define JSFUN_INTERPRETED 0x8000 /* use u.i if set, u.n if unset */
|
||||
|
||||
|
@ -102,6 +110,26 @@ struct JSFunction {
|
|||
#define FUN_MINARGS(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
|
||||
? 0 \
|
||||
: (fun)->nargs)
|
||||
#define FUN_CLASP(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
|
||||
JS_ASSERT(!((fun)->flags & JSFUN_TRACEABLE)), \
|
||||
fun->u.n.u.clasp)
|
||||
#define FUN_TRCINFO(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
|
||||
JS_ASSERT((fun)->flags & JSFUN_TRACEABLE), \
|
||||
fun->u.n.u.trcinfo)
|
||||
|
||||
/*
|
||||
* Traceable native. This expands to a JSFunctionSpec initializer (like JS_FN
|
||||
* in jsapi.h). fastcall is a JSFastNative; trcinfo is a JSTraceableNative *.
|
||||
*/
|
||||
#ifdef JS_TRACER
|
||||
/* MSVC demands the intermediate (void *) cast here. */
|
||||
# define JS_TN(name,fastcall,nargs,flags,trcinfo) \
|
||||
{name, (JSNative)(void *)(trcinfo), nargs, \
|
||||
(flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS | JSFUN_TRACEABLE, 0}
|
||||
#else
|
||||
# define JS_TN(name,fastcall,nargs,flags,trcinfo) \
|
||||
JS_FN(name, fastcall, nargs, flags)
|
||||
#endif
|
||||
|
||||
extern JSClass js_ArgumentsClass;
|
||||
extern JS_FRIEND_DATA(JSClass) js_CallClass;
|
||||
|
|
|
@ -1764,8 +1764,11 @@ js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp)
|
|||
|
||||
if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) {
|
||||
fun2 = GET_FUNCTION_PRIVATE(cx, obj2);
|
||||
if (!FUN_INTERPRETED(fun2) && fun2->u.n.clasp)
|
||||
clasp = fun2->u.n.clasp;
|
||||
if (!FUN_INTERPRETED(fun2) &&
|
||||
!(fun2->flags & JSFUN_TRACEABLE) &&
|
||||
fun2->u.n.u.clasp) {
|
||||
clasp = fun2->u.n.u.clasp;
|
||||
}
|
||||
}
|
||||
}
|
||||
obj = js_NewObject(cx, clasp, proto, parent, 0);
|
||||
|
|
|
@ -434,7 +434,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
|
|||
goto out;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool) JS_FASTCALL
|
||||
JS_FRIEND_API(JSBool) JS_FASTCALL
|
||||
js_CloseIterator(JSContext *cx, jsval v)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
|
|
@ -72,7 +72,7 @@ JS_BEGIN_EXTERN_C
|
|||
extern JS_FRIEND_API(JSBool)
|
||||
js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp);
|
||||
|
||||
extern JS_FRIEND_API(bool) JS_FASTCALL
|
||||
extern JS_FRIEND_API(JSBool) JS_FASTCALL
|
||||
js_CloseIterator(JSContext *cx, jsval v);
|
||||
|
||||
/*
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "prmjtime.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbuiltins.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsversion.h"
|
||||
#include "jslock.h"
|
||||
|
@ -55,6 +56,8 @@
|
|||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
extern jsdouble js_NaN;
|
||||
|
||||
#ifndef M_E
|
||||
#define M_E 2.7182818284590452354
|
||||
#endif
|
||||
|
@ -223,8 +226,8 @@ math_atan2(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_ceil(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
math_ceil(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
|
@ -239,8 +242,8 @@ js_math_ceil(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_cos(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
math_cos(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
|
@ -283,8 +286,8 @@ math_exp(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_floor(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
math_floor(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
|
@ -299,8 +302,8 @@ js_math_floor(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_log(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
math_log(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
|
@ -321,8 +324,8 @@ js_math_log(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_max(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
math_max(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x, z = *cx->runtime->jsNegativeInfinity;
|
||||
jsval *argv;
|
||||
|
@ -383,8 +386,8 @@ math_min(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_pow(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
math_pow(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x, y, z;
|
||||
|
||||
|
@ -488,8 +491,8 @@ js_random_nextDouble(JSRuntime *rt)
|
|||
return d / rt->rngDscale;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_random(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
math_random(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
jsdouble z;
|
||||
|
@ -533,8 +536,8 @@ math_round(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_sin(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
math_sin(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
|
@ -549,8 +552,8 @@ js_math_sin(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_sqrt(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
math_sqrt(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
|
@ -590,28 +593,99 @@ math_toSource(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
#define MATH_BUILTIN_1(name) \
|
||||
jsdouble FASTCALL js_Math_##name(jsdouble d) { return name(d); } \
|
||||
JS_DEFINE_CALLINFO_1(DOUBLE, Math_##name, DOUBLE, 1, 1) \
|
||||
static const JSTraceableNative math_##name##_trcinfo = \
|
||||
{ math_##name, &ci_Math_##name, "", "d", INFALLIBLE };
|
||||
|
||||
MATH_BUILTIN_1(sin)
|
||||
MATH_BUILTIN_1(cos)
|
||||
MATH_BUILTIN_1(sqrt)
|
||||
MATH_BUILTIN_1(floor)
|
||||
MATH_BUILTIN_1(ceil)
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_log(jsdouble d)
|
||||
{
|
||||
#if !JS_USE_FDLIBM_MATH && defined(SOLARIS) && defined(__GNUC__)
|
||||
if (d < 0)
|
||||
return js_NaN;
|
||||
#endif
|
||||
return log(d);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_max(jsdouble d, jsdouble p)
|
||||
{
|
||||
if (JSDOUBLE_IS_NaN(d) || JSDOUBLE_IS_NaN(p))
|
||||
return js_NaN;
|
||||
|
||||
if (p == 0 && p == d && fd_copysign(1.0, d) == -1)
|
||||
return p;
|
||||
return (d > p) ? d : p;
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_pow(jsdouble d, jsdouble p)
|
||||
{
|
||||
if (!JSDOUBLE_IS_FINITE(p) && (d == 1.0 || d == -1.0))
|
||||
return js_NaN;
|
||||
if (p == 0)
|
||||
return 1.0;
|
||||
return pow(d, p);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_Math_random(JSRuntime* rt)
|
||||
{
|
||||
JS_LOCK_RUNTIME(rt);
|
||||
js_random_init(rt);
|
||||
jsdouble z = js_random_nextDouble(rt);
|
||||
JS_UNLOCK_RUNTIME(rt);
|
||||
return z;
|
||||
}
|
||||
|
||||
JS_DEFINE_CALLINFO_1(DOUBLE, Math_log, DOUBLE, 1, 1)
|
||||
JS_DEFINE_CALLINFO_2(DOUBLE, Math_max, DOUBLE, DOUBLE, 1, 1)
|
||||
JS_DEFINE_CALLINFO_2(DOUBLE, Math_pow, DOUBLE, DOUBLE, 1, 1)
|
||||
JS_DEFINE_CALLINFO_1(DOUBLE, Math_random, RUNTIME, 0, 0)
|
||||
|
||||
static const JSTraceableNative math_log_trcinfo =
|
||||
{ math_log, &ci_Math_log, "", "d", INFALLIBLE };
|
||||
static const JSTraceableNative math_max_trcinfo =
|
||||
{ math_max, &ci_Math_max, "", "dd", INFALLIBLE };
|
||||
static const JSTraceableNative math_pow_trcinfo =
|
||||
{ math_pow, &ci_Math_pow, "", "dd", INFALLIBLE };
|
||||
static const JSTraceableNative math_random_trcinfo =
|
||||
{ math_random, &ci_Math_random, "R", "", INFALLIBLE };
|
||||
|
||||
#endif /* JS_TRACER */
|
||||
|
||||
static JSFunctionSpec math_static_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
JS_FN(js_toSource_str, math_toSource, 0, 0),
|
||||
JS_FN(js_toSource_str, math_toSource, 0, 0),
|
||||
#endif
|
||||
JS_FN("abs", math_abs, 1, 0),
|
||||
JS_FN("acos", math_acos, 1, 0),
|
||||
JS_FN("asin", math_asin, 1, 0),
|
||||
JS_FN("atan", math_atan, 1, 0),
|
||||
JS_FN("atan2", math_atan2, 2, 0),
|
||||
JS_FN("ceil", js_math_ceil, 1, 0),
|
||||
JS_FN("cos", js_math_cos, 1, 0),
|
||||
JS_FN("exp", math_exp, 1, 0),
|
||||
JS_FN("floor", js_math_floor, 1, 0),
|
||||
JS_FN("log", js_math_log, 1, 0),
|
||||
JS_FN("max", js_math_max, 2, 0),
|
||||
JS_FN("min", math_min, 2, 0),
|
||||
JS_FN("pow", js_math_pow, 2, 0),
|
||||
JS_FN("random", js_math_random, 0, 0),
|
||||
JS_FN("round", math_round, 1, 0),
|
||||
JS_FN("sin", js_math_sin, 1, 0),
|
||||
JS_FN("sqrt", js_math_sqrt, 1, 0),
|
||||
JS_FN("tan", math_tan, 1, 0),
|
||||
JS_FN("abs", math_abs, 1, 0),
|
||||
JS_FN("acos", math_acos, 1, 0),
|
||||
JS_FN("asin", math_asin, 1, 0),
|
||||
JS_FN("atan", math_atan, 1, 0),
|
||||
JS_FN("atan2", math_atan2, 2, 0),
|
||||
JS_TN("ceil", math_ceil, 1, 0, &math_ceil_trcinfo),
|
||||
JS_TN("cos", math_cos, 1, 0, &math_cos_trcinfo),
|
||||
JS_FN("exp", math_exp, 1, 0),
|
||||
JS_TN("floor", math_floor, 1, 0, &math_floor_trcinfo),
|
||||
JS_TN("log", math_log, 1, 0, &math_log_trcinfo),
|
||||
JS_TN("max", math_max, 2, 0, &math_max_trcinfo),
|
||||
JS_FN("min", math_min, 2, 0),
|
||||
JS_TN("pow", math_pow, 2, 0, &math_pow_trcinfo),
|
||||
JS_TN("random", math_random, 0, 0, &math_random_trcinfo),
|
||||
JS_FN("round", math_round, 1, 0),
|
||||
JS_TN("sin", math_sin, 1, 0, &math_sin_trcinfo),
|
||||
JS_TN("sqrt", math_sqrt, 1, 0, &math_sqrt_trcinfo),
|
||||
JS_FN("tan", math_tan, 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
|
102
js/src/jsnum.cpp
102
js/src/jsnum.cpp
|
@ -54,6 +54,7 @@
|
|||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbuiltins.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsversion.h"
|
||||
#include "jsdtoa.h"
|
||||
|
@ -98,8 +99,8 @@ num_isFinite(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_num_parseFloat(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
num_parseFloat(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
jsdouble d;
|
||||
|
@ -122,9 +123,25 @@ js_num_parseFloat(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, d, vp);
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
jsdouble FASTCALL
|
||||
js_ParseFloat(JSContext* cx, JSString* str)
|
||||
{
|
||||
const jschar* bp;
|
||||
const jschar* end;
|
||||
const jschar* ep;
|
||||
jsdouble d;
|
||||
|
||||
JSSTRING_CHARS_AND_END(str, bp, end);
|
||||
if (!js_strtod(cx, bp, end, &ep, &d) || ep == bp)
|
||||
return js_NaN;
|
||||
return d;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* See ECMA 15.1.2.2. */
|
||||
JSBool
|
||||
js_num_parseInt(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
num_parseInt(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsint radix;
|
||||
JSString *str;
|
||||
|
@ -165,6 +182,30 @@ js_num_parseInt(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_NewNumberInRootedValue(cx, d, vp);
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
jsdouble FASTCALL
|
||||
js_ParseInt(JSContext* cx, JSString* str)
|
||||
{
|
||||
const jschar* bp;
|
||||
const jschar* end;
|
||||
const jschar* ep;
|
||||
jsdouble d;
|
||||
|
||||
JSSTRING_CHARS_AND_END(str, bp, end);
|
||||
if (!js_strtointeger(cx, bp, end, &ep, 0, &d) || ep == bp)
|
||||
return js_NaN;
|
||||
return d;
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_ParseIntDouble(jsdouble d)
|
||||
{
|
||||
if (!JSDOUBLE_IS_FINITE(d))
|
||||
return js_NaN;
|
||||
return floor(d);
|
||||
}
|
||||
#endif
|
||||
|
||||
const char js_Infinity_str[] = "Infinity";
|
||||
const char js_NaN_str[] = "NaN";
|
||||
const char js_isNaN_str[] = "isNaN";
|
||||
|
@ -172,11 +213,27 @@ const char js_isFinite_str[] = "isFinite";
|
|||
const char js_parseFloat_str[] = "parseFloat";
|
||||
const char js_parseInt_str[] = "parseInt";
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
JS_DEFINE_CALLINFO_2(DOUBLE, ParseInt, CONTEXT, STRING, 1, 1)
|
||||
JS_DEFINE_CALLINFO_1(DOUBLE, ParseIntDouble, DOUBLE, 1, 1)
|
||||
JS_DEFINE_CALLINFO_2(DOUBLE, ParseFloat, CONTEXT, STRING, 1, 1)
|
||||
|
||||
static const JSTraceableNative num_parseInt_trcinfo[] = {
|
||||
{ num_parseInt, &ci_ParseInt, "C", "s", INFALLIBLE | JSTN_MORE },
|
||||
{ num_parseInt, &ci_ParseIntDouble, "", "d", INFALLIBLE }
|
||||
};
|
||||
static const JSTraceableNative num_parseFloat_trcinfo[] = {
|
||||
{ num_parseFloat, &ci_ParseFloat, "C", "s", INFALLIBLE }
|
||||
};
|
||||
|
||||
#endif /* JS_TRACER */
|
||||
|
||||
static JSFunctionSpec number_functions[] = {
|
||||
JS_FN(js_isNaN_str, num_isNaN, 1,0),
|
||||
JS_FN(js_isFinite_str, num_isFinite, 1,0),
|
||||
JS_FN(js_parseFloat_str, js_num_parseFloat, 1,0),
|
||||
JS_FN(js_parseInt_str, js_num_parseInt, 2,0),
|
||||
JS_TN(js_parseFloat_str, num_parseFloat, 1,0, num_parseFloat_trcinfo),
|
||||
JS_TN(js_parseInt_str, num_parseInt, 2,0, num_parseInt_trcinfo),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -274,8 +331,8 @@ js_IntToCString(jsint i, char *buf, size_t bufSize)
|
|||
return cp;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_num_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
num_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval v;
|
||||
jsdouble d;
|
||||
|
@ -332,7 +389,7 @@ num_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
|
|||
* Create the string, move back to bytes to make string twiddling
|
||||
* a bit easier and so we can insert platform charset seperators.
|
||||
*/
|
||||
if (!js_num_toString(cx, 0, vp))
|
||||
if (!num_toString(cx, 0, vp))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(JSVAL_IS_STRING(*vp));
|
||||
numStr = JSVAL_TO_STRING(*vp);
|
||||
|
@ -515,21 +572,32 @@ static JSBool
|
|||
num_toPrecision(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc == 0 || JSVAL_IS_VOID(vp[2]))
|
||||
return js_num_toString(cx, 0, vp);
|
||||
return num_toString(cx, 0, vp);
|
||||
return num_to(cx, DTOSTR_STANDARD, DTOSTR_PRECISION, 1, MAX_PRECISION, 0,
|
||||
argc, vp);
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
JS_DEFINE_CALLINFO_2(STRING, NumberToString, CONTEXT, DOUBLE, 1, 1)
|
||||
|
||||
static const JSTraceableNative num_toString_trcinfo[] = {
|
||||
{ num_toString, &ci_NumberToString, "TC", "", FAIL_NULL }
|
||||
};
|
||||
|
||||
#endif /* JS_TRACER */
|
||||
|
||||
static JSFunctionSpec number_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
JS_FN(js_toSource_str, num_toSource, 0,JSFUN_THISP_NUMBER),
|
||||
JS_FN(js_toSource_str, num_toSource, 0,JSFUN_THISP_NUMBER),
|
||||
#endif
|
||||
JS_FN(js_toString_str, js_num_toString, 1,JSFUN_THISP_NUMBER),
|
||||
JS_FN(js_toLocaleString_str, num_toLocaleString, 0,JSFUN_THISP_NUMBER),
|
||||
JS_FN(js_valueOf_str, num_valueOf, 0,JSFUN_THISP_NUMBER),
|
||||
JS_FN("toFixed", num_toFixed, 1,JSFUN_THISP_NUMBER),
|
||||
JS_FN("toExponential", num_toExponential, 1,JSFUN_THISP_NUMBER),
|
||||
JS_FN("toPrecision", num_toPrecision, 1,JSFUN_THISP_NUMBER),
|
||||
JS_TN(js_toString_str, num_toString, 1,JSFUN_THISP_NUMBER,
|
||||
num_toString_trcinfo),
|
||||
JS_FN(js_toLocaleString_str, num_toLocaleString, 0,JSFUN_THISP_NUMBER),
|
||||
JS_FN(js_valueOf_str, num_valueOf, 0,JSFUN_THISP_NUMBER),
|
||||
JS_FN("toFixed", num_toFixed, 1,JSFUN_THISP_NUMBER),
|
||||
JS_FN("toExponential", num_toExponential, 1,JSFUN_THISP_NUMBER),
|
||||
JS_FN("toPrecision", num_toPrecision, 1,JSFUN_THISP_NUMBER),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#ifndef jsnum_h___
|
||||
#define jsnum_h___
|
||||
|
||||
/*
|
||||
* JS number (IEEE double) interface.
|
||||
*
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "jsarray.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbool.h"
|
||||
#include "jsbuiltins.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsversion.h"
|
||||
#include "jsemit.h"
|
||||
|
@ -1177,8 +1178,8 @@ js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
|
|||
return caller->script->filename;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool
|
||||
obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSStackFrame *fp, *caller;
|
||||
JSBool indirectCall;
|
||||
|
@ -1475,8 +1476,8 @@ obj_unwatch(JSContext *cx, uintN argc, jsval *vp)
|
|||
*/
|
||||
|
||||
/* Proposed ECMA 15.2.4.5. */
|
||||
JSBool
|
||||
js_obj_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
obj_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
|
@ -1555,6 +1556,19 @@ js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
int32 FASTCALL
|
||||
js_Object_p_hasOwnProperty(JSContext* cx, JSObject* obj, JSString *str)
|
||||
{
|
||||
jsid id = ATOM_TO_JSID(STRING_TO_JSVAL(str));
|
||||
jsval v;
|
||||
if (!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &v))
|
||||
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
|
||||
return JSVAL_TO_BOOLEAN(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Proposed ECMA 15.2.4.6. */
|
||||
static JSBool
|
||||
obj_isPrototypeOf(JSContext *cx, uintN argc, jsval *vp)
|
||||
|
@ -1570,8 +1584,8 @@ obj_isPrototypeOf(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
/* Proposed ECMA 15.2.4.7. */
|
||||
JSBool
|
||||
js_obj_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
obj_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsid id;
|
||||
JSObject *obj;
|
||||
|
@ -1583,6 +1597,19 @@ js_obj_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp)
|
|||
return obj && js_PropertyIsEnumerable(cx, obj, id, vp);
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
int32 FASTCALL
|
||||
js_Object_p_propertyIsEnumerable(JSContext* cx, JSObject* obj, JSString *str)
|
||||
{
|
||||
jsid id = ATOM_TO_JSID(STRING_TO_JSVAL(str));
|
||||
jsval v;
|
||||
if (!js_PropertyIsEnumerable(cx, obj, id, &v))
|
||||
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
|
||||
return JSVAL_TO_BOOLEAN(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
JSBool
|
||||
js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
|
@ -1782,6 +1809,20 @@ const char js_lookupGetter_str[] = "__lookupGetter__";
|
|||
const char js_lookupSetter_str[] = "__lookupSetter__";
|
||||
#endif
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
JS_DEFINE_CALLINFO_3(INT32, Object_p_hasOwnProperty, CONTEXT, OBJECT, STRING, 0, 0)
|
||||
JS_DEFINE_CALLINFO_3(INT32, Object_p_propertyIsEnumerable, CONTEXT, OBJECT, STRING, 0, 0)
|
||||
|
||||
static const JSTraceableNative obj_hasOwnProperty_trcinfo[] = {
|
||||
{ obj_hasOwnProperty, &ci_Object_p_hasOwnProperty, "TC", "s", FAIL_VOID }
|
||||
};
|
||||
static const JSTraceableNative obj_propertyIsEnumerable_trcinfo[] = {
|
||||
{ obj_propertyIsEnumerable, &ci_Object_p_propertyIsEnumerable, "TC", "s", FAIL_VOID }
|
||||
};
|
||||
|
||||
#endif /* JS_TRACER */
|
||||
|
||||
static JSFunctionSpec object_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
JS_FN(js_toSource_str, obj_toSource, 0,0),
|
||||
|
@ -1793,9 +1834,11 @@ static JSFunctionSpec object_methods[] = {
|
|||
JS_FN(js_watch_str, obj_watch, 2,0),
|
||||
JS_FN(js_unwatch_str, obj_unwatch, 1,0),
|
||||
#endif
|
||||
JS_FN(js_hasOwnProperty_str, js_obj_hasOwnProperty, 1,0),
|
||||
JS_TN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0,
|
||||
obj_hasOwnProperty_trcinfo),
|
||||
JS_FN(js_isPrototypeOf_str, obj_isPrototypeOf, 1,0),
|
||||
JS_FN(js_propertyIsEnumerable_str, js_obj_propertyIsEnumerable, 1,0),
|
||||
JS_TN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0,
|
||||
obj_propertyIsEnumerable_trcinfo),
|
||||
#if JS_HAS_GETTER_SETTER
|
||||
JS_FN(js_defineGetter_str, obj_defineGetter, 2,0),
|
||||
JS_FN(js_defineSetter_str, obj_defineSetter, 2,0),
|
||||
|
@ -1806,7 +1849,7 @@ static JSFunctionSpec object_methods[] = {
|
|||
};
|
||||
|
||||
static JSFunctionSpec object_static_methods[] = {
|
||||
JS_FN("getPrototypeOf", obj_getPrototypeOf, 1,0),
|
||||
JS_FN("getPrototypeOf", obj_getPrototypeOf, 1,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -2291,7 +2334,7 @@ js_InitEval(JSContext *cx, JSObject *obj)
|
|||
{
|
||||
/* ECMA (15.1.2.1) says 'eval' is a property of the global object. */
|
||||
if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom,
|
||||
js_obj_eval, 1, 0)) {
|
||||
obj_eval, 1, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -395,9 +395,6 @@ js_LeaveSharpObject(JSContext *cx, JSIdArray **idap);
|
|||
extern void
|
||||
js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map);
|
||||
|
||||
extern JSBool
|
||||
js_obj_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc,
|
||||
jsval *vp);
|
||||
|
@ -406,9 +403,6 @@ extern JSBool
|
|||
js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
|
||||
jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_obj_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
|
@ -727,9 +721,6 @@ extern const char *
|
|||
js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
|
||||
JSPrincipals *principals, uintN *linenop);
|
||||
|
||||
extern JSBool
|
||||
js_obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_FRIEND_API(void) js_DumpChars(const jschar *s, size_t n);
|
||||
JS_FRIEND_API(void) js_DumpString(JSString *str);
|
||||
|
|
|
@ -124,6 +124,7 @@ typedef struct JSScopeProperty JSScopeProperty;
|
|||
typedef struct JSStackHeader JSStackHeader;
|
||||
typedef struct JSStringBuffer JSStringBuffer;
|
||||
typedef struct JSSubString JSSubString;
|
||||
typedef struct JSTraceableNative JSTraceableNative;
|
||||
typedef struct JSXML JSXML;
|
||||
typedef struct JSXMLArray JSXMLArray;
|
||||
typedef struct JSXMLArrayCursor JSXMLArrayCursor;
|
||||
|
|
304
js/src/jsstr.cpp
304
js/src/jsstr.cpp
|
@ -59,6 +59,7 @@
|
|||
#include "jsarray.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbool.h"
|
||||
#include "jsbuiltins.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsversion.h"
|
||||
#include "jsgc.h"
|
||||
|
@ -732,8 +733,8 @@ str_toString(JSContext *cx, uintN argc, jsval *vp)
|
|||
/*
|
||||
* Java-like string native methods.
|
||||
*/
|
||||
JSBool
|
||||
js_str_substring(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_substring(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
jsdouble d;
|
||||
|
@ -779,6 +780,25 @@ js_str_substring(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSString* FASTCALL
|
||||
js_String_p_substring(JSContext* cx, JSString* str, int32 begin, int32 end)
|
||||
{
|
||||
JS_ASSERT(end >= begin);
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_substring_1(JSContext* cx, JSString* str, int32 begin)
|
||||
{
|
||||
int32 end = JSSTRING_LENGTH(str);
|
||||
JS_ASSERT(end >= begin);
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
|
||||
}
|
||||
#endif
|
||||
|
||||
JSString* JS_FASTCALL
|
||||
js_toLowerCase(JSContext *cx, JSString *str)
|
||||
{
|
||||
|
@ -800,8 +820,8 @@ js_toLowerCase(JSContext *cx, JSString *str)
|
|||
return str;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_str_toLowerCase(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_toLowerCase(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
|
@ -826,7 +846,7 @@ str_toLocaleLowerCase(JSContext *cx, uintN argc, jsval *vp)
|
|||
NORMALIZE_THIS(cx, vp, str);
|
||||
return cx->localeCallbacks->localeToLowerCase(cx, str, vp);
|
||||
}
|
||||
return js_str_toLowerCase(cx, 0, vp);
|
||||
return str_toLowerCase(cx, 0, vp);
|
||||
}
|
||||
|
||||
JSString* JS_FASTCALL
|
||||
|
@ -850,8 +870,8 @@ js_toUpperCase(JSContext *cx, JSString *str)
|
|||
return str;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_str_toUpperCase(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_toUpperCase(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
|
@ -876,7 +896,7 @@ str_toLocaleUpperCase(JSContext *cx, uintN argc, jsval *vp)
|
|||
NORMALIZE_THIS(cx, vp, str);
|
||||
return cx->localeCallbacks->localeToUpperCase(cx, str, vp);
|
||||
}
|
||||
return js_str_toUpperCase(cx, 0, vp);
|
||||
return str_toUpperCase(cx, 0, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -900,8 +920,8 @@ str_localeCompare(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_str_charAt(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_charAt(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval t;
|
||||
JSString *str;
|
||||
|
@ -944,8 +964,8 @@ out_of_range:
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_str_charCodeAt(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_charCodeAt(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval t;
|
||||
JSString *str;
|
||||
|
@ -985,6 +1005,16 @@ out_of_range:
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
int32 FASTCALL
|
||||
js_String_p_charCodeAt(JSString* str, int32 i)
|
||||
{
|
||||
if (i < 0 || (int32)JSSTRING_LENGTH(str) <= i)
|
||||
return -1;
|
||||
return JSSTRING_CHARS(str)[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
jsint
|
||||
js_BoyerMooreHorspool(const jschar *text, jsint textlen,
|
||||
const jschar *pat, jsint patlen,
|
||||
|
@ -1299,8 +1329,8 @@ match_or_replace(JSContext *cx,
|
|||
test = JS_TRUE;
|
||||
} else {
|
||||
/*
|
||||
* MODE_MATCH implies js_str_match is being called from a script or
|
||||
* a scripted function. If the caller cares only about testing null
|
||||
* MODE_MATCH implies str_match is being called from a script or a
|
||||
* scripted function. If the caller cares only about testing null
|
||||
* vs. non-null return value, optimize away the array object that
|
||||
* would normally be returned in *vp.
|
||||
*
|
||||
|
@ -1365,6 +1395,8 @@ match_glob(JSContext *cx, jsint count, GlobData *data)
|
|||
return JS_FALSE;
|
||||
v = STRING_TO_JSVAL(matchstr);
|
||||
JS_ASSERT(count <= JSVAL_INT_MAX);
|
||||
|
||||
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
|
||||
return OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(count), &v);
|
||||
}
|
||||
|
||||
|
@ -1387,8 +1419,8 @@ js_StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc)
|
|||
return ok;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_str_match(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_match(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSStackFrame *fp;
|
||||
|
||||
|
@ -1397,6 +1429,30 @@ js_str_match(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_StringMatchHelper(cx, argc, vp, fp ? fp->regs->pc : NULL);
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSObject* FASTCALL
|
||||
js_String_p_match(JSContext* cx, JSString* str, jsbytecode *pc, JSObject* regexp)
|
||||
{
|
||||
jsval vp[3] = { JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
|
||||
if (!js_StringMatchHelper(cx, 1, vp, pc))
|
||||
return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
|
||||
(!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
|
||||
return JSVAL_TO_OBJECT(vp[0]);
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_String_p_match_obj(JSContext* cx, JSObject* str, jsbytecode *pc, JSObject* regexp)
|
||||
{
|
||||
jsval vp[3] = { JSVAL_NULL, OBJECT_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
|
||||
if (!js_StringMatchHelper(cx, 1, vp, pc))
|
||||
return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
|
||||
(!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
|
||||
return JSVAL_TO_OBJECT(vp[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
str_search(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
|
@ -1498,7 +1554,7 @@ find_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep)
|
|||
* Save the regExpStatics from the current regexp, since they may be
|
||||
* clobbered by a RegExp usage in the lambda function. Note that all
|
||||
* members of JSRegExpStatics are JSSubStrings, so not GC roots, save
|
||||
* input, which is rooted otherwise via vp[1] in js_str_replace.
|
||||
* input, which is rooted otherwise via vp[1] in str_replace.
|
||||
*/
|
||||
JSRegExpStatics save = cx->regExpStatics;
|
||||
JSBool freeMoreParens = JS_FALSE;
|
||||
|
@ -1678,8 +1734,8 @@ replace_glob(JSContext *cx, jsint count, GlobData *data)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_str_replace(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_replace(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *lambda;
|
||||
JSString *repstr;
|
||||
|
@ -1697,6 +1753,46 @@ js_str_replace(JSContext *cx, uintN argc, jsval *vp)
|
|||
return js_StringReplaceHelper(cx, argc, lambda, repstr, vp);
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSString* FASTCALL
|
||||
js_String_p_replace_str(JSContext* cx, JSString* str, JSObject* regexp, JSString* repstr)
|
||||
{
|
||||
jsval vp[4] = {
|
||||
JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp), STRING_TO_JSVAL(repstr)
|
||||
};
|
||||
if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_STRING(vp[0]));
|
||||
return JSVAL_TO_STRING(vp[0]);
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_replace_str2(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr)
|
||||
{
|
||||
jsval vp[4] = {
|
||||
JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr)
|
||||
};
|
||||
if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_STRING(vp[0]));
|
||||
return JSVAL_TO_STRING(vp[0]);
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_replace_str3(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr,
|
||||
JSString* flagstr)
|
||||
{
|
||||
jsval vp[5] = {
|
||||
JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr),
|
||||
STRING_TO_JSVAL(flagstr)
|
||||
};
|
||||
if (!js_StringReplaceHelper(cx, 3, NULL, repstr, vp))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_STRING(vp[0]));
|
||||
return JSVAL_TO_STRING(vp[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
JSBool
|
||||
js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda,
|
||||
JSString *repstr, jsval *vp)
|
||||
|
@ -1785,7 +1881,7 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Subroutine used by js_str_split to find the next split point in str, starting
|
||||
* Subroutine used by str_split to find the next split point in str, starting
|
||||
* at offset *ip and looking either for the separator substring given by sep, or
|
||||
* for the next re match. In the re case, return the matched separator in *sep,
|
||||
* and the possibly updated offset in *ip.
|
||||
|
@ -1810,7 +1906,7 @@ find_split(JSContext *cx, JSString *str, JSRegExp *re, jsint *ip,
|
|||
*
|
||||
* and the resulting array converts back to the string "ab," for symmetry.
|
||||
* However, we ape Perl and do this only if there is a sufficiently large
|
||||
* limit argument (see js_str_split).
|
||||
* limit argument (see str_split).
|
||||
*/
|
||||
i = *ip;
|
||||
length = JSSTRING_LENGTH(str);
|
||||
|
@ -1896,8 +1992,8 @@ find_split(JSContext *cx, JSString *str, JSRegExp *re, jsint *ip,
|
|||
return k;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_str_split(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_split(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str, *sub;
|
||||
JSObject *arrayobj;
|
||||
|
@ -1998,6 +2094,19 @@ js_str_split(JSContext *cx, uintN argc, jsval *vp)
|
|||
return ok;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSObject* FASTCALL
|
||||
js_String_p_split(JSContext* cx, JSString* str, JSString* sepstr)
|
||||
{
|
||||
// FIXME: Avoid building and then parsing this array.
|
||||
jsval vp[4] = { JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(sepstr), JSVAL_VOID };
|
||||
if (!str_split(cx, 2, vp))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(vp[0]));
|
||||
return JSVAL_TO_OBJECT(vp[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if JS_HAS_PERL_SUBSTR
|
||||
static JSBool
|
||||
str_substr(JSContext *cx, uintN argc, jsval *vp)
|
||||
|
@ -2049,8 +2158,8 @@ str_substr(JSContext *cx, uintN argc, jsval *vp)
|
|||
/*
|
||||
* Python-esque sequence operations.
|
||||
*/
|
||||
JSBool
|
||||
js_str_concat(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_concat(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str, *str2;
|
||||
jsval *argv;
|
||||
|
@ -2073,6 +2182,39 @@ js_str_concat(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSString* FASTCALL
|
||||
js_String_p_concat_1int(JSContext* cx, JSString* str, int32 i)
|
||||
{
|
||||
// FIXME: should be able to use stack buffer and avoid istr...
|
||||
JSString* istr = js_NumberToString(cx, i);
|
||||
if (!istr)
|
||||
return NULL;
|
||||
return js_ConcatStrings(cx, str, istr);
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_concat_2str(JSContext* cx, JSString* str, JSString* a, JSString* b)
|
||||
{
|
||||
str = js_ConcatStrings(cx, str, a);
|
||||
if (str)
|
||||
return js_ConcatStrings(cx, str, b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_p_concat_3str(JSContext* cx, JSString* str, JSString* a, JSString* b, JSString* c)
|
||||
{
|
||||
str = js_ConcatStrings(cx, str, a);
|
||||
if (str) {
|
||||
str = js_ConcatStrings(cx, str, b);
|
||||
if (str)
|
||||
return js_ConcatStrings(cx, str, c);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
str_slice(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
|
@ -2308,6 +2450,73 @@ str_sub(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
#endif /* JS_HAS_STR_HTML_HELPERS */
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_getelem(JSContext* cx, JSString* str, int32 i)
|
||||
{
|
||||
if ((size_t)i >= JSSTRING_LENGTH(str))
|
||||
return NULL;
|
||||
return js_GetUnitString(cx, str, (size_t)i);
|
||||
}
|
||||
|
||||
JS_DEFINE_CALLINFO_2(BOOL, EqualStrings, STRING, STRING, 1, 1)
|
||||
JS_DEFINE_CALLINFO_2(INT32, CompareStrings, STRING, STRING, 1, 1)
|
||||
|
||||
JS_DEFINE_CALLINFO_4(STRING, String_p_substring, CONTEXT, STRING, INT32, INT32, 1, 1)
|
||||
JS_DEFINE_CALLINFO_3(STRING, String_p_substring_1, CONTEXT, STRING, INT32, 1, 1)
|
||||
JS_DEFINE_CALLINFO_3(STRING, String_getelem, CONTEXT, STRING, INT32, 1, 1)
|
||||
JS_DEFINE_CALLINFO_2(INT32, String_p_charCodeAt, STRING, INT32, 1, 1)
|
||||
JS_DEFINE_CALLINFO_3(STRING, ConcatStrings, CONTEXT, STRING, STRING, 1, 1)
|
||||
JS_DEFINE_CALLINFO_3(STRING, String_p_concat_1int, CONTEXT, STRING, INT32, 1, 1)
|
||||
JS_DEFINE_CALLINFO_4(STRING, String_p_concat_2str, CONTEXT, STRING, STRING, STRING, 1, 1)
|
||||
JS_DEFINE_CALLINFO_5(STRING, String_p_concat_3str, CONTEXT, STRING, STRING, STRING, STRING, 1, 1)
|
||||
JS_DEFINE_CALLINFO_4(OBJECT, String_p_match, CONTEXT, STRING, PC, OBJECT, 1, 1)
|
||||
JS_DEFINE_CALLINFO_4(OBJECT, String_p_match_obj, CONTEXT, OBJECT, PC, OBJECT, 1, 1)
|
||||
JS_DEFINE_CALLINFO_4(STRING, String_p_replace_str, CONTEXT, STRING, OBJECT, STRING, 1, 1)
|
||||
JS_DEFINE_CALLINFO_4(STRING, String_p_replace_str2, CONTEXT, STRING, STRING, STRING, 1, 1)
|
||||
JS_DEFINE_CALLINFO_5(STRING, String_p_replace_str3, CONTEXT, STRING, STRING, STRING, STRING, 1, 1)
|
||||
JS_DEFINE_CALLINFO_3(OBJECT, String_p_split, CONTEXT, STRING, STRING, 0, 0)
|
||||
JS_DEFINE_CALLINFO_2(STRING, toLowerCase, CONTEXT, STRING, 1, 1)
|
||||
JS_DEFINE_CALLINFO_2(STRING, toUpperCase, CONTEXT, STRING, 1, 1)
|
||||
|
||||
static const JSTraceableNative str_substring_trcinfo[] = {
|
||||
{ str_substring, &ci_String_p_substring, "SC", "ii", FAIL_NULL | JSTN_MORE},
|
||||
{ str_substring, &ci_String_p_substring_1, "SC", "i", FAIL_NULL }
|
||||
};
|
||||
static const JSTraceableNative str_charAt_trcinfo[] = {
|
||||
{ str_charAt, &ci_String_getelem, "SC", "i", FAIL_NULL }
|
||||
};
|
||||
static const JSTraceableNative str_charCodeAt_trcinfo[] = {
|
||||
{ str_charCodeAt, &ci_String_p_charCodeAt, "S", "i", FAIL_NEG }
|
||||
};
|
||||
static const JSTraceableNative str_concat_trcinfo[] = {
|
||||
{ str_concat, &ci_String_p_concat_1int, "SC", "i", FAIL_NULL | JSTN_MORE },
|
||||
{ str_concat, &ci_ConcatStrings, "SC", "s", FAIL_NULL | JSTN_MORE },
|
||||
{ str_concat, &ci_String_p_concat_2str, "SC", "ss", FAIL_NULL | JSTN_MORE },
|
||||
{ str_concat, &ci_String_p_concat_3str, "SC", "sss", FAIL_NULL }
|
||||
};
|
||||
static const JSTraceableNative str_match_trcinfo[] = {
|
||||
{ str_match, &ci_String_p_match, "PSC", "r", FAIL_VOID | JSTN_MORE },
|
||||
{ str_match, &ci_String_p_match_obj, "PTC", "r", FAIL_VOID }
|
||||
};
|
||||
static const JSTraceableNative str_replace_trcinfo[] = {
|
||||
{ str_replace, &ci_String_p_replace_str, "SC", "sr", FAIL_NULL | JSTN_MORE },
|
||||
{ str_replace, &ci_String_p_replace_str2,"SC", "ss", FAIL_NULL | JSTN_MORE },
|
||||
{ str_replace, &ci_String_p_replace_str3,"SC", "sss", FAIL_NULL }
|
||||
};
|
||||
static const JSTraceableNative str_split_trcinfo[] = {
|
||||
{ str_split, &ci_String_p_split, "SC", "s", FAIL_NULL }
|
||||
};
|
||||
static const JSTraceableNative str_toLowerCase_trcinfo[] = {
|
||||
{ str_toLowerCase, &ci_toLowerCase, "SC", "", FAIL_NULL }
|
||||
};
|
||||
static const JSTraceableNative str_toUpperCase_trcinfo[] = {
|
||||
{ str_toUpperCase, &ci_toUpperCase, "SC", "", FAIL_NULL }
|
||||
};
|
||||
|
||||
#endif /* JS_TRACER */
|
||||
|
||||
#define GENERIC JSFUN_GENERIC_NATIVE
|
||||
#define PRIMITIVE JSFUN_THISP_PRIMITIVE
|
||||
#define GENERIC_PRIMITIVE (GENERIC | PRIMITIVE)
|
||||
|
@ -2321,11 +2530,11 @@ static JSFunctionSpec string_methods[] = {
|
|||
/* Java-like methods. */
|
||||
JS_FN(js_toString_str, str_toString, 0,JSFUN_THISP_STRING),
|
||||
JS_FN(js_valueOf_str, str_toString, 0,JSFUN_THISP_STRING),
|
||||
JS_FN("substring", js_str_substring, 2,GENERIC_PRIMITIVE),
|
||||
JS_FN("toLowerCase", js_str_toLowerCase, 0,GENERIC_PRIMITIVE),
|
||||
JS_FN("toUpperCase", js_str_toUpperCase, 0,GENERIC_PRIMITIVE),
|
||||
JS_FN("charAt", js_str_charAt, 1,GENERIC_PRIMITIVE),
|
||||
JS_FN("charCodeAt", js_str_charCodeAt, 1,GENERIC_PRIMITIVE),
|
||||
JS_TN("substring", str_substring, 2,GENERIC_PRIMITIVE, str_substring_trcinfo),
|
||||
JS_TN("toLowerCase", str_toLowerCase, 0,GENERIC_PRIMITIVE, str_toLowerCase_trcinfo),
|
||||
JS_TN("toUpperCase", str_toUpperCase, 0,GENERIC_PRIMITIVE, str_toUpperCase_trcinfo),
|
||||
JS_TN("charAt", str_charAt, 1,GENERIC_PRIMITIVE, str_charAt_trcinfo),
|
||||
JS_TN("charCodeAt", str_charCodeAt, 1,GENERIC_PRIMITIVE, str_charCodeAt_trcinfo),
|
||||
JS_FN("indexOf", str_indexOf, 1,GENERIC_PRIMITIVE),
|
||||
JS_FN("lastIndexOf", str_lastIndexOf, 1,GENERIC_PRIMITIVE),
|
||||
JS_FN("trim", str_trim, 0,GENERIC_PRIMITIVE),
|
||||
|
@ -2336,16 +2545,16 @@ static JSFunctionSpec string_methods[] = {
|
|||
JS_FN("localeCompare", str_localeCompare, 1,GENERIC_PRIMITIVE),
|
||||
|
||||
/* Perl-ish methods (search is actually Python-esque). */
|
||||
JS_FN("match", js_str_match, 1,GENERIC_PRIMITIVE),
|
||||
JS_TN("match", str_match, 1,GENERIC_PRIMITIVE, str_match_trcinfo),
|
||||
JS_FN("search", str_search, 1,GENERIC_PRIMITIVE),
|
||||
JS_FN("replace", js_str_replace, 2,GENERIC_PRIMITIVE),
|
||||
JS_FN("split", js_str_split, 2,GENERIC_PRIMITIVE),
|
||||
JS_TN("replace", str_replace, 2,GENERIC_PRIMITIVE, str_replace_trcinfo),
|
||||
JS_TN("split", str_split, 2,GENERIC_PRIMITIVE, str_split_trcinfo),
|
||||
#if JS_HAS_PERL_SUBSTR
|
||||
JS_FN("substr", str_substr, 2,GENERIC_PRIMITIVE),
|
||||
#endif
|
||||
|
||||
/* Python-esque sequence methods. */
|
||||
JS_FN("concat", js_str_concat, 1,GENERIC_PRIMITIVE),
|
||||
JS_TN("concat", str_concat, 1,GENERIC_PRIMITIVE, str_concat_trcinfo),
|
||||
JS_FN("slice", str_slice, 2,GENERIC_PRIMITIVE),
|
||||
|
||||
/* HTML string methods. */
|
||||
|
@ -2389,8 +2598,8 @@ String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_str_fromCharCode(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
str_fromCharCode(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval *argv;
|
||||
uintN i;
|
||||
|
@ -2429,8 +2638,27 @@ js_str_fromCharCode(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
JSString* FASTCALL
|
||||
js_String_fromCharCode(JSContext* cx, int32 i)
|
||||
{
|
||||
JS_ASSERT(JS_ON_TRACE(cx));
|
||||
jschar c = (jschar)i;
|
||||
if (c < UNIT_STRING_LIMIT)
|
||||
return js_GetUnitStringForChar(cx, c);
|
||||
return js_NewStringCopyN(cx, &c, 1);
|
||||
}
|
||||
|
||||
JS_DEFINE_CALLINFO_2(STRING, String_fromCharCode, CONTEXT, INT32, 1, 1)
|
||||
|
||||
static const JSTraceableNative str_fromCharCode_trcinfo[] = {
|
||||
{ str_fromCharCode, &ci_String_fromCharCode, "C", "i", FAIL_NULL }};
|
||||
|
||||
#endif /* JS_TRACER */
|
||||
|
||||
static JSFunctionSpec string_static_methods[] = {
|
||||
JS_FN("fromCharCode", js_str_fromCharCode, 1,0),
|
||||
JS_TN("fromCharCode", str_fromCharCode, 1, 0, str_fromCharCode_trcinfo),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -2920,7 +3148,7 @@ js_EqualStrings(JSString *str1, JSString *str2)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
jsint JS_FASTCALL
|
||||
int32 JS_FASTCALL
|
||||
js_CompareStrings(JSString *str1, JSString *str2)
|
||||
{
|
||||
size_t l1, l2, n, i;
|
||||
|
|
|
@ -519,7 +519,7 @@ js_EqualStrings(JSString *str1, JSString *str2);
|
|||
* Return less than, equal to, or greater than zero depending on whether
|
||||
* str1 is less than, equal to, or greater than str2.
|
||||
*/
|
||||
extern jsint JS_FASTCALL
|
||||
extern int32 JS_FASTCALL
|
||||
js_CompareStrings(JSString *str1, JSString *str2);
|
||||
|
||||
/*
|
||||
|
@ -620,25 +620,10 @@ js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
extern JSBool
|
||||
js_StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc);
|
||||
|
||||
extern JSBool
|
||||
js_str_match(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_str_replace(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda,
|
||||
JSString *repstr, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_str_split(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_str_toLowerCase(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_str_toUpperCase(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
/*
|
||||
* Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
|
||||
* least 6 bytes long. Return the number of UTF-8 bytes of data written.
|
||||
|
|
|
@ -51,8 +51,7 @@
|
|||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include "nanojit/avmplus.h" // nanojit
|
||||
#include "nanojit/nanojit.h"
|
||||
#include "nanojit.h"
|
||||
#include "jsarray.h" // higher-level library and API headers
|
||||
#include "jsbool.h"
|
||||
#include "jscntxt.h"
|
||||
|
@ -384,7 +383,7 @@ static bool isi2f(LInsp i)
|
|||
i->oprnd1()->isop(LIR_call) &&
|
||||
i->oprnd2()->isop(LIR_callh))
|
||||
{
|
||||
if (i->oprnd1()->imm8() == F_i2f)
|
||||
if (i->oprnd1()->callInfo() == &ci_i2f)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -402,7 +401,7 @@ static bool isu2f(LInsp i)
|
|||
i->oprnd1()->isop(LIR_call) &&
|
||||
i->oprnd2()->isop(LIR_callh))
|
||||
{
|
||||
if (i->oprnd1()->imm8() == F_u2f)
|
||||
if (i->oprnd1()->callInfo() == &ci_u2f)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -478,10 +477,10 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
LInsp quadCall(uint32_t fid, LInsp args[]) {
|
||||
LInsp quadCall(const CallInfo *ci, LInsp args[]) {
|
||||
LInsp qlo, qhi;
|
||||
|
||||
qlo = out->insCall(fid, args);
|
||||
qlo = out->insCall(ci, args);
|
||||
qhi = out->ins1(LIR_callh, qlo);
|
||||
return out->qjoin(qlo, qhi);
|
||||
}
|
||||
|
@ -489,13 +488,13 @@ public:
|
|||
LInsp ins1(LOpcode v, LInsp s0)
|
||||
{
|
||||
if (v == LIR_fneg)
|
||||
return quadCall(F_fneg, &s0);
|
||||
return quadCall(&ci_fneg, &s0);
|
||||
|
||||
if (v == LIR_i2f)
|
||||
return quadCall(F_i2f, &s0);
|
||||
return quadCall(&ci_i2f, &s0);
|
||||
|
||||
if (v == LIR_u2f)
|
||||
return quadCall(F_u2f, &s0);
|
||||
return quadCall(&ci_u2f, &s0);
|
||||
|
||||
return out->ins1(v, s0);
|
||||
}
|
||||
|
@ -507,7 +506,7 @@ public:
|
|||
|
||||
// change the numeric value and order of these LIR opcodes and die
|
||||
if (LIR_fadd <= v && v <= LIR_fdiv) {
|
||||
static uint32_t fmap[] = { F_fadd, F_fsub, F_fmul, F_fdiv };
|
||||
static const CallInfo *fmap[] = { &ci_fadd, &ci_fsub, &ci_fmul, &ci_fdiv };
|
||||
|
||||
args[0] = s1;
|
||||
args[1] = s0;
|
||||
|
@ -516,7 +515,7 @@ public:
|
|||
}
|
||||
|
||||
if (LIR_feq <= v && v <= LIR_fge) {
|
||||
static uint32_t fmap[] = { F_fcmpeq, F_fcmplt, F_fcmpgt, F_fcmple, F_fcmpge };
|
||||
static const CallInfo *fmap[] = { &ci_fcmpeq, &ci_fcmplt, &ci_fcmpgt, &ci_fcmple, &ci_fcmpge };
|
||||
|
||||
args[0] = s1;
|
||||
args[1] = s0;
|
||||
|
@ -528,14 +527,14 @@ public:
|
|||
return out->ins2(v, s0, s1);
|
||||
}
|
||||
|
||||
LInsp insCall(uint32_t fid, LInsp args[])
|
||||
LInsp insCall(const CallInfo *ci, LInsp args[])
|
||||
{
|
||||
// if the return type is ARGSIZE_F, we have
|
||||
// to do a quadCall ( qjoin(call,callh) )
|
||||
if ((builtins[fid]._argtypes & 3) == ARGSIZE_F)
|
||||
return quadCall(fid, args);
|
||||
if ((ci->_argtypes & 3) == ARGSIZE_F)
|
||||
return quadCall(ci, args);
|
||||
|
||||
return out->insCall(fid, args);
|
||||
return out->insCall(ci, args);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -635,17 +634,15 @@ public:
|
|||
return out->ins2(v, s0, s1);
|
||||
}
|
||||
|
||||
LInsp insCall(uint32_t fid, LInsp args[])
|
||||
LInsp insCall(const CallInfo *ci, LInsp args[])
|
||||
{
|
||||
LInsp s0 = args[0];
|
||||
switch (fid) {
|
||||
case F_DoubleToUint32:
|
||||
if (ci == &ci_DoubleToUint32) {
|
||||
if (s0->isconstq())
|
||||
return out->insImm(js_DoubleToECMAUint32(s0->constvalf()));
|
||||
if (isi2f(s0) || isu2f(s0))
|
||||
return iu2fArg(s0);
|
||||
break;
|
||||
case F_DoubleToInt32:
|
||||
} else if (ci == &ci_DoubleToInt32) {
|
||||
if (s0->isconstq())
|
||||
return out->insImm(js_DoubleToECMAInt32(s0->constvalf()));
|
||||
if (s0->isop(LIR_fadd) || s0->isop(LIR_fsub) || s0->isop(LIR_fmul)) {
|
||||
|
@ -658,29 +655,27 @@ public:
|
|||
}
|
||||
if (isi2f(s0) || isu2f(s0))
|
||||
return iu2fArg(s0);
|
||||
// XXX ARM -- check for qjoin(call(F_UnboxDouble),call(F_UnboxDouble))
|
||||
if (s0->isCall() && s0->fid() == F_UnboxDouble) {
|
||||
// XXX ARM -- check for qjoin(call(UnboxDouble),call(UnboxDouble))
|
||||
if (s0->isCall() && s0->callInfo() == &ci_UnboxDouble) {
|
||||
LIns* args2[] = { callArgN(s0, 0) };
|
||||
return out->insCall(F_UnboxInt32, args2);
|
||||
return out->insCall(&ci_UnboxInt32, args2);
|
||||
}
|
||||
if (s0->isCall() && s0->fid() == F_StringToNumber) {
|
||||
if (s0->isCall() && s0->callInfo() == &ci_StringToNumber) {
|
||||
// callArgN's ordering is that as seen by the builtin, not as stored in args here.
|
||||
// True story!
|
||||
LIns* args2[] = { callArgN(s0, 1), callArgN(s0, 0) };
|
||||
return out->insCall(F_StringToInt32, args2);
|
||||
return out->insCall(&ci_StringToInt32, args2);
|
||||
}
|
||||
break;
|
||||
case F_BoxDouble:
|
||||
} else if (ci == &ci_BoxDouble) {
|
||||
JS_ASSERT(s0->isQuad());
|
||||
if (s0->isop(LIR_i2f)) {
|
||||
LIns* args2[] = { s0->oprnd1(), args[1] };
|
||||
return out->insCall(F_BoxInt32, args2);
|
||||
return out->insCall(&ci_BoxInt32, args2);
|
||||
}
|
||||
if (s0->isCall() && s0->fid() == F_UnboxDouble)
|
||||
if (s0->isCall() && s0->callInfo() == &ci_UnboxDouble)
|
||||
return callArgN(s0, 0);
|
||||
break;
|
||||
}
|
||||
return out->insCall(fid, args);
|
||||
return out->insCall(ci, args);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1942,7 +1937,7 @@ TraceRecorder::emitTreeCall(Fragment* inner, GuardRecord* lr)
|
|||
TreeInfo* ti = (TreeInfo*)inner->vmprivate;
|
||||
/* Invoke the inner tree. */
|
||||
LIns* args[] = { INS_CONSTPTR(inner), lirbuf->state }; /* reverse order */
|
||||
LIns* ret = lir->insCall(F_CallTree, args);
|
||||
LIns* ret = lir->insCall(&ci_CallTree, args);
|
||||
/* Read back all registers, in case the called tree changed any of them. */
|
||||
SideExit* exit = lr->exit;
|
||||
import(ti, inner_sp_ins, exit->numGlobalSlots, exit->calldepth,
|
||||
|
@ -2277,9 +2272,9 @@ js_RecordTree(JSContext* cx, JSTraceMonitor* tm, Fragment* f)
|
|||
f->root = f;
|
||||
/* allocate space to store the LIR for this tree */
|
||||
if (!f->lirbuf) {
|
||||
f->lirbuf = new (&gc) LirBuffer(tm->fragmento, builtins);
|
||||
f->lirbuf = new (&gc) LirBuffer(tm->fragmento, NULL);
|
||||
#ifdef DEBUG
|
||||
f->lirbuf->names = new (&gc) LirNameMap(&gc, builtins, tm->fragmento->labels);
|
||||
f->lirbuf->names = new (&gc) LirNameMap(&gc, NULL, tm->fragmento->labels);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2881,7 +2876,6 @@ js_InitJIT(JSTraceMonitor *tm)
|
|||
JS_ASSERT(!tm->globalSlots && !tm->globalTypeMap && !tm->recoveryDoublePool);
|
||||
Fragmento* fragmento = new (&gc) Fragmento(core, 24);
|
||||
verbose_only(fragmento->labels = new (&gc) LabelMap(core, NULL);)
|
||||
fragmento->assm()->setCallTable(builtins);
|
||||
tm->fragmento = fragmento;
|
||||
tm->globalSlots = new (&gc) SlotList();
|
||||
tm->globalTypeMap = new (&gc) TypeMap();
|
||||
|
@ -3084,7 +3078,7 @@ TraceRecorder::stack(int n, LIns* i)
|
|||
|
||||
LIns* TraceRecorder::f2i(LIns* f)
|
||||
{
|
||||
return lir->insCall(F_DoubleToInt32, &f);
|
||||
return lir->insCall(&ci_DoubleToInt32, &f);
|
||||
}
|
||||
|
||||
LIns* TraceRecorder::makeNumberInt32(LIns* f)
|
||||
|
@ -3158,7 +3152,7 @@ TraceRecorder::switchop()
|
|||
} else if (JSVAL_IS_STRING(v)) {
|
||||
LIns* args[] = { v_ins, INS_CONSTPTR(JSVAL_TO_STRING(v)) };
|
||||
guard(true,
|
||||
addName(lir->ins_eq0(lir->ins_eq0(lir->insCall(F_EqualStrings, args))),
|
||||
addName(lir->ins_eq0(lir->ins_eq0(lir->insCall(&ci_EqualStrings, args))),
|
||||
"guard(switch on string)"),
|
||||
BRANCH_EXIT);
|
||||
} else if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
|
||||
|
@ -3326,9 +3320,9 @@ TraceRecorder::cmp(LOpcode op, int flags)
|
|||
} else {
|
||||
LIns* args[] = { r_ins, l_ins };
|
||||
if (op == LIR_feq)
|
||||
l_ins = lir->ins_eq0(lir->insCall(F_EqualStrings, args));
|
||||
l_ins = lir->ins_eq0(lir->insCall(&ci_EqualStrings, args));
|
||||
else
|
||||
l_ins = lir->insCall(F_CompareStrings, args);
|
||||
l_ins = lir->insCall(&ci_CompareStrings, args);
|
||||
r_ins = lir->insImm(0);
|
||||
cond = evalCmp(op, JSVAL_TO_STRING(l), JSVAL_TO_STRING(r));
|
||||
}
|
||||
|
@ -3347,7 +3341,7 @@ TraceRecorder::cmp(LOpcode op, int flags)
|
|||
u.d = js_NaN;
|
||||
l_ins = lir->insImmq(u.u64);
|
||||
} else if (JSVAL_IS_STRING(l)) {
|
||||
l_ins = lir->insCall(F_StringToNumber, args);
|
||||
l_ins = lir->insCall(&ci_StringToNumber, args);
|
||||
} else if (JSVAL_TAG(l) == JSVAL_BOOLEAN) {
|
||||
/*
|
||||
* What I really want here is for undefined to be type-specialized
|
||||
|
@ -3356,7 +3350,7 @@ TraceRecorder::cmp(LOpcode op, int flags)
|
|||
* branched. Failing that, I want to be able to ins_choose on quads
|
||||
* without cmov. Failing that, eat flaming builtin!
|
||||
*/
|
||||
l_ins = lir->insCall(F_BooleanToNumber, args);
|
||||
l_ins = lir->insCall(&ci_BooleanToNumber, args);
|
||||
} else if (!isNumber(l)) {
|
||||
ABORT_TRACE("unsupported LHS type for cmp vs number");
|
||||
}
|
||||
|
@ -3369,10 +3363,10 @@ TraceRecorder::cmp(LOpcode op, int flags)
|
|||
u.d = js_NaN;
|
||||
r_ins = lir->insImmq(u.u64);
|
||||
} else if (JSVAL_IS_STRING(r)) {
|
||||
r_ins = lir->insCall(F_StringToNumber, args);
|
||||
r_ins = lir->insCall(&ci_StringToNumber, args);
|
||||
} else if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
|
||||
// See above for the sob story.
|
||||
r_ins = lir->insCall(F_BooleanToNumber, args);
|
||||
r_ins = lir->insCall(&ci_BooleanToNumber, args);
|
||||
} else if (!isNumber(r)) {
|
||||
ABORT_TRACE("unsupported RHS type for cmp vs number");
|
||||
}
|
||||
|
@ -3483,20 +3477,20 @@ TraceRecorder::binary(LOpcode op)
|
|||
if (JSVAL_IS_STRING(l)) {
|
||||
args[0] = a;
|
||||
args[1] = cx_ins;
|
||||
a = lir->insCall(F_StringToNumber, args);
|
||||
a = lir->insCall(&ci_StringToNumber, args);
|
||||
leftNumber = true;
|
||||
}
|
||||
if (JSVAL_IS_STRING(r)) {
|
||||
args[0] = b;
|
||||
args[1] = cx_ins;
|
||||
b = lir->insCall(F_StringToNumber, args);
|
||||
b = lir->insCall(&ci_StringToNumber, args);
|
||||
rightNumber = true;
|
||||
}
|
||||
}
|
||||
if (leftNumber && rightNumber) {
|
||||
if (intop) {
|
||||
LIns *args[] = { a };
|
||||
a = lir->insCall(op == LIR_ush ? F_DoubleToUint32 : F_DoubleToInt32, args);
|
||||
a = lir->insCall(op == LIR_ush ? &ci_DoubleToUint32 : &ci_DoubleToInt32, args);
|
||||
b = f2i(b);
|
||||
}
|
||||
a = lir->ins2(op, a, b);
|
||||
|
@ -3781,7 +3775,7 @@ TraceRecorder::box_jsval(jsval v, LIns*& v_ins)
|
|||
{
|
||||
if (isNumber(v)) {
|
||||
LIns* args[] = { v_ins, cx_ins };
|
||||
v_ins = lir->insCall(F_BoxDouble, args);
|
||||
v_ins = lir->insCall(&ci_BoxDouble, args);
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)),
|
||||
OOM_EXIT);
|
||||
return true;
|
||||
|
@ -3813,7 +3807,7 @@ TraceRecorder::unbox_jsval(jsval v, LIns*& v_ins)
|
|||
JSVAL_DOUBLE))),
|
||||
MISMATCH_EXIT);
|
||||
LIns* args[] = { v_ins };
|
||||
v_ins = lir->insCall(F_UnboxDouble, args);
|
||||
v_ins = lir->insCall(&ci_UnboxDouble, args);
|
||||
return true;
|
||||
}
|
||||
switch (JSVAL_TAG(v)) {
|
||||
|
@ -4113,7 +4107,7 @@ TraceRecorder::record_JSOP_ARGUMENTS()
|
|||
ABORT_TRACE("can't trace arguments yet");
|
||||
#else
|
||||
LIns* args[] = { cx_ins };
|
||||
LIns* a_ins = lir->insCall(F_Arguments, args);
|
||||
LIns* a_ins = lir->insCall(&ci_Arguments, args);
|
||||
guard(false, lir->ins_eq0(a_ins), OOM_EXIT);
|
||||
stack(0, a_ins);
|
||||
return true;
|
||||
|
@ -4225,15 +4219,15 @@ TraceRecorder::record_JSOP_ADD()
|
|||
} else {
|
||||
LIns* args2[] = { get(&r), cx_ins };
|
||||
if (JSVAL_IS_NUMBER(r)) {
|
||||
args[0] = lir->insCall(F_NumberToString, args2);
|
||||
args[0] = lir->insCall(&ci_NumberToString, args2);
|
||||
} else if (JSVAL_IS_OBJECT(r)) {
|
||||
args[0] = lir->insCall(F_ObjectToString, args2);
|
||||
args[0] = lir->insCall(&ci_ObjectToString, args2);
|
||||
} else {
|
||||
ABORT_TRACE("untraceable right operand to string-JSOP_ADD");
|
||||
}
|
||||
guard(false, lir->ins_eq0(args[0]), OOM_EXIT);
|
||||
}
|
||||
LIns* concat = lir->insCall(F_ConcatStrings, args);
|
||||
LIns* concat = lir->insCall(&ci_ConcatStrings, args);
|
||||
guard(false, lir->ins_eq0(concat), OOM_EXIT);
|
||||
set(&l, concat);
|
||||
return true;
|
||||
|
@ -4271,12 +4265,12 @@ TraceRecorder::record_JSOP_MOD()
|
|||
/* We can't demote this in a filter since we need the actual values of l and r. */
|
||||
if (isPromote(l_ins) && isPromote(r_ins) && asNumber(l) >= 0 && asNumber(r) > 0) {
|
||||
LIns* args[] = { ::demote(lir, r_ins), ::demote(lir, l_ins) };
|
||||
x = lir->insCall(F_imod, args);
|
||||
x = lir->insCall(&ci_imod, args);
|
||||
guard(false, lir->ins2(LIR_eq, x, lir->insImm(-1)), BRANCH_EXIT);
|
||||
x = lir->ins1(LIR_i2f, x);
|
||||
} else {
|
||||
LIns* args[] = { r_ins, l_ins };
|
||||
x = lir->insCall(F_dmod, args);
|
||||
x = lir->insCall(&ci_dmod, args);
|
||||
}
|
||||
set(&l, x);
|
||||
return true;
|
||||
|
@ -4382,19 +4376,19 @@ TraceRecorder::record_JSOP_NEW()
|
|||
|
||||
if (FUN_INTERPRETED(fun)) {
|
||||
LIns* args[] = { get(&fval), cx_ins };
|
||||
LIns* tv_ins = lir->insCall(F_FastNewObject, args);
|
||||
LIns* tv_ins = lir->insCall(&ci_FastNewObject, args);
|
||||
guard(false, lir->ins_eq0(tv_ins), OOM_EXIT);
|
||||
set(&tval, tv_ins);
|
||||
return interpretedFunctionCall(fval, fun, argc, true);
|
||||
}
|
||||
|
||||
static JSTraceableNative knownNatives[] = {
|
||||
{ (JSFastNative)js_Array, F_FastNewArray, "pC", "", FAIL_NULL },
|
||||
{ (JSFastNative)js_Array, F_Array_1int, "pC", "i", FAIL_NULL },
|
||||
{ (JSFastNative)js_Array, F_Array_2obj, "pC", "oo", FAIL_NULL },
|
||||
{ (JSFastNative)js_Array, F_Array_3num, "pC", "ddd", FAIL_NULL },
|
||||
{ (JSFastNative)js_Object, F_FastNewObject, "fC", "", FAIL_NULL },
|
||||
{ (JSFastNative)js_Date, F_FastNewDate, "pC", "", FAIL_NULL },
|
||||
{ (JSFastNative)js_Array, &ci_FastNewArray, "pC", "", FAIL_NULL },
|
||||
{ (JSFastNative)js_Array, &ci_Array_1int, "pC", "i", FAIL_NULL },
|
||||
{ (JSFastNative)js_Array, &ci_Array_2obj, "pC", "oo", FAIL_NULL },
|
||||
{ (JSFastNative)js_Array, &ci_Array_3num, "pC", "ddd", FAIL_NULL },
|
||||
{ (JSFastNative)js_Object, &ci_FastNewObject, "fC", "", FAIL_NULL },
|
||||
{ (JSFastNative)js_Date, &ci_FastNewDate, "pC", "", FAIL_NULL },
|
||||
};
|
||||
|
||||
for (uintN i = 0; i < JS_ARRAY_LENGTH(knownNatives); i++) {
|
||||
|
@ -4506,7 +4500,7 @@ TraceRecorder::record_JSOP_NEW()
|
|||
#endif
|
||||
|
||||
LIns* res_ins = lir->insCall(known->builtin, args);
|
||||
switch (known->errtype) {
|
||||
switch (JSTN_ERRTYPE(known)) {
|
||||
case FAIL_NULL:
|
||||
guard(false, lir->ins_eq0(res_ins), OOM_EXIT);
|
||||
break;
|
||||
|
@ -4527,7 +4521,7 @@ TraceRecorder::record_JSOP_NEW()
|
|||
return true;
|
||||
}
|
||||
|
||||
if (fun->u.n.clasp)
|
||||
if (!(fun->flags & JSFUN_TRACEABLE) && FUN_CLASP(fun))
|
||||
ABORT_TRACE("can't trace native constructor");
|
||||
|
||||
ABORT_TRACE("can't trace unknown constructor");
|
||||
|
@ -4566,10 +4560,10 @@ TraceRecorder::record_JSOP_TYPEOF()
|
|||
// We specialize identically for boolean and undefined. We must not have a hole here.
|
||||
// Pass the unboxed type here, since TypeOfBoolean knows how to handle it.
|
||||
JS_ASSERT(JSVAL_TO_BOOLEAN(r) <= 2);
|
||||
type = lir->insCall(F_TypeOfBoolean, args);
|
||||
type = lir->insCall(&ci_TypeOfBoolean, args);
|
||||
} else {
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(r));
|
||||
type = lir->insCall(F_TypeOfObject, args);
|
||||
type = lir->insCall(&ci_TypeOfObject, args);
|
||||
}
|
||||
}
|
||||
set(&r, type);
|
||||
|
@ -4583,12 +4577,6 @@ TraceRecorder::record_JSOP_VOID()
|
|||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_num_parseFloat(JSContext* cx, uintN argc, jsval* vp);
|
||||
|
||||
JSBool
|
||||
js_num_parseInt(JSContext* cx, uintN argc, jsval* vp);
|
||||
|
||||
bool
|
||||
TraceRecorder::record_JSOP_INCNAME()
|
||||
{
|
||||
|
@ -4735,7 +4723,7 @@ TraceRecorder::record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop
|
|||
|
||||
if (entry->kshape != PCVCAP_SHAPE(entry->vcap)) {
|
||||
LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins };
|
||||
LIns* ok_ins = lir->insCall(F_AddProperty, args);
|
||||
LIns* ok_ins = lir->insCall(&ci_AddProperty, args);
|
||||
guard(false, lir->ins_eq0(ok_ins), OOM_EXIT);
|
||||
}
|
||||
|
||||
|
@ -4787,7 +4775,7 @@ TraceRecorder::record_JSOP_GETELEM()
|
|||
ABORT_TRACE("Invalid string index in JSOP_GETELEM");
|
||||
idx_ins = makeNumberInt32(idx_ins);
|
||||
LIns* args[] = { idx_ins, obj_ins, cx_ins };
|
||||
LIns* unitstr_ins = lir->insCall(F_String_getelem, args);
|
||||
LIns* unitstr_ins = lir->insCall(&ci_String_getelem, args);
|
||||
guard(false, lir->ins_eq0(unitstr_ins), MISMATCH_EXIT);
|
||||
set(&lval, unitstr_ins);
|
||||
return true;
|
||||
|
@ -4817,7 +4805,7 @@ TraceRecorder::record_JSOP_GETELEM()
|
|||
return false;
|
||||
}
|
||||
LIns* args[] = { idx_ins, obj_ins, cx_ins };
|
||||
v_ins = lir->insCall(F_Any_getprop, args);
|
||||
v_ins = lir->insCall(&ci_Any_getprop, args);
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), MISMATCH_EXIT);
|
||||
if (!unbox_jsval(v, v_ins))
|
||||
ABORT_TRACE("JSOP_GETELEM");
|
||||
|
@ -4840,7 +4828,7 @@ TraceRecorder::record_JSOP_GETELEM()
|
|||
idx = ID_TO_VALUE(id);
|
||||
if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, getProperty), &v))
|
||||
return false;
|
||||
LIns* v_ins = lir->insCall(F_Any_getelem, args);
|
||||
LIns* v_ins = lir->insCall(&ci_Any_getelem, args);
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), MISMATCH_EXIT);
|
||||
if (!unbox_jsval(v, v_ins))
|
||||
ABORT_TRACE("JSOP_GETELEM");
|
||||
|
@ -4885,8 +4873,8 @@ TraceRecorder::record_JSOP_SETELEM()
|
|||
if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, setProperty), NULL))
|
||||
return false;
|
||||
LIns* args[] = { boxed_v_ins, idx_ins, obj_ins, cx_ins };
|
||||
LIns* ok_ins = lir->insCall(F_Any_setprop, args);
|
||||
guard(false, lir->ins_eq0(ok_ins), MISMATCH_EXIT);
|
||||
LIns* ok_ins = lir->insCall(&ci_Any_setprop, args);
|
||||
guard(false, lir->ins_eq0(ok_ins), MISMATCH_EXIT);
|
||||
} else if (JSVAL_IS_INT(idx)) {
|
||||
if (JSVAL_TO_INT(idx) < 0)
|
||||
ABORT_TRACE("negative JSOP_SETELEM index");
|
||||
|
@ -4894,14 +4882,14 @@ TraceRecorder::record_JSOP_SETELEM()
|
|||
LIns* args[] = { boxed_v_ins, idx_ins, obj_ins, cx_ins };
|
||||
LIns* res_ins;
|
||||
if (guardDenseArray(obj, obj_ins)) {
|
||||
res_ins = lir->insCall(F_Array_dense_setelem, args);
|
||||
res_ins = lir->insCall(&ci_Array_dense_setelem, args);
|
||||
} else {
|
||||
if (!js_IndexToId(cx, JSVAL_TO_INT(idx), &id))
|
||||
return false;
|
||||
idx = ID_TO_VALUE(id);
|
||||
if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, setProperty), NULL))
|
||||
return false;
|
||||
res_ins = lir->insCall(F_Any_setelem, args);
|
||||
res_ins = lir->insCall(&ci_Any_setelem, args);
|
||||
}
|
||||
guard(false, lir->ins_eq0(res_ins), MISMATCH_EXIT);
|
||||
} else {
|
||||
|
@ -5021,24 +5009,7 @@ TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc,
|
|||
return true;
|
||||
}
|
||||
|
||||
#define KNOWN_NATIVE_DECL(name) JSBool name(JSContext* cx, uintN argc, jsval* vp);
|
||||
|
||||
KNOWN_NATIVE_DECL(js_fun_apply)
|
||||
KNOWN_NATIVE_DECL(js_math_ceil)
|
||||
KNOWN_NATIVE_DECL(js_math_cos)
|
||||
KNOWN_NATIVE_DECL(js_math_floor)
|
||||
KNOWN_NATIVE_DECL(js_math_log)
|
||||
KNOWN_NATIVE_DECL(js_math_max)
|
||||
KNOWN_NATIVE_DECL(js_math_pow)
|
||||
KNOWN_NATIVE_DECL(js_math_random)
|
||||
KNOWN_NATIVE_DECL(js_math_sin)
|
||||
KNOWN_NATIVE_DECL(js_math_sqrt)
|
||||
KNOWN_NATIVE_DECL(js_num_toString)
|
||||
KNOWN_NATIVE_DECL(js_str_charAt)
|
||||
KNOWN_NATIVE_DECL(js_str_charCodeAt)
|
||||
KNOWN_NATIVE_DECL(js_str_concat)
|
||||
KNOWN_NATIVE_DECL(js_str_fromCharCode)
|
||||
KNOWN_NATIVE_DECL(js_str_substring)
|
||||
JSBool js_fun_apply(JSContext* cx, uintN argc, jsval* vp);
|
||||
|
||||
bool
|
||||
TraceRecorder::record_JSOP_CALL()
|
||||
|
@ -5075,48 +5046,6 @@ TraceRecorder::record_JSOP_CALL()
|
|||
if (FUN_SLOW_NATIVE(fun))
|
||||
ABORT_TRACE("slow native");
|
||||
|
||||
static JSTraceableNative knownNatives[] = {
|
||||
{ js_array_join, F_Array_p_join, "TC", "s", FAIL_NULL },
|
||||
{ js_array_push, F_Array_p_push1, "TC", "v", FAIL_JSVAL },
|
||||
{ js_array_pop, F_Array_p_pop, "TC", "", FAIL_JSVAL },
|
||||
{ js_math_sin, F_Math_sin, "", "d", INFALLIBLE },
|
||||
{ js_math_cos, F_Math_cos, "", "d", INFALLIBLE },
|
||||
{ js_math_pow, F_Math_pow, "", "dd", INFALLIBLE },
|
||||
{ js_math_sqrt, F_Math_sqrt, "", "d", INFALLIBLE },
|
||||
{ js_math_floor, F_Math_floor, "", "d", INFALLIBLE },
|
||||
{ js_math_ceil, F_Math_ceil, "", "d", INFALLIBLE },
|
||||
{ js_math_random, F_Math_random, "R", "", INFALLIBLE },
|
||||
{ js_math_log, F_Math_log, "", "d", INFALLIBLE },
|
||||
{ js_math_max, F_Math_max, "", "dd", INFALLIBLE },
|
||||
{ js_num_parseInt, F_ParseInt, "C", "s", INFALLIBLE },
|
||||
{ js_num_parseInt, F_ParseIntDouble, "", "d", INFALLIBLE },
|
||||
{ js_num_parseFloat, F_ParseFloat, "C", "s", INFALLIBLE },
|
||||
{ js_num_toString, F_NumberToString, "TC", "", FAIL_NULL },
|
||||
{ js_obj_hasOwnProperty, F_Object_p_hasOwnProperty,
|
||||
"TC", "s", FAIL_VOID },
|
||||
{ js_obj_propertyIsEnumerable, F_Object_p_propertyIsEnumerable,
|
||||
"TC", "s", FAIL_VOID },
|
||||
{ js_str_charAt, F_String_getelem, "SC", "i", FAIL_NULL },
|
||||
{ js_str_charCodeAt, F_String_p_charCodeAt, "S", "i", FAIL_NEG },
|
||||
{ js_str_concat, F_String_p_concat_1int, "SC", "i", FAIL_NULL },
|
||||
{ js_str_concat, F_ConcatStrings, "SC", "s", FAIL_NULL },
|
||||
{ js_str_concat, F_String_p_concat_2str, "SC", "ss", FAIL_NULL },
|
||||
{ js_str_concat, F_String_p_concat_3str, "SC", "sss", FAIL_NULL },
|
||||
{ js_str_fromCharCode, F_String_fromCharCode, "C", "i", FAIL_NULL },
|
||||
{ js_str_match, F_String_p_match, "PSC", "r", FAIL_VOID },
|
||||
{ js_str_match, F_String_p_match_obj, "PTC", "r", FAIL_VOID },
|
||||
{ js_str_replace, F_String_p_replace_str, "SC", "sr", FAIL_NULL },
|
||||
{ js_str_replace, F_String_p_replace_str2,"SC", "ss", FAIL_NULL },
|
||||
{ js_str_replace, F_String_p_replace_str3,"SC", "sss", FAIL_NULL },
|
||||
{ js_str_split, F_String_p_split, "SC", "s", FAIL_NULL },
|
||||
{ js_str_substring, F_String_p_substring, "SC", "ii", FAIL_NULL },
|
||||
{ js_str_substring, F_String_p_substring_1, "SC", "i", FAIL_NULL },
|
||||
{ js_str_toLowerCase, F_toLowerCase, "SC", "", FAIL_NULL },
|
||||
{ js_str_toUpperCase, F_toUpperCase, "SC", "", FAIL_NULL },
|
||||
{ js_date_now, F_Date_now, "C", "", INFALLIBLE },
|
||||
};
|
||||
|
||||
uintN i = 0;
|
||||
LIns* arg1_ins = NULL;
|
||||
jsval arg1 = JSVAL_VOID;
|
||||
jsval thisval = tval;
|
||||
|
@ -5142,7 +5071,7 @@ TraceRecorder::record_JSOP_CALL()
|
|||
if (!aval_ins->isCall())
|
||||
ABORT_TRACE("can't trace Function.prototype.apply on non-builtin-call 2nd arg");
|
||||
|
||||
if (aval_ins->fid() == F_Arguments) {
|
||||
if (aval_ins->callInfo() == &ci_Arguments) {
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, aobj) == &js_ArgumentsClass);
|
||||
JS_ASSERT(OBJ_GET_PRIVATE(cx, aobj) == fp);
|
||||
if (!FUN_INTERPRETED(tfun))
|
||||
|
@ -5177,7 +5106,7 @@ TraceRecorder::record_JSOP_CALL()
|
|||
return interpretedFunctionCall(tval, tfun, argc, false);
|
||||
}
|
||||
|
||||
if (aval_ins->fid() != F_Array_1str)
|
||||
if (aval_ins->callInfo() != &ci_Array_1str)
|
||||
ABORT_TRACE("can't trace Function.prototype.apply on other than [str] 2nd arg");
|
||||
|
||||
JS_ASSERT(OBJ_IS_ARRAY(cx, aobj));
|
||||
|
@ -5187,16 +5116,8 @@ TraceRecorder::record_JSOP_CALL()
|
|||
if (FUN_INTERPRETED(tfun))
|
||||
ABORT_TRACE("can't trace Function.prototype.apply for scripted functions");
|
||||
|
||||
JSTraceableNative* known;
|
||||
for (;;) {
|
||||
known = &knownNatives[i];
|
||||
if (known->native == (JSFastNative)tfun->u.n.native)
|
||||
break;
|
||||
if (++i == JS_ARRAY_LENGTH(knownNatives))
|
||||
ABORT_TRACE("unknown native being Function.prototype.apply'ed");
|
||||
}
|
||||
if (strlen(known->argtypes) != 1)
|
||||
ABORT_TRACE("known native being Function.prototype.apply'ed with wrong argc");
|
||||
if (!(tfun->flags & JSFUN_TRACEABLE))
|
||||
ABORT_TRACE("Function.prototype.apply on untraceable native");
|
||||
|
||||
thisval = oval;
|
||||
this_ins = get(&oval);
|
||||
|
@ -5206,11 +5127,11 @@ TraceRecorder::record_JSOP_CALL()
|
|||
argc = 1;
|
||||
}
|
||||
|
||||
for (; i < JS_ARRAY_LENGTH(knownNatives); i++) {
|
||||
JSTraceableNative* known = &knownNatives[i];
|
||||
if (known->native != (JSFastNative)fun->u.n.native)
|
||||
continue;
|
||||
if (!(fun->flags & JSFUN_TRACEABLE))
|
||||
ABORT_TRACE("untraceable native");
|
||||
|
||||
JSTraceableNative* known = FUN_TRCINFO(fun);
|
||||
do {
|
||||
uintN knownargc = strlen(known->argtypes);
|
||||
if (argc != knownargc)
|
||||
continue;
|
||||
|
@ -5324,7 +5245,7 @@ TraceRecorder::record_JSOP_CALL()
|
|||
* If we got this far, and we have a charCodeAt, check that charCodeAt
|
||||
* isn't going to return a NaN.
|
||||
*/
|
||||
if (known->builtin == F_String_p_charCodeAt) {
|
||||
if (known->builtin == &ci_String_p_charCodeAt) {
|
||||
JSString* str = JSVAL_TO_STRING(thisval);
|
||||
jsval& arg = arg1_ins ? arg1 : stackval(-1);
|
||||
|
||||
|
@ -5349,7 +5270,7 @@ TraceRecorder::record_JSOP_CALL()
|
|||
|
||||
rval_ins = lir->insCall(known->builtin, args);
|
||||
|
||||
switch (known->errtype) {
|
||||
switch (JSTN_ERRTYPE(known)) {
|
||||
case FAIL_NULL:
|
||||
guard(false, lir->ins_eq0(rval_ins), OOM_EXIT);
|
||||
break;
|
||||
|
@ -5377,9 +5298,8 @@ TraceRecorder::record_JSOP_CALL()
|
|||
pendingTraceableNative = known;
|
||||
|
||||
return true;
|
||||
}
|
||||
} while ((known++)->flags & JSTN_MORE);
|
||||
|
||||
/* Didn't find it. */
|
||||
ABORT_TRACE("unknown native");
|
||||
}
|
||||
|
||||
|
@ -5405,7 +5325,7 @@ TraceRecorder::record_FastNativeCallComplete()
|
|||
LIns* v_ins = get(&v);
|
||||
|
||||
bool ok = true;
|
||||
if (pendingTraceableNative->errtype == FAIL_JSVAL) {
|
||||
if (JSTN_ERRTYPE(pendingTraceableNative) == FAIL_JSVAL) {
|
||||
ok = unbox_jsval(v, v_ins);
|
||||
if (ok)
|
||||
set(&v, v_ins);
|
||||
|
@ -5508,7 +5428,7 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32& slot, LIns*& v_ins)
|
|||
if (sprop->shortid == REGEXP_LAST_INDEX)
|
||||
ABORT_TRACE("can't trace regexp.lastIndex yet");
|
||||
LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins };
|
||||
v_ins = lir->insCall(F_CallGetter, args);
|
||||
v_ins = lir->insCall(&ci_CallGetter, args);
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), OOM_EXIT);
|
||||
if (!unbox_jsval((sprop->shortid == REGEXP_SOURCE) ? JSVAL_STRING : JSVAL_BOOLEAN,
|
||||
v_ins)) {
|
||||
|
@ -5791,11 +5711,11 @@ TraceRecorder::record_JSOP_NEWINIT()
|
|||
{
|
||||
JSProtoKey key = JSProtoKey(GET_INT8(cx->fp->regs->pc));
|
||||
JSObject* obj;
|
||||
uint32 fid;
|
||||
const CallInfo *ci;
|
||||
if (key == JSProto_Array) {
|
||||
if (!js_GetClassPrototype(cx, globalObj, INT_TO_JSID(key), &obj))
|
||||
return false;
|
||||
fid = F_FastNewArray;
|
||||
ci = &ci_FastNewArray;
|
||||
} else {
|
||||
jsval v_obj;
|
||||
if (!js_FindClassObject(cx, globalObj, INT_TO_JSID(key), &v_obj))
|
||||
|
@ -5803,10 +5723,10 @@ TraceRecorder::record_JSOP_NEWINIT()
|
|||
if (JSVAL_IS_PRIMITIVE(v_obj))
|
||||
ABORT_TRACE("primitive Object value");
|
||||
obj = JSVAL_TO_OBJECT(v_obj);
|
||||
fid = F_FastNewObject;
|
||||
ci = &ci_FastNewObject;
|
||||
}
|
||||
LIns* args[] = { INS_CONSTPTR(obj), cx_ins };
|
||||
LIns* v_ins = lir->insCall(fid, args);
|
||||
LIns* v_ins = lir->insCall(ci, args);
|
||||
guard(false, lir->ins_eq0(v_ins), OOM_EXIT);
|
||||
stack(0, v_ins);
|
||||
return true;
|
||||
|
@ -5823,9 +5743,9 @@ TraceRecorder::record_JSOP_ENDINIT()
|
|||
if (obj->fslots[JSSLOT_ARRAY_LENGTH] == 1 &&
|
||||
obj->dslots && JSVAL_IS_STRING(obj->dslots[0])) {
|
||||
LIns* v_ins = get(&v);
|
||||
JS_ASSERT(v_ins->isCall() && v_ins->fid() == F_FastNewArray);
|
||||
JS_ASSERT(v_ins->isCall() && v_ins->callInfo() == &ci_FastNewArray);
|
||||
LIns* args[] = { stack(1), callArgN(v_ins, 1), cx_ins };
|
||||
v_ins = lir->insCall(F_Array_1str, args);
|
||||
v_ins = lir->insCall(&ci_Array_1str, args);
|
||||
set(&v, v_ins);
|
||||
}
|
||||
}
|
||||
|
@ -5912,7 +5832,7 @@ TraceRecorder::record_JSOP_ITER()
|
|||
if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
jsuint flags = cx->fp->regs->pc[1];
|
||||
LIns* args[] = { get(&v), INS_CONST(flags), cx_ins };
|
||||
LIns* v_ins = lir->insCall(F_FastValueToIterator, args);
|
||||
LIns* v_ins = lir->insCall(&ci_FastValueToIterator, args);
|
||||
guard(false, lir->ins_eq0(v_ins), MISMATCH_EXIT);
|
||||
set(&v, v_ins);
|
||||
return true;
|
||||
|
@ -5927,7 +5847,7 @@ TraceRecorder::forInLoop(jsval* vp)
|
|||
jsval& iterobj_val = stackval(-1);
|
||||
if (!JSVAL_IS_PRIMITIVE(iterobj_val)) {
|
||||
LIns* args[] = { get(&iterobj_val), cx_ins };
|
||||
LIns* v_ins = lir->insCall(F_FastCallIteratorNext, args);
|
||||
LIns* v_ins = lir->insCall(&ci_FastCallIteratorNext, args);
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), OOM_EXIT);
|
||||
|
||||
LIns* flag_ins = lir->ins_eq0(lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_HOLE)));
|
||||
|
@ -5950,7 +5870,7 @@ bool
|
|||
TraceRecorder::record_JSOP_ENDITER()
|
||||
{
|
||||
LIns* args[] = { stack(-1), cx_ins };
|
||||
LIns* ok_ins = lir->insCall(F_CloseIterator, args);
|
||||
LIns* ok_ins = lir->insCall(&ci_CloseIterator, args);
|
||||
guard(false, lir->ins_eq0(ok_ins), MISMATCH_EXIT);
|
||||
return true;
|
||||
}
|
||||
|
@ -6114,7 +6034,7 @@ TraceRecorder::record_JSOP_IN()
|
|||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
|
||||
LIns* args[] = { get(&lval), obj_ins, cx_ins };
|
||||
x = lir->insCall(F_HasNamedProperty, args);
|
||||
x = lir->insCall(&ci_HasNamedProperty, args);
|
||||
guard(false, lir->ins2i(LIR_eq, x, JSVAL_TO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
|
||||
x = lir->ins2i(LIR_eq, x, 1);
|
||||
} while (0);
|
||||
|
|
|
@ -49,23 +49,7 @@
|
|||
#include "jslock.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsinterp.h"
|
||||
|
||||
#include "nanojit/nanojit.h"
|
||||
|
||||
/*
|
||||
* We use a magic boxed pointer value to represent error conditions that
|
||||
* trigger a side exit. The address is so low that it should never be actually
|
||||
* in use. If it is, a performance regression occurs, not an actual runtime
|
||||
* error.
|
||||
*/
|
||||
#define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((void*)0x10)
|
||||
|
||||
/*
|
||||
* We also need a magic unboxed 32-bit integer that signals an error. Again if
|
||||
* this number is hit we experience a performance regression, not a runtime
|
||||
* error.
|
||||
*/
|
||||
#define INT32_ERROR_COOKIE 0xffffabcd
|
||||
#include "jsbuiltins.h"
|
||||
|
||||
template <typename T>
|
||||
class Queue : public GCObject {
|
||||
|
@ -200,17 +184,6 @@ public:
|
|||
fragment = _fragment;
|
||||
}
|
||||
};
|
||||
|
||||
extern struct nanojit::CallInfo builtins[];
|
||||
|
||||
enum JSTNErrType { INFALLIBLE, FAIL_NULL, FAIL_NEG, FAIL_VOID, FAIL_JSVAL };
|
||||
struct JSTraceableNative {
|
||||
JSFastNative native;
|
||||
int builtin;
|
||||
const char *prefix;
|
||||
const char *argtypes;
|
||||
JSTNErrType errtype;
|
||||
};
|
||||
|
||||
class TraceRecorder : public GCObject {
|
||||
JSContext* cx;
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace nanojit
|
|||
for (;;) {
|
||||
LInsp i = in->read();
|
||||
if (!i || i->isGuard()
|
||||
|| i->isCall() && !assm->_functions[i->fid()]._cse
|
||||
|| i->isCall() && !i->callInfo()->_cse
|
||||
|| !assm->ignoreInstruction(i))
|
||||
return i;
|
||||
}
|
||||
|
@ -312,12 +312,6 @@ namespace nanojit
|
|||
}
|
||||
#endif
|
||||
|
||||
const CallInfo* Assembler::callInfoFor(uint32_t fid)
|
||||
{
|
||||
NanoAssert(fid < CI_Max);
|
||||
return &_functions[fid];
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
void Assembler::resourceConsistencyCheck()
|
||||
|
|
|
@ -111,24 +111,6 @@ namespace nanojit
|
|||
// fargs = args - iargs
|
||||
};
|
||||
|
||||
#define FUNCTIONID(name) CI_avmplus_##name
|
||||
|
||||
#define INTERP_FOPCODE_LIST_BEGIN enum FunctionID {
|
||||
#define INTERP_FOPCODE_LIST_ENTRY_PRIM(nm)
|
||||
#define INTERP_FOPCODE_LIST_ENTRY_FUNCPRIM(nm,argtypes,cse,fold,ret,args) FUNCTIONID(nm),
|
||||
#define INTERP_FOPCODE_LIST_ENTRY_SUPER(nm,off)
|
||||
#define INTERP_FOPCODE_LIST_ENTRY_EXTERN(nm,off)
|
||||
#define INTERP_FOPCODE_LIST_ENTRY_LITC(nm,i)
|
||||
#define INTERP_FOPCODE_LIST_END CI_Max } ;
|
||||
#include "vm_fops.h"
|
||||
#undef INTERP_FOPCODE_LIST_BEGIN
|
||||
#undef INTERP_FOPCODE_LIST_ENTRY_PRIM
|
||||
#undef INTERP_FOPCODE_LIST_ENTRY_FUNCPRIM
|
||||
#undef INTERP_FOPCODE_LIST_ENTRY_SUPER
|
||||
#undef INTERP_FOPCODE_LIST_ENTRY_EXTERN
|
||||
#undef INTERP_FOPCODE_LIST_ENTRY_LITC
|
||||
#undef INTERP_FOPCODE_LIST_END
|
||||
|
||||
#ifdef AVMPLUS_WIN32
|
||||
#define AVMPLUS_ALIGN16(type) __declspec(align(16)) type
|
||||
#else
|
||||
|
@ -219,12 +201,6 @@ namespace nanojit
|
|||
|
||||
Stats _stats;
|
||||
|
||||
const CallInfo* callInfoFor(uint32_t fid);
|
||||
const CallInfo* callInfoFor(LInsp call)
|
||||
{
|
||||
return callInfoFor(call->fid());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void gen(LirFilter* toCompile, NInsList& loopJumps);
|
||||
|
|
|
@ -462,7 +462,7 @@ namespace nanojit
|
|||
#endif
|
||||
case LIR_call:
|
||||
case LIR_fcall:
|
||||
i -= argwords(i->argc())+1;
|
||||
i -= i->callInsWords();
|
||||
break;
|
||||
|
||||
case LIR_skip:
|
||||
|
@ -575,7 +575,7 @@ namespace nanojit
|
|||
|
||||
bool LIns::isCse(const CallInfo *functions) const
|
||||
{
|
||||
return nanojit::isCse(u.code) || isCall() && functions[fid()]._cse;
|
||||
return nanojit::isCse(u.code) || isCall() && callInfo()->_cse;
|
||||
}
|
||||
|
||||
void LIns::setimm16(int32_t x)
|
||||
|
@ -934,18 +934,15 @@ namespace nanojit
|
|||
ins2(LIR_and, iffalse, ins1(LIR_not, ncond)));
|
||||
}
|
||||
|
||||
LIns* LirBufWriter::insCall(uint32_t fid, LInsp args[])
|
||||
LIns* LirBufWriter::insCall(const CallInfo *ci, LInsp args[])
|
||||
{
|
||||
static const LOpcode k_callmap[] = { LIR_call, LIR_fcall, LIR_call, LIR_callh };
|
||||
|
||||
NanoAssert(fid < CI_Max);
|
||||
|
||||
const CallInfo& ci = _functions[fid];
|
||||
uint32_t argt = ci._argtypes;
|
||||
uint32_t argt = ci->_argtypes;
|
||||
LOpcode op = k_callmap[argt & 3];
|
||||
|
||||
ArgSize sizes[10];
|
||||
uint32_t argc = ci.get_sizes(sizes);
|
||||
uint32_t argc = ci->get_sizes(sizes);
|
||||
|
||||
#ifdef NJ_SOFTFLOAT
|
||||
if (op == LIR_fcall)
|
||||
|
@ -969,11 +966,13 @@ namespace nanojit
|
|||
|
||||
NanoAssert(argc < 8);
|
||||
uint32_t words = argwords(argc);
|
||||
ensureRoom(words+argc+1); // ins size + possible tramps
|
||||
ensureRoom(words+LIns::callInfoWords+1+argc); // ins size + possible tramps
|
||||
for (uint32_t i=0; i < argc; i++)
|
||||
args[i] = ensureReferenceable(args[i], argc-i);
|
||||
uint8_t* offs = (uint8_t*)_buf->next();
|
||||
LIns *l = _buf->next() + words;
|
||||
*(const CallInfo **)l = ci;
|
||||
l += LIns::callInfoWords;
|
||||
for (uint32_t i=0; i < argc; i++)
|
||||
offs[i] = (uint8_t) l->reference(args[i]);
|
||||
#if defined NANOJIT_64BIT
|
||||
|
@ -981,9 +980,9 @@ namespace nanojit
|
|||
#else
|
||||
l->initOpcode(op==LIR_callh ? LIR_call : op);
|
||||
#endif
|
||||
l->c.imm8a = fid;
|
||||
l->c.imm8a = 0;
|
||||
l->c.imm8b = argc;
|
||||
_buf->commit(words+1);
|
||||
_buf->commit(words+LIns::callInfoWords+1);
|
||||
_buf->_stats.lir++;
|
||||
return l;
|
||||
}
|
||||
|
@ -1117,7 +1116,7 @@ namespace nanojit
|
|||
NanoAssert(argc < 10);
|
||||
for (int32_t j=0; j < argc; j++)
|
||||
args[j] = i->arg(j);
|
||||
return hashcall(i->fid(), argc, args);
|
||||
return hashcall(i->callInfo(), argc, args);
|
||||
}
|
||||
default:
|
||||
if (operandCount[op] == 2)
|
||||
|
@ -1153,7 +1152,7 @@ namespace nanojit
|
|||
case LIR_callh:
|
||||
#endif
|
||||
{
|
||||
if (a->fid() != b->fid()) return false;
|
||||
if (a->callInfo() != b->callInfo()) return false;
|
||||
uint32_t argc=a->argc();
|
||||
NanoAssert(argc == b->argc());
|
||||
for (uint32_t i=0; i < argc; i++)
|
||||
|
@ -1251,8 +1250,8 @@ namespace nanojit
|
|||
return _hashfinish(_hashptr(hash, b));
|
||||
}
|
||||
|
||||
uint32_t LInsHashSet::hashcall(uint32_t fid, uint32_t argc, LInsp args[]) {
|
||||
uint32_t hash = _hash32(0,fid);
|
||||
uint32_t LInsHashSet::hashcall(const CallInfo *ci, uint32_t argc, LInsp args[]) {
|
||||
uint32_t hash = _hashptr(0, ci);
|
||||
for (int32_t j=argc-1; j >= 0; j--)
|
||||
hash = _hashptr(hash,args[j]);
|
||||
return _hashfinish(hash);
|
||||
|
@ -1334,16 +1333,16 @@ namespace nanojit
|
|||
return true;
|
||||
}
|
||||
|
||||
LInsp LInsHashSet::findcall(uint32_t fid, uint32_t argc, LInsp args[], uint32_t &i)
|
||||
LInsp LInsHashSet::findcall(const CallInfo *ci, uint32_t argc, LInsp args[], uint32_t &i)
|
||||
{
|
||||
uint32_t cap = m_list.size();
|
||||
const InsList& list = m_list;
|
||||
const uint32_t bitmask = (cap - 1) & ~0x1;
|
||||
uint32_t hash = hashcall(fid, argc, args) & bitmask;
|
||||
uint32_t hash = hashcall(ci, argc, args) & bitmask;
|
||||
uint32_t n = 7 << 1;
|
||||
LInsp k;
|
||||
while ((k = list.get(hash)) != NULL &&
|
||||
(!k->isCall() || k->fid() != fid || !argsmatch(k, argc, args)))
|
||||
(!k->isCall() || k->callInfo() != ci || !argsmatch(k, argc, args)))
|
||||
{
|
||||
hash = (hash + (n += 2)) & bitmask; // quadratic probe
|
||||
}
|
||||
|
@ -1424,8 +1423,7 @@ namespace nanojit
|
|||
total++;
|
||||
|
||||
// first handle side-effect instructions
|
||||
if (i->isStore() || i->isGuard() ||
|
||||
i->isCall() && !assm->callInfoFor(i->fid())->_cse)
|
||||
if (i->isStore() || i->isGuard() || i->isCall() && !i->callInfo()->_cse)
|
||||
{
|
||||
live.add(i,0);
|
||||
if (i->isGuard())
|
||||
|
@ -1559,7 +1557,7 @@ namespace nanojit
|
|||
ref = ref->oprnd1();
|
||||
} else {
|
||||
#endif
|
||||
copyName(ref, _functions[ref->fid()]._name, funccounts.add(ref->fid()));
|
||||
copyName(ref, ref->callInfo()->_name, funccounts.add(ref->callInfo()));
|
||||
#if !defined NANOJIT_64BIT
|
||||
}
|
||||
#endif
|
||||
|
@ -1609,7 +1607,7 @@ namespace nanojit
|
|||
#endif
|
||||
case LIR_fcall:
|
||||
case LIR_call: {
|
||||
sprintf(s, "%s ( ", _functions[i->fid()]._name);
|
||||
sprintf(s, "%s ( ", i->callInfo()->_name);
|
||||
for (int32_t j=i->argc()-1; j >= 0; j--) {
|
||||
s += strlen(s);
|
||||
sprintf(s, "%s ",formatRef(i->arg(j)));
|
||||
|
@ -1793,18 +1791,17 @@ namespace nanojit
|
|||
return out->insGuard(v, c, x);
|
||||
}
|
||||
|
||||
LInsp CseFilter::insCall(uint32_t fid, LInsp args[])
|
||||
LInsp CseFilter::insCall(const CallInfo *ci, LInsp args[])
|
||||
{
|
||||
const CallInfo *c = &_functions[fid];
|
||||
if (c->_cse) {
|
||||
if (ci->_cse) {
|
||||
uint32_t k;
|
||||
uint32_t argc = c->count_args();
|
||||
LInsp found = exprs.findcall(fid, argc, args, k);
|
||||
uint32_t argc = ci->count_args();
|
||||
LInsp found = exprs.findcall(ci, argc, args, k);
|
||||
if (found)
|
||||
return found;
|
||||
return exprs.add(out->insCall(fid, args), k);
|
||||
return exprs.add(out->insCall(ci, args), k);
|
||||
}
|
||||
return out->insCall(fid, args);
|
||||
return out->insCall(ci, args);
|
||||
}
|
||||
|
||||
CseReader::CseReader(LirFilter *in, LInsHashSet *exprs, const CallInfo *functions)
|
||||
|
|
|
@ -271,6 +271,15 @@ namespace nanojit
|
|||
sti_type sti;
|
||||
};
|
||||
|
||||
enum {
|
||||
callInfoWords =
|
||||
#ifdef NANOJIT_64BIT
|
||||
2
|
||||
#else
|
||||
1
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t reference(LIns*) const;
|
||||
LIns* deref(int32_t off) const;
|
||||
|
||||
|
@ -298,7 +307,7 @@ namespace nanojit
|
|||
inline LIns* arg(uint32_t i) {
|
||||
uint32_t c = argc();
|
||||
NanoAssert(i < c);
|
||||
uint8_t* offs = (uint8_t*) (this-argwords(c));
|
||||
uint8_t* offs = (uint8_t*) (this-callInfoWords-argwords(c));
|
||||
return deref(offs[i]);
|
||||
}
|
||||
|
||||
|
@ -399,14 +408,16 @@ namespace nanojit
|
|||
|
||||
SideExit *exit();
|
||||
|
||||
inline uint32_t argc() {
|
||||
inline uint32_t argc() const {
|
||||
NanoAssert(isCall());
|
||||
return c.imm8b;
|
||||
}
|
||||
inline uint8_t fid() const {
|
||||
NanoAssert(isCall());
|
||||
return c.imm8a;
|
||||
}
|
||||
inline size_t callInsWords() const {
|
||||
return argwords(argc()) + callInfoWords + 1;
|
||||
}
|
||||
inline const CallInfo *callInfo() const {
|
||||
return *(const CallInfo **) (this - callInfoWords);
|
||||
}
|
||||
};
|
||||
typedef LIns* LInsp;
|
||||
|
||||
|
@ -463,8 +474,8 @@ namespace nanojit
|
|||
return isS8(d) ? out->insStorei(value, base, d)
|
||||
: out->insStore(value, base, insImm(d));
|
||||
}
|
||||
virtual LInsp insCall(uint32_t fid, LInsp args[]) {
|
||||
return out->insCall(fid, args);
|
||||
virtual LInsp insCall(const CallInfo *call, LInsp args[]) {
|
||||
return out->insCall(call, args);
|
||||
}
|
||||
|
||||
// convenience
|
||||
|
@ -517,18 +528,22 @@ namespace nanojit
|
|||
|
||||
class LirNameMap MMGC_SUBCLASS_DECL
|
||||
{
|
||||
class CountMap: public avmplus::SortedMap<int, int, avmplus::LIST_NonGCObjects> {
|
||||
template <class Key>
|
||||
class CountMap : public avmplus::SortedMap<Key, int, avmplus::LIST_NonGCObjects> {
|
||||
public:
|
||||
CountMap(GC*gc) : avmplus::SortedMap<int, int, avmplus::LIST_NonGCObjects>(gc) {};
|
||||
int add(int i) {
|
||||
CountMap(GC*gc) : avmplus::SortedMap<Key, int, avmplus::LIST_NonGCObjects>(gc) {}
|
||||
int add(Key k) {
|
||||
int c = 1;
|
||||
if (containsKey(i)) {
|
||||
c = 1+get(i);
|
||||
if (containsKey(k)) {
|
||||
c = 1+get(k);
|
||||
}
|
||||
put(i,c);
|
||||
put(k,c);
|
||||
return c;
|
||||
}
|
||||
} lircounts, funccounts;
|
||||
};
|
||||
CountMap<int> lircounts;
|
||||
CountMap<const CallInfo *> funccounts;
|
||||
|
||||
class Entry MMGC_SUBCLASS_DECL
|
||||
{
|
||||
public:
|
||||
|
@ -603,8 +618,8 @@ namespace nanojit
|
|||
LIns* ins2(LOpcode v, LInsp a, LInsp b) {
|
||||
return v == LIR_2 ? out->ins2(v,a,b) : add(out->ins2(v, a, b));
|
||||
}
|
||||
LIns* insCall(uint32_t fid, LInsp args[]) {
|
||||
return add(out->insCall(fid, args));
|
||||
LIns* insCall(const CallInfo *call, LInsp args[]) {
|
||||
return add(out->insCall(call, args));
|
||||
}
|
||||
LIns* insParam(int32_t i) {
|
||||
return add(out->insParam(i));
|
||||
|
@ -655,7 +670,7 @@ namespace nanojit
|
|||
LInsp find64(uint64_t a, uint32_t &i);
|
||||
LInsp find1(LOpcode v, LInsp a, uint32_t &i);
|
||||
LInsp find2(LOpcode v, LInsp a, LInsp b, uint32_t &i);
|
||||
LInsp findcall(uint32_t fid, uint32_t argc, LInsp args[], uint32_t &i);
|
||||
LInsp findcall(const CallInfo *call, uint32_t argc, LInsp args[], uint32_t &i);
|
||||
LInsp add(LInsp i, uint32_t k);
|
||||
void replace(LInsp i);
|
||||
|
||||
|
@ -663,7 +678,7 @@ namespace nanojit
|
|||
static uint32_t FASTCALL hashimmq(uint64_t);
|
||||
static uint32_t FASTCALL hash1(LOpcode v, LInsp);
|
||||
static uint32_t FASTCALL hash2(LOpcode v, LInsp, LInsp);
|
||||
static uint32_t FASTCALL hashcall(uint32_t fid, uint32_t argc, LInsp args[]);
|
||||
static uint32_t FASTCALL hashcall(const CallInfo *call, uint32_t argc, LInsp args[]);
|
||||
};
|
||||
|
||||
class CseFilter: public LirWriter
|
||||
|
@ -676,7 +691,7 @@ namespace nanojit
|
|||
LIns* ins1(LOpcode v, LInsp);
|
||||
LIns* ins2(LOpcode v, LInsp, LInsp);
|
||||
LIns* insLoad(LOpcode v, LInsp b, LInsp d);
|
||||
LIns* insCall(uint32_t fid, LInsp args[]);
|
||||
LIns* insCall(const CallInfo *call, LInsp args[]);
|
||||
LIns* insGuard(LOpcode op, LInsp cond, SideExit *x);
|
||||
};
|
||||
|
||||
|
@ -737,7 +752,7 @@ namespace nanojit
|
|||
LInsp insParam(int32_t i);
|
||||
LInsp insImm(int32_t imm);
|
||||
LInsp insImmq(uint64_t imm);
|
||||
LInsp insCall(uint32_t fid, LInsp args[]);
|
||||
LInsp insCall(const CallInfo *call, LInsp args[]);
|
||||
LInsp insGuard(LOpcode op, LInsp cond, SideExit *x);
|
||||
|
||||
// buffer mgmt
|
||||
|
|
|
@ -158,7 +158,7 @@ Assembler::genEpilogue(RegisterMask restore)
|
|||
void
|
||||
Assembler::asm_call(LInsp ins)
|
||||
{
|
||||
const CallInfo* call = callInfoFor(ins->fid());
|
||||
const CallInfo* call = ins->callInfo();
|
||||
Reservation *callRes = getresv(ins);
|
||||
|
||||
uint32_t atypes = call->_argtypes;
|
||||
|
|
|
@ -171,7 +171,7 @@ namespace nanojit
|
|||
|
||||
void Assembler::asm_call(LInsp ins)
|
||||
{
|
||||
const CallInfo* call = callInfoFor(ins->fid());
|
||||
const CallInfo* call = ins->callInfo();
|
||||
uint32_t atypes = call->_argtypes;
|
||||
uint32_t roffset = 0;
|
||||
|
||||
|
|
|
@ -230,8 +230,7 @@ namespace nanojit
|
|||
#if defined NANOJIT_IA32
|
||||
void Assembler::asm_call(LInsp ins)
|
||||
{
|
||||
uint32_t fid = ins->fid();
|
||||
const CallInfo* call = callInfoFor(fid);
|
||||
const CallInfo* call = ins->callInfo();
|
||||
// must be signed, not unsigned
|
||||
const uint32_t iargs = call->count_iargs();
|
||||
int32_t fstack = call->count_args() - iargs;
|
||||
|
@ -309,8 +308,7 @@ namespace nanojit
|
|||
void Assembler::asm_call(LInsp ins)
|
||||
{
|
||||
Register fpu_reg = XMM0;
|
||||
uint32_t fid = ins->fid();
|
||||
const CallInfo* call = callInfoFor(fid);
|
||||
const CallInfo* call = ins->callInfo();
|
||||
int n = 0;
|
||||
|
||||
CALL(call);
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is [Open Source Virtual Machine].
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Adobe System Incorporated.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004-2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Adobe AS3 Team
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define BUILTIN1(op, at0, atr, tr, t0, cse, fold) F_##op,
|
||||
#define BUILTIN2(op, at0, at1, atr, tr, t0, t1, cse, fold) F_##op,
|
||||
#define BUILTIN3(op, at0, at1, at2, atr, tr, t0, t1, t2, cse, fold) F_##op,
|
||||
#define BUILTIN4(op, at0, at1, at2, at3, atr, tr, t0, t1, t2, t3, cse, fold) F_##op,
|
||||
#define BUILTIN5(op, at0, at1, at2, at3, at4, atr, tr, t0, t1, t2, t3, t4, cse, fold) F_##op,
|
||||
|
||||
INTERP_FOPCODE_LIST_BEGIN
|
||||
#include "builtins.tbl"
|
||||
INTERP_FOPCODE_LIST_END
|
||||
|
||||
#undef BUILTIN1
|
||||
#undef BUILTIN2
|
||||
#undef BUILTIN3
|
||||
#undef BUILTIN4
|
||||
#undef BUILTIN5
|
Загрузка…
Ссылка в новой задаче