diff --git a/src/builtins/array-filter.tq b/src/builtins/array-filter.tq index fa2706777c..4bf175a787 100644 --- a/src/builtins/array-filter.tq +++ b/src/builtins/array-filter.tq @@ -46,7 +46,7 @@ namespace array_filter { // the output array. After incrementing k and to, we can glide into the loop // continuation builtin. if (ToBoolean(result)) { - CreateDataProperty(outputArray, numberTo, valueK); + FastCreateDataProperty(outputArray, numberTo, valueK); numberTo = numberTo + 1; } @@ -83,7 +83,7 @@ namespace array_filter { // iii. If selected is true, then... if (ToBoolean(result)) { // 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue). - CreateDataProperty(array, to, kValue); + FastCreateDataProperty(array, to, kValue); // 2. Increase to by 1. to = to + 1; } @@ -123,7 +123,7 @@ namespace array_filter { fastOutputW.Push(value) otherwise SlowStore; } label SlowStore { - CreateDataProperty(fastOutputW.stable, to, value); + FastCreateDataProperty(fastOutputW.stable, to, value); } to = to + 1; } diff --git a/src/builtins/array-map.tq b/src/builtins/array-map.tq index d01daab6d5..d3bba56220 100644 --- a/src/builtins/array-map.tq +++ b/src/builtins/array-map.tq @@ -44,7 +44,7 @@ namespace array_map { // continuation builtin. // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). - CreateDataProperty(outputArray, numberK, result); + FastCreateDataProperty(outputArray, numberK, result); // 7d. Increase k by 1. numberK = numberK + 1; @@ -78,7 +78,7 @@ namespace array_map { Call(context, callbackfn, thisArg, kValue, k, o); // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value). - CreateDataProperty(array, k, mappedValue); + FastCreateDataProperty(array, k, mappedValue); } // 7d. Increase k by 1. (done by the loop). diff --git a/src/builtins/array-of.tq b/src/builtins/array-of.tq index 0ca720073a..70fda8d2eb 100644 --- a/src/builtins/array-of.tq +++ b/src/builtins/array-of.tq @@ -39,7 +39,7 @@ namespace array_of { // b. Let Pk be ! ToString(k). // c. Perform ? CreateDataPropertyOrThrow(A, Pk, kValue). - CreateDataProperty(a, k, kValue); + FastCreateDataProperty(a, k, kValue); // d. Increase k by 1. k++; diff --git a/src/builtins/array-slice.tq b/src/builtins/array-slice.tq index ec381ac62f..847729b607 100644 --- a/src/builtins/array-slice.tq +++ b/src/builtins/array-slice.tq @@ -193,7 +193,7 @@ namespace array_slice { const kValue: Object = GetProperty(o, pK); // ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(n), kValue). - CreateDataProperty(a, n, kValue); + FastCreateDataProperty(a, n, kValue); } // d. Increase k by 1. diff --git a/src/builtins/array-splice.tq b/src/builtins/array-splice.tq index 5389949c7b..586630cd39 100644 --- a/src/builtins/array-splice.tq +++ b/src/builtins/array-splice.tq @@ -197,7 +197,7 @@ namespace array_splice { const fromValue: Object = GetProperty(o, from); // ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(k), fromValue). - CreateDataProperty(a, k, fromValue); + FastCreateDataProperty(a, k, fromValue); } // d. Increment k by 1. diff --git a/src/builtins/base.tq b/src/builtins/base.tq index e760ca8963..41225bf132 100644 --- a/src/builtins/base.tq +++ b/src/builtins/base.tq @@ -675,8 +675,6 @@ extern builtin ToString(Context, Object): String; extern transitioning runtime NormalizeElements(Context, JSObject); extern transitioning runtime TransitionElementsKindWithKind( Context, JSObject, Smi); -extern transitioning runtime CreateDataProperty(implicit context: Context)( - JSReceiver, Object, Object); extern macro LoadBufferObject(RawPtr, constexpr int32): Object; extern macro LoadBufferPointer(RawPtr, constexpr int32): RawPtr; @@ -1861,3 +1859,51 @@ macro BranchIfFastJSArrayForCopy(o: Object, context: Context): never macro IsFastJSArrayWithNoCustomIteration(context: Context, o: Object): bool { return Is(o); } + +extern transitioning runtime +CreateDataProperty(implicit context: Context)(JSReceiver, Object, Object); + +transitioning builtin FastCreateDataProperty(implicit context: Context)( + receiver: JSReceiver, key: Object, value: Object): Object { + try { + let array = Cast(receiver) otherwise Slow; + const index: Smi = Cast(key) otherwise goto Slow; + if (index < 0 || index > array.length) goto Slow; + array::EnsureWriteableFastElements(array); + const isAppend = index == array.length; + const kind = array.map.elements_kind; + // We may have to transition a. + // For now, if transition is required, jump away to slow. + if (IsFastSmiElementsKind(kind)) { + const smiValue = Cast(value) otherwise Slow; + if (isAppend) { + BuildAppendJSArray(HOLEY_SMI_ELEMENTS, array, value) otherwise Slow; + } else { + const elements = Cast(array.elements) otherwise unreachable; + elements[index] = smiValue; + } + } else if (IsDoubleElementsKind(kind)) { + const numberValue = Cast(value) otherwise Slow; + if (isAppend) { + BuildAppendJSArray(HOLEY_DOUBLE_ELEMENTS, array, value) + otherwise Slow; + } else { + const doubleElements = Cast(array.elements) + otherwise unreachable; + doubleElements[index] = numberValue; + } + } else { + assert(IsFastSmiOrTaggedElementsKind(kind)); + if (isAppend) { + BuildAppendJSArray(HOLEY_ELEMENTS, array, value) otherwise Slow; + } else { + const elements = Cast(array.elements) otherwise unreachable; + elements[index] = value; + } + } + } + label Slow { + CreateDataProperty(receiver, key, value); + } + return Undefined; +} diff --git a/src/builtins/object-fromentries.tq b/src/builtins/object-fromentries.tq index cb2c4afd5c..2557b082a7 100644 --- a/src/builtins/object-fromentries.tq +++ b/src/builtins/object-fromentries.tq @@ -22,7 +22,7 @@ namespace object { // Symbol.toPrimitive, toString, and valueOf, which could // invalidate assumptions about the iterable. if (Is(pair.key)) goto IfSlow; - CreateDataProperty(result, pair.key, pair.value); + FastCreateDataProperty(result, pair.key, pair.value); } return result; } @@ -55,7 +55,7 @@ namespace object { iterator::IteratorValue(step, fastIteratorResultMap); const pair: KeyValuePair = collections::LoadKeyValuePair(iteratorValue); - CreateDataProperty(result, pair.key, pair.value); + FastCreateDataProperty(result, pair.key, pair.value); } return result; } catch (e) deferred { diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc index 29ce9b4368..40f2dc4f3a 100644 --- a/src/debug/debug-evaluate.cc +++ b/src/debug/debug-evaluate.cc @@ -980,6 +980,14 @@ static bool TransitivelyCalledBuiltinHasNoSideEffect(Builtins::Name caller, default: return false; } + case Builtins::kFastCreateDataProperty: + switch (caller) { + case Builtins::kArrayPrototypeSlice: + case Builtins::kArrayFilter: + return true; + default: + return false; + } case Builtins::kSetProperty: switch (caller) { case Builtins::kArrayPrototypeSlice: