[builtins] Port TypedArray join, toString, and toLocaleString to Torque.

Micro-benchmarks show speed improvements across the various types:

TypedArrays-JoinBigIntTypes                7246   8297  14.50%
TypedArrays-JoinBigIntTypes                7194   8637  20.06%
TypedArrays-JoinBigIntTypes                7258   8586  18.30%
TypedArrays-JoinFloatTypes                24461  28628  17.04%
TypedArrays-JoinFloatTypes                24523  29647  20.89%
TypedArrays-JoinFloatTypes                24419  29327  20.10%
TypedArrays-JoinIntTypes                  23378  33928  45.13%
TypedArrays-JoinIntTypes                  23333  34034  45.86%
TypedArrays-JoinIntTypes                  21653  34000  57.02%
TypedArrays-JoinWithSeparatorBigIntTypes   6620   7339  10.86%
TypedArrays-JoinWithSeparatorBigIntTypes   6566   7579  15.43%
TypedArrays-JoinWithSeparatorBigIntTypes   6631   7481  12.82%
TypedArrays-JoinWithSeparatorFloatTypes   18695  19670   5.22%
TypedArrays-JoinWithSeparatorFloatTypes   18518  20088   8.48%
TypedArrays-JoinWithSeparatorFloatTypes   18482  20193   9.26%
TypedArrays-JoinWithSeparatorIntTypes     17849  21482  20.35%
TypedArrays-JoinWithSeparatorIntTypes     17831  21578  21.01%
TypedArrays-JoinWithSeparatorIntTypes     17937  21578  20.30%

Drive-by: Removed unused CSA helper InternalArrayCreate.

Bug: v8:7624
Change-Id: I8e63815982439cfd2267417d03cd2b71b4b7a812
Reviewed-on: https://chromium-review.googlesource.com/c/1369330
Commit-Queue: Peter Wong <peter.wm.wong@gmail.com>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58167}
diff --git a/BUILD.gn b/BUILD.gn
index 8bfda8d..c361555 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -724,8 +724,6 @@
     "src/js/macros.py",
     "src/message-template.h",
     "src/js/prologue.js",
-    "src/js/array.js",
-    "src/js/typedarray.js",
   ]
 
   outputs = [
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index b5231fb..e614189 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1629,6 +1629,7 @@
         *info);
   }
 
+  Handle<JSFunction> array_prototype_to_string_fun;
   {  // --- A r r a y ---
     Handle<JSFunction> array_function = InstallFunction(
         isolate_, global, "Array", JS_ARRAY_TYPE, JSArray::kSize, 0,
@@ -1745,8 +1746,9 @@
                           Builtins::kArrayReduceRight, 1, false);
     SimpleInstallFunction(isolate_, proto, "toLocaleString",
                           Builtins::kArrayPrototypeToLocaleString, 0, false);
-    SimpleInstallFunction(isolate_, proto, "toString",
-                          Builtins::kArrayPrototypeToString, 0, false);
+    array_prototype_to_string_fun =
+        SimpleInstallFunction(isolate_, proto, "toString",
+                              Builtins::kArrayPrototypeToString, 0, false);
   }
 
   {  // --- A r r a y I t e r a t o r ---
@@ -3201,6 +3203,8 @@
                           Builtins::kTypedArrayPrototypeIncludes, 1, false);
     SimpleInstallFunction(isolate_, prototype, "indexOf",
                           Builtins::kTypedArrayPrototypeIndexOf, 1, false);
+    SimpleInstallFunction(isolate_, prototype, "join",
+                          Builtins::kTypedArrayPrototypeJoin, 1, false);
     SimpleInstallFunction(isolate_, prototype, "lastIndexOf",
                           Builtins::kTypedArrayPrototypeLastIndexOf, 1, false);
     SimpleInstallFunction(isolate_, prototype, "map",
@@ -3221,6 +3225,11 @@
                           Builtins::kTypedArrayPrototypeSort, 1, false);
     SimpleInstallFunction(isolate_, prototype, "subarray",
                           Builtins::kTypedArrayPrototypeSubArray, 2, false);
+    SimpleInstallFunction(isolate_, prototype, "toLocaleString",
+                          Builtins::kTypedArrayPrototypeToLocaleString, 0,
+                          false);
+    JSObject::AddProperty(isolate_, prototype, factory->toString_string(),
+                          array_prototype_to_string_fun, DONT_ENUM);
   }
 
   {  // -- T y p e d A r r a y s
diff --git a/src/builtins/array-join.tq b/src/builtins/array-join.tq
index 4f5cee9..f331f8b 100644
--- a/src/builtins/array-join.tq
+++ b/src/builtins/array-join.tq
@@ -55,6 +55,14 @@
     }
   }
 
+  builtin LoadJoinTypedElement<T: type>(
+      context: Context, receiver: JSReceiver, k: Number): Object {
+    const typedArray: JSTypedArray = UnsafeCast<JSTypedArray>(receiver);
+    return typed_array::LoadFixedTypedArrayElementAsTagged(
+        typedArray.data_ptr, UnsafeCast<Smi>(k),
+        typed_array::KindForArrayType<T>(), SMI_PARAMETERS);
+  }
+
   transitioning builtin ConvertToLocaleString(
       context: Context, element: Object, locales: Object,
       options: Object): String {
@@ -80,9 +88,17 @@
 
   // Verifies the current element JSArray accessor can still be safely used
   // (see LoadJoinElement<ElementsAccessor>).
-  macro CannotUseSameArrayAccessor(implicit context: Context)(
-      originalMap: Object, originalLen: Object, receiver: JSReceiver): never
+  macro CannotUseSameArrayAccessor<T: type>(implicit context: Context)(
+      loadFn: LoadJoinElementFn, receiver: JSReceiver, originalMap: Map,
+      originalLen: Number): never
+      labels Cannot, Can;
+
+  CannotUseSameArrayAccessor<JSArray>(implicit context: Context)(
+      loadFn: LoadJoinElementFn, receiver: JSReceiver, originalMap: Map,
+      originalLen: Number): never
       labels Cannot, Can {
+    if (loadFn == LoadJoinElement<GenericElementsAccessor>) goto Can;
+
     const array: JSArray = UnsafeCast<JSArray>(receiver);
     if (originalMap != array.map) goto Cannot;
     if (originalLen != array.length) goto Cannot;
@@ -90,6 +106,18 @@
     goto Can;
   }
 
+  CannotUseSameArrayAccessor<JSTypedArray>(implicit context: Context)(
+      loadFn: LoadJoinElementFn, receiver: JSReceiver, initialMap: Map,
+      initialLen: Number): never
+      labels Cannot, Can {
+    // It is assumed that neither loading a typed array element nor converting a
+    // number to string have side-effects. As such, it safe to use the initial
+    // LoadJoinElement specialization and it cannot change through out the join
+    // call.
+    assert(!IsDetachedBuffer(UnsafeCast<JSTypedArray>(receiver).buffer));
+    goto Can;
+  }
+
   // Calculates the running total length of the resulting string.  If the
   // calculated length exceeds the maximum string length (see
   // String::kMaxLength), throws a range error.
@@ -245,15 +273,15 @@
         buffer.fixedArray, buffer.index, sep, r);
   }
 
-  transitioning macro ArrayJoinImpl(
-      context: Context, receiver: JSReceiver, sep: String, lengthNumber: Number,
+  transitioning macro ArrayJoinImpl<T: type>(implicit context: Context)(
+      receiver: JSReceiver, sep: String, lengthNumber: Number,
       useToLocaleString: constexpr bool, locales: Object, options: Object,
-      initialLoadJoinElement: LoadJoinElementFn): String {
+      initialLoadFn: LoadJoinElementFn): String {
     const initialMap: Map = receiver.map;
     const len: uintptr = Convert<uintptr>(lengthNumber);
     const separatorLength: intptr = sep.length;
     let nofSeparators: intptr = 0;
-    let loadJoinElements: LoadJoinElementFn = initialLoadJoinElement;
+    let loadFn: LoadJoinElementFn = initialLoadFn;
     let buffer: Buffer = BufferInit(len, sep);
 
     // 6. Let k be 0.
@@ -264,20 +292,15 @@
       if (k > 0) {
         // a. If k > 0, let R be the string-concatenation of R and sep.
         nofSeparators = nofSeparators + 1;
-
-        // Verify the current LoadJoinElement specialization can safely be
-        // used. Otherwise, fall back to generic element access (see
-        // LoadJoinElement<GenericElementsAccessor>).
-        if (loadJoinElements != LoadJoinElement<GenericElementsAccessor>&&
-            CannotUseSameArrayAccessor(initialMap, lengthNumber, receiver))
+        if (CannotUseSameArrayAccessor<T>(
+                loadFn, receiver, initialMap, lengthNumber))
           deferred {
-            loadJoinElements = LoadJoinElement<GenericElementsAccessor>;
+            loadFn = LoadJoinElement<GenericElementsAccessor>;
           }
       }
 
       // b. Let element be ? Get(O, ! ToString(k)).
-      const element: Object =
-          loadJoinElements(context, receiver, Convert<Number>(k++));
+      const element: Object = loadFn(context, receiver, Convert<Number>(k++));
 
       // c. If element is undefined or null, let next be the empty String;
       //    otherwise, let next be ? ToString(element).
@@ -313,12 +336,16 @@
     return BufferJoin(buffer, sep);
   }
 
-  transitioning macro ArrayJoin(implicit context: Context)(
+  transitioning macro ArrayJoin<T: type>(implicit context: Context)(
+      useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String,
+      lenNumber: Number, locales: Object, options: Object): Object;
+
+  ArrayJoin<JSArray>(implicit context: Context)(
       useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String,
       lenNumber: Number, locales: Object, options: Object): Object {
     const map: Map = receiver.map;
     const kind: ElementsKind = map.elements_kind;
-    let loadJoinElements: LoadJoinElementFn;
+    let loadFn: LoadJoinElementFn;
 
     try {
       const array: JSArray = Cast<JSArray>(receiver) otherwise IfSlowPath;
@@ -327,9 +354,9 @@
       if (IsNoElementsProtectorCellInvalid()) goto IfSlowPath;
 
       if (IsElementsKindLessThanOrEqual(kind, HOLEY_ELEMENTS)) {
-        loadJoinElements = LoadJoinElement<FastSmiOrObjectElements>;
+        loadFn = LoadJoinElement<FastSmiOrObjectElements>;
       } else if (IsElementsKindLessThanOrEqual(kind, HOLEY_DOUBLE_ELEMENTS)) {
-        loadJoinElements = LoadJoinElement<FastDoubleElements>;
+        loadFn = LoadJoinElement<FastDoubleElements>;
       } else if (kind == DICTIONARY_ELEMENTS)
         deferred {
           const dict: NumberDictionary =
@@ -346,7 +373,7 @@
               ThrowInvalidStringLength(context);
             }
           } else {
-            loadJoinElements = LoadJoinElement<DictionaryElements>;
+            loadFn = LoadJoinElement<DictionaryElements>;
           }
         }
       else {
@@ -354,11 +381,52 @@
       }
     }
     label IfSlowPath {
-      loadJoinElements = LoadJoinElement<GenericElementsAccessor>;
+      loadFn = LoadJoinElement<GenericElementsAccessor>;
     }
-    return ArrayJoinImpl(
-        context, receiver, sep, lenNumber, useToLocaleString, locales, options,
-        loadJoinElements);
+    return ArrayJoinImpl<JSArray>(
+        receiver, sep, lenNumber, useToLocaleString, locales, options, loadFn);
+  }
+
+  ArrayJoin<JSTypedArray>(implicit context: Context)(
+      useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String,
+      lenNumber: Number, locales: Object, options: Object): Object {
+    const map: Map = receiver.map;
+    const kind: ElementsKind = map.elements_kind;
+    let loadFn: LoadJoinElementFn;
+
+    if (IsElementsKindGreaterThan(kind, UINT32_ELEMENTS)) {
+      if (kind == INT32_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedInt32Array>;
+      } else if (kind == FLOAT32_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedFloat32Array>;
+      } else if (kind == FLOAT64_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedFloat64Array>;
+      } else if (kind == UINT8_CLAMPED_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedUint8ClampedArray>;
+      } else if (kind == BIGUINT64_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedBigUint64Array>;
+      } else if (kind == BIGINT64_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedBigInt64Array>;
+      } else {
+        unreachable;
+      }
+    } else {
+      if (kind == UINT8_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedUint8Array>;
+      } else if (kind == INT8_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedInt8Array>;
+      } else if (kind == UINT16_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedUint16Array>;
+      } else if (kind == INT16_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedInt16Array>;
+      } else if (kind == UINT32_ELEMENTS) {
+        loadFn = LoadJoinTypedElement<FixedUint32Array>;
+      } else {
+        unreachable;
+      }
+    }
+    return ArrayJoinImpl<JSTypedArray>(
+        receiver, sep, lenNumber, useToLocaleString, locales, options, loadFn);
   }
 
   // The Join Stack detects cyclical calls to Array Join builtins
@@ -474,18 +542,10 @@
   }
 
   // Main entry point for all builtins using Array Join functionality.
-  transitioning macro CycleProtectedArrayJoin(implicit context: Context)(
-      useToLocaleString: constexpr bool, receiver: Object, sepObj: Object,
-      locales: Object, options: Object): Object {
-    // 1. Let O be ? ToObject(this value).
-    const o: JSReceiver = ToObject_Inline(context, receiver);
-
-    // 2. Let len be ? ToLength(? Get(O, "length")).
-    const len: Number = GetLengthProperty(o);
-    // Only handle valid array lengths. Although the spec allows larger values,
-    // this matches historical V8 behavior.
-    if (len > kMaxArrayIndex + 1) ThrowTypeError(context, kInvalidArrayLength);
-
+  transitioning macro CycleProtectedArrayJoin<T: type>(implicit context:
+                                                            Context)(
+      useToLocaleString: constexpr bool, o: JSReceiver, len: Number,
+      sepObj: Object, locales: Object, options: Object): Object {
     // 3. If separator is undefined, let sep be the single-element String ",".
     // 4. Else, let sep be ? ToString(separator).
     let sep: String =
@@ -496,7 +556,7 @@
     if (len > 0 && JoinStackPushInline(o)) {
       try {
         const result: Object =
-            ArrayJoin(useToLocaleString, o, sep, len, locales, options);
+            ArrayJoin<T>(useToLocaleString, o, sep, len, locales, options);
         JoinStackPopInline(o);
         return result;
       } catch (e) deferred {
@@ -512,19 +572,42 @@
   transitioning javascript builtin
   ArrayPrototypeJoin(context: Context, receiver: Object, ...arguments): Object {
     const separator: Object = arguments[0];
-    return CycleProtectedArrayJoin(
-        false, receiver, separator, Undefined, Undefined);
+
+    // 1. Let O be ? ToObject(this value).
+    const o: JSReceiver = ToObject_Inline(context, receiver);
+
+    // 2. Let len be ? ToLength(? Get(O, "length")).
+    const len: Number = GetLengthProperty(o);
+
+    // Only handle valid array lengths. Although the spec allows larger values,
+    // this matches historical V8 behavior.
+    if (len > kMaxArrayIndex + 1) ThrowTypeError(context, kInvalidArrayLength);
+
+    return CycleProtectedArrayJoin<JSArray>(
+        false, o, len, separator, Undefined, Undefined);
   }
 
-  // https://tc39.github.io/ecma262/#sec-array.prototype.toLocaleString
+  // https://tc39.github.io/ecma262/#sec-array.prototype.tolocalestring
   transitioning javascript builtin ArrayPrototypeToLocaleString(
       context: Context, receiver: Object, ...arguments): Object {
     const locales: Object = arguments[0];
     const options: Object = arguments[1];
-    return CycleProtectedArrayJoin(true, receiver, ',', locales, options);
+
+    // 1. Let O be ? ToObject(this value).
+    const o: JSReceiver = ToObject_Inline(context, receiver);
+
+    // 2. Let len be ? ToLength(? Get(O, "length")).
+    const len: Number = GetLengthProperty(o);
+
+    // Only handle valid array lengths. Although the spec allows larger values,
+    // this matches historical V8 behavior.
+    if (len > kMaxArrayIndex + 1) ThrowTypeError(context, kInvalidArrayLength);
+
+    return CycleProtectedArrayJoin<JSArray>(
+        true, o, len, ',', locales, options);
   }
 
-  // https://tc39.github.io/ecma262/#sec-array.prototype.toString
+  // https://tc39.github.io/ecma262/#sec-array.prototype.tostring
   transitioning javascript builtin ArrayPrototypeToString(
       context: Context, receiver: Object, ...arguments): Object {
     // 1. Let array be ? ToObject(this value).
@@ -544,4 +627,35 @@
       return ObjectToString(context, array);
     }
   }
+
+  // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.join
+  transitioning javascript builtin TypedArrayPrototypeJoin(
+      context: Context, receiver: Object, ...arguments): Object {
+    const separator: Object = arguments[0];
+
+    // Spec: ValidateTypedArray is applied to the this value prior to evaluating
+    // the algorithm.
+    const typedArray: JSTypedArray = typed_array::ValidateTypedArray(
+        context, receiver, '%TypedArray%.prototype.join');
+    const length: Smi = typedArray.length;
+
+    return CycleProtectedArrayJoin<JSTypedArray>(
+        false, typedArray, length, separator, Undefined, Undefined);
+  }
+
+  // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.tolocalestring
+  transitioning javascript builtin TypedArrayPrototypeToLocaleString(
+      context: Context, receiver: Object, ...arguments): Object {
+    const locales: Object = arguments[0];
+    const options: Object = arguments[1];
+
+    // Spec: ValidateTypedArray is applied to the this value prior to evaluating
+    // the algorithm.
+    const typedArray: JSTypedArray = typed_array::ValidateTypedArray(
+        context, receiver, '%TypedArray%.prototype.toLocaleString');
+    const length: Smi = typedArray.length;
+
+    return CycleProtectedArrayJoin<JSTypedArray>(
+        true, typedArray, length, ',', locales, options);
+  }
 }
diff --git a/src/builtins/base.tq b/src/builtins/base.tq
index 3f10bb2..b145e4a 100644
--- a/src/builtins/base.tq
+++ b/src/builtins/base.tq
@@ -322,7 +322,6 @@
     Context, constexpr MessageTemplate, Object, Object, Object): never;
 extern macro ArraySpeciesCreate(Context, Object, Number): JSReceiver;
 extern macro ArrayCreate(implicit context: Context)(Number): JSArray;
-extern macro InternalArrayCreate(Context, Number): JSArray;
 extern macro EnsureArrayPushable(Map): ElementsKind
     labels Bailout;
 extern macro EnsureArrayLengthWritable(Map) labels Bailout;
@@ -526,6 +525,8 @@
 
 extern macro HeapObjectToJSDataView(HeapObject): JSDataView
     labels CastError;
+extern macro HeapObjectToJSTypedArray(HeapObject): JSTypedArray
+    labels CastError;
 extern macro TaggedToHeapObject(Object): HeapObject
     labels CastError;
 extern macro TaggedToSmi(Object): Smi
@@ -578,6 +579,12 @@
   return HeapObjectToJSDataView(o) otherwise CastError;
 }
 
+CastHeapObject<JSTypedArray>(o: HeapObject): JSTypedArray
+    labels CastError {
+  if (IsJSTypedArray(o)) return %RawObjectCast<JSTypedArray>(o);
+  goto CastError;
+}
+
 CastHeapObject<Callable>(o: HeapObject): Callable
     labels CastError {
   return HeapObjectToCallable(o) otherwise CastError;
@@ -1180,6 +1187,7 @@
 extern macro IsMap(HeapObject): bool;
 extern macro IsJSFunction(HeapObject): bool;
 extern macro IsJSObject(HeapObject): bool;
+extern macro IsJSTypedArray(HeapObject): bool;
 extern macro IsNumberDictionary(HeapObject): bool;
 extern macro IsFixedTypedArray(HeapObject): bool;
 extern macro IsContext(HeapObject): bool;
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index c676cf4..0d57139 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -12928,14 +12928,6 @@
   return Construct(context, constructor, len);
 }
 
-TNode<JSReceiver> CodeStubAssembler::InternalArrayCreate(TNode<Context> context,
-                                                         TNode<Number> len) {
-  TNode<Context> native_context = LoadNativeContext(context);
-  TNode<JSReceiver> constructor = CAST(LoadContextElement(
-      native_context, Context::INTERNAL_ARRAY_FUNCTION_INDEX));
-  return Construct(context, constructor, len);
-}
-
 Node* CodeStubAssembler::IsDetachedBuffer(Node* buffer) {
   CSA_ASSERT(this, HasInstanceType(buffer, JS_ARRAY_BUFFER_TYPE));
   TNode<Uint32T> buffer_bit_field = LoadJSArrayBufferBitField(CAST(buffer));
diff --git a/src/code-stub-assembler.h b/src/code-stub-assembler.h
index 1369841..998c05a 100644
--- a/src/code-stub-assembler.h
+++ b/src/code-stub-assembler.h
@@ -1516,8 +1516,6 @@
   TNode<JSReceiver> ArraySpeciesCreate(TNode<Context> context,
                                        TNode<Object> originalArray,
                                        TNode<Number> len);
-  TNode<JSReceiver> InternalArrayCreate(TNode<Context> context,
-                                        TNode<Number> len);
 
   void FillFixedArrayWithValue(ElementsKind kind, Node* array, Node* from_index,
                                Node* to_index, RootIndex value_root_index,
diff --git a/src/js/array.js b/src/js/array.js
deleted file mode 100644
index 6945ad9..0000000
--- a/src/js/array.js
+++ /dev/null
@@ -1,478 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function(global, utils, extrasUtils) {
-
-"use strict";
-
-%CheckIsBootstrapping();
-
-// -------------------------------------------------------------------
-// Imports
-
-var GlobalArray = global.Array;
-var InternalArray = utils.InternalArray;
-var ObjectToString = global.Object.prototype.toString;
-var iteratorSymbol = utils.ImportNow("iterator_symbol");
-var unscopablesSymbol = utils.ImportNow("unscopables_symbol");
-
-// -------------------------------------------------------------------
-
-macro INVERT_NEG_ZERO(arg)
-((arg) + 0)
-endmacro
-
-function ArraySpeciesCreate(array, length) {
-  length = INVERT_NEG_ZERO(length);
-  var constructor = %ArraySpeciesConstructor(array);
-  return new constructor(length);
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function KeySortCompare(a, b) {
-  return a - b;
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function GetSortedArrayKeys(array, indices) {
-  if (IS_NUMBER(indices)) {
-    // It's an interval
-    var limit = indices;
-    var keys = new InternalArray();
-    for (var i = 0; i < limit; ++i) {
-      var e = array[i];
-      if (!IS_UNDEFINED(e) || i in array) {
-        keys.push(i);
-      }
-    }
-    return keys;
-  }
-  return InnerArraySort(indices, indices.length, KeySortCompare);
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function SparseJoinWithSeparatorJS(
-    array, keys, length, use_locale, separator, locales, options) {
-  var keys_length = keys.length;
-  var elements = new InternalArray(keys_length * 2);
-  for (var i = 0; i < keys_length; i++) {
-    var key = keys[i];
-    elements[i * 2] = key;
-    elements[i * 2 + 1] = ConvertToString(
-        use_locale, array[key], locales, options);
-  }
-  return %SparseJoinWithSeparator(elements, length, separator);
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-// Optimized for sparse arrays if separator is ''.
-function SparseJoin(array, keys, use_locale, locales, options) {
-  var keys_length = keys.length;
-  var elements = new InternalArray(keys_length);
-  for (var i = 0; i < keys_length; i++) {
-    elements[i] = ConvertToString(use_locale, array[keys[i]], locales, options);
-  }
-  return %StringBuilderConcat(elements, keys_length, '');
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function UseSparseVariant(array, length, is_array, touched) {
-  // Only use the sparse variant on arrays that are likely to be sparse and the
-  // number of elements touched in the operation is relatively small compared to
-  // the overall size of the array.
-  if (!is_array || length < 1000 || %HasComplexElements(array)) {
-    return false;
-  }
-  if (!%_IsSmi(length)) {
-    return true;
-  }
-  var elements_threshold = length >> 2;  // No more than 75% holes
-  var estimated_elements = %EstimateNumberOfElements(array);
-  return (estimated_elements < elements_threshold) &&
-    (touched > estimated_elements * 4);
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function Stack() {
-  this.length = 0;
-  this.values = new InternalArray();
-}
-
-// Predeclare the instance variables on the prototype. Otherwise setting them in
-// the constructor will leak the instance through settings on Object.prototype.
-Stack.prototype.length = null;
-Stack.prototype.values = null;
-
-function StackPush(stack, value) {
-  stack.values[stack.length++] = value;
-}
-
-function StackPop(stack) {
-  stack.values[--stack.length] = null
-}
-
-function StackHas(stack, v) {
-  var length = stack.length;
-  var values = stack.values;
-  for (var i = 0; i < length; i++) {
-    if (values[i] === v) return true;
-  }
-  return false;
-}
-
-// Global list of arrays visited during toString, toLocaleString and
-// join invocations.
-var visited_arrays = new Stack();
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function DoJoin(
-    array, length, is_array, separator, use_locale, locales, options) {
-  if (UseSparseVariant(array, length, is_array, length)) {
-    %NormalizeElements(array);
-    var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, length));
-    if (separator === '') {
-      if (keys.length === 0) return '';
-      return SparseJoin(array, keys, use_locale, locales, options);
-    } else {
-      return SparseJoinWithSeparatorJS(
-          array, keys, length, use_locale, separator, locales, options);
-    }
-  }
-
-  // Fast case for one-element arrays.
-  if (length === 1) {
-    return ConvertToString(use_locale, array[0], locales, options);
-  }
-
-  // Construct an array for the elements.
-  var elements = new InternalArray(length);
-  for (var i = 0; i < length; i++) {
-    elements[i] = ConvertToString(use_locale, array[i], locales, options);
-  }
-
-  if (separator === '') {
-    return %StringBuilderConcat(elements, length, '');
-  } else {
-    return %StringBuilderJoin(elements, length, separator);
-  }
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function Join(array, length, separator, use_locale, locales, options) {
-  if (length === 0) return '';
-
-  var is_array = IS_ARRAY(array);
-
-  if (is_array) {
-    // If the array is cyclic, return the empty string for already
-    // visited arrays.
-    if (StackHas(visited_arrays, array)) return '';
-    StackPush(visited_arrays, array);
-  }
-
-  // Attempt to convert the elements.
-  try {
-    return DoJoin(
-        array, length, is_array, separator, use_locale, locales, options);
-  } finally {
-    // Make sure to remove the last element of the visited array no
-    // matter what happens.
-    if (is_array) StackPop(visited_arrays);
-  }
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function ConvertToString(use_locale, x, locales, options) {
-  if (IS_NULL_OR_UNDEFINED(x)) return '';
-  if (use_locale) {
-    if (IS_NULL_OR_UNDEFINED(locales)) {
-      return TO_STRING(x.toLocaleString());
-    } else if (IS_NULL_OR_UNDEFINED(options)) {
-      return TO_STRING(x.toLocaleString(locales));
-    }
-    return TO_STRING(x.toLocaleString(locales, options));
-  }
-
-  return TO_STRING(x);
-}
-
-
-// -------------------------------------------------------------------
-
-// ecma402 #sup-array.prototype.tolocalestring
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function InnerArrayToLocaleString(array, length, locales, options) {
-  return Join(array, TO_LENGTH(length), ',', true, locales, options);
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function InnerArrayJoin(separator, array, length) {
-  if (IS_UNDEFINED(separator)) {
-    separator = ',';
-  } else {
-    separator = TO_STRING(separator);
-  }
-
-  // Fast case for one-element arrays.
-  if (length === 1) {
-    var e = array[0];
-    if (IS_NULL_OR_UNDEFINED(e)) return '';
-    return TO_STRING(e);
-  }
-
-  return Join(array, length, separator, false);
-}
-
-
-
-
-// Oh the humanity... don't remove the following function because js2c for some
-// reason gets symbol minifiation wrong if it's not there. Instead of spending
-// the time fixing js2c (which will go away when all of the internal .js runtime
-// files are gone), just keep this work-around.
-function ArraySliceFallback(start, end) {
-  return null;
-}
-
-// TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-function InnerArraySort(array, length, comparefn) {
-  // In-place QuickSort algorithm.
-  // For short (length <= 10) arrays, insertion sort is used for efficiency.
-
-  if (!IS_CALLABLE(comparefn)) {
-    comparefn = function (x, y) {
-      if (x === y) return 0;
-      if (%_IsSmi(x) && %_IsSmi(y)) {
-        return %SmiLexicographicCompare(x, y);
-      }
-      x = TO_STRING(x);
-      y = TO_STRING(y);
-      if (x == y) return 0;
-      else return x < y ? -1 : 1;
-    };
-  }
-  function InsertionSort(a, from, to) {
-    for (var i = from + 1; i < to; i++) {
-      var element = a[i];
-      for (var j = i - 1; j >= from; j--) {
-        var tmp = a[j];
-        var order = comparefn(tmp, element);
-        if (order > 0) {
-          a[j + 1] = tmp;
-        } else {
-          break;
-        }
-      }
-      a[j + 1] = element;
-    }
-  };
-
-  function GetThirdIndex(a, from, to) {
-    var t_array = new InternalArray();
-    // Use both 'from' and 'to' to determine the pivot candidates.
-    var increment = 200 + ((to - from) & 15);
-    var j = 0;
-    from += 1;
-    to -= 1;
-    for (var i = from; i < to; i += increment) {
-      t_array[j] = [i, a[i]];
-      j++;
-    }
-    t_array.sort(function(a, b) {
-      return comparefn(a[1], b[1]);
-    });
-    var third_index = t_array[t_array.length >> 1][0];
-    return third_index;
-  }
-
-  function QuickSort(a, from, to) {
-    var third_index = 0;
-    while (true) {
-      // Insertion sort is faster for short arrays.
-      if (to - from <= 10) {
-        InsertionSort(a, from, to);
-        return;
-      }
-      if (to - from > 1000) {
-        third_index = GetThirdIndex(a, from, to);
-      } else {
-        third_index = from + ((to - from) >> 1);
-      }
-      // Find a pivot as the median of first, last and middle element.
-      var v0 = a[from];
-      var v1 = a[to - 1];
-      var v2 = a[third_index];
-      var c01 = comparefn(v0, v1);
-      if (c01 > 0) {
-        // v1 < v0, so swap them.
-        var tmp = v0;
-        v0 = v1;
-        v1 = tmp;
-      } // v0 <= v1.
-      var c02 = comparefn(v0, v2);
-      if (c02 >= 0) {
-        // v2 <= v0 <= v1.
-        var tmp = v0;
-        v0 = v2;
-        v2 = v1;
-        v1 = tmp;
-      } else {
-        // v0 <= v1 && v0 < v2
-        var c12 = comparefn(v1, v2);
-        if (c12 > 0) {
-          // v0 <= v2 < v1
-          var tmp = v1;
-          v1 = v2;
-          v2 = tmp;
-        }
-      }
-      // v0 <= v1 <= v2
-      a[from] = v0;
-      a[to - 1] = v2;
-      var pivot = v1;
-      var low_end = from + 1;   // Upper bound of elements lower than pivot.
-      var high_start = to - 1;  // Lower bound of elements greater than pivot.
-      a[third_index] = a[low_end];
-      a[low_end] = pivot;
-
-      // From low_end to i are elements equal to pivot.
-      // From i to high_start are elements that haven't been compared yet.
-      partition: for (var i = low_end + 1; i < high_start; i++) {
-        var element = a[i];
-        var order = comparefn(element, pivot);
-        if (order < 0) {
-          a[i] = a[low_end];
-          a[low_end] = element;
-          low_end++;
-        } else if (order > 0) {
-          do {
-            high_start--;
-            if (high_start == i) break partition;
-            var top_elem = a[high_start];
-            order = comparefn(top_elem, pivot);
-          } while (order > 0);
-          a[i] = a[high_start];
-          a[high_start] = element;
-          if (order < 0) {
-            element = a[i];
-            a[i] = a[low_end];
-            a[low_end] = element;
-            low_end++;
-          }
-        }
-      }
-      if (to - high_start < low_end - from) {
-        QuickSort(a, high_start, to);
-        to = low_end;
-      } else {
-        QuickSort(a, from, low_end);
-        from = high_start;
-      }
-    }
-  };
-
-  if (length < 2) return array;
-
-  // For compatibility with JSC, we also sort elements inherited from
-  // the prototype chain on non-Array objects.
-  // We do this by copying them to this object and sorting only
-  // own elements. This is not very efficient, but sorting with
-  // inherited elements happens very, very rarely, if at all.
-  // The specification allows "implementation dependent" behavior
-  // if an element on the prototype chain has an element that
-  // might interact with sorting.
-  //
-  // We also move all non-undefined elements to the front of the
-  // array and move the undefineds after that. Holes are removed.
-  // This happens for Array as well as non-Array objects.
-  var num_non_undefined = %PrepareElementsForSort(array, length);
-
-  QuickSort(array, 0, num_non_undefined);
-
-  return array;
-}
-
-
-// Set up unscopable properties on the Array.prototype object.
-var unscopables = {
-  __proto__: null,
-  copyWithin: true,
-  entries: true,
-  fill: true,
-  find: true,
-  findIndex: true,
-  includes: true,
-  keys: true,
-};
-
-%ToFastProperties(unscopables);
-
-%AddNamedProperty(GlobalArray.prototype, unscopablesSymbol, unscopables,
-                  DONT_ENUM | READ_ONLY);
-
-var ArrayIndexOf = GlobalArray.prototype.indexOf;
-var ArrayJoin = GlobalArray.prototype.join;
-var ArrayPop = GlobalArray.prototype.pop;
-var ArrayPush = GlobalArray.prototype.push;
-var ArraySlice = GlobalArray.prototype.slice;
-var ArrayShift = GlobalArray.prototype.shift;
-var ArraySort = GlobalArray.prototype.sort;
-var ArraySplice = GlobalArray.prototype.splice;
-var ArrayToString = GlobalArray.prototype.toString;
-var ArrayUnshift = GlobalArray.prototype.unshift;
-
-// Array prototype functions that return iterators. They are exposed to the
-// public API via Template::SetIntrinsicDataProperty().
-var ArrayEntries = GlobalArray.prototype.entries;
-var ArrayForEach = GlobalArray.prototype.forEach;
-var ArrayKeys = GlobalArray.prototype.keys;
-var ArrayValues = GlobalArray.prototype[iteratorSymbol];
-
-
-// The internal Array prototype doesn't need to be fancy, since it's never
-// exposed to user code.
-// Adding only the functions that are actually used.
-utils.SetUpLockedPrototype(InternalArray, GlobalArray(), [
-  "indexOf", ArrayIndexOf,
-  "join", ArrayJoin,
-  "pop", ArrayPop,
-  "push", ArrayPush,
-  "shift", ArrayShift,
-  "sort", ArraySort,
-  "splice", ArraySplice
-]);
-
-// V8 extras get a separate copy of InternalPackedArray. We give them the basic
-// manipulation methods.
-utils.SetUpLockedPrototype(extrasUtils.InternalPackedArray, GlobalArray(), [
-  "push", ArrayPush,
-  "pop", ArrayPop,
-  "shift", ArrayShift,
-  "unshift", ArrayUnshift,
-  "splice", ArraySplice,
-  "slice", ArraySlice
-]);
-
-// -------------------------------------------------------------------
-// Exports
-
-utils.Export(function(to) {
-  to.ArrayJoin = ArrayJoin;
-  to.ArrayPush = ArrayPush;
-  to.ArrayToString = ArrayToString;
-  to.ArrayValues = ArrayValues;
-  // TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-  to.InnerArrayJoin = InnerArrayJoin;
-  // TODO(pwong): Remove once TypedArray.prototype.join() is ported to Torque.
-  to.InnerArrayToLocaleString = InnerArrayToLocaleString;
-});
-
-%InstallToContext([
-  "array_entries_iterator", ArrayEntries,
-  "array_for_each_iterator", ArrayForEach,
-  "array_keys_iterator", ArrayKeys,
-  "array_values_iterator", ArrayValues,
-]);
-
-});
diff --git a/src/js/prologue.js b/src/js/prologue.js
index d3c3463..ebd669f 100644
--- a/src/js/prologue.js
+++ b/src/js/prologue.js
@@ -68,6 +68,8 @@
   %ToFastProperties(prototype);
 }
 
+var GlobalArray = global.Array;
+var InternalArray;
 
 // -----------------------------------------------------------------------
 // To be called by bootstrapper
@@ -75,6 +77,81 @@
 function PostNatives(utils) {
   %CheckIsBootstrapping();
 
+  // -------------------------------------------------------------------
+  // Array
+
+  InternalArray = utils.InternalArray;
+  var iteratorSymbol = ImportNow("iterator_symbol");
+  var unscopablesSymbol = ImportNow("unscopables_symbol");
+
+  // Set up unscopable properties on the Array.prototype object.
+  var unscopables = {
+    __proto__: null,
+    copyWithin: true,
+    entries: true,
+    fill: true,
+    find: true,
+    findIndex: true,
+    includes: true,
+    keys: true,
+  };
+
+  %ToFastProperties(unscopables);
+
+  %AddNamedProperty(GlobalArray.prototype, unscopablesSymbol, unscopables,
+                    DONT_ENUM | READ_ONLY);
+
+  var ArrayIndexOf = GlobalArray.prototype.indexOf;
+  var ArrayJoin = GlobalArray.prototype.join;
+  var ArrayPop = GlobalArray.prototype.pop;
+  var ArrayPush = GlobalArray.prototype.push;
+  var ArraySlice = GlobalArray.prototype.slice;
+  var ArrayShift = GlobalArray.prototype.shift;
+  var ArraySort = GlobalArray.prototype.sort;
+  var ArraySplice = GlobalArray.prototype.splice;
+  var ArrayUnshift = GlobalArray.prototype.unshift;
+
+  // Array prototype functions that return iterators. They are exposed to the
+  // public API via Template::SetIntrinsicDataProperty().
+  var ArrayEntries = GlobalArray.prototype.entries;
+  var ArrayForEach = GlobalArray.prototype.forEach;
+  var ArrayKeys = GlobalArray.prototype.keys;
+  var ArrayValues = GlobalArray.prototype[iteratorSymbol];
+
+
+  // The internal Array prototype doesn't need to be fancy, since it's never
+  // exposed to user code.
+  // Adding only the functions that are actually used.
+  SetUpLockedPrototype(InternalArray, GlobalArray(), [
+    "indexOf", ArrayIndexOf,
+    "join", ArrayJoin,
+    "pop", ArrayPop,
+    "push", ArrayPush,
+    "shift", ArrayShift,
+    "sort", ArraySort,
+    "splice", ArraySplice
+  ]);
+
+  // V8 extras get a separate copy of InternalPackedArray. We give them the basic
+  // manipulation methods.
+  SetUpLockedPrototype(extrasUtils.InternalPackedArray, GlobalArray(), [
+    "push", ArrayPush,
+    "pop", ArrayPop,
+    "shift", ArrayShift,
+    "unshift", ArrayUnshift,
+    "splice", ArraySplice,
+    "slice", ArraySlice
+  ]);
+
+  %InstallToContext([
+    "array_entries_iterator", ArrayEntries,
+    "array_for_each_iterator", ArrayForEach,
+    "array_keys_iterator", ArrayKeys,
+    "array_values_iterator", ArrayValues,
+  ]);
+
+  // -------------------------------------------------------------------
+
   for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
     imports(exports_container);
   }
@@ -94,7 +171,6 @@
 utils.Import = Import;
 utils.ImportNow = ImportNow;
 utils.Export = Export;
-utils.SetUpLockedPrototype = SetUpLockedPrototype;
 utils.PostNatives = PostNatives;
 
 %ToFastProperties(utils);
diff --git a/src/js/typedarray.js b/src/js/typedarray.js
deleted file mode 100644
index e1a4f19..0000000
--- a/src/js/typedarray.js
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function(global, utils) {
-
-"use strict";
-
-%CheckIsBootstrapping();
-
-// -------------------------------------------------------------------
-// Imports
-
-// array.js has to come before typedarray.js for this to work
-var ArrayToString = utils.ImportNow("ArrayToString");
-var InnerArrayJoin;
-var InnerArrayToLocaleString;
-
-macro TYPED_ARRAYS(FUNCTION)
-FUNCTION(Uint8Array, 1)
-FUNCTION(Int8Array, 1)
-FUNCTION(Uint16Array, 2)
-FUNCTION(Int16Array, 2)
-FUNCTION(Uint32Array, 4)
-FUNCTION(Int32Array, 4)
-FUNCTION(Float32Array, 4)
-FUNCTION(Float64Array, 8)
-FUNCTION(Uint8ClampedArray, 1)
-FUNCTION(BigUint64Array, 8)
-FUNCTION(BigInt64Array, 8)
-endmacro
-
-macro DECLARE_GLOBALS(NAME, SIZE)
-var GlobalNAME = global.NAME;
-endmacro
-
-TYPED_ARRAYS(DECLARE_GLOBALS)
-
-macro IS_TYPEDARRAY(arg)
-(%_IsTypedArray(arg))
-endmacro
-
-var GlobalTypedArray = %object_get_prototype_of(GlobalUint8Array);
-
-utils.Import(function(from) {
-  InnerArrayJoin = from.InnerArrayJoin;
-  InnerArrayToLocaleString = from.InnerArrayToLocaleString;
-});
-
-// --------------- Typed Arrays ---------------------
-
-// ES6 section 22.2.3.5.1 ValidateTypedArray ( O )
-function ValidateTypedArray(array, methodName) {
-  if (!IS_TYPEDARRAY(array)) throw %make_type_error(kNotTypedArray);
-
-  if (%ArrayBufferViewWasDetached(array))
-    throw %make_type_error(kDetachedOperation, methodName);
-}
-
-
-// ES6 section 22.2.3.27
-// ecma402 #sup-array.prototype.tolocalestring
-DEFINE_METHOD(
-  GlobalTypedArray.prototype,
-  toLocaleString() {
-    ValidateTypedArray(this, "%TypedArray%.prototype.toLocaleString");
-
-    var locales = arguments[0];
-    var options = arguments[1];
-    var length = %TypedArrayGetLength(this);
-    return InnerArrayToLocaleString(this, length, locales, options);
-  }
-);
-
-
-// ES6 section 22.2.3.14
-DEFINE_METHOD(
-  GlobalTypedArray.prototype,
-  join(separator) {
-    ValidateTypedArray(this, "%TypedArray%.prototype.join");
-
-    var length = %TypedArrayGetLength(this);
-
-    return InnerArrayJoin(separator, this, length);
-  }
-);
-
-// -------------------------------------------------------------------
-
-%AddNamedProperty(GlobalTypedArray.prototype, "toString", ArrayToString,
-                  DONT_ENUM);
-
-})
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 8026660..ec90ad9 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -4296,9 +4296,9 @@
     CHECK_EQ(count_by_type[i::Script::TYPE_WASM], 0);
     CHECK_EQ(count_by_type[i::Script::TYPE_INSPECTOR], 0);
 
-    i::Handle<i::Script> native_array_script =
-        FindScript(i_isolate, scripts, "native array.js").ToHandleChecked();
-    CHECK_EQ(native_array_script->type(), i::Script::TYPE_NATIVE);
+    i::Handle<i::Script> native_prologue_script =
+        FindScript(i_isolate, scripts, "native prologue.js").ToHandleChecked();
+    CHECK_EQ(native_prologue_script->type(), i::Script::TYPE_NATIVE);
 
     i::Handle<i::Script> gc_script =
         FindScript(i_isolate, scripts, "v8/gc").ToHandleChecked();