Bug 458735 - Improve internal API for traceable natives (r=brendan, nanojit r=edwsmith)

This commit is contained in:
Jason Orendorff 2008-10-08 17:08:33 -05:00
Родитель 90b150b28d
Коммит c6bca4ae17
36 изменённых файлов: 1316 добавлений и 1183 удалений

Просмотреть файл

@ -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"
};

202
js/src/jsbuiltins.h Normal file
Просмотреть файл

@ -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
};

Просмотреть файл

@ -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;

Просмотреть файл

@ -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