tor-browser

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

commit c4692f4209d521f00fac507337bfd7eba8d02227
parent 99d7fb18a57a0696df663401f4a229727676cf13
Author: André Bargull <andre.bargull@gmail.com>
Date:   Mon, 20 Oct 2025 12:27:42 +0000

Bug 1991402 - Part 11: Convert (Shared)ArrayBuffer getters. r=jandem

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

Diffstat:
Mjs/src/jit/CacheIR.cpp | 166+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mjs/src/jit/CacheIRGenerator.h | 5++---
Mjs/src/jit/InlinableNatives.cpp | 2++
Mjs/src/jit/InlinableNatives.h | 4++++
Mjs/src/vm/ArrayBufferObject.cpp | 4+++-
Mjs/src/vm/ArrayBufferObject.h | 4----
Mjs/src/vm/SharedArrayObject.cpp | 4+++-
Mjs/src/vm/SharedArrayObject.h | 4----
8 files changed, 117 insertions(+), 76 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(tryAttachArrayBufferMaybeShared(obj, objId, id)); TRY_ATTACH(tryAttachRegExp(obj, objId, id)); TRY_ATTACH(tryAttachNative(obj, objId, id, receiverId)); TRY_ATTACH(tryAttachModuleNamespace(obj, objId, id)); @@ -2462,68 +2461,6 @@ AttachDecision GetPropIRGenerator::tryAttachInlinableNativeGetter( return nativeGen.tryAttachStub(); } -AttachDecision GetPropIRGenerator::tryAttachArrayBufferMaybeShared( - HandleObject obj, ObjOperandId objId, HandleId id) { - if (!obj->is<ArrayBufferObjectMaybeShared>()) { - return AttachDecision::NoAction; - } - auto* buf = &obj->as<ArrayBufferObjectMaybeShared>(); - - if (mode_ != ICState::Mode::Specialized) { - return AttachDecision::NoAction; - } - - // Receiver should be the object. - if (isSuper()) { - return AttachDecision::NoAction; - } - - if (!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; - } - - auto& fun = holder->getGetter(*prop)->as<JSFunction>(); - if (buf->is<ArrayBufferObject>()) { - if (!ArrayBufferObject::isOriginalByteLengthGetter(fun.native())) { - return AttachDecision::NoAction; - } - } else { - if (!SharedArrayBufferObject::isOriginalByteLengthGetter(fun.native())) { - return AttachDecision::NoAction; - } - } - - maybeEmitIdGuard(id); - // Emit all the normal guards for calling this native, but specialize - // callNativeGetterResult. - emitCallGetterResultGuards(buf, holder, id, *prop, objId); - if (!buf->is<GrowableSharedArrayBufferObject>()) { - if (buf->byteLength() <= INT32_MAX) { - writer.loadArrayBufferByteLengthInt32Result(objId); - } else { - writer.loadArrayBufferByteLengthDoubleResult(objId); - } - } else { - if (buf->byteLength() <= INT32_MAX) { - writer.growableSharedArrayBufferByteLengthInt32Result(objId); - } else { - writer.growableSharedArrayBufferByteLengthDoubleResult(objId); - } - } - writer.returnFromIC(); - - trackAttached("GetProp.ArrayBufferMaybeSharedByteLength"); - return AttachDecision::Attach; -} - AttachDecision GetPropIRGenerator::tryAttachRegExp(HandleObject obj, ObjOperandId objId, HandleId id) { @@ -11931,6 +11868,101 @@ AttachDecision InlinableNativeIRGenerator::tryAttachTypedArrayLength( return AttachDecision::Attach; } +AttachDecision InlinableNativeIRGenerator::tryAttachArrayBufferByteLength() { + // Expecting no arguments. + if (args_.length() != 0) { + return AttachDecision::NoAction; + } + + // Ensure |this| is an ArrayBufferObject. + if (!thisval_.isObject() || !thisval_.toObject().is<ArrayBufferObject>()) { + return AttachDecision::NoAction; + } + + auto* buf = &thisval_.toObject().as<ArrayBufferObject>(); + + // Initialize the input operand. + Int32OperandId argcId = initializeInputOperand(); + + // Guard callee is the 'byteLength' native function. + ObjOperandId calleeId = emitNativeCalleeGuard(argcId); + + // Guard |this| is an ArrayBufferObject. + ValOperandId thisValId = loadThis(calleeId); + ObjOperandId objId = writer.guardToObject(thisValId); + + if (buf->is<FixedLengthArrayBufferObject>()) { + emitOptimisticClassGuard(objId, buf, + GuardClassKind::FixedLengthArrayBuffer); + } else if (buf->is<ImmutableArrayBufferObject>()) { + emitOptimisticClassGuard(objId, buf, GuardClassKind::ImmutableArrayBuffer); + } else { + emitOptimisticClassGuard(objId, buf, GuardClassKind::ResizableArrayBuffer); + } + + if (buf->byteLength() <= INT32_MAX) { + writer.loadArrayBufferByteLengthInt32Result(objId); + } else { + writer.loadArrayBufferByteLengthDoubleResult(objId); + } + + writer.returnFromIC(); + + trackAttached("ArrayBufferByteLength"); + return AttachDecision::Attach; +} + +AttachDecision +InlinableNativeIRGenerator::tryAttachSharedArrayBufferByteLength() { + // Expecting no arguments. + if (args_.length() != 0) { + return AttachDecision::NoAction; + } + + // Ensure |this| is a SharedArrayBufferObject. + if (!thisval_.isObject() || + !thisval_.toObject().is<SharedArrayBufferObject>()) { + return AttachDecision::NoAction; + } + + auto* buf = &thisval_.toObject().as<SharedArrayBufferObject>(); + + // Initialize the input operand. + Int32OperandId argcId = initializeInputOperand(); + + // Guard callee is the 'byteLength' native function. + ObjOperandId calleeId = emitNativeCalleeGuard(argcId); + + // Guard |this| is a SharedArrayBufferObject. + ValOperandId thisValId = loadThis(calleeId); + ObjOperandId objId = writer.guardToObject(thisValId); + + if (buf->is<FixedLengthSharedArrayBufferObject>()) { + emitOptimisticClassGuard(objId, buf, + GuardClassKind::FixedLengthSharedArrayBuffer); + + if (buf->byteLength() <= INT32_MAX) { + writer.loadArrayBufferByteLengthInt32Result(objId); + } else { + writer.loadArrayBufferByteLengthDoubleResult(objId); + } + } else { + emitOptimisticClassGuard(objId, buf, + GuardClassKind::GrowableSharedArrayBuffer); + + if (buf->byteLength() <= INT32_MAX) { + writer.growableSharedArrayBufferByteLengthInt32Result(objId); + } else { + writer.growableSharedArrayBufferByteLengthDoubleResult(objId); + } + } + + writer.returnFromIC(); + + trackAttached("SharedArrayBufferByteLength"); + return AttachDecision::Attach; +} + AttachDecision InlinableNativeIRGenerator::tryAttachIsConstructing() { // Self-hosted code calls this with no arguments in function scripts. MOZ_ASSERT(args_.length() == 0); @@ -13523,6 +13555,14 @@ AttachDecision InlinableNativeIRGenerator::tryAttachStub() { case InlinableNative::WeakSetHas: return tryAttachWeakSetHas(); + // ArrayBuffer natives. + case InlinableNative::ArrayBufferByteLength: + return tryAttachArrayBufferByteLength(); + + // SharedArrayBuffer natives. + case InlinableNative::SharedArrayBufferByteLength: + return tryAttachSharedArrayBufferByteLength(); + // Testing functions. case InlinableNative::TestBailout: if (js::SupportDifferentialTesting()) { diff --git a/js/src/jit/CacheIRGenerator.h b/js/src/jit/CacheIRGenerator.h @@ -176,9 +176,6 @@ class MOZ_RAII GetPropIRGenerator : public IRGenerator { ValOperandId receiverId); AttachDecision tryAttachObjectLength(HandleObject obj, ObjOperandId objId, HandleId id); - AttachDecision tryAttachArrayBufferMaybeShared(HandleObject obj, - ObjOperandId objId, - HandleId id); AttachDecision tryAttachRegExp(HandleObject obj, ObjOperandId objId, HandleId id); AttachDecision tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId, @@ -890,6 +887,8 @@ class MOZ_RAII InlinableNativeIRGenerator { AttachDecision tryAttachWeakMapHas(); AttachDecision tryAttachWeakMapGet(); AttachDecision tryAttachWeakSetHas(); + AttachDecision tryAttachArrayBufferByteLength(); + AttachDecision tryAttachSharedArrayBufferByteLength(); #ifdef FUZZING_JS_FUZZILLI AttachDecision tryAttachFuzzilliHash(); #endif diff --git a/js/src/jit/InlinableNatives.cpp b/js/src/jit/InlinableNatives.cpp @@ -267,6 +267,7 @@ bool js::jit::CanInlineNativeCrossRealm(InlinableNative native) { case InlinableNative::ArrayShift: case InlinableNative::ArrayPush: case InlinableNative::ArraySlice: + case InlinableNative::ArrayBufferByteLength: case InlinableNative::AtomicsCompareExchange: case InlinableNative::AtomicsExchange: case InlinableNative::AtomicsLoad: @@ -329,6 +330,7 @@ bool js::jit::CanInlineNativeCrossRealm(InlinableNative native) { case InlinableNative::SetDelete: case InlinableNative::SetAdd: case InlinableNative::SetSize: + case InlinableNative::SharedArrayBufferByteLength: case InlinableNative::String: case InlinableNative::StringToString: case InlinableNative::StringValueOf: diff --git a/js/src/jit/InlinableNatives.h b/js/src/jit/InlinableNatives.h @@ -39,6 +39,8 @@ _(ArrayPush) \ _(ArraySlice) \ \ + _(ArrayBufferByteLength) \ + \ _(AtomicsCompareExchange) \ _(AtomicsExchange) \ _(AtomicsLoad) \ @@ -171,6 +173,8 @@ _(SetAdd) \ _(SetSize) \ \ + _(SharedArrayBufferByteLength) \ + \ _(String) \ _(StringToString) \ _(StringValueOf) \ diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp @@ -32,6 +32,7 @@ #include "gc/Barrier.h" #include "gc/Memory.h" +#include "jit/InlinableNatives.h" #include "js/ArrayBuffer.h" #include "js/Conversions.h" #include "js/experimental/TypedData.h" // JS_IsArrayBufferViewObject @@ -346,7 +347,8 @@ static const JSFunctionSpec arraybuffer_proto_functions[] = { }; static const JSPropertySpec arraybuffer_proto_properties[] = { - JS_PSG("byteLength", ArrayBufferObject::byteLengthGetter, 0), + JS_INLINABLE_PSG("byteLength", ArrayBufferObject::byteLengthGetter, 0, + ArrayBufferByteLength), JS_PSG("maxByteLength", ArrayBufferObject::maxByteLengthGetter, 0), JS_PSG("resizable", ArrayBufferObject::resizableGetter, 0), JS_PSG("detached", ArrayBufferObject::detachedGetter, 0), diff --git a/js/src/vm/ArrayBufferObject.h b/js/src/vm/ArrayBufferObject.h @@ -475,10 +475,6 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared { static bool class_constructor(JSContext* cx, unsigned argc, Value* vp); - static bool isOriginalByteLengthGetter(Native native) { - return native == byteLengthGetter; - } - static ArrayBufferObject* createForContents(JSContext* cx, size_t nbytes, BufferContents contents); diff --git a/js/src/vm/SharedArrayObject.cpp b/js/src/vm/SharedArrayObject.cpp @@ -15,6 +15,7 @@ #include "gc/GCContext.h" #include "gc/Memory.h" #include "jit/AtomicOperations.h" +#include "jit/InlinableNatives.h" #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* #include "js/Prefs.h" #include "js/PropertySpec.h" @@ -957,7 +958,8 @@ static const JSFunctionSpec sharedarray_proto_functions[] = { }; static const JSPropertySpec sharedarray_proto_properties[] = { - JS_PSG("byteLength", SharedArrayBufferObject::byteLengthGetter, 0), + JS_INLINABLE_PSG("byteLength", SharedArrayBufferObject::byteLengthGetter, 0, + SharedArrayBufferByteLength), JS_PSG("maxByteLength", SharedArrayBufferObject::maxByteLengthGetter, 0), JS_PSG("growable", SharedArrayBufferObject::growableGetter, 0), JS_STRING_SYM_PS(toStringTag, "SharedArrayBuffer", JSPROP_READONLY), diff --git a/js/src/vm/SharedArrayObject.h b/js/src/vm/SharedArrayObject.h @@ -283,10 +283,6 @@ class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared { static bool slice(JSContext* cx, unsigned argc, Value* vp); - static bool isOriginalByteLengthGetter(Native native) { - return native == byteLengthGetter; - } - private: template <class SharedArrayBufferType> static SharedArrayBufferType* NewWith(JSContext* cx,