commit 3780175e555f28193cedd0784439dddf45706e10
parent 378269b56a893ed24be7ccd65b5ea6bfe8a27ec8
Author: André Bargull <andre.bargull@gmail.com>
Date: Tue, 21 Oct 2025 07:05:42 +0000
Bug 1991402 - Part 11: Convert (Shared)ArrayBuffer getters. r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D266603
Diffstat:
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,