commit a0d144ed2675890e61a4263e963443715dcb1039
parent d116ad129f4007f7da989de8846fd8c9e80d6c06
Author: André Bargull <andre.bargull@gmail.com>
Date: Tue, 21 Oct 2025 07:05:43 +0000
Bug 1991402 - Part 17: Make {PackedArray,Arguments}SliceResult shared CacheIR instructions. r=jandem
Use `AutoCallVM` to implement both instructions in `CacheIRCompiler`. `AutoCallVM`
can't be used together with `FailurePath`, so we have to move the packed array
guard into a separate instruction.
Differential Revision: https://phabricator.services.mozilla.com/D266773
Diffstat:
6 files changed, 77 insertions(+), 94 deletions(-)
diff --git a/js/src/jit-test/tests/cacheir/inlinable-native-accessor-6.js b/js/src/jit-test/tests/cacheir/inlinable-native-accessor-6.js
@@ -38,3 +38,21 @@ function testStringAt() {
}
}
testStringAt();
+
+function testArraySlice() {
+ Object.defineProperty(Array.prototype, "sliced", {get: Array.prototype.slice});
+
+ for (var i = 0; i < 100; ++i) {
+ assertEq([1, 2].sliced.length, 2);
+ }
+}
+testArraySlice();
+
+function testArraySliceArguments() {
+ Object.defineProperty(arguments, "sliced", {get: Array.prototype.slice});
+
+ for (var i = 0; i < 100; ++i) {
+ assertEq(arguments.sliced.length, 0);
+ }
+}
+testArraySliceArguments();
diff --git a/js/src/jit/BaselineCacheIRCompiler.cpp b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -1107,85 +1107,6 @@ bool BaselineCacheIRCompiler::emitArrayJoinResult(ObjOperandId objId,
return true;
}
-bool BaselineCacheIRCompiler::emitPackedArraySliceResult(
- uint32_t templateObjectOffset, ObjOperandId arrayId, Int32OperandId beginId,
- Int32OperandId endId) {
- JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
-
- AutoOutputRegister output(*this);
- AutoScratchRegisterMaybeOutput scratch1(allocator, masm, output);
- AutoScratchRegisterMaybeOutputType scratch2(allocator, masm, output);
-
- Register array = allocator.useRegister(masm, arrayId);
- Register begin = allocator.useRegister(masm, beginId);
- Register end = allocator.useRegister(masm, endId);
-
- FailurePath* failure;
- if (!addFailurePath(&failure)) {
- return false;
- }
-
- masm.branchArrayIsNotPacked(array, scratch1, scratch2, failure->label());
-
- allocator.discardStack(masm);
-
- AutoStubFrame stubFrame(*this);
- stubFrame.enter(masm, scratch1);
-
- // Don't attempt to pre-allocate the object, instead always use the slow
- // path.
- ImmPtr result(nullptr);
-
- masm.Push(result);
- masm.Push(end);
- masm.Push(begin);
- masm.Push(array);
-
- using Fn =
- JSObject* (*)(JSContext*, HandleObject, int32_t, int32_t, HandleObject);
- callVM<Fn, ArraySliceDense>(masm);
-
- stubFrame.leave(masm);
-
- masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, output.valueReg());
- return true;
-}
-
-bool BaselineCacheIRCompiler::emitArgumentsSliceResult(
- uint32_t templateObjectOffset, ObjOperandId argsId, Int32OperandId beginId,
- Int32OperandId endId) {
- JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
-
- AutoOutputRegister output(*this);
- AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
-
- Register args = allocator.useRegister(masm, argsId);
- Register begin = allocator.useRegister(masm, beginId);
- Register end = allocator.useRegister(masm, endId);
-
- allocator.discardStack(masm);
-
- AutoStubFrame stubFrame(*this);
- stubFrame.enter(masm, scratch);
-
- // Don't attempt to pre-allocate the object, instead always use the slow path.
- ImmPtr result(nullptr);
-
- masm.Push(result);
- masm.Push(end);
- masm.Push(begin);
- masm.Push(args);
-
- using Fn =
- JSObject* (*)(JSContext*, HandleObject, int32_t, int32_t, HandleObject);
- callVM<Fn, ArgumentsSliceDense>(masm);
-
- stubFrame.leave(masm);
-
- masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, output.valueReg());
- return true;
-}
-
bool BaselineCacheIRCompiler::emitIsArrayResult(ValOperandId inputId) {
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp
@@ -6804,6 +6804,7 @@ AttachDecision InlinableNativeIRGenerator::tryAttachArraySlice() {
if (isPackedArray) {
emitOptimisticClassGuard(objId, &thisval_.toObject(),
GuardClassKind::Array);
+ writer.guardArrayIsPacked(objId);
} else {
auto* args = &thisval_.toObject().as<ArgumentsObject>();
diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp
@@ -7334,6 +7334,62 @@ bool CacheIRCompiler::emitArrayPush(ObjOperandId objId, ValOperandId rhsId) {
return true;
}
+bool CacheIRCompiler::emitPackedArraySliceResult(uint32_t templateObjectOffset,
+ ObjOperandId arrayId,
+ Int32OperandId beginId,
+ Int32OperandId endId) {
+ JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
+
+ AutoCallVM callvm(masm, this, allocator);
+
+ Register array = allocator.useRegister(masm, arrayId);
+ Register begin = allocator.useRegister(masm, beginId);
+ Register end = allocator.useRegister(masm, endId);
+
+ callvm.prepare();
+
+ // Don't attempt to pre-allocate the object, instead always use the slow path.
+ ImmPtr result(nullptr);
+
+ masm.Push(result);
+ masm.Push(end);
+ masm.Push(begin);
+ masm.Push(array);
+
+ using Fn =
+ JSObject* (*)(JSContext*, HandleObject, int32_t, int32_t, HandleObject);
+ callvm.call<Fn, ArraySliceDense>();
+ return true;
+}
+
+bool CacheIRCompiler::emitArgumentsSliceResult(uint32_t templateObjectOffset,
+ ObjOperandId argsId,
+ Int32OperandId beginId,
+ Int32OperandId endId) {
+ JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
+
+ AutoCallVM callvm(masm, this, allocator);
+
+ Register args = allocator.useRegister(masm, argsId);
+ Register begin = allocator.useRegister(masm, beginId);
+ Register end = allocator.useRegister(masm, endId);
+
+ callvm.prepare();
+
+ // Don't attempt to pre-allocate the object, instead always use the slow path.
+ ImmPtr result(nullptr);
+
+ masm.Push(result);
+ masm.Push(end);
+ masm.Push(begin);
+ masm.Push(args);
+
+ using Fn =
+ JSObject* (*)(JSContext*, HandleObject, int32_t, int32_t, HandleObject);
+ callvm.call<Fn, ArgumentsSliceDense>();
+ return true;
+}
+
bool CacheIRCompiler::emitStoreTypedArrayElement(ObjOperandId objId,
Scalar::Type elementType,
IntPtrOperandId indexId,
diff --git a/js/src/jit/CacheIROps.yaml b/js/src/jit/CacheIROps.yaml
@@ -1204,7 +1204,7 @@
array: ObjId
- name: PackedArraySliceResult
- shared: false
+ shared: true
transpile: true
cost_estimate: 5
args:
@@ -1214,7 +1214,7 @@
end: Int32Id
- name: ArgumentsSliceResult
- shared: false
+ shared: true
transpile: true
cost_estimate: 5
args:
diff --git a/js/src/jit/IonCacheIRCompiler.cpp b/js/src/jit/IonCacheIRCompiler.cpp
@@ -2335,19 +2335,6 @@ bool IonCacheIRCompiler::emitArrayJoinResult(ObjOperandId objId,
MOZ_CRASH("Call ICs not used in ion");
}
-bool IonCacheIRCompiler::emitPackedArraySliceResult(
- uint32_t templateObjectOffset, ObjOperandId arrayId, Int32OperandId beginId,
- Int32OperandId endId) {
- MOZ_CRASH("Call ICs not used in ion");
-}
-
-bool IonCacheIRCompiler::emitArgumentsSliceResult(uint32_t templateObjectOffset,
- ObjOperandId argsId,
- Int32OperandId beginId,
- Int32OperandId endId) {
- MOZ_CRASH("Call ICs not used in ion");
-}
-
bool IonCacheIRCompiler::emitIsArrayResult(ValOperandId inputId) {
MOZ_CRASH("Call ICs not used in ion");
}