tor-browser

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

commit 5b4768d1dd6709c9e7e08b67fc94664396902d1c
parent 62273e72609efc2f03a1a562befb22e93b3c329f
Author: André Bargull <andre.bargull@gmail.com>
Date:   Mon, 20 Oct 2025 12:27:44 +0000

Bug 1991402 - Part 19: Make (Specialized)BindFunctionResult shared CacheIR instructions. r=jandem

Inlined GetProp ICs don't have additional arguments we need to load from the stack,
so we don't have to load anything from the stub frame.

Differential Revision: https://phabricator.services.mozilla.com/D266775

Diffstat:
Mjs/src/jit-test/tests/cacheir/inlinable-native-accessor-6.js | 14++++++++++++++
Mjs/src/jit/BaselineCacheIRCompiler.cpp | 80-------------------------------------------------------------------------------
Mjs/src/jit/CacheIRCompiler.cpp | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mjs/src/jit/CacheIROps.yaml | 4++--
Mjs/src/jit/IonCacheIRCompiler.cpp | 11-----------
5 files changed, 93 insertions(+), 93 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 @@ -66,3 +66,17 @@ function testArrayJoin() { } } testArrayJoin(); + +function testFunctionBind() { + Object.defineProperty(Function.prototype, "bound", {get: Function.prototype.bind}); + + for (var i = 0; i < 100; ++i) { + // |SpecializedBindFunctionResult| CacheIROp. + assertEq(function(){ return i; }.bound(), i); + + // |BindFunctionResult| CacheIROp. + var r = Math.random.bound(); + assertEq(0 <= r && r < 1, true); + } +} +testFunctionBind(); diff --git a/js/src/jit/BaselineCacheIRCompiler.cpp b/js/src/jit/BaselineCacheIRCompiler.cpp @@ -4093,86 +4093,6 @@ bool BaselineCacheIRCompiler::emitNewFunctionCloneResult( return true; } -bool BaselineCacheIRCompiler::emitBindFunctionResult( - ObjOperandId targetId, uint32_t argc, uint32_t templateObjectOffset) { - JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); - - AutoOutputRegister output(*this); - AutoScratchRegister scratch(allocator, masm); - - Register target = allocator.useRegister(masm, targetId); - - allocator.discardStack(masm); - - AutoStubFrame stubFrame(*this); - stubFrame.enter(masm, scratch); - - // Push the arguments in reverse order. - for (uint32_t i = 0; i < argc; i++) { - Address argAddress(FramePointer, - BaselineStubFrameLayout::Size() + i * sizeof(Value)); - masm.pushValue(argAddress); - } - masm.moveStackPtrTo(scratch.get()); - - masm.Push(ImmWord(0)); // nullptr for maybeBound - masm.Push(Imm32(argc)); - masm.Push(scratch); - masm.Push(target); - - using Fn = BoundFunctionObject* (*)(JSContext*, Handle<JSObject*>, Value*, - uint32_t, Handle<BoundFunctionObject*>); - callVM<Fn, BoundFunctionObject::functionBindImpl>(masm); - - stubFrame.leave(masm); - masm.storeCallPointerResult(scratch); - - masm.tagValue(JSVAL_TYPE_OBJECT, scratch, output.valueReg()); - return true; -} - -bool BaselineCacheIRCompiler::emitSpecializedBindFunctionResult( - ObjOperandId targetId, uint32_t argc, uint32_t templateObjectOffset) { - JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); - - AutoOutputRegister output(*this); - AutoScratchRegisterMaybeOutput scratch1(allocator, masm); - AutoScratchRegister scratch2(allocator, masm); - - Register target = allocator.useRegister(masm, targetId); - - StubFieldOffset objectField(templateObjectOffset, StubField::Type::JSObject); - emitLoadStubField(objectField, scratch2); - - allocator.discardStack(masm); - - AutoStubFrame stubFrame(*this); - stubFrame.enter(masm, scratch1); - - // Push the arguments in reverse order. - for (uint32_t i = 0; i < argc; i++) { - Address argAddress(FramePointer, - BaselineStubFrameLayout::Size() + i * sizeof(Value)); - masm.pushValue(argAddress); - } - masm.moveStackPtrTo(scratch1.get()); - - masm.Push(scratch2); - masm.Push(Imm32(argc)); - masm.Push(scratch1); - masm.Push(target); - - using Fn = BoundFunctionObject* (*)(JSContext*, Handle<JSObject*>, Value*, - uint32_t, Handle<BoundFunctionObject*>); - callVM<Fn, BoundFunctionObject::functionBindSpecializedBaseline>(masm); - - stubFrame.leave(masm); - masm.storeCallPointerResult(scratch1); - - masm.tagValue(JSVAL_TYPE_OBJECT, scratch1, output.valueReg()); - return true; -} - bool BaselineCacheIRCompiler::emitCloseIterScriptedResult( ObjOperandId iterId, ObjOperandId calleeId, CompletionKind kind, uint32_t calleeNargs) { diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp @@ -4548,6 +4548,79 @@ bool CacheIRCompiler::emitLoadFunctionNameResult(ObjOperandId objId) { return true; } +bool CacheIRCompiler::emitBindFunctionResult(ObjOperandId targetId, + uint32_t argc, + uint32_t templateObjectOffset) { + JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); + + AutoCallVM callvm(masm, this, allocator); + AutoScratchRegisterMaybeOutput scratch(allocator, masm, callvm.output()); + + Register target = allocator.useRegister(masm, targetId); + + callvm.prepare(); + + if (isBaseline()) { + // Push the arguments in reverse order. + for (uint32_t i = 0; i < argc; i++) { + Address argAddress(FramePointer, + BaselineStubFrameLayout::Size() + i * sizeof(Value)); + masm.pushValue(argAddress); + } + } else { + MOZ_ASSERT(argc == 0, "Call ICs not used in ion"); + } + masm.moveStackPtrTo(scratch.get()); + + masm.Push(ImmWord(0)); // nullptr for maybeBound + masm.Push(Imm32(argc)); + masm.Push(scratch); + masm.Push(target); + + using Fn = BoundFunctionObject* (*)(JSContext*, Handle<JSObject*>, Value*, + uint32_t, Handle<BoundFunctionObject*>); + callvm.call<Fn, BoundFunctionObject::functionBindImpl>(); + return true; +} + +bool CacheIRCompiler::emitSpecializedBindFunctionResult( + ObjOperandId targetId, uint32_t argc, uint32_t templateObjectOffset) { + JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); + + AutoCallVM callvm(masm, this, allocator); + AutoScratchRegisterMaybeOutput scratch1(allocator, masm, callvm.output()); + AutoScratchRegister scratch2(allocator, masm); + + Register target = allocator.useRegister(masm, targetId); + + StubFieldOffset objectField(templateObjectOffset, StubField::Type::JSObject); + emitLoadStubField(objectField, scratch2); + + callvm.prepare(); + + if (isBaseline()) { + // Push the arguments in reverse order. + for (uint32_t i = 0; i < argc; i++) { + Address argAddress(FramePointer, + BaselineStubFrameLayout::Size() + i * sizeof(Value)); + masm.pushValue(argAddress); + } + } else { + MOZ_ASSERT(argc == 0, "Call ICs not used in ion"); + } + masm.moveStackPtrTo(scratch1.get()); + + masm.Push(scratch2); + masm.Push(Imm32(argc)); + masm.Push(scratch1); + masm.Push(target); + + using Fn = BoundFunctionObject* (*)(JSContext*, Handle<JSObject*>, Value*, + uint32_t, Handle<BoundFunctionObject*>); + callvm.call<Fn, BoundFunctionObject::functionBindSpecializedBaseline>(); + return true; +} + bool CacheIRCompiler::emitLinearizeForCharAccess(StringOperandId strId, Int32OperandId indexId, StringOperandId resultId) { @@ -12027,6 +12100,10 @@ template <> struct ReturnTypeToJSValueType<SetObject*> { static constexpr JSValueType result = JSVAL_TYPE_OBJECT; }; +template <> +struct ReturnTypeToJSValueType<BoundFunctionObject*> { + static constexpr JSValueType result = JSVAL_TYPE_OBJECT; +}; template <typename Fn> void AutoCallVM::storeResult() { diff --git a/js/src/jit/CacheIROps.yaml b/js/src/jit/CacheIROps.yaml @@ -2254,7 +2254,7 @@ thisShape: ShapeField - name: BindFunctionResult - shared: false + shared: true transpile: true cost_estimate: 5 args: @@ -2263,7 +2263,7 @@ templateObject: ObjectField - name: SpecializedBindFunctionResult - shared: false + shared: true transpile: true cost_estimate: 4 args: diff --git a/js/src/jit/IonCacheIRCompiler.cpp b/js/src/jit/IonCacheIRCompiler.cpp @@ -2308,17 +2308,6 @@ bool IonCacheIRCompiler::emitCallInlinedFunction(ObjOperandId calleeId, MOZ_CRASH("Call ICs not used in ion"); } -bool IonCacheIRCompiler::emitBindFunctionResult(ObjOperandId targetId, - uint32_t argc, - uint32_t templateObjectOffset) { - MOZ_CRASH("Call ICs not used in ion"); -} - -bool IonCacheIRCompiler::emitSpecializedBindFunctionResult( - ObjOperandId targetId, uint32_t argc, uint32_t templateObjectOffset) { - MOZ_CRASH("Call ICs not used in ion"); -} - bool IonCacheIRCompiler::emitLoadArgumentFixedSlot(ValOperandId resultId, uint8_t slotIndex) { MOZ_CRASH("Call ICs not used in ion");