mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge.
This commit is contained in:
commit
3fd013cd9b
@ -57,6 +57,10 @@ BUILTIN3(String_getelem, LO, LO, LO, LO, JSString*, JSContext*, JSString*
|
||||
BUILTIN2(String_fromCharCode, LO, LO, LO, 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, LO, JSString*, JSContest*, JSString*, jsint, 1, 1)
|
||||
BUILTIN3(String_p_match, LO, LO, LO, LO, JSObject*, JSContext*, JSString*, JSObject*, 1, 1)
|
||||
BUILTIN4(String_p_replace_fun, LO, LO, LO, LO, LO, JSString*, JSContext*, JSString*, JSObject*, JSObject*, 1, 1)
|
||||
BUILTIN4(String_p_replace_str, LO, LO, LO, LO, LO, JSString*, JSContext*, JSString*, JSObject*, JSString*, 1, 1)
|
||||
BUILTIN5(String_p_replace_str3, LO, LO, LO, LO, LO, LO, JSString*, JSContext*, JSString*, JSString*, JSString*, JSString*, 1, 1)
|
||||
BUILTIN1(Math_random, LO, F, jsdouble, JSRuntime*, 1, 1)
|
||||
BUILTIN2(EqualStrings, LO, LO, LO, bool, JSString*, JSString*, 1, 1)
|
||||
BUILTIN2(CompareStrings, LO, LO, LO, bool, JSString*, JSString*, 1, 1)
|
||||
@ -69,6 +73,7 @@ BUILTIN2(CloseIterator, LO, LO, LO, bool, JSContext*, jsval, 1,
|
||||
BUILTIN2(CallTree, LO, LO, LO, nanojit::GuardRecord*, avmplus::InterpState*, nanojit::Fragment*, 0, 0)
|
||||
BUILTIN2(FastNewObject, LO, LO, LO, JSObject*, JSContext*, JSObject*, 1, 1)
|
||||
BUILTIN3(AddProperty, LO, LO, LO, LO, bool, JSContext*, JSObject*, JSScopeProperty*, 1, 1)
|
||||
BUILTIN3(CallGetter, LO, LO, LO, LO, jsval, JSContext*, JSObject*, JSScopeProperty*, 1, 1)
|
||||
BUILTIN2(TypeOfObject, LO, LO, LO, JSString*, JSContext*, JSObject*, 1, 1)
|
||||
BUILTIN2(TypeOfBoolean, LO, LO, LO, JSString*, JSContext*, jsint, 1, 1)
|
||||
BUILTIN2(NumberToString, LO, F, LO, JSString*, JSContext*, jsdouble, 1, 1)
|
||||
|
@ -266,6 +266,55 @@ js_String_p_concat_1int(JSContext* cx, JSString* str, jsint i)
|
||||
return js_ConcatStrings(cx, str, istr);
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
js_String_p_match(JSContext* cx, JSString* str, JSObject* regexp)
|
||||
{
|
||||
jsval vp[4] = { JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
|
||||
if (!js_str_match(cx, 1, vp))
|
||||
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_fun(JSContext* cx, JSString* str, JSObject* regexp, JSObject* lambda)
|
||||
{
|
||||
jsval vp[4] = {
|
||||
JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp), OBJECT_TO_JSVAL(lambda)
|
||||
};
|
||||
if (!js_StringReplaceHelper(cx, 2, lambda, NULL, vp))
|
||||
return NULL;
|
||||
JS_ASSERT(JSVAL_IS_STRING(vp[0]));
|
||||
return JSVAL_TO_STRING(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_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]);
|
||||
}
|
||||
|
||||
jsdouble FASTCALL
|
||||
js_StringToNumber(JSContext* cx, JSString* str)
|
||||
{
|
||||
@ -444,6 +493,16 @@ js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
||||
return false;
|
||||
}
|
||||
|
||||
jsval FASTCALL
|
||||
js_CallGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
||||
{
|
||||
JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop));
|
||||
jsval v;
|
||||
if (!SPROP_GET(cx, sprop, obj, obj, &v))
|
||||
return JSVAL_ERROR_COOKIE;
|
||||
return v;
|
||||
}
|
||||
|
||||
JSString* FASTCALL
|
||||
js_TypeOfObject(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
@ -504,8 +563,10 @@ js_BooleanToNumber(JSContext* cx, jsint unboxed)
|
||||
{ (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) \
|
||||
#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[] = {
|
||||
#include "builtins.tbl"
|
||||
|
@ -1905,7 +1905,7 @@ file_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
JSFILE_CHECK_NATIVE("list");
|
||||
|
||||
if (argc==1) {
|
||||
if (JSVAL_IS_REGEXP(cx, argv[0])) {
|
||||
if (VALUE_IS_REGEXP(cx, argv[0])) {
|
||||
re = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
|
||||
}else
|
||||
if (VALUE_IS_FUNCTION(cx, argv[0])) {
|
||||
|
@ -3592,15 +3592,6 @@ out:
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
enum regexp_tinyid {
|
||||
REGEXP_SOURCE = -1,
|
||||
REGEXP_GLOBAL = -2,
|
||||
REGEXP_IGNORE_CASE = -3,
|
||||
REGEXP_LAST_INDEX = -4,
|
||||
REGEXP_MULTILINE = -5,
|
||||
REGEXP_STICKY = -6
|
||||
};
|
||||
|
||||
#define REGEXP_PROP_ATTRS (JSPROP_PERMANENT | JSPROP_SHARED)
|
||||
#define RO_REGEXP_PROP_ATTRS (REGEXP_PROP_ATTRS | JSPROP_READONLY)
|
||||
|
||||
|
@ -141,12 +141,21 @@ js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res);
|
||||
extern void
|
||||
js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res);
|
||||
|
||||
#define JSVAL_IS_REGEXP(cx, v) \
|
||||
#define VALUE_IS_REGEXP(cx, v) \
|
||||
(JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) && \
|
||||
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_RegExpClass)
|
||||
|
||||
extern JSClass js_RegExpClass;
|
||||
|
||||
enum regexp_tinyid {
|
||||
REGEXP_SOURCE = -1,
|
||||
REGEXP_GLOBAL = -2,
|
||||
REGEXP_IGNORE_CASE = -3,
|
||||
REGEXP_LAST_INDEX = -4,
|
||||
REGEXP_MULTILINE = -5,
|
||||
REGEXP_STICKY = -6
|
||||
};
|
||||
|
||||
extern JSObject *
|
||||
js_InitRegExpClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
|
@ -1167,7 +1167,7 @@ match_or_replace(JSContext *cx,
|
||||
NORMALIZE_THIS(cx, vp, str);
|
||||
data->str = str;
|
||||
|
||||
if (argc != 0 && JSVAL_IS_REGEXP(cx, vp[2])) {
|
||||
if (argc != 0 && VALUE_IS_REGEXP(cx, vp[2])) {
|
||||
reobj = JSVAL_TO_OBJECT(vp[2]);
|
||||
re = (JSRegExp *) JS_GetPrivate(cx, reobj);
|
||||
} else {
|
||||
@ -1230,8 +1230,8 @@ match_or_replace(JSContext *cx,
|
||||
test = JS_TRUE;
|
||||
} else {
|
||||
/*
|
||||
* MODE_MATCH implies str_match is being called from a script or a
|
||||
* scripted function. If the caller cares only about testing null
|
||||
* MODE_MATCH implies js_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.
|
||||
*/
|
||||
@ -1306,8 +1306,8 @@ match_glob(JSContext *cx, jsint count, GlobData *data)
|
||||
return OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(count), &v);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
str_match(JSContext *cx, uintN argc, jsval *vp)
|
||||
JSBool
|
||||
js_str_match(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSTempValueRooter tvr;
|
||||
MatchData mdata;
|
||||
@ -1425,7 +1425,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 str_replace.
|
||||
* input, which is rooted otherwise via vp[1] in js_str_replace.
|
||||
*/
|
||||
JSRegExpStatics save = cx->regExpStatics;
|
||||
JSBool freeMoreParens = JS_FALSE;
|
||||
@ -1605,15 +1605,11 @@ replace_glob(JSContext *cx, jsint count, GlobData *data)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
str_replace(JSContext *cx, uintN argc, jsval *vp)
|
||||
JSBool
|
||||
js_str_replace(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *lambda;
|
||||
JSString *repstr, *str;
|
||||
ReplaceData rdata;
|
||||
JSBool ok;
|
||||
jschar *chars;
|
||||
size_t leftlen, rightlen, length;
|
||||
JSString *repstr;
|
||||
|
||||
if (argc >= 2 && JS_TypeOfValue(cx, vp[3]) == JSTYPE_FUNCTION) {
|
||||
lambda = JSVAL_TO_OBJECT(vp[3]);
|
||||
@ -1625,6 +1621,19 @@ str_replace(JSContext *cx, uintN argc, jsval *vp)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return js_StringReplaceHelper(cx, argc, lambda, repstr, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda,
|
||||
JSString *repstr, jsval *vp)
|
||||
{
|
||||
ReplaceData rdata;
|
||||
JSBool ok;
|
||||
size_t leftlen, rightlen, length;
|
||||
jschar *chars;
|
||||
JSString *str;
|
||||
|
||||
/*
|
||||
* For ECMA Edition 3, the first argument is to be converted to a string
|
||||
* to match in a "flat" sense (without regular expression metachars having
|
||||
@ -1838,7 +1847,7 @@ str_split(JSContext *cx, uintN argc, jsval *vp)
|
||||
v = STRING_TO_JSVAL(str);
|
||||
ok = OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(0), &v);
|
||||
} else {
|
||||
if (JSVAL_IS_REGEXP(cx, vp[2])) {
|
||||
if (VALUE_IS_REGEXP(cx, vp[2])) {
|
||||
re = (JSRegExp *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(vp[2]));
|
||||
sep = &tmp;
|
||||
|
||||
@ -2251,9 +2260,9 @@ static JSFunctionSpec string_methods[] = {
|
||||
JS_FN("localeCompare", str_localeCompare, 1,GENERIC_PRIMITIVE),
|
||||
|
||||
/* Perl-ish methods (search is actually Python-esque). */
|
||||
JS_FN("match", str_match, 1,GENERIC_PRIMITIVE),
|
||||
JS_FN("match", js_str_match, 1,GENERIC_PRIMITIVE),
|
||||
JS_FN("search", str_search, 1,GENERIC_PRIMITIVE),
|
||||
JS_FN("replace", str_replace, 2,GENERIC_PRIMITIVE),
|
||||
JS_FN("replace", js_str_replace, 2,GENERIC_PRIMITIVE),
|
||||
JS_FN("split", str_split, 2,GENERIC_PRIMITIVE),
|
||||
#if JS_HAS_PERL_SUBSTR
|
||||
JS_FN("substr", str_substr, 2,GENERIC_PRIMITIVE),
|
||||
|
@ -608,10 +608,21 @@ js_GetStringBytes(JSContext *cx, JSString *str);
|
||||
extern void
|
||||
js_PurgeDeflatedStringCache(JSRuntime *rt, JSString *str);
|
||||
|
||||
JSBool
|
||||
/* Export a few natives and a helper to other files in SpiderMonkey. */
|
||||
extern JSBool
|
||||
js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "jsiter.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsregexp.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsscript.h"
|
||||
#include "jstracer.h"
|
||||
@ -2369,21 +2370,19 @@ TraceRecorder::test_property_cache_direct_slot(JSObject* obj, LIns* obj_ins, uin
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Handle only gets and sets on the directly addressed object. */
|
||||
if (obj2 != obj)
|
||||
ABORT_TRACE("PC hit on prototype chain");
|
||||
/* Insist if setting on obj being the directly addressed object. */
|
||||
uint32 setflags = (js_CodeSpec[*cx->fp->regs->pc].format & (JOF_SET | JOF_INCDEC));
|
||||
if (setflags && obj2 != obj)
|
||||
ABORT_TRACE("JOF_SET opcode hit prototype chain");
|
||||
|
||||
/* Don't trace getter or setter calls, our caller wants a direct slot. */
|
||||
if (PCVAL_IS_SPROP(pcval)) {
|
||||
JSScopeProperty* sprop = PCVAL_TO_SPROP(pcval);
|
||||
|
||||
if (js_CodeSpec[*cx->fp->regs->pc].format & JOF_SET) {
|
||||
if (!SPROP_HAS_STUB_SETTER(sprop))
|
||||
ABORT_TRACE("non-stub setter");
|
||||
} else {
|
||||
if (!SPROP_HAS_STUB_GETTER(sprop))
|
||||
ABORT_TRACE("non-stub getter");
|
||||
}
|
||||
if (setflags && !SPROP_HAS_STUB_SETTER(sprop))
|
||||
ABORT_TRACE("non-stub setter");
|
||||
if (setflags != JOF_SET && !SPROP_HAS_STUB_GETTER(sprop))
|
||||
ABORT_TRACE("non-stub getter");
|
||||
if (!SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)))
|
||||
ABORT_TRACE("no valid slot");
|
||||
slot = sprop->slot;
|
||||
@ -2462,7 +2461,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);
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, lir->insImmPtr((void*)JSVAL_ERROR_COOKIE)),
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, INS_CONSTPTR(JSVAL_ERROR_COOKIE)),
|
||||
OOM_EXIT);
|
||||
return true;
|
||||
}
|
||||
@ -3197,8 +3196,8 @@ TraceRecorder::record_JSOP_GETELEM()
|
||||
|
||||
LIns* args[] = { get(&r), get(&l), cx_ins };
|
||||
LIns* v_ins = lir->insCall(F_Any_getelem, args);
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, lir->insImmPtr((void*)JSVAL_ERROR_COOKIE)),
|
||||
MISMATCH_EXIT);
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, INS_CONSTPTR(JSVAL_ERROR_COOKIE)),
|
||||
MISMATCH_EXIT);
|
||||
if (!unbox_jsval(v, v_ins))
|
||||
ABORT_TRACE("JSOP_GETELEM");
|
||||
set(&l, v_ins);
|
||||
@ -3404,23 +3403,27 @@ TraceRecorder::record_JSOP_CALL()
|
||||
JSTNErrType errtype;
|
||||
JSClass *tclasp;
|
||||
} knownNatives[] = {
|
||||
{ js_math_sin, F_Math_sin, "", "d", INFALLIBLE, NULL },
|
||||
{ js_math_cos, F_Math_cos, "", "d", INFALLIBLE, NULL },
|
||||
{ js_math_pow, F_Math_pow, "", "dd", INFALLIBLE, NULL },
|
||||
{ js_math_sqrt, F_Math_sqrt, "", "d", INFALLIBLE, NULL },
|
||||
{ js_math_floor, F_Math_floor, "", "d", INFALLIBLE, NULL },
|
||||
{ js_str_substring, F_String_p_substring, "TC", "ii", FAIL_NULL, NULL },
|
||||
{ js_str_substring, F_String_p_substring_1, "TC", "i", FAIL_NULL, NULL },
|
||||
{ js_str_fromCharCode, F_String_fromCharCode, "C", "i", FAIL_NULL, NULL },
|
||||
{ js_str_charCodeAt, F_String_p_charCodeAt, "T", "i", FAIL_NEG, NULL },
|
||||
{ js_str_charAt, F_String_getelem, "TC", "i", FAIL_NULL, NULL },
|
||||
{ js_math_random, F_Math_random, "R", "", INFALLIBLE, NULL },
|
||||
{ js_str_concat, F_String_p_concat_1int, "TC", "i", FAIL_NULL, NULL },
|
||||
{ js_array_join, F_Array_p_join, "TC", "s", FAIL_NULL, NULL },
|
||||
{ js_obj_hasOwnProperty, F_Object_p_hasOwnProperty,
|
||||
"TC", "s", FAIL_VOID, NULL },
|
||||
{ js_math_sin, F_Math_sin, "", "d", INFALLIBLE, NULL },
|
||||
{ js_math_cos, F_Math_cos, "", "d", INFALLIBLE, NULL },
|
||||
{ js_math_pow, F_Math_pow, "", "dd", INFALLIBLE, NULL },
|
||||
{ js_math_sqrt, F_Math_sqrt, "", "d", INFALLIBLE, NULL },
|
||||
{ js_math_floor, F_Math_floor, "", "d", INFALLIBLE, NULL },
|
||||
{ js_str_substring, F_String_p_substring, "TC", "ii", FAIL_NULL, NULL },
|
||||
{ js_str_substring, F_String_p_substring_1, "TC", "i", FAIL_NULL, NULL },
|
||||
{ js_str_fromCharCode, F_String_fromCharCode, "C", "i", FAIL_NULL, NULL },
|
||||
{ js_str_charCodeAt, F_String_p_charCodeAt, "T", "i", FAIL_NEG, NULL },
|
||||
{ js_str_charAt, F_String_getelem, "TC", "i", FAIL_NULL, NULL },
|
||||
{ js_str_match, F_String_p_match, "TC", "r", FAIL_VOID, NULL },
|
||||
{ js_str_replace, F_String_p_replace_str3,"TC","sss", FAIL_NULL, NULL },
|
||||
{ js_str_replace, F_String_p_replace_str, "TC", "sr", FAIL_NULL, NULL },
|
||||
{ js_str_replace, F_String_p_replace_fun, "TC", "fr", FAIL_NULL, NULL },
|
||||
{ js_math_random, F_Math_random, "R", "", INFALLIBLE, NULL },
|
||||
{ js_str_concat, F_String_p_concat_1int, "TC", "i", FAIL_NULL, NULL },
|
||||
{ js_array_join, F_Array_p_join, "TC", "s", FAIL_NULL, NULL },
|
||||
{ js_obj_hasOwnProperty, F_Object_p_hasOwnProperty,
|
||||
"TC", "s", FAIL_VOID, NULL },
|
||||
{ js_obj_propertyIsEnumerable, F_Object_p_propertyIsEnumerable,
|
||||
"TC", "s", FAIL_NEG, NULL },
|
||||
"TC", "s", FAIL_NEG, NULL },
|
||||
};
|
||||
|
||||
for (uintN i = 0; i < JS_ARRAY_LENGTH(knownNatives); i++) {
|
||||
@ -3430,7 +3433,7 @@ TraceRecorder::record_JSOP_CALL()
|
||||
|
||||
uintN knownargc = strlen(known->argtypes);
|
||||
if (argc != knownargc)
|
||||
continue; // might have another specialization for this argc
|
||||
continue;
|
||||
|
||||
intN prefixc = strlen(known->prefix);
|
||||
LIns* args[5];
|
||||
@ -3439,14 +3442,14 @@ TraceRecorder::record_JSOP_CALL()
|
||||
|
||||
jsval& thisval = stackval(0 - (argc + 1));
|
||||
LIns* thisval_ins = get(&thisval);
|
||||
if (known->tclasp) {
|
||||
if (JSVAL_IS_PRIMITIVE(thisval))
|
||||
ABORT_TRACE("known native with class guard called on primitive this");
|
||||
if (!guardClass(JSVAL_TO_OBJECT(thisval), thisval_ins, known->tclasp))
|
||||
return false;
|
||||
if (known->tclasp &&
|
||||
!JSVAL_IS_PRIMITIVE(thisval) &&
|
||||
!guardClass(JSVAL_TO_OBJECT(thisval), thisval_ins, known->tclasp)) {
|
||||
continue; /* might have another specialization for |this| */
|
||||
}
|
||||
|
||||
#define HANDLE_PREFIX(i) \
|
||||
JS_BEGIN_MACRO \
|
||||
argtype = known->prefix[i]; \
|
||||
if (argtype == 'C') { \
|
||||
*argp = cx_ins; \
|
||||
@ -3457,7 +3460,8 @@ TraceRecorder::record_JSOP_CALL()
|
||||
} else { \
|
||||
JS_NOT_REACHED("unknown prefix arg type"); \
|
||||
} \
|
||||
argp--;
|
||||
argp--; \
|
||||
JS_END_MACRO
|
||||
|
||||
switch (prefixc) {
|
||||
case 2:
|
||||
@ -3475,23 +3479,32 @@ TraceRecorder::record_JSOP_CALL()
|
||||
#undef HANDLE_PREFIX
|
||||
|
||||
#define HANDLE_ARG(i) \
|
||||
JS_BEGIN_MACRO \
|
||||
jsval& arg = stackval(-(i + 1)); \
|
||||
argtype = known->argtypes[i]; \
|
||||
if (argtype == 'd' || argtype == 'i') { \
|
||||
jsval& arg = stackval(-(i + 1)); \
|
||||
if (!isNumber(arg)) \
|
||||
ABORT_TRACE("arg in position " #i " must be numeric"); \
|
||||
continue; /* might have another specialization for arg */ \
|
||||
*argp = get(&arg); \
|
||||
if (argtype == 'i') \
|
||||
*argp = f2i(*argp); \
|
||||
} else if (argtype == 's') { \
|
||||
jsval& arg = stackval(-(i + 1)); \
|
||||
if (!JSVAL_IS_STRING(arg)) \
|
||||
ABORT_TRACE("arg in position " #i " must be a string"); \
|
||||
continue; /* might have another specialization for arg */ \
|
||||
*argp = get(&arg); \
|
||||
} else if (argtype == 'r') { \
|
||||
if (!VALUE_IS_REGEXP(cx, arg)) \
|
||||
continue; /* might have another specialization for arg */ \
|
||||
*argp = get(&arg); \
|
||||
} else if (argtype == 'f') { \
|
||||
if (!VALUE_IS_FUNCTION(cx, arg)) \
|
||||
continue; /* might have another specialization for arg */ \
|
||||
*argp = get(&arg); \
|
||||
} else { \
|
||||
JS_NOT_REACHED("unknown arg type"); \
|
||||
continue; /* might have another specialization for arg */ \
|
||||
} \
|
||||
argp--;
|
||||
argp--; \
|
||||
JS_END_MACRO
|
||||
|
||||
switch (strlen(known->argtypes)) {
|
||||
case 4:
|
||||
@ -3515,16 +3528,22 @@ TraceRecorder::record_JSOP_CALL()
|
||||
#undef HANDLE_ARG
|
||||
|
||||
LIns* res_ins = lir->insCall(known->builtin, args);
|
||||
if (known->errtype == FAIL_NULL) {
|
||||
switch (known->errtype) {
|
||||
case FAIL_NULL:
|
||||
guard(false, lir->ins_eq0(res_ins), OOM_EXIT);
|
||||
} else if (known->errtype == FAIL_NEG) {
|
||||
break;
|
||||
case FAIL_NEG:
|
||||
{
|
||||
res_ins = lir->ins1(LIR_i2f, res_ins);
|
||||
|
||||
jsdpun u;
|
||||
u.d = 0.0;
|
||||
guard(false, lir->ins2(LIR_flt, res_ins, lir->insImmq(u.u64)), OOM_EXIT);
|
||||
} else if (known->errtype == FAIL_VOID) {
|
||||
break;
|
||||
}
|
||||
case FAIL_VOID:
|
||||
guard(false, lir->ins2i(LIR_eq, res_ins, 2), OOM_EXIT);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
set(&fval, res_ins);
|
||||
return true;
|
||||
@ -3543,7 +3562,8 @@ TraceRecorder::name(jsval*& vp)
|
||||
|
||||
LIns* obj_ins = lir->insLoadi(lir->insLoadi(cx_ins, offsetof(JSContext, fp)),
|
||||
offsetof(JSStackFrame, scopeChain));
|
||||
/* Can't use getProp here, because we don't want unboxing. */
|
||||
|
||||
/* Can't use prop here, because we don't want unboxing from global slots. */
|
||||
uint32 slot;
|
||||
if (!test_property_cache_direct_slot(obj, obj_ins, slot))
|
||||
return false;
|
||||
@ -3569,18 +3589,61 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32& slot, LIns*& v_ins)
|
||||
ABORT_TRACE("prop op aliases global");
|
||||
guard(false, lir->ins2(LIR_eq, obj_ins, lir->insImmPtr((void*)globalObj)), MISMATCH_EXIT);
|
||||
|
||||
if (!test_property_cache_direct_slot(obj, obj_ins, slot))
|
||||
/*
|
||||
* Property cache ensures that we are dealing with an existing property,
|
||||
* and guards the shape for us.
|
||||
*/
|
||||
JSObject* obj2;
|
||||
jsuword pcval;
|
||||
if (!test_property_cache(obj, obj_ins, obj2, pcval))
|
||||
return false;
|
||||
|
||||
/* Check for non-existent property reference, which results in undefined. */
|
||||
if (slot == SPROP_INVALID_SLOT) {
|
||||
const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
|
||||
JS_ASSERT(cs.ndefs == 1);
|
||||
const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
|
||||
if (PCVAL_IS_NULL(pcval)) {
|
||||
v_ins = lir->insImm(JSVAL_TO_BOOLEAN(JSVAL_VOID));
|
||||
JS_ASSERT(cs.ndefs == 1);
|
||||
stack(-cs.nuses, v_ins);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Insist if setting on obj being the directly addressed object. */
|
||||
uint32 setflags = (cs.format & (JOF_SET | JOF_INCDEC));
|
||||
if (setflags && obj2 != obj)
|
||||
ABORT_TRACE("JOF_SET opcode hit prototype chain");
|
||||
|
||||
/* Don't trace getter or setter calls, our caller wants a direct slot. */
|
||||
if (PCVAL_IS_SPROP(pcval)) {
|
||||
JSScopeProperty* sprop = PCVAL_TO_SPROP(pcval);
|
||||
|
||||
if (setflags && !SPROP_HAS_STUB_SETTER(sprop))
|
||||
ABORT_TRACE("non-stub setter");
|
||||
if (setflags != JOF_SET && !SPROP_HAS_STUB_GETTER(sprop)) {
|
||||
// FIXME 450335: generalize this away from regexp built-in getters.
|
||||
if (setflags == 0 &&
|
||||
sprop->getter == js_RegExpClass.getProperty &&
|
||||
sprop->shortid < 0) {
|
||||
LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins };
|
||||
v_ins = lir->insCall(F_CallGetter, args);
|
||||
if (!unbox_jsval((sprop->shortid == REGEXP_SOURCE) ? JSVAL_STRING : JSVAL_FALSE,
|
||||
v_ins)) {
|
||||
ABORT_TRACE("unboxing");
|
||||
}
|
||||
JS_ASSERT(cs.ndefs == 1);
|
||||
stack(-cs.nuses, v_ins);
|
||||
return true;
|
||||
}
|
||||
ABORT_TRACE("non-stub getter");
|
||||
}
|
||||
if (!SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)))
|
||||
ABORT_TRACE("no valid slot");
|
||||
slot = sprop->slot;
|
||||
} else {
|
||||
if (!PCVAL_IS_SLOT(pcval))
|
||||
ABORT_TRACE("PCE is not a slot");
|
||||
slot = PCVAL_TO_SLOT(pcval);
|
||||
}
|
||||
|
||||
LIns* dslots_ins = NULL;
|
||||
v_ins = stobj_get_slot(obj_ins, slot, dslots_ins);
|
||||
if (!unbox_jsval(STOBJ_GET_SLOT(obj, slot), v_ins))
|
||||
|
@ -39,6 +39,7 @@
|
||||
#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"
|
||||
@ -48,3 +49,4 @@ INTERP_FOPCODE_LIST_END
|
||||
#undef BUILTIN2
|
||||
#undef BUILTIN3
|
||||
#undef BUILTIN4
|
||||
#undef BUILTIN5
|
||||
|
Loading…
Reference in New Issue
Block a user