Backed out 4 changesets (bug 1263558) for jit OOM crashes a=backout
authorWes Kocher <wkocher@mozilla.com>
Fri, 15 Apr 2016 10:21:35 -0700
changeset 331225 354cb3932e36994d7e772cedba237e9c3c60fe4c
parent 331224 afd82f887093e5e9e4015115ca5795ec82a6f732
child 331285 ded7cf683d5a66df2c6780ad23233497ce4aed59
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1263558
milestone48.0a1
backs out7fcc62dda4e35167b7062f9f72133042a72ac01c
faa055e3ace88ef200b81badb3df0749bf4ede02
94805cd19c1594ee7098118e2b47da2fa94bde2b
ad22cb06de5d204449676d7b717a101fc43c283a
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1263558) for jit OOM crashes a=backout Backed out changeset 7fcc62dda4e3 (bug 1263558) Backed out changeset faa055e3ace8 (bug 1263558) Backed out changeset 94805cd19c15 (bug 1263558) Backed out changeset ad22cb06de5d (bug 1263558) MozReview-Commit-ID: JkWyfHDBf1E
js/src/builtin/Array.js
js/src/builtin/String.js
js/src/jit-test/tests/auto-regress/bug1263558.js
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsarray.h
js/src/jsobj.cpp
js/src/jsstr.cpp
js/src/jsstr.h
js/src/tests/js1_6/Array/generics.js
js/src/tests/js1_6/String/generics.js
js/src/vm/SelfHosting.cpp
js/xpconnect/tests/chrome/test_xrayToJS.xul
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -1022,65 +1022,8 @@ function ArrayConcat(arg1) {
 }
 
 function ArrayStaticConcat(arr, arg1) {
     if (arguments.length < 1)
         ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.concat');
     var args = callFunction(std_Array_slice, arguments, 1);
     return callFunction(std_Function_apply, ArrayConcat, arr, args);
 }
-
-function ArrayStaticJoin(arr, separator) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.join');
-    return callFunction(std_Array_join, arr, separator);
-}
-
-function ArrayStaticReverse(arr) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.reverse');
-    return callFunction(std_Array_reverse, arr);
-}
-
-function ArrayStaticSort(arr, comparefn) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.sort');
-    return callFunction(std_Array_sort, arr, comparefn);
-}
-
-function ArrayStaticPush(arr, arg1) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.push');
-    var args = callFunction(std_Array_slice, arguments, 1);
-    return callFunction(std_Function_apply, std_Array_push, arr, args);
-}
-
-function ArrayStaticPop(arr) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.pop');
-    return callFunction(std_Array_pop, arr);
-}
-
-function ArrayStaticShift(arr) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.shift');
-    return callFunction(std_Array_shift, arr);
-}
-
-function ArrayStaticUnshift(arr, arg1) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.unshift');
-    var args = callFunction(std_Array_slice, arguments, 1);
-    return callFunction(std_Function_apply, std_Array_unshift, arr, args);
-}
-
-function ArrayStaticSplice(arr, start, deleteCount) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.splice');
-    var args = callFunction(std_Array_slice, arguments, 1);
-    return callFunction(std_Function_apply, std_Array_splice, arr, args);
-}
-
-function ArrayStaticSlice(arr, start, end) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.slice');
-    return callFunction(std_Array_slice, arr, start, end);
-}
--- a/js/src/builtin/String.js
+++ b/js/src/builtin/String.js
@@ -717,21 +717,17 @@ function String_static_raw(callSite, ...
  * Mozilla proprietary.
  * Spec: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String#String_generic_methods
  */
 function String_static_localeCompare(str1, str2) {
     if (arguments.length < 1)
         ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "String.localeCompare");
     var locales = arguments.length > 2 ? arguments[2] : undefined;
     var options = arguments.length > 3 ? arguments[3] : undefined;
-#if EXPOSE_INTL_API
     return callFunction(String_localeCompare, str1, str2, locales, options);
-#else
-    return callFunction(std_String_localeCompare, str1, str2, locales, options);
-#endif
 }
 
 // ES6 draft 2014-04-27 B.2.3.3
 function String_big() {
     RequireObjectCoercible(this);
     return "<big>" + ToString(this) + "</big>";
 }
 
@@ -823,113 +819,8 @@ function String_fontsize(size) {
 }
 
 // ES6 draft 2014-04-27 B.2.3.10
 function String_link(url) {
     RequireObjectCoercible(this);
     var S = ToString(this);
     return '<a href="' + EscapeAttributeValue(url) + '">' + S + "</a>";
 }
-
-function String_static_toLowerCase(string) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toLowerCase');
-    return callFunction(std_String_toLowerCase, string);
-}
-
-function String_static_toUpperCase(string) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toUpperCase');
-    return callFunction(std_String_toUpperCase, string);
-}
-
-function String_static_charAt(string, pos) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.charAt');
-    return callFunction(std_String_charAt, string, pos);
-}
-
-function String_static_charCodeAt(string, pos) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.charCodeAt');
-    return callFunction(std_String_charCodeAt, string, pos);
-}
-
-function String_static_includes(string, searchString) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.includes');
-    var position = arguments.length > 2 ? arguments[2] : undefined;
-    return callFunction(std_String_includes, string, searchString, position);
-}
-
-function String_static_indexOf(string, searchString) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.indexOf');
-    var position = arguments.length > 2 ? arguments[2] : undefined;
-    return callFunction(std_String_indexOf, string, searchString, position);
-}
-
-function String_static_lastIndexOf(string, searchString) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.lastIndexOf');
-    var position = arguments.length > 2 ? arguments[2] : undefined;
-    return callFunction(std_String_lastIndexOf, string, searchString, position);
-}
-
-function String_static_startsWith(string, searchString) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.startsWith');
-    var position = arguments.length > 2 ? arguments[2] : undefined;
-    return callFunction(std_String_startsWith, string, searchString, position);
-}
-
-function String_static_endsWith(string, searchString) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.endsWith');
-    var endPosition = arguments.length > 2 ? arguments[2] : undefined;
-    return callFunction(std_String_endsWith, string, searchString, endPosition);
-}
-
-function String_static_trim(string) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trim');
-    return callFunction(std_String_trim, string);
-}
-
-function String_static_trimLeft(string) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimLeft');
-    return callFunction(std_String_trimLeft, string);
-}
-
-function String_static_trimRight(string) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimRight');
-    return callFunction(std_String_trimRight, string);
-}
-
-function String_static_toLocaleLowerCase(string) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toLocaleLowerCase');
-    return callFunction(std_String_toLocaleLowerCase, string);
-}
-
-function String_static_toLocaleUpperCase(string) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toLocaleUpperCase');
-    return callFunction(std_String_toLocaleUpperCase, string);
-}
-
-#if EXPOSE_INTL_API
-function String_static_normalize(string) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.normalize');
-    var form = arguments.length > 1 ? arguments[1] : undefined;
-    return callFunction(std_String_normalize, string, form);
-}
-#endif
-
-function String_static_concat(string, arg1) {
-    if (arguments.length < 1)
-        ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.concat');
-    var args = callFunction(std_Array_slice, arguments, 1);
-    return callFunction(std_Function_apply, std_String_concat, string, args);
-}
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug1263558.js
+++ /dev/null
@@ -1,16 +0,0 @@
-if (!('oomTest' in this))
-    quit();
-
-evalcx(`
-    eval('\
-        var appendToActual = function(s) {};\
-        gczeal = function() {};\
-        gcslice = function() {};\
-        selectforgc = function() {};\
-        if (!("verifyprebarriers" in this)) {\
-            verifyprebarriers = function() {};\
-        }\
-    ');
-    oomTest(() => eval('Array(..."")'));
-    Intl.NumberFormat.prototype.format(0);
-`, newGlobal());
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -832,17 +832,27 @@ class MOZ_STACK_CLASS SourceBufferHolder
 #define JSPROP_INTERNAL_USE_BIT 0x80    /* internal JS engine use only */
 //                             0x100    /* Unused */
 #define JSFUN_STUB_GSOPS       0x200    /* use JS_PropertyStub getter/setter
                                            instead of defaulting to class gsops
                                            for property holding function */
 
 #define JSFUN_CONSTRUCTOR      0x400    /* native that can be called as a ctor */
 
-//                             0x800    /* Unused */
+/*
+ * Specify a generic native prototype methods, i.e., methods of a class
+ * prototype that are exposed as static methods taking an extra leading
+ * argument: the generic |this| parameter.
+ *
+ * If you set this flag in a JSFunctionSpec struct's flags initializer, then
+ * that struct must live at least as long as the native static method object
+ * created due to this flag by JS_DefineFunctions or JS_InitClass.  Typically
+ * JSFunctionSpec structs are allocated in static arrays.
+ */
+#define JSFUN_GENERIC_NATIVE   0x800
 
 #define JSFUN_HAS_REST        0x1000    /* function has ...rest parameter. */
 
 #define JSFUN_FLAGS_MASK      0x1e00    /* | of all the JSFUN_* flags */
 
 /*
  * If set, will allow redefining a non-configurable property, but only on a
  * non-DOM global.  This is a temporary hack that will need to go away in bug
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1385,18 +1385,18 @@ ArrayReverseDenseKernel(JSContext* cx, H
     }
 
     return DenseElementResult::Success;
 }
 
 DefineBoxedOrUnboxedFunctor3(ArrayReverseDenseKernel,
                              JSContext*, HandleObject, uint32_t);
 
-bool
-js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
+static bool
+array_reverse(JSContext* cx, unsigned argc, Value* vp)
 {
     AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.reverse");
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     uint32_t len;
@@ -2376,18 +2376,18 @@ CanOptimizeForDenseStorage(HandleObject 
      * other indexed properties on the object.  (Note that non-writable length
      * is subsumed by the initializedLength comparison.)
      */
     return !ObjectMayHaveExtraIndexedProperties(arr) &&
            startingIndex + count <= GetAnyBoxedOrUnboxedInitializedLength(arr);
 }
 
 /* ES 2016 draft Mar 25, 2016 22.1.3.26. */
-bool
-js::array_splice(JSContext* cx, unsigned argc, Value* vp)
+static bool
+array_splice(JSContext* cx, unsigned argc, Value* vp)
 {
     return array_splice_impl(cx, argc, vp, true);
 }
 
 static inline bool
 ArraySpliceCopy(JSContext* cx, HandleObject arr, HandleObject obj,
                 uint32_t actualStart, uint32_t actualDeleteCount)
 {
@@ -3077,36 +3077,38 @@ array_of(JSContext* cx, unsigned argc, V
     if (!SetLengthProperty(cx, obj, args.length()))
         return false;
 
     // Step 11.
     args.rval().setObject(*obj);
     return true;
 }
 
+#define GENERIC JSFUN_GENERIC_NATIVE
+
 static const JSFunctionSpec array_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,      array_toSource,     0,0),
 #endif
     JS_SELF_HOSTED_FN(js_toString_str, "ArrayToString",      0,0),
     JS_FN(js_toLocaleString_str,       array_toLocaleString, 0,0),
 
     /* Perl-ish methods. */
-    JS_INLINABLE_FN("join",     array_join,         1,0, ArrayJoin),
-    JS_FN("reverse",            array_reverse,      0,0),
-    JS_FN("sort",               array_sort,         1,0),
-    JS_INLINABLE_FN("push",     array_push,         1,0, ArrayPush),
-    JS_INLINABLE_FN("pop",      array_pop,          0,0, ArrayPop),
-    JS_INLINABLE_FN("shift",    array_shift,        0,0, ArrayShift),
-    JS_FN("unshift",            array_unshift,      1,0),
-    JS_INLINABLE_FN("splice",   array_splice,       2,0, ArraySplice),
+    JS_INLINABLE_FN("join",     array_join,         1,JSFUN_GENERIC_NATIVE, ArrayJoin),
+    JS_FN("reverse",            array_reverse,      0,JSFUN_GENERIC_NATIVE),
+    JS_FN("sort",               array_sort,         1,JSFUN_GENERIC_NATIVE),
+    JS_INLINABLE_FN("push",     array_push,         1,JSFUN_GENERIC_NATIVE, ArrayPush),
+    JS_INLINABLE_FN("pop",      array_pop,          0,JSFUN_GENERIC_NATIVE, ArrayPop),
+    JS_INLINABLE_FN("shift",    array_shift,        0,JSFUN_GENERIC_NATIVE, ArrayShift),
+    JS_FN("unshift",            array_unshift,      1,JSFUN_GENERIC_NATIVE),
+    JS_INLINABLE_FN("splice",   array_splice,       2,JSFUN_GENERIC_NATIVE, ArraySplice),
 
     /* Pythonic sequence methods. */
     JS_SELF_HOSTED_FN("concat",      "ArrayConcat",      1,0),
-    JS_INLINABLE_FN("slice",    array_slice,        2,0, ArraySlice),
+    JS_INLINABLE_FN("slice",    array_slice,        2,JSFUN_GENERIC_NATIVE, ArraySlice),
 
     JS_SELF_HOSTED_FN("lastIndexOf", "ArrayLastIndexOf", 1,0),
     JS_SELF_HOSTED_FN("indexOf",     "ArrayIndexOf",     1,0),
     JS_SELF_HOSTED_FN("forEach",     "ArrayForEach",     1,0),
     JS_SELF_HOSTED_FN("map",         "ArrayMap",         1,0),
     JS_SELF_HOSTED_FN("filter",      "ArrayFilter",      1,0),
     JS_SELF_HOSTED_FN("reduce",      "ArrayReduce",      1,0),
     JS_SELF_HOSTED_FN("reduceRight", "ArrayReduceRight", 1,0),
@@ -3137,25 +3139,16 @@ static const JSFunctionSpec array_static
     JS_SELF_HOSTED_FN("indexOf",     "ArrayStaticIndexOf", 2,0),
     JS_SELF_HOSTED_FN("forEach",     "ArrayStaticForEach", 2,0),
     JS_SELF_HOSTED_FN("map",         "ArrayStaticMap",   2,0),
     JS_SELF_HOSTED_FN("filter",      "ArrayStaticFilter", 2,0),
     JS_SELF_HOSTED_FN("every",       "ArrayStaticEvery", 2,0),
     JS_SELF_HOSTED_FN("some",        "ArrayStaticSome",  2,0),
     JS_SELF_HOSTED_FN("reduce",      "ArrayStaticReduce", 2,0),
     JS_SELF_HOSTED_FN("reduceRight", "ArrayStaticReduceRight", 2,0),
-    JS_SELF_HOSTED_FN("join",        "ArrayStaticJoin", 2,0),
-    JS_SELF_HOSTED_FN("reverse",     "ArrayStaticReverse", 1,0),
-    JS_SELF_HOSTED_FN("sort",        "ArrayStaticSort", 2,0),
-    JS_SELF_HOSTED_FN("push",        "ArrayStaticPush", 2,0),
-    JS_SELF_HOSTED_FN("pop",         "ArrayStaticPop", 1,0),
-    JS_SELF_HOSTED_FN("shift",       "ArrayStaticShift", 1,0),
-    JS_SELF_HOSTED_FN("unshift",     "ArrayStaticUnshift", 2,0),
-    JS_SELF_HOSTED_FN("splice",      "ArrayStaticSplice", 3,0),
-    JS_SELF_HOSTED_FN("slice",       "ArrayStaticSlice", 3,0),
     JS_SELF_HOSTED_FN("from",        "ArrayFrom", 3,0),
     JS_FN("of",                 array_of,           0,0),
 
     JS_FS_END
 };
 
 const JSPropertySpec array_static_props[] = {
     JS_SELF_HOSTED_SYM_GET(species, "ArraySpecies", 0),
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -179,22 +179,16 @@ extern bool
 array_unshift(JSContext* cx, unsigned argc, js::Value* vp);
 
 extern bool
 array_slice(JSContext* cx, unsigned argc, js::Value* vp);
 
 extern JSObject*
 array_slice_dense(JSContext* cx, HandleObject obj, int32_t begin, int32_t end, HandleObject result);
 
-extern bool
-array_reverse(JSContext* cx, unsigned argc, js::Value* vp);
-
-extern bool
-array_splice(JSContext* cx, unsigned argc, js::Value* vp);
-
 /*
  * Append the given (non-hole) value to the end of an array.  The array must be
  * a newborn array -- that is, one which has not been exposed to script for
  * arbitrary manipulation.  (This method optimizes on the assumption that
  * extending the array to accommodate the element will never make the array
  * sparse, which requires that the array be completely filled.)
  */
 extern bool
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2894,16 +2894,44 @@ js::HasDataProperty(JSContext* cx, Nativ
             *vp = obj->getSlot(shape->slot());
             return true;
         }
     }
 
     return false;
 }
 
+static bool
+GenericNativeMethodDispatcher(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    const JSFunctionSpec* fs = (JSFunctionSpec*)
+        args.callee().as<JSFunction>().getExtendedSlot(0).toPrivate();
+    MOZ_ASSERT((fs->flags & JSFUN_GENERIC_NATIVE) != 0);
+
+    if (argc < 1) {
+        ReportMissingArg(cx, args.calleev(), 0);
+        return false;
+    }
+
+    /*
+     * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
+     * which is almost always the class constructor object, e.g. Array.  Then
+     * call the corresponding prototype native method with our first argument
+     * passed as |this|.
+     */
+    memmove(vp + 1, vp + 2, argc * sizeof(Value));
+
+    /* Clear the last parameter in case too few arguments were passed. */
+    vp[2 + --argc].setUndefined();
+
+    return fs->call.op(cx, argc, vp);
+}
+
 extern bool
 PropertySpecNameToId(JSContext* cx, const char* name, MutableHandleId id,
                      js::PinningBehavior pin = js::DoNotPinAtom);
 
 static bool
 DefineFunctionFromSpec(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs, unsigned flags,
                        DefineAsIntrinsic intrinsic)
 {
@@ -2921,16 +2949,37 @@ DefineFunctionFromSpec(JSContext* cx, Ha
         MOZ_ASSERT(gop != JS_PropertyStub);
         MOZ_ASSERT(sop != JS_StrictPropertyStub);
     }
 
     RootedId id(cx);
     if (!PropertySpecNameToId(cx, fs->name, &id))
         return false;
 
+    // Define a generic arity N+1 static method for the arity N prototype
+    // method if flags contains JSFUN_GENERIC_NATIVE.
+    if (flags & JSFUN_GENERIC_NATIVE) {
+        // We require that any consumers using JSFUN_GENERIC_NATIVE stash
+        // the prototype and constructor in the global slots before invoking
+        // JS_DefineFunctions on the proto.
+        JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
+        MOZ_ASSERT(obj == &obj->global().getPrototype(key).toObject());
+        RootedObject ctor(cx, &obj->global().getConstructor(key).toObject());
+
+        flags &= ~JSFUN_GENERIC_NATIVE;
+        JSFunction* fun = DefineFunction(cx, ctor, id,
+                                         GenericNativeMethodDispatcher,
+                                         fs->nargs + 1, flags,
+                                         gc::AllocKind::FUNCTION_EXTENDED);
+        if (!fun)
+            return false;
+
+        fun->setExtendedSlot(0, PrivateValue(const_cast<JSFunctionSpec*>(fs)));
+    }
+
     JSFunction* fun = NewFunctionFromSpec(cx, fs, id);
     if (!fun)
         return false;
 
     if (intrinsic == AsIntrinsic)
         fun->setIsIntrinsic();
 
     RootedValue funVal(cx, ObjectValue(*fun));
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -677,18 +677,18 @@ ToLowerCaseHelper(JSContext* cx, CallRec
 }
 
 bool
 js::str_toLowerCase(JSContext* cx, unsigned argc, Value* vp)
 {
     return ToLowerCaseHelper(cx, CallArgsFromVp(argc, vp));
 }
 
-bool
-js::str_toLocaleLowerCase(JSContext* cx, unsigned argc, Value* vp)
+static bool
+str_toLocaleLowerCase(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /*
      * Forcefully ignore the first (or any) argument and return toLowerCase(),
      * ECMA has reserved that argument, presumably for defining the locale.
      */
     if (cx->runtime()->localeCallbacks && cx->runtime()->localeCallbacks->localeToLowerCase) {
@@ -828,18 +828,18 @@ ToUpperCaseHelper(JSContext* cx, CallRec
 }
 
 bool
 js::str_toUpperCase(JSContext* cx, unsigned argc, Value* vp)
 {
     return ToUpperCaseHelper(cx, CallArgsFromVp(argc, vp));
 }
 
-bool
-js::str_toLocaleUpperCase(JSContext* cx, unsigned argc, Value* vp)
+static bool
+str_toLocaleUpperCase(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /*
      * Forcefully ignore the first (or any) argument and return toUpperCase(),
      * ECMA has reserved that argument, presumably for defining the locale.
      */
     if (cx->runtime()->localeCallbacks && cx->runtime()->localeCallbacks->localeToUpperCase) {
@@ -854,18 +854,18 @@ js::str_toLocaleUpperCase(JSContext* cx,
         args.rval().set(result);
         return true;
     }
 
     return ToUpperCaseHelper(cx, args);
 }
 
 #if !EXPOSE_INTL_API
-bool
-js::str_localeCompare(JSContext* cx, unsigned argc, Value* vp)
+static bool
+str_localeCompare(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedString str(cx, ThisToStringForStringProto(cx, args));
     if (!str)
         return false;
 
     RootedString thatStr(cx, ToString<CanGC>(cx, args.get(0)));
     if (!thatStr)
@@ -886,18 +886,18 @@ js::str_localeCompare(JSContext* cx, uns
 
     args.rval().setInt32(result);
     return true;
 }
 #endif
 
 #if EXPOSE_INTL_API
 /* ES6 20140210 draft 21.1.3.12. */
-bool
-js::str_normalize(JSContext* cx, unsigned argc, Value* vp)
+static bool
+str_normalize(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     // Steps 1-3.
     RootedString str(cx, ThisToStringForStringProto(cx, args));
     if (!str)
         return false;
 
@@ -1815,18 +1815,18 @@ js::str_startsWith(JSContext* cx, unsign
     if (!text)
         return false;
 
     args.rval().setBoolean(HasSubstringAt(text, searchStr, start));
     return true;
 }
 
 /* ES6 draft rc3 21.1.3.6. */
-bool
-js::str_endsWith(JSContext* cx, unsigned argc, Value* vp)
+static bool
+str_endsWith(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     // Steps 1, 2, and 3
     RootedString str(cx, ThisToStringForStringProto(cx, args));
     if (!str)
         return false;
 
@@ -1934,30 +1934,30 @@ TrimString(JSContext* cx, Value* vp, boo
     str = NewDependentString(cx, str, begin, end - begin);
     if (!str)
         return false;
 
     call.rval().setString(str);
     return true;
 }
 
-bool
-js::str_trim(JSContext* cx, unsigned argc, Value* vp)
+static bool
+str_trim(JSContext* cx, unsigned argc, Value* vp)
 {
     return TrimString(cx, vp, true, true);
 }
 
-bool
-js::str_trimLeft(JSContext* cx, unsigned argc, Value* vp)
+static bool
+str_trimLeft(JSContext* cx, unsigned argc, Value* vp)
 {
     return TrimString(cx, vp, true, false);
 }
 
-bool
-js::str_trimRight(JSContext* cx, unsigned argc, Value* vp)
+static bool
+str_trimRight(JSContext* cx, unsigned argc, Value* vp)
 {
     return TrimString(cx, vp, false, true);
 }
 
 // Utility for building a rope (lazy concatenation) of strings.
 class RopeBuilder {
     JSContext* cx;
     RootedString res;
@@ -2481,18 +2481,18 @@ js::str_split_string(JSContext* cx, Hand
         return CharSplitHelper(cx, linearStr, limit, group);
 
     return SplitHelper(cx, linearStr, limit, linearSep, group);
 }
 
 /*
  * Python-esque sequence operations.
  */
-bool
-js::str_concat(JSContext* cx, unsigned argc, Value* vp)
+static bool
+str_concat(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JSString* str = ThisToStringForStringProto(cx, args);
     if (!str)
         return false;
 
     for (unsigned i = 0; i < args.length(); i++) {
         JSString* argStr = ToString<NoGC>(cx, args[i]);
@@ -2522,53 +2522,53 @@ js::str_concat(JSContext* cx, unsigned a
 static const JSFunctionSpec string_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,     str_toSource,          0,0),
 #endif
 
     /* Java-like methods. */
     JS_FN(js_toString_str,     str_toString,          0,0),
     JS_FN(js_valueOf_str,      str_toString,          0,0),
-    JS_FN("toLowerCase",       str_toLowerCase,       0,0),
-    JS_FN("toUpperCase",       str_toUpperCase,       0,0),
-    JS_INLINABLE_FN("charAt",  str_charAt,            1,0, StringCharAt),
-    JS_INLINABLE_FN("charCodeAt", str_charCodeAt,     1,0, StringCharCodeAt),
+    JS_FN("toLowerCase",       str_toLowerCase,       0,JSFUN_GENERIC_NATIVE),
+    JS_FN("toUpperCase",       str_toUpperCase,       0,JSFUN_GENERIC_NATIVE),
+    JS_INLINABLE_FN("charAt",  str_charAt,            1,JSFUN_GENERIC_NATIVE, StringCharAt),
+    JS_INLINABLE_FN("charCodeAt", str_charCodeAt,     1,JSFUN_GENERIC_NATIVE, StringCharCodeAt),
     JS_SELF_HOSTED_FN("substring", "String_substring", 2,0),
     JS_SELF_HOSTED_FN("padStart", "String_pad_start", 2,0),
     JS_SELF_HOSTED_FN("padEnd", "String_pad_end", 2,0),
     JS_SELF_HOSTED_FN("codePointAt", "String_codePointAt", 1,0),
-    JS_FN("includes",          str_includes,          1,0),
-    JS_FN("indexOf",           str_indexOf,           1,0),
-    JS_FN("lastIndexOf",       str_lastIndexOf,       1,0),
-    JS_FN("startsWith",        str_startsWith,        1,0),
-    JS_FN("endsWith",          str_endsWith,          1,0),
-    JS_FN("trim",              str_trim,              0,0),
-    JS_FN("trimLeft",          str_trimLeft,          0,0),
-    JS_FN("trimRight",         str_trimRight,         0,0),
-    JS_FN("toLocaleLowerCase", str_toLocaleLowerCase, 0,0),
-    JS_FN("toLocaleUpperCase", str_toLocaleUpperCase, 0,0),
+    JS_FN("includes",          str_includes,          1,JSFUN_GENERIC_NATIVE),
+    JS_FN("indexOf",           str_indexOf,           1,JSFUN_GENERIC_NATIVE),
+    JS_FN("lastIndexOf",       str_lastIndexOf,       1,JSFUN_GENERIC_NATIVE),
+    JS_FN("startsWith",        str_startsWith,        1,JSFUN_GENERIC_NATIVE),
+    JS_FN("endsWith",          str_endsWith,          1,JSFUN_GENERIC_NATIVE),
+    JS_FN("trim",              str_trim,              0,JSFUN_GENERIC_NATIVE),
+    JS_FN("trimLeft",          str_trimLeft,          0,JSFUN_GENERIC_NATIVE),
+    JS_FN("trimRight",         str_trimRight,         0,JSFUN_GENERIC_NATIVE),
+    JS_FN("toLocaleLowerCase", str_toLocaleLowerCase, 0,JSFUN_GENERIC_NATIVE),
+    JS_FN("toLocaleUpperCase", str_toLocaleUpperCase, 0,JSFUN_GENERIC_NATIVE),
 #if EXPOSE_INTL_API
     JS_SELF_HOSTED_FN("localeCompare", "String_localeCompare", 1,0),
 #else
-    JS_FN("localeCompare",     str_localeCompare,     1,0),
+    JS_FN("localeCompare",     str_localeCompare,     1,JSFUN_GENERIC_NATIVE),
 #endif
     JS_SELF_HOSTED_FN("repeat", "String_repeat",      1,0),
 #if EXPOSE_INTL_API
-    JS_FN("normalize",         str_normalize,         0,0),
+    JS_FN("normalize",         str_normalize,         0,JSFUN_GENERIC_NATIVE),
 #endif
 
     /* Perl-ish methods (search is actually Python-esque). */
     JS_SELF_HOSTED_FN("match", "String_match",        1,0),
     JS_SELF_HOSTED_FN("search", "String_search",      1,0),
     JS_SELF_HOSTED_FN("replace", "String_replace",    2,0),
     JS_SELF_HOSTED_FN("split",  "String_split",       2,0),
     JS_SELF_HOSTED_FN("substr", "String_substr",      2,0),
 
     /* Python-esque sequence methods. */
-    JS_FN("concat",            str_concat,            1,0),
+    JS_FN("concat",            str_concat,            1,JSFUN_GENERIC_NATIVE),
     JS_SELF_HOSTED_FN("slice", "String_slice",        2,0),
 
     /* HTML string methods. */
     JS_SELF_HOSTED_FN("bold",     "String_bold",       0,0),
     JS_SELF_HOSTED_FN("italics",  "String_italics",    0,0),
     JS_SELF_HOSTED_FN("fixed",    "String_fixed",      0,0),
     JS_SELF_HOSTED_FN("strike",   "String_strike",     0,0),
     JS_SELF_HOSTED_FN("small",    "String_small",      0,0),
@@ -2711,36 +2711,21 @@ static const JSFunctionSpec string_stati
     JS_SELF_HOSTED_FN("substr",          "String_static_substr",        3,0),
     JS_SELF_HOSTED_FN("slice",           "String_static_slice",         3,0),
 
     JS_SELF_HOSTED_FN("match",           "String_generic_match",        2,0),
     JS_SELF_HOSTED_FN("replace",         "String_generic_replace",      3,0),
     JS_SELF_HOSTED_FN("search",          "String_generic_search",       2,0),
     JS_SELF_HOSTED_FN("split",           "String_generic_split",        3,0),
 
-    JS_SELF_HOSTED_FN("toLowerCase",     "String_static_toLowerCase",   1,0),
-    JS_SELF_HOSTED_FN("toUpperCase",     "String_static_toUpperCase",   1,0),
-    JS_SELF_HOSTED_FN("charAt",          "String_static_charAt",        2,0),
-    JS_SELF_HOSTED_FN("charCodeAt",      "String_static_charCodeAt",    2,0),
-    JS_SELF_HOSTED_FN("includes",        "String_static_includes",      2,0),
-    JS_SELF_HOSTED_FN("indexOf",         "String_static_indexOf",       2,0),
-    JS_SELF_HOSTED_FN("lastIndexOf",     "String_static_lastIndexOf",   2,0),
-    JS_SELF_HOSTED_FN("startsWith",      "String_static_startsWith",    2,0),
-    JS_SELF_HOSTED_FN("endsWith",        "String_static_endsWith",      2,0),
-    JS_SELF_HOSTED_FN("trim",            "String_static_trim",          1,0),
-    JS_SELF_HOSTED_FN("trimLeft",        "String_static_trimLeft",      1,0),
-    JS_SELF_HOSTED_FN("trimRight",       "String_static_trimRight",     1,0),
-    JS_SELF_HOSTED_FN("toLocaleLowerCase","String_static_toLocaleLowerCase",1,0),
-    JS_SELF_HOSTED_FN("toLocaleUpperCase","String_static_toLocaleUpperCase",1,0),
+    // This must be at the end because of bug 853075: functions listed after
+    // self-hosted methods aren't available in self-hosted code.
 #if EXPOSE_INTL_API
-    JS_SELF_HOSTED_FN("normalize",       "String_static_normalize",     1,0),
+    JS_SELF_HOSTED_FN("localeCompare",   "String_static_localeCompare", 2,0),
 #endif
-    JS_SELF_HOSTED_FN("concat",          "String_static_concat",        2,0),
-
-    JS_SELF_HOSTED_FN("localeCompare",   "String_static_localeCompare", 2,0),
     JS_FS_END
 };
 
 /* static */ Shape*
 StringObject::assignInitialShape(ExclusiveContext* cx, Handle<StringObject*> obj)
 {
     MOZ_ASSERT(obj->empty());
 
@@ -2762,35 +2747,35 @@ js::InitStringClass(JSContext* cx, Handl
 
     /* Now create the String function. */
     RootedFunction ctor(cx);
     ctor = global->createConstructor(cx, StringConstructor, cx->names().String, 1,
                                      AllocKind::FUNCTION, &jit::JitInfo_String);
     if (!ctor)
         return nullptr;
 
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_String, ctor, proto))
+        return nullptr;
+
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return nullptr;
 
     if (!DefinePropertiesAndFunctions(cx, proto, nullptr, string_methods) ||
         !DefinePropertiesAndFunctions(cx, ctor, nullptr, string_static_methods))
     {
         return nullptr;
     }
 
     /*
      * Define escape/unescape, the URI encode/decode functions, and maybe
      * uneval on the global object.
      */
     if (!JS_DefineFunctions(cx, global, string_functions))
         return nullptr;
 
-    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_String, ctor, proto))
-        return nullptr;
-
     return proto;
 }
 
 const char*
 js::ValueToPrintable(JSContext* cx, const Value& vArg, JSAutoByteString* bytes, bool asSource)
 {
     RootedValue v(cx, vArg);
     JSString* str;
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -333,49 +333,16 @@ str_toString(JSContext* cx, unsigned arg
 extern bool
 str_charAt(JSContext* cx, unsigned argc, Value* vp);
 
 extern bool
 str_charCodeAt_impl(JSContext* cx, HandleString string, HandleValue index, MutableHandleValue res);
 
 extern bool
 str_charCodeAt(JSContext* cx, unsigned argc, Value* vp);
-
-extern bool
-str_contains(JSContext *cx, unsigned argc, Value *vp);
-
-extern bool
-str_endsWith(JSContext* cx, unsigned argc, Value* vp);
-
-extern bool
-str_trim(JSContext* cx, unsigned argc, Value* vp);
-
-extern bool
-str_trimLeft(JSContext* cx, unsigned argc, Value* vp);
-
-extern bool
-str_trimRight(JSContext* cx, unsigned argc, Value* vp);
-
-extern bool
-str_toLocaleLowerCase(JSContext* cx, unsigned argc, Value* vp);
-
-extern bool
-str_toLocaleUpperCase(JSContext* cx, unsigned argc, Value* vp);
-
-#if !EXPOSE_INTL_API
-extern bool
-str_localeCompare(JSContext* cx, unsigned argc, Value* vp);
-#else
-extern bool
-str_normalize(JSContext* cx, unsigned argc, Value* vp);
-#endif
-
-extern bool
-str_concat(JSContext* cx, unsigned argc, Value* vp);
-
 /*
  * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
  * least 4 bytes long.  Return the number of UTF-8 bytes of data written.
  */
 extern uint32_t
 OneUcs4ToUtf8Char(uint8_t* utf8Buffer, uint32_t ucs4Char);
 
 extern size_t
deleted file mode 100644
--- a/js/src/tests/js1_6/Array/generics.js
+++ /dev/null
@@ -1,331 +0,0 @@
-var BUGNUMBER = 1263558;
-var summary = "Self-host all Array generics.";
-
-print(BUGNUMBER + ": " + summary);
-
-var arr, arrLike, tmp, f;
-
-function reset() {
-  arr = [5, 7, 13];
-  arrLike = {
-    length: 3,
-    0: 5,
-    1: 7,
-    2: 13,
-    toString() {
-      return "arrLike";
-    }
-  };
-  tmp = [];
-}
-function toString() {
-  return "G";
-}
-
-// Array.join (test this first to use it in remaining tests).
-reset();
-assertThrowsInstanceOf(() => Array.join(), TypeError);
-assertEq(Array.join(arr), "5,7,13");
-assertEq(Array.join(arr, "-"), "5-7-13");
-assertEq(Array.join(arrLike), "5,7,13");
-assertEq(Array.join(arrLike, "-"), "5-7-13");
-
-// Array.concat.
-reset();
-assertThrowsInstanceOf(() => Array.concat(), TypeError);
-assertEq(Array.join(Array.concat(arr), ","), "5,7,13");
-assertEq(Array.join(Array.concat(arr, 11), ","), "5,7,13,11");
-assertEq(Array.join(Array.concat(arr, 11, 17), ","), "5,7,13,11,17");
-assertEq(Array.join(Array.concat(arrLike), ","), "arrLike");
-assertEq(Array.join(Array.concat(arrLike, 11), ","), "arrLike,11");
-assertEq(Array.join(Array.concat(arrLike, 11, 17), ","), "arrLike,11,17");
-
-// Array.lastIndexOf.
-reset();
-assertThrowsInstanceOf(() => Array.lastIndexOf(), TypeError);
-assertEq(Array.lastIndexOf(arr), -1);
-assertEq(Array.lastIndexOf(arr, 1), -1);
-assertEq(Array.lastIndexOf(arr, 5), 0);
-assertEq(Array.lastIndexOf(arr, 7), 1);
-assertEq(Array.lastIndexOf(arr, 13, 1), -1);
-assertEq(Array.lastIndexOf(arrLike), -1);
-assertEq(Array.lastIndexOf(arrLike, 1), -1);
-assertEq(Array.lastIndexOf(arrLike, 5), 0);
-assertEq(Array.lastIndexOf(arrLike, 7), 1);
-assertEq(Array.lastIndexOf(arrLike, 13, 1), -1);
-
-// Array.indexOf.
-reset();
-assertThrowsInstanceOf(() => Array.indexOf(), TypeError);
-assertEq(Array.indexOf(arr), -1);
-assertEq(Array.indexOf(arr, 1), -1);
-assertEq(Array.indexOf(arr, 5), 0);
-assertEq(Array.indexOf(arr, 7), 1);
-assertEq(Array.indexOf(arr, 1, 5), -1);
-assertEq(Array.indexOf(arrLike), -1);
-assertEq(Array.indexOf(arrLike, 1), -1);
-assertEq(Array.indexOf(arrLike, 5), 0);
-assertEq(Array.indexOf(arrLike, 7), 1);
-assertEq(Array.indexOf(arrLike, 1, 5), -1);
-
-// Array.forEach.
-reset();
-assertThrowsInstanceOf(() => Array.forEach(), TypeError);
-assertThrowsInstanceOf(() => Array.forEach(arr), TypeError);
-assertThrowsInstanceOf(() => Array.forEach(arrLike), TypeError);
-f = function(...args) {
-  tmp.push(this, ...args);
-};
-tmp = [];
-Array.forEach(arr, f);
-assertEq(tmp.join(","), "G,5,0,5,7,13," + "G,7,1,5,7,13," + "G,13,2,5,7,13");
-tmp = [];
-Array.forEach(arr, f, "T");
-assertEq(tmp.join(","), "T,5,0,5,7,13," + "T,7,1,5,7,13," + "T,13,2,5,7,13");
-tmp = [];
-Array.forEach(arrLike, f);
-assertEq(tmp.join(","), "G,5,0,arrLike," + "G,7,1,arrLike," + "G,13,2,arrLike");
-tmp = [];
-Array.forEach(arrLike, f, "T");
-assertEq(tmp.join(","), "T,5,0,arrLike," + "T,7,1,arrLike," + "T,13,2,arrLike");
-
-// Array.map.
-reset();
-assertThrowsInstanceOf(() => Array.map(), TypeError);
-assertThrowsInstanceOf(() => Array.map(arr), TypeError);
-assertThrowsInstanceOf(() => Array.map(arrLike), TypeError);
-f = function(...args) {
-  tmp.push(this, ...args);
-  return args[0] * 2;
-}
-tmp = [];
-assertEq(Array.join(Array.map(arr, f), ","), "10,14,26");
-assertEq(tmp.join(","), "G,5,0,5,7,13," + "G,7,1,5,7,13," + "G,13,2,5,7,13");
-tmp = [];
-assertEq(Array.join(Array.map(arr, f, "T"), ","), "10,14,26");
-assertEq(tmp.join(","), "T,5,0,5,7,13," + "T,7,1,5,7,13," + "T,13,2,5,7,13");
-tmp = [];
-assertEq(Array.join(Array.map(arrLike, f), ","), "10,14,26");
-assertEq(tmp.join(","), "G,5,0,arrLike," + "G,7,1,arrLike," + "G,13,2,arrLike");
-tmp = [];
-assertEq(Array.join(Array.map(arrLike, f, "T"), ","), "10,14,26");
-assertEq(tmp.join(","), "T,5,0,arrLike," + "T,7,1,arrLike," + "T,13,2,arrLike");
-
-// Array.filter.
-reset();
-assertThrowsInstanceOf(() => Array.filter(), TypeError);
-assertThrowsInstanceOf(() => Array.filter(arr), TypeError);
-assertThrowsInstanceOf(() => Array.filter(arrLike), TypeError);
-f = function(...args) {
-  tmp.push(this, ...args);
-  return args[0] < 10;
-}
-tmp = [];
-assertEq(Array.join(Array.filter(arr, f), ","), "5,7");
-assertEq(tmp.join(","), "G,5,0,5,7,13," + "G,7,1,5,7,13," + "G,13,2,5,7,13");
-tmp = [];
-assertEq(Array.join(Array.filter(arr, f, "T"), ","), "5,7");
-assertEq(tmp.join(","), "T,5,0,5,7,13," + "T,7,1,5,7,13," + "T,13,2,5,7,13");
-tmp = [];
-assertEq(Array.join(Array.filter(arrLike, f), ","), "5,7");
-assertEq(tmp.join(","), "G,5,0,arrLike," + "G,7,1,arrLike," + "G,13,2,arrLike");
-tmp = [];
-assertEq(Array.join(Array.filter(arrLike, f, "T"), ","), "5,7");
-assertEq(tmp.join(","), "T,5,0,arrLike," + "T,7,1,arrLike," + "T,13,2,arrLike");
-
-// Array.every.
-reset();
-assertThrowsInstanceOf(() => Array.every(), TypeError);
-assertThrowsInstanceOf(() => Array.every(arr), TypeError);
-assertThrowsInstanceOf(() => Array.every(arrLike), TypeError);
-f = function(...args) {
-  tmp.push(this, ...args);
-  return args[0] < 6;
-}
-tmp = [];
-assertEq(Array.every(arr, f), false);
-assertEq(tmp.join(","), "G,5,0,5,7,13," + "G,7,1,5,7,13");
-tmp = [];
-assertEq(Array.every(arr, f, "T"), false);
-assertEq(tmp.join(","), "T,5,0,5,7,13," + "T,7,1,5,7,13");
-tmp = [];
-assertEq(Array.every(arrLike, f), false);
-assertEq(tmp.join(","), "G,5,0,arrLike," + "G,7,1,arrLike");
-tmp = [];
-assertEq(Array.every(arrLike, f, "T"), false);
-assertEq(tmp.join(","), "T,5,0,arrLike," + "T,7,1,arrLike");
-
-// Array.some.
-reset();
-assertThrowsInstanceOf(() => Array.some(), TypeError);
-assertThrowsInstanceOf(() => Array.some(arr), TypeError);
-assertThrowsInstanceOf(() => Array.some(arrLike), TypeError);
-f = function(...args) {
-  tmp.push(this, ...args);
-  return args[0] == 7;
-}
-tmp = [];
-assertEq(Array.some(arr, f), true);
-assertEq(tmp.join(","), "G,5,0,5,7,13," + "G,7,1,5,7,13");
-tmp = [];
-assertEq(Array.some(arr, f, "T"), true);
-assertEq(tmp.join(","), "T,5,0,5,7,13," + "T,7,1,5,7,13");
-tmp = [];
-assertEq(Array.some(arrLike, f), true);
-assertEq(tmp.join(","), "G,5,0,arrLike," + "G,7,1,arrLike");
-tmp = [];
-assertEq(Array.some(arrLike, f, "T"), true);
-assertEq(tmp.join(","), "T,5,0,arrLike," + "T,7,1,arrLike");
-
-// Array.reduce.
-reset();
-assertThrowsInstanceOf(() => Array.reduce(), TypeError);
-assertThrowsInstanceOf(() => Array.reduce(arr), TypeError);
-assertThrowsInstanceOf(() => Array.reduce(arrLike), TypeError);
-f = function(...args) {
-  tmp.push(...args);
-  return args[0] + args[1];
-}
-tmp = [];
-assertEq(Array.reduce(arr, f), 25);
-assertEq(tmp.join(","), "5,7,1,5,7,13," + "12,13,2,5,7,13");
-tmp = [];
-assertEq(Array.reduce(arr, f, 17), 42);
-assertEq(tmp.join(","), "17,5,0,5,7,13," + "22,7,1,5,7,13," + "29,13,2,5,7,13");
-tmp = [];
-assertEq(Array.reduce(arrLike, f), 25);
-assertEq(tmp.join(","), "5,7,1,arrLike," + "12,13,2,arrLike");
-tmp = [];
-assertEq(Array.reduce(arrLike, f, 17), 42);
-assertEq(tmp.join(","), "17,5,0,arrLike," + "22,7,1,arrLike," + "29,13,2,arrLike");
-
-// Array.reduceRight.
-reset();
-assertThrowsInstanceOf(() => Array.reduceRight(), TypeError);
-assertThrowsInstanceOf(() => Array.reduceRight(arr), TypeError);
-assertThrowsInstanceOf(() => Array.reduceRight(arrLike), TypeError);
-f = function(...args) {
-  tmp.push(...args);
-  return args[0] + args[1];
-}
-tmp = [];
-assertEq(Array.reduceRight(arr, f), 25);
-assertEq(tmp.join(","), "13,7,1,5,7,13," + "20,5,0,5,7,13");
-tmp = [];
-assertEq(Array.reduceRight(arr, f, 17), 42);
-assertEq(tmp.join(","), "17,13,2,5,7,13," + "30,7,1,5,7,13," + "37,5,0,5,7,13");
-tmp = [];
-assertEq(Array.reduceRight(arrLike, f), 25);
-assertEq(tmp.join(","), "13,7,1,arrLike," + "20,5,0,arrLike");
-tmp = [];
-assertEq(Array.reduceRight(arrLike, f, 17), 42);
-assertEq(tmp.join(","), "17,13,2,arrLike," + "30,7,1,arrLike," + "37,5,0,arrLike");
-
-// Array.reverse.
-reset();
-assertThrowsInstanceOf(() => Array.reverse(), TypeError);
-assertEq(Array.join(Array.reverse(arr), ","), "13,7,5");
-assertEq(Array.join(arr, ","), "13,7,5");
-assertEq(Array.join(Array.reverse(arrLike), ","), "13,7,5");
-assertEq(Array.join(arrLike, ","), "13,7,5");
-
-// Array.sort.
-reset();
-assertThrowsInstanceOf(() => Array.sort(), TypeError);
-f = function(x, y) {
-  return y - x;
-}
-assertEq(Array.join(Array.sort(arr), ","), "13,5,7");
-assertEq(Array.join(Array.sort(arr, f), ","), "13,7,5");
-assertEq(Array.join(Array.sort(arrLike), ","), "13,5,7");
-assertEq(Array.join(Array.sort(arrLike, f), ","), "13,7,5");
-
-// Array.push.
-reset();
-assertThrowsInstanceOf(() => Array.push(), TypeError);
-assertEq(Array.push(arr), 3);
-assertEq(Array.join(arr), "5,7,13");
-assertEq(Array.push(arr, 17), 4);
-assertEq(Array.join(arr), "5,7,13,17");
-assertEq(Array.push(arr, 19, 21), 6);
-assertEq(Array.join(arr), "5,7,13,17,19,21");
-assertEq(Array.push(arrLike), 3);
-assertEq(Array.join(arrLike), "5,7,13");
-assertEq(Array.push(arrLike, 17), 4);
-assertEq(Array.join(arrLike), "5,7,13,17");
-assertEq(Array.push(arrLike, 19, 21), 6);
-assertEq(Array.join(arrLike), "5,7,13,17,19,21");
-
-// Array.pop.
-reset();
-assertThrowsInstanceOf(() => Array.pop(), TypeError);
-assertEq(Array.pop(arr), 13);
-assertEq(Array.join(arr), "5,7");
-assertEq(Array.pop(arr), 7);
-assertEq(Array.join(arr), "5");
-assertEq(Array.pop(arrLike), 13);
-assertEq(Array.join(arrLike), "5,7");
-assertEq(Array.pop(arrLike), 7);
-assertEq(Array.join(arrLike), "5");
-
-// Array.shift.
-reset();
-assertThrowsInstanceOf(() => Array.shift(), TypeError);
-assertEq(Array.shift(arr), 5);
-assertEq(Array.join(arr), "7,13");
-assertEq(Array.shift(arr), 7);
-assertEq(Array.join(arr), "13");
-assertEq(Array.shift(arrLike), 5);
-assertEq(Array.join(arrLike), "7,13");
-assertEq(Array.shift(arrLike), 7);
-assertEq(Array.join(arrLike), "13");
-
-// Array.unshift.
-reset();
-assertThrowsInstanceOf(() => Array.unshift(), TypeError);
-assertEq(Array.unshift(arr), 3);
-assertEq(Array.join(arr), "5,7,13");
-assertEq(Array.unshift(arr, 17), 4);
-assertEq(Array.join(arr), "17,5,7,13");
-assertEq(Array.unshift(arr, 19, 21), 6);
-assertEq(Array.join(arr), "19,21,17,5,7,13");
-assertEq(Array.unshift(arrLike), 3);
-assertEq(Array.join(arrLike), "5,7,13");
-assertEq(Array.unshift(arrLike, 17), 4);
-assertEq(Array.join(arrLike), "17,5,7,13");
-assertEq(Array.unshift(arrLike, 19, 21), 6);
-assertEq(Array.join(arrLike), "19,21,17,5,7,13");
-
-// Array.splice.
-reset();
-assertThrowsInstanceOf(() => Array.splice(), TypeError);
-assertEq(Array.join(Array.splice(arr)), "");
-assertEq(Array.join(arr), "5,7,13");
-assertEq(Array.join(Array.splice(arr, 1)), "7,13");
-assertEq(Array.join(arr), "5");
-reset();
-assertEq(Array.join(Array.splice(arr, 1, 1)), "7");
-assertEq(Array.join(arr), "5,13");
-reset();
-assertEq(Array.join(Array.splice(arrLike)), "");
-assertEq(Array.join(arrLike), "5,7,13");
-assertEq(Array.join(Array.splice(arrLike, 1)), "7,13");
-assertEq(Array.join(arrLike), "5");
-reset();
-assertEq(Array.join(Array.splice(arrLike, 1, 1)), "7");
-assertEq(Array.join(arrLike), "5,13");
-
-// Array.slice.
-reset();
-assertThrowsInstanceOf(() => Array.slice(), TypeError);
-assertEq(Array.join(Array.slice(arr)), "5,7,13");
-assertEq(Array.join(Array.slice(arr, 1)), "7,13");
-assertEq(Array.join(Array.slice(arr, 1, 1)), "");
-assertEq(Array.join(Array.slice(arr, 1, 2)), "7");
-assertEq(Array.join(Array.slice(arrLike)), "5,7,13");
-assertEq(Array.join(Array.slice(arrLike, 1)), "7,13");
-assertEq(Array.join(Array.slice(arrLike, 1, 1)), "");
-assertEq(Array.join(Array.slice(arrLike, 1, 2)), "7");
-
-if (typeof reportCompare === "function")
-  reportCompare(true, true);
deleted file mode 100644
--- a/js/src/tests/js1_6/String/generics.js
+++ /dev/null
@@ -1,228 +0,0 @@
-var BUGNUMBER = 1263558;
-var summary = "Self-host all String generics.";
-
-print(BUGNUMBER + ": " + summary);
-
-var result;
-var str = "ABCde";
-var strObj = {
-  toString() {
-    return "ABCde";
-  }
-};
-
-// String.substring.
-assertThrowsInstanceOf(() => String.substring(), TypeError);
-assertEq(String.substring(str), "ABCde");
-assertEq(String.substring(str, 1), "BCde");
-assertEq(String.substring(str, 1, 3), "BC");
-assertEq(String.substring(strObj), "ABCde");
-assertEq(String.substring(strObj, 1), "BCde");
-assertEq(String.substring(strObj, 1, 3), "BC");
-
-// String.substr.
-assertThrowsInstanceOf(() => String.substr(), TypeError);
-assertEq(String.substr(str), "ABCde");
-assertEq(String.substr(str, 1), "BCde");
-assertEq(String.substr(str, 1, 3), "BCd");
-assertEq(String.substr(strObj), "ABCde");
-assertEq(String.substr(strObj, 1), "BCde");
-assertEq(String.substr(strObj, 1, 3), "BCd");
-
-// String.slice.
-assertThrowsInstanceOf(() => String.slice(), TypeError);
-assertEq(String.slice(str), "ABCde");
-assertEq(String.slice(str, 1), "BCde");
-assertEq(String.slice(str, 1, 3), "BC");
-assertEq(String.slice(strObj), "ABCde");
-assertEq(String.slice(strObj, 1), "BCde");
-assertEq(String.slice(strObj, 1, 3), "BC");
-
-// String.match.
-assertThrowsInstanceOf(() => String.match(), TypeError);
-result = String.match(str);
-assertEq(result.index, 0);
-assertEq(result.length, 1);
-assertEq(result[0], "");
-result = String.match(str, /c/i);
-assertEq(result.index, 2);
-assertEq(result.length, 1);
-assertEq(result[0], "C");
-result = String.match(strObj);
-assertEq(result.index, 0);
-assertEq(result.length, 1);
-assertEq(result[0], "");
-result = String.match(strObj, /c/i);
-assertEq(result.index, 2);
-assertEq(result.length, 1);
-assertEq(result[0], "C");
-
-// String.replace.
-assertThrowsInstanceOf(() => String.replace(), TypeError);
-assertEq(String.replace(str), "ABCde");
-assertEq(String.replace(str, /c/i), "ABundefinedde");
-assertEq(String.replace(str, /c/i, "x"), "ABxde");
-assertEq(String.replace(strObj), "ABCde");
-assertEq(String.replace(strObj, /c/i), "ABundefinedde");
-assertEq(String.replace(strObj, /c/i, "x"), "ABxde");
-
-// String.search.
-assertThrowsInstanceOf(() => String.search(), TypeError);
-assertEq(String.search(str), 0);
-assertEq(String.search(str, /c/i), 2);
-assertEq(String.search(strObj), 0);
-assertEq(String.search(strObj, /c/i), 2);
-
-// String.split.
-assertThrowsInstanceOf(() => String.split(), TypeError);
-assertEq(String.split(str).join(","), "ABCde");
-assertEq(String.split(str, /[bd]/i).join(","), "A,C,e");
-assertEq(String.split(str, /[bd]/i, 2).join(","), "A,C");
-assertEq(String.split(strObj).join(","), "ABCde");
-assertEq(String.split(strObj, /[bd]/i).join(","), "A,C,e");
-assertEq(String.split(strObj, /[bd]/i, 2).join(","), "A,C");
-
-// String.toLowerCase.
-assertThrowsInstanceOf(() => String.toLowerCase(), TypeError);
-assertEq(String.toLowerCase(str), "abcde");
-assertEq(String.toLowerCase(strObj), "abcde");
-
-// String.toUpperCase.
-assertThrowsInstanceOf(() => String.toUpperCase(), TypeError);
-assertEq(String.toUpperCase(str), "ABCDE");
-assertEq(String.toUpperCase(strObj), "ABCDE");
-
-// String.charAt.
-assertThrowsInstanceOf(() => String.charAt(), TypeError);
-assertEq(String.charAt(str), "A");
-assertEq(String.charAt(str, 2), "C");
-assertEq(String.charAt(strObj), "A");
-assertEq(String.charAt(strObj, 2), "C");
-
-// String.charCodeAt.
-assertThrowsInstanceOf(() => String.charCodeAt(), TypeError);
-assertEq(String.charCodeAt(str), 65);
-assertEq(String.charCodeAt(str, 2), 67);
-assertEq(String.charCodeAt(strObj), 65);
-assertEq(String.charCodeAt(strObj, 2), 67);
-
-// String.includes.
-assertThrowsInstanceOf(() => String.includes(), TypeError);
-assertEq(String.includes(str), false);
-assertEq(String.includes(str, "C"), true);
-assertEq(String.includes(str, "C", 2), true);
-assertEq(String.includes(str, "C", 3), false);
-assertEq(String.includes(strObj), false);
-assertEq(String.includes(strObj, "C"), true);
-assertEq(String.includes(strObj, "C", 2), true);
-assertEq(String.includes(strObj, "C", 3), false);
-
-// String.indexOf.
-assertThrowsInstanceOf(() => String.indexOf(), TypeError);
-assertEq(String.indexOf(str), -1);
-assertEq(String.indexOf(str, "C"), 2);
-assertEq(String.indexOf(str, "C", 2), 2);
-assertEq(String.indexOf(str, "C", 3), -1);
-assertEq(String.indexOf(strObj), -1);
-assertEq(String.indexOf(strObj, "C"), 2);
-assertEq(String.indexOf(strObj, "C", 2), 2);
-assertEq(String.indexOf(strObj, "C", 3), -1);
-
-// String.lastIndexOf.
-assertThrowsInstanceOf(() => String.lastIndexOf(), TypeError);
-assertEq(String.lastIndexOf(str), -1);
-assertEq(String.lastIndexOf(str, "C"), 2);
-assertEq(String.lastIndexOf(str, "C", 2), 2);
-assertEq(String.lastIndexOf(str, "C", 1), -1);
-assertEq(String.lastIndexOf(strObj), -1);
-assertEq(String.lastIndexOf(strObj, "C"), 2);
-assertEq(String.lastIndexOf(strObj, "C", 2), 2);
-assertEq(String.lastIndexOf(strObj, "C", 1), -1);
-
-// String.startsWith.
-assertThrowsInstanceOf(() => String.startsWith(), TypeError);
-assertEq(String.startsWith(str), false);
-assertEq(String.startsWith(str, "A"), true);
-assertEq(String.startsWith(str, "B", 0), false);
-assertEq(String.startsWith(str, "B", 1), true);
-assertEq(String.startsWith(strObj), false);
-assertEq(String.startsWith(strObj, "A"), true);
-assertEq(String.startsWith(strObj, "B", 0), false);
-assertEq(String.startsWith(strObj, "B", 1), true);
-
-// String.endsWith.
-assertThrowsInstanceOf(() => String.endsWith(), TypeError);
-assertEq(String.endsWith(str), false);
-assertEq(String.endsWith(str, "e"), true);
-assertEq(String.endsWith(str, "B", 0), false);
-assertEq(String.endsWith(str, "B", 2), true);
-assertEq(String.endsWith(strObj), false);
-assertEq(String.endsWith(strObj, "e"), true);
-assertEq(String.endsWith(strObj, "B", 0), false);
-assertEq(String.endsWith(strObj, "B", 2), true);
-
-// String.trim.
-var str2 = "  ABCde  ";
-var strObj2 = {
-  toString() {
-    return "  ABCde  ";
-  }
-};
-assertThrowsInstanceOf(() => String.trim(), TypeError);
-assertEq(String.trim(str2), "ABCde");
-assertEq(String.trim(strObj2), "ABCde");
-
-// String.trimLeft.
-assertThrowsInstanceOf(() => String.trimLeft(), TypeError);
-assertEq(String.trimLeft(str2), "ABCde  ");
-assertEq(String.trimLeft(strObj2), "ABCde  ");
-
-// String.trimRight.
-assertThrowsInstanceOf(() => String.trimRight(), TypeError);
-assertEq(String.trimRight(str2), "  ABCde");
-assertEq(String.trimRight(strObj2), "  ABCde");
-
-// String.toLocaleLowerCase.
-assertThrowsInstanceOf(() => String.toLocaleLowerCase(), TypeError);
-assertEq(String.toLocaleLowerCase(str), str.toLocaleLowerCase());
-assertEq(String.toLocaleLowerCase(strObj), str.toLocaleLowerCase());
-
-// String.toLocaleUpperCase.
-assertThrowsInstanceOf(() => String.toLocaleUpperCase(), TypeError);
-assertEq(String.toLocaleUpperCase(str), str.toLocaleUpperCase());
-assertEq(String.toLocaleUpperCase(strObj), str.toLocaleUpperCase());
-
-// String.localeCompare.
-assertThrowsInstanceOf(() => String.localeCompare(), TypeError);
-assertEq(String.localeCompare(str), str.localeCompare());
-assertEq(String.localeCompare(str, "abcde"), str.localeCompare("abcde"));
-assertEq(String.localeCompare(strObj), str.localeCompare());
-assertEq(String.localeCompare(strObj, "abcde"), str.localeCompare("abcde"));
-
-// String.normalize.
-if ("normalize" in String.prototype) {
-  var str3 = "\u3082\u3058\u3089 \u3082\u3057\u3099\u3089";
-  var strObj3 = {
-    toString() {
-      return "\u3082\u3058\u3089 \u3082\u3057\u3099\u3089";
-    }
-  };
-  assertThrowsInstanceOf(() => String.normalize(), TypeError);
-
-  assertEq(String.normalize(str3), "\u3082\u3058\u3089 \u3082\u3058\u3089");
-  assertEq(String.normalize(str3, "NFD"), "\u3082\u3057\u3099\u3089 \u3082\u3057\u3099\u3089");
-  assertEq(String.normalize(strObj3), "\u3082\u3058\u3089 \u3082\u3058\u3089");
-  assertEq(String.normalize(strObj3, "NFD"), "\u3082\u3057\u3099\u3089 \u3082\u3057\u3099\u3089");
-}
-
-// String.concat.
-assertThrowsInstanceOf(() => String.concat(), TypeError);
-assertEq(String.concat(str), "ABCde");
-assertEq(String.concat(str, "f"), "ABCdef");
-assertEq(String.concat(str, "f", "g"), "ABCdefg");
-assertEq(String.concat(strObj), "ABCde");
-assertEq(String.concat(strObj, "f"), "ABCdef");
-assertEq(String.concat(strObj, "f", "g"), "ABCdefg");
-
-if (typeof reportCompare === "function")
-  reportCompare(true, true);
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2243,18 +2243,16 @@ static const JSFunctionSpec intrinsic_fu
     JS_INLINABLE_FN("std_Array",                 ArrayConstructor,             1,0, Array),
     JS_FN("std_Array_join",                      array_join,                   1,0),
     JS_INLINABLE_FN("std_Array_push",            array_push,                   1,0, ArrayPush),
     JS_INLINABLE_FN("std_Array_pop",             array_pop,                    0,0, ArrayPop),
     JS_INLINABLE_FN("std_Array_shift",           array_shift,                  0,0, ArrayShift),
     JS_FN("std_Array_unshift",                   array_unshift,                1,0),
     JS_INLINABLE_FN("std_Array_slice",           array_slice,                  2,0, ArraySlice),
     JS_FN("std_Array_sort",                      array_sort,                   1,0),
-    JS_FN("std_Array_reverse",                   array_reverse,                0,0),
-    JS_INLINABLE_FN("std_Array_splice",          array_splice,                 2,0, ArraySplice),
 
     JS_FN("std_Date_now",                        date_now,                     0,0),
     JS_FN("std_Date_valueOf",                    date_valueOf,                 0,0),
 
     JS_FN("std_Function_apply",                  fun_apply,                    2,0),
 
     JS_INLINABLE_FN("std_Math_floor",            math_floor,                   1,0, MathFloor),
     JS_INLINABLE_FN("std_Math_max",              math_max,                     2,0, MathMax),
@@ -2287,31 +2285,16 @@ static const JSFunctionSpec intrinsic_fu
     JS_INLINABLE_FN("std_String_charCodeAt",     str_charCodeAt,               1,0, StringCharCodeAt),
     JS_FN("std_String_includes",                 str_includes,                 1,0),
     JS_FN("std_String_indexOf",                  str_indexOf,                  1,0),
     JS_FN("std_String_lastIndexOf",              str_lastIndexOf,              1,0),
     JS_FN("std_String_startsWith",               str_startsWith,               1,0),
     JS_FN("std_String_toLowerCase",              str_toLowerCase,              0,0),
     JS_FN("std_String_toUpperCase",              str_toUpperCase,              0,0),
 
-    JS_INLINABLE_FN("std_String_charAt",         str_charAt,                   1,0, StringCharAt),
-    JS_FN("std_String_endsWith",                 str_endsWith,                 1,0),
-    JS_FN("std_String_trim",                     str_trim,                     0,0),
-    JS_FN("std_String_trimLeft",                 str_trimLeft,                 0,0),
-    JS_FN("std_String_trimRight",                str_trimRight,                0,0),
-    JS_FN("std_String_toLocaleLowerCase",        str_toLocaleLowerCase,        0,0),
-    JS_FN("std_String_toLocaleUpperCase",        str_toLocaleUpperCase,        0,0),
-#if !EXPOSE_INTL_API
-    JS_FN("std_String_localeCompare",            str_localeCompare,            1,0),
-#else
-    JS_FN("std_String_normalize",                str_normalize,                0,0),
-#endif
-    JS_FN("std_String_concat",                   str_concat,                   1,0),
-
-
     JS_FN("std_WeakMap_has",                     WeakMap_has,                  1,0),
     JS_FN("std_WeakMap_get",                     WeakMap_get,                  2,0),
     JS_FN("std_WeakMap_set",                     WeakMap_set,                  2,0),
     JS_FN("std_WeakMap_delete",                  WeakMap_delete,               1,0),
 
     JS_FN("std_SIMD_Int8x16_extractLane",        simd_int8x16_extractLane,     2,0),
     JS_FN("std_SIMD_Int16x8_extractLane",        simd_int16x8_extractLane,     2,0),
     JS_INLINABLE_FN("std_SIMD_Int32x4_extractLane",   simd_int32x4_extractLane,  2,0, SimdInt32x4_extractLane),
--- a/js/xpconnect/tests/chrome/test_xrayToJS.xul
+++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul
@@ -534,17 +534,23 @@ https://bugzilla.mozilla.org/show_bug.cg
     // |own| data property. So we add it to the ignore list here, and check it
     // separately.
     //
     // |Symbol.unscopables| should in principle be exposed, but it is
     // inconvenient (as it's a data property, unsupported by ClassSpec) and
     // low value.
     let propsToSkip = ['length', Symbol.unscopables];
 
-    testXray('Array', new iwin.Array(20), new iwin.Array(), propsToSkip);
+    // On the constructor, we want to skip all the non-standard "generic"
+    // functions.  We're trying to remove them anyway; no point doing extra work
+    // to expose them over Xrays.
+    let ctorPropsToSkip = ["join", "reverse", "sort", "push", "pop", "shift",
+                           "unshift", "splice", "slice"];
+    testXray('Array', new iwin.Array(20), new iwin.Array(), propsToSkip,
+             ctorPropsToSkip);
 
     let symbolProps = '';
     uniqueSymbol = iwin.eval('var uniqueSymbol = Symbol("uniqueSymbol"); uniqueSymbol');
     symbolProps = `trickyArray[uniqueSymbol] = 43;
                    trickyArray[Symbol.for("registrySymbolProp")] = 44;`;
     var trickyArray =
       iwin.eval(`var trickyArray = [];
                  trickyArray.primitiveProp = 42;