diff --git a/js/src/builtins.tbl b/js/src/builtins.tbl index e88e5d0e7a5..5488b3003c1 100644 --- a/js/src/builtins.tbl +++ b/js/src/builtins.tbl @@ -49,6 +49,7 @@ BUILTIN2(Math_pow, F, F, F, jsdouble, jsdouble, jsdouble, BUILTIN1(Math_sqrt, F, F, jsdouble, jsdouble, 1, 1) BUILTIN1(Math_floor, F, F, jsdouble, jsdouble, 1, 1) BUILTIN4(Array_dense_setelem, LO, LO, LO, LO, LO, bool, JSContext*, JSObject*, jsint, jsval, 1, 1) +BUILTIN3(Array_p_join, LO, LO, LO, LO, JSString*, JSContext*, JSObject*, JSString*, 1, 1) BUILTIN4(String_p_substring, LO, LO, LO, LO, LO, JSString*, JSContext*, JSString*, jsint, jsint, 1, 1) BUILTIN3(String_p_substring_1, LO, LO, LO, LO, JSString*, JSContext*, JSString*, jsint, 1, 1) BUILTIN3(FastConcatStrings, LO, LO, LO, LO, JSString*, JSContext*, JSString*, JSString*, 1, 1) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 3eca7b8832b..786f2e50d57 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -1183,20 +1183,14 @@ 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. */ -static JSBool -array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op, - JSString *sep, jsval *rval) +JSBool +js_array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op, + JSString *sep, jsval *rval) { JSBool ok, hole; jsuint length, index; @@ -1414,7 +1408,7 @@ array_toSource(JSContext *cx, uintN argc, jsval *vp) !JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) { return JS_FALSE; } - return array_join_sub(cx, obj, TO_SOURCE, NULL, vp); + return js_array_join_sub(cx, obj, TO_SOURCE, NULL, vp); } #endif @@ -1428,7 +1422,7 @@ array_toString(JSContext *cx, uintN argc, jsval *vp) !JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) { return JS_FALSE; } - return array_join_sub(cx, obj, TO_STRING, NULL, vp); + return js_array_join_sub(cx, obj, TO_STRING, NULL, vp); } static JSBool @@ -1446,7 +1440,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 array_join_sub(cx, obj, TO_LOCALE_STRING, NULL, vp); + return js_array_join_sub(cx, obj, TO_LOCALE_STRING, NULL, vp); } static JSBool @@ -1505,8 +1499,8 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, jsval *vector, /* * Perl-inspired join, reverse, and sort. */ -static JSBool -array_join(JSContext *cx, uintN argc, jsval *vp) +JSBool +js_array_join(JSContext *cx, uintN argc, jsval *vp) { JSString *str; JSObject *obj; @@ -1520,7 +1514,7 @@ array_join(JSContext *cx, uintN argc, jsval *vp) vp[2] = STRING_TO_JSVAL(str); } obj = JS_THIS_OBJECT(cx, vp); - return obj && array_join_sub(cx, obj, TO_STRING, str, vp); + return obj && js_array_join_sub(cx, obj, TO_STRING, str, vp); } static JSBool @@ -2880,7 +2874,7 @@ static JSFunctionSpec array_methods[] = { JS_FN(js_toLocaleString_str,array_toLocaleString,0,0), /* Perl-ish methods. */ - JS_FN("join", array_join, 1,JSFUN_GENERIC_NATIVE), + JS_FN("join", js_array_join, 1,JSFUN_GENERIC_NATIVE), JS_FN("reverse", array_reverse, 0,JSFUN_GENERIC_NATIVE), JS_FN("sort", array_sort, 1,JSFUN_GENERIC_NATIVE), JS_FN("push", array_push, 1,JSFUN_GENERIC_NATIVE), diff --git a/js/src/jsarray.h b/js/src/jsarray.h index bec5569d4a5..88ef0a51c55 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -123,6 +123,19 @@ 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); + +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); + JS_END_EXTERN_C #endif /* jsarray_h___ */ diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index c2922f03a3b..7c3fdc6a2bd 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -195,6 +195,16 @@ js_Array_dense_setelem(JSContext* cx, JSObject* obj, jsint i, jsval v) return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(i), &v) ? true : false; } +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); +} + JSString* FASTCALL js_String_p_substring(JSContext* cx, JSString* str, jsint begin, jsint end) { diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index d8006d050a4..8b68fe32ba6 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3246,19 +3246,21 @@ TraceRecorder::record_JSOP_CALL() const char *prefix; const char *argtypes; JSTNErrType errtype; + JSClass *tclasp; } knownNatives[] = { - { 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_str_substring, F_String_p_substring, "TC", "ii", FAIL_NULL, }, - { js_str_substring, F_String_p_substring_1, "TC", "i", FAIL_NULL, }, - { js_str_fromCharCode, F_String_fromCharCode, "C", "i", FAIL_NULL, }, - { js_str_charCodeAt, F_String_p_charCodeAt, "T", "i", FAIL_NEG, }, - { js_str_charAt, F_String_getelem, "TC", "i", FAIL_NULL, }, - { js_math_random, F_Math_random, "R", "", INFALLIBLE, }, - { js_str_concat, F_String_p_concat_1int, "TC", "i", FAIL_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_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 }, }; for (uintN i = 0; i < JS_ARRAY_LENGTH(knownNatives); i++) { @@ -3275,7 +3277,14 @@ TraceRecorder::record_JSOP_CALL() LIns** argp = &args[argc + prefixc - 1]; char argtype; - LIns* thisval_ins = stack(0 - (argc + 1)); + 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; + } #define HANDLE_PREFIX(i) \ argtype = known->prefix[i]; \ @@ -3308,11 +3317,17 @@ TraceRecorder::record_JSOP_CALL() #define HANDLE_ARG(i) \ argtype = known->argtypes[i]; \ if (argtype == 'd' || argtype == 'i') { \ - if (!isNumber(stackval(-(i + 1)))) \ + jsval& arg = stackval(-(i + 1)); \ + if (!isNumber(arg)) \ ABORT_TRACE("arg in position " #i " must be numeric"); \ - *argp = get(&stackval(-(i + 1))); \ + *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"); \ + *argp = get(&arg); \ } else { \ JS_NOT_REACHED("unknown arg type"); \ } \