tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 2cfc9651020f7415b97d36eda8a4d26210b7e507
parent ed55b76e9d66855ad187b4c9b43a071a879086f9
Author: André Bargull <andre.bargull@gmail.com>
Date:   Mon, 20 Oct 2025 12:27:44 +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:
Mjs/src/jit-test/tests/cacheir/inlinable-native-accessor-6.js | 18++++++++++++++++++
Mjs/src/jit/BaselineCacheIRCompiler.cpp | 79-------------------------------------------------------------------------------
Mjs/src/jit/CacheIR.cpp | 1+
Mjs/src/jit/CacheIRCompiler.cpp | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mjs/src/jit/CacheIROps.yaml | 4++--
Mjs/src/jit/IonCacheIRCompiler.cpp | 13-------------
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"); }