tor-browser

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

commit 2cf5974bdb57bcd4ab0032929e0b6c19d70e65fb
parent 54d2c4effea83c8e93c7ac72a054930dbdb68e0c
Author: André Bargull <andre.bargull@gmail.com>
Date:   Mon, 20 Oct 2025 12:27:42 +0000

Bug 1991402 - Part 9: Convert TypedArray getters. r=jandem

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

Diffstat:
Mjs/src/jit/CacheIR.cpp | 235+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Mjs/src/jit/CacheIRGenerator.h | 5+++--
Mjs/src/jit/InlinableNatives.cpp | 3+++
Mjs/src/jit/InlinableNatives.h | 3+++
Mjs/src/vm/TypedArrayObject.cpp | 23+++++------------------
Mjs/src/vm/TypedArrayObject.h | 6------
6 files changed, 149 insertions(+), 126 deletions(-)

diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp @@ -465,7 +465,6 @@ AttachDecision GetPropIRGenerator::tryAttachStub() { if (nameOrSymbol) { TRY_ATTACH(tryAttachObjectLength(obj, objId, id)); - TRY_ATTACH(tryAttachTypedArray(obj, objId, id)); TRY_ATTACH(tryAttachDataView(obj, objId, id)); TRY_ATTACH(tryAttachArrayBufferMaybeShared(obj, objId, id)); TRY_ATTACH(tryAttachRegExp(obj, objId, id)); @@ -2464,105 +2463,6 @@ AttachDecision GetPropIRGenerator::tryAttachInlinableNativeGetter( return nativeGen.tryAttachStub(); } -AttachDecision GetPropIRGenerator::tryAttachTypedArray(HandleObject obj, - ObjOperandId objId, - HandleId id) { - if (!obj->is<TypedArrayObject>()) { - return AttachDecision::NoAction; - } - - if (mode_ != ICState::Mode::Specialized) { - return AttachDecision::NoAction; - } - - // Receiver should be the object. - if (isSuper()) { - return AttachDecision::NoAction; - } - - bool isLength = id.isAtom(cx_->names().length); - bool isByteOffset = id.isAtom(cx_->names().byteOffset); - if (!isLength && !isByteOffset && !id.isAtom(cx_->names().byteLength)) { - return AttachDecision::NoAction; - } - - NativeObject* holder = nullptr; - Maybe<PropertyInfo> prop; - NativeGetPropKind kind = - CanAttachNativeGetProp(cx_, obj, id, &holder, &prop, pc_); - if (kind != NativeGetPropKind::NativeGetter) { - return AttachDecision::NoAction; - } - - JSFunction& fun = holder->getGetter(*prop)->as<JSFunction>(); - if (isLength) { - if (!TypedArrayObject::isOriginalLengthGetter(fun.native())) { - return AttachDecision::NoAction; - } - } else if (isByteOffset) { - if (!TypedArrayObject::isOriginalByteOffsetGetter(fun.native())) { - return AttachDecision::NoAction; - } - } else { - if (!TypedArrayObject::isOriginalByteLengthGetter(fun.native())) { - return AttachDecision::NoAction; - } - } - - auto* tarr = &obj->as<TypedArrayObject>(); - - maybeEmitIdGuard(id); - // Emit all the normal guards for calling this native, but specialize - // callNativeGetterResult. - emitCallGetterResultGuards(tarr, holder, id, *prop, objId); - if (isLength) { - size_t length = tarr->length().valueOr(0); - if (!tarr->is<ResizableTypedArrayObject>()) { - if (length <= INT32_MAX) { - writer.loadArrayBufferViewLengthInt32Result(objId); - } else { - writer.loadArrayBufferViewLengthDoubleResult(objId); - } - } else { - if (length <= INT32_MAX) { - writer.resizableTypedArrayLengthInt32Result(objId); - } else { - writer.resizableTypedArrayLengthDoubleResult(objId); - } - } - trackAttached("GetProp.TypedArrayLength"); - } else if (isByteOffset) { - // byteOffset doesn't need to use different code paths for fixed-length and - // resizable TypedArrays. - size_t byteOffset = tarr->byteOffset().valueOr(0); - if (byteOffset <= INT32_MAX) { - writer.arrayBufferViewByteOffsetInt32Result(objId); - } else { - writer.arrayBufferViewByteOffsetDoubleResult(objId); - } - trackAttached("GetProp.TypedArrayByteOffset"); - } else { - size_t byteLength = tarr->byteLength().valueOr(0); - if (!tarr->is<ResizableTypedArrayObject>()) { - if (byteLength <= INT32_MAX) { - writer.typedArrayByteLengthInt32Result(objId); - } else { - writer.typedArrayByteLengthDoubleResult(objId); - } - } else { - if (byteLength <= INT32_MAX) { - writer.resizableTypedArrayByteLengthInt32Result(objId); - } else { - writer.resizableTypedArrayByteLengthDoubleResult(objId); - } - } - trackAttached("GetProp.TypedArrayByteLength"); - } - writer.returnFromIC(); - - return AttachDecision::Attach; -} - AttachDecision GetPropIRGenerator::tryAttachDataView(HandleObject obj, ObjOperandId objId, HandleId id) { @@ -11757,6 +11657,135 @@ AttachDecision InlinableNativeIRGenerator::tryAttachTypedArraySubarray() { return AttachDecision::Attach; } +AttachDecision InlinableNativeIRGenerator::tryAttachTypedArrayLength() { + // Expecting no arguments. + if (args_.length() != 0) { + return AttachDecision::NoAction; + } + + // Ensure |this| is a TypedArrayObject. + if (!thisval_.isObject() || !thisval_.toObject().is<TypedArrayObject>()) { + return AttachDecision::NoAction; + } + + auto* tarr = &thisval_.toObject().as<TypedArrayObject>(); + + // Initialize the input operand. + Int32OperandId argcId = initializeInputOperand(); + + // Guard callee is the 'length' native function. + ObjOperandId calleeId = emitNativeCalleeGuard(argcId); + + // Guard |this| is a TypedArrayObject. + ValOperandId thisValId = loadThis(calleeId); + ObjOperandId objId = writer.guardToObject(thisValId); + writer.guardShapeForClass(objId, tarr->shape()); + + size_t length = tarr->length().valueOr(0); + if (!tarr->is<ResizableTypedArrayObject>()) { + if (length <= INT32_MAX) { + writer.loadArrayBufferViewLengthInt32Result(objId); + } else { + writer.loadArrayBufferViewLengthDoubleResult(objId); + } + } else { + if (length <= INT32_MAX) { + writer.resizableTypedArrayLengthInt32Result(objId); + } else { + writer.resizableTypedArrayLengthDoubleResult(objId); + } + } + + writer.returnFromIC(); + + trackAttached("TypedArrayLength"); + return AttachDecision::Attach; +} + +AttachDecision InlinableNativeIRGenerator::tryAttachTypedArrayByteLength() { + // Expecting no arguments. + if (args_.length() != 0) { + return AttachDecision::NoAction; + } + + // Ensure |this| is a TypedArrayObject. + if (!thisval_.isObject() || !thisval_.toObject().is<TypedArrayObject>()) { + return AttachDecision::NoAction; + } + + auto* tarr = &thisval_.toObject().as<TypedArrayObject>(); + + // Initialize the input operand. + Int32OperandId argcId = initializeInputOperand(); + + // Guard callee is the 'byteLength' native function. + ObjOperandId calleeId = emitNativeCalleeGuard(argcId); + + // Guard |this| is a TypedArrayObject. + ValOperandId thisValId = loadThis(calleeId); + ObjOperandId objId = writer.guardToObject(thisValId); + writer.guardShapeForClass(objId, tarr->shape()); + + size_t byteLength = tarr->byteLength().valueOr(0); + if (!tarr->is<ResizableTypedArrayObject>()) { + if (byteLength <= INT32_MAX) { + writer.typedArrayByteLengthInt32Result(objId); + } else { + writer.typedArrayByteLengthDoubleResult(objId); + } + } else { + if (byteLength <= INT32_MAX) { + writer.resizableTypedArrayByteLengthInt32Result(objId); + } else { + writer.resizableTypedArrayByteLengthDoubleResult(objId); + } + } + + writer.returnFromIC(); + + trackAttached("TypedArrayByteLength"); + return AttachDecision::Attach; +} + +AttachDecision InlinableNativeIRGenerator::tryAttachTypedArrayByteOffset() { + // Expecting no arguments. + if (args_.length() != 0) { + return AttachDecision::NoAction; + } + + // Ensure |this| is a TypedArrayObject. + if (!thisval_.isObject() || !thisval_.toObject().is<TypedArrayObject>()) { + return AttachDecision::NoAction; + } + + auto* tarr = &thisval_.toObject().as<TypedArrayObject>(); + + // Initialize the input operand. + Int32OperandId argcId = initializeInputOperand(); + + // Guard callee is the 'byteLength' native function. + ObjOperandId calleeId = emitNativeCalleeGuard(argcId); + + // Guard |this| is a TypedArrayObject. + ValOperandId thisValId = loadThis(calleeId); + ObjOperandId objId = writer.guardToObject(thisValId); + writer.guardShapeForClass(objId, tarr->shape()); + + // byteOffset doesn't need to use different code paths for fixed-length and + // resizable TypedArrays. + size_t byteOffset = tarr->byteOffset().valueOr(0); + if (byteOffset <= INT32_MAX) { + writer.arrayBufferViewByteOffsetInt32Result(objId); + } else { + writer.arrayBufferViewByteOffsetDoubleResult(objId); + } + + writer.returnFromIC(); + + trackAttached("TypedArrayByteOffset"); + return AttachDecision::Attach; +} + AttachDecision InlinableNativeIRGenerator::tryAttachIsTypedArray( bool isPossiblyWrapped) { // Self-hosted code calls this with a single object argument. @@ -13334,6 +13363,12 @@ AttachDecision InlinableNativeIRGenerator::tryAttachStub() { return tryAttachTypedArraySet(); case InlinableNative::TypedArraySubarray: return tryAttachTypedArraySubarray(); + case InlinableNative::TypedArrayLength: + return tryAttachTypedArrayLength(); + case InlinableNative::TypedArrayByteLength: + return tryAttachTypedArrayByteLength(); + case InlinableNative::TypedArrayByteOffset: + return tryAttachTypedArrayByteOffset(); // TypedArray intrinsics. case InlinableNative::IntrinsicIsTypedArray: diff --git a/js/src/jit/CacheIRGenerator.h b/js/src/jit/CacheIRGenerator.h @@ -176,8 +176,6 @@ class MOZ_RAII GetPropIRGenerator : public IRGenerator { ValOperandId receiverId); AttachDecision tryAttachObjectLength(HandleObject obj, ObjOperandId objId, HandleId id); - AttachDecision tryAttachTypedArray(HandleObject obj, ObjOperandId objId, - HandleId id); AttachDecision tryAttachDataView(HandleObject obj, ObjOperandId objId, HandleId id); AttachDecision tryAttachArrayBufferMaybeShared(HandleObject obj, @@ -832,6 +830,9 @@ class MOZ_RAII InlinableNativeIRGenerator { AttachDecision tryAttachTypedArrayFill(); AttachDecision tryAttachTypedArraySet(); AttachDecision tryAttachTypedArraySubarray(); + AttachDecision tryAttachTypedArrayLength(); + AttachDecision tryAttachTypedArrayByteLength(); + AttachDecision tryAttachTypedArrayByteOffset(); AttachDecision tryAttachIsTypedArray(bool isPossiblyWrapped); AttachDecision tryAttachIsTypedArrayConstructor(); AttachDecision tryAttachTypedArrayLength(bool isPossiblyWrapped); diff --git a/js/src/jit/InlinableNatives.cpp b/js/src/jit/InlinableNatives.cpp @@ -358,6 +358,9 @@ bool js::jit::CanInlineNativeCrossRealm(InlinableNative native) { case InlinableNative::TypedArrayFill: case InlinableNative::TypedArraySet: case InlinableNative::TypedArraySubarray: + case InlinableNative::TypedArrayLength: + case InlinableNative::TypedArrayByteLength: + case InlinableNative::TypedArrayByteOffset: case InlinableNative::WeakMapGet: case InlinableNative::WeakMapHas: case InlinableNative::WeakSetHas: diff --git a/js/src/jit/InlinableNatives.h b/js/src/jit/InlinableNatives.h @@ -204,6 +204,9 @@ _(TypedArrayFill) \ _(TypedArraySet) \ _(TypedArraySubarray) \ + _(TypedArrayLength) \ + _(TypedArrayByteLength) \ + _(TypedArrayByteOffset) \ \ _(TestBailout) \ _(TestAssertFloat32) \ diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp @@ -1840,10 +1840,12 @@ static bool TypedArray_toStringTagGetter(JSContext* cx, unsigned argc, } /* static */ const JSPropertySpec TypedArrayObject::protoAccessors[] = { - JS_PSG("length", TypedArray_lengthGetter, 0), + JS_INLINABLE_PSG("length", TypedArray_lengthGetter, 0, TypedArrayLength), JS_PSG("buffer", TypedArray_bufferGetter, 0), - JS_PSG("byteLength", TypedArray_byteLengthGetter, 0), - JS_PSG("byteOffset", TypedArray_byteOffsetGetter, 0), + JS_INLINABLE_PSG("byteLength", TypedArray_byteLengthGetter, 0, + TypedArrayByteLength), + JS_INLINABLE_PSG("byteOffset", TypedArray_byteOffsetGetter, 0, + TypedArrayByteOffset), JS_SYM_GET(toStringTag, TypedArray_toStringTagGetter, 0), JS_PS_END, }; @@ -6186,21 +6188,6 @@ const JSClass TypedArrayObject::protoClasses[Scalar::MaxTypedArrayViewType] = { #undef IMPL_TYPED_ARRAY_PROTO_CLASS }; -/* static */ -bool TypedArrayObject::isOriginalLengthGetter(Native native) { - return native == TypedArray_lengthGetter; -} - -/* static */ -bool TypedArrayObject::isOriginalByteOffsetGetter(Native native) { - return native == TypedArray_byteOffsetGetter; -} - -/* static */ -bool TypedArrayObject::isOriginalByteLengthGetter(Native native) { - return native == TypedArray_byteLengthGetter; -} - bool js::IsTypedArrayConstructor(const JSObject* obj) { #define CHECK_TYPED_ARRAY_CONSTRUCTOR(_, T, N) \ if (IsNativeFunction(obj, TypedArrayObjectTemplate<T>::class_constructor)) { \ diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h @@ -136,12 +136,6 @@ class TypedArrayObject : public ArrayBufferViewObject { // Maximum allowed byte length for any typed array. static constexpr size_t ByteLengthLimit = ArrayBufferObject::ByteLengthLimit; - static bool isOriginalLengthGetter(Native native); - - static bool isOriginalByteOffsetGetter(Native native); - - static bool isOriginalByteLengthGetter(Native native); - /* Accessors and functions */ static bool sort(JSContext* cx, unsigned argc, Value* vp);