mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1674108 part 1 - Store dense and TypedArray index in PropertyResult. r=jonco
This refactors PropertyResult so that we can also store indexes. This will help us support typed arrays larger than 2 GB because it lets us replace JSID_TO_INT (limited to INT32_MAX) with the size_t we stored. Differential Revision: https://phabricator.services.mozilla.com/D95141
This commit is contained in:
parent
3b35332b4f
commit
2a0dab8062
@ -227,54 +227,67 @@ class ObjectOpResult {
|
||||
};
|
||||
|
||||
class PropertyResult {
|
||||
union {
|
||||
js::Shape* shape_;
|
||||
uintptr_t bits_;
|
||||
enum class Kind : uint8_t {
|
||||
NotFound,
|
||||
NativeProperty,
|
||||
NonNativeProperty,
|
||||
DenseElement,
|
||||
TypedArrayElement,
|
||||
};
|
||||
|
||||
static const uintptr_t NotFound = 0;
|
||||
static const uintptr_t NonNativeProperty = 1;
|
||||
static const uintptr_t DenseOrTypedArrayElement = 1;
|
||||
union {
|
||||
// Set if kind is NativeProperty.
|
||||
js::Shape* shape_;
|
||||
// Set if kind is DenseElement.
|
||||
uint32_t denseIndex_;
|
||||
// Set if kind is TypedArrayElement.
|
||||
size_t typedArrayIndex_;
|
||||
};
|
||||
Kind kind_ = Kind::NotFound;
|
||||
|
||||
public:
|
||||
PropertyResult() : bits_(NotFound) {}
|
||||
|
||||
explicit PropertyResult(js::Shape* propertyShape) : shape_(propertyShape) {
|
||||
MOZ_ASSERT(!isFound() || isNativeProperty());
|
||||
}
|
||||
PropertyResult() = default;
|
||||
|
||||
explicit operator bool() const { return isFound(); }
|
||||
|
||||
bool isFound() const { return bits_ != NotFound; }
|
||||
|
||||
bool isNonNativeProperty() const { return bits_ == NonNativeProperty; }
|
||||
|
||||
bool isDenseOrTypedArrayElement() const {
|
||||
return bits_ == DenseOrTypedArrayElement;
|
||||
}
|
||||
|
||||
bool isNativeProperty() const { return isFound() && !isNonNativeProperty(); }
|
||||
|
||||
js::Shape* maybeShape() const {
|
||||
MOZ_ASSERT(!isNonNativeProperty());
|
||||
return isFound() ? shape_ : nullptr;
|
||||
}
|
||||
bool isFound() const { return kind_ != Kind::NotFound; }
|
||||
bool isNonNativeProperty() const { return kind_ == Kind::NonNativeProperty; }
|
||||
bool isDenseElement() const { return kind_ == Kind::DenseElement; }
|
||||
bool isTypedArrayElement() const { return kind_ == Kind::TypedArrayElement; }
|
||||
bool isNativeProperty() const { return kind_ == Kind::NativeProperty; }
|
||||
|
||||
js::Shape* shape() const {
|
||||
MOZ_ASSERT(isNativeProperty());
|
||||
return shape_;
|
||||
}
|
||||
|
||||
void setNotFound() { bits_ = NotFound; }
|
||||
|
||||
void setNativeProperty(js::Shape* propertyShape) {
|
||||
shape_ = propertyShape;
|
||||
MOZ_ASSERT(isNativeProperty());
|
||||
uint32_t denseElementIndex() const {
|
||||
MOZ_ASSERT(isDenseElement());
|
||||
return denseIndex_;
|
||||
}
|
||||
|
||||
void setNonNativeProperty() { bits_ = NonNativeProperty; }
|
||||
size_t typedArrayElementIndex() const {
|
||||
MOZ_ASSERT(isTypedArrayElement());
|
||||
return typedArrayIndex_;
|
||||
}
|
||||
|
||||
void setDenseOrTypedArrayElement() { bits_ = DenseOrTypedArrayElement; }
|
||||
void setNotFound() { kind_ = Kind::NotFound; }
|
||||
|
||||
void setNativeProperty(js::Shape* propertyShape) {
|
||||
kind_ = Kind::NativeProperty;
|
||||
shape_ = propertyShape;
|
||||
}
|
||||
|
||||
void setNonNativeProperty() { kind_ = Kind::NonNativeProperty; }
|
||||
|
||||
void setDenseElement(uint32_t index) {
|
||||
kind_ = Kind::DenseElement;
|
||||
denseIndex_ = index;
|
||||
}
|
||||
|
||||
void setTypedArrayElement(size_t index) {
|
||||
kind_ = Kind::TypedArrayElement;
|
||||
typedArrayIndex_ = index;
|
||||
}
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
@ -292,14 +305,15 @@ class WrappedPtrOperations<JS::PropertyResult, Wrapper> {
|
||||
public:
|
||||
bool isFound() const { return value().isFound(); }
|
||||
explicit operator bool() const { return bool(value()); }
|
||||
js::Shape* maybeShape() const { return value().maybeShape(); }
|
||||
js::Shape* shape() const { return value().shape(); }
|
||||
uint32_t denseElementIndex() const { return value().denseElementIndex(); }
|
||||
size_t typedArrayElementIndex() const {
|
||||
return value().typedArrayElementIndex();
|
||||
}
|
||||
bool isNativeProperty() const { return value().isNativeProperty(); }
|
||||
bool isNonNativeProperty() const { return value().isNonNativeProperty(); }
|
||||
bool isDenseOrTypedArrayElement() const {
|
||||
return value().isDenseOrTypedArrayElement();
|
||||
}
|
||||
js::Shape* asTaggedShape() const { return value().asTaggedShape(); }
|
||||
bool isDenseElement() const { return value().isDenseElement(); }
|
||||
bool isTypedArrayElement() const { return value().isTypedArrayElement(); }
|
||||
};
|
||||
|
||||
template <class Wrapper>
|
||||
@ -311,7 +325,10 @@ class MutableWrappedPtrOperations<JS::PropertyResult, Wrapper>
|
||||
void setNotFound() { value().setNotFound(); }
|
||||
void setNativeProperty(js::Shape* shape) { value().setNativeProperty(shape); }
|
||||
void setNonNativeProperty() { value().setNonNativeProperty(); }
|
||||
void setDenseOrTypedArrayElement() { value().setDenseOrTypedArrayElement(); }
|
||||
void setDenseElement(uint32_t index) { value().setDenseElement(index); }
|
||||
void setTypedArrayElement(size_t index) {
|
||||
value().setTypedArrayElement(index);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
@ -485,13 +485,12 @@ static bool IsCacheableProtoChain(JSObject* obj, JSObject* holder) {
|
||||
}
|
||||
|
||||
static bool IsCacheableGetPropReadSlot(JSObject* obj, JSObject* holder,
|
||||
PropertyResult prop) {
|
||||
if (!prop || !IsCacheableProtoChain(obj, holder)) {
|
||||
Shape* shape) {
|
||||
if (!shape->isDataProperty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Shape* shape = prop.shape();
|
||||
if (!shape->isDataProperty()) {
|
||||
if (!IsCacheableProtoChain(obj, holder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -508,7 +507,9 @@ enum NativeGetPropCacheability {
|
||||
static NativeGetPropCacheability IsCacheableGetPropCall(JSObject* obj,
|
||||
JSObject* holder,
|
||||
Shape* shape) {
|
||||
if (!shape || !IsCacheableProtoChain(obj, holder)) {
|
||||
MOZ_ASSERT(shape);
|
||||
|
||||
if (!IsCacheableProtoChain(obj, holder)) {
|
||||
return CanAttachNone;
|
||||
}
|
||||
|
||||
@ -606,10 +607,7 @@ static bool IsCacheableNoProperty(JSContext* cx, JSObject* obj,
|
||||
JSObject* holder, Shape* shape, jsid id,
|
||||
jsbytecode* pc,
|
||||
GetPropertyResultFlags resultFlags) {
|
||||
if (shape) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!shape);
|
||||
MOZ_ASSERT(!holder);
|
||||
|
||||
// Idempotent ICs may only attach missing-property stubs if undefined
|
||||
@ -645,25 +643,28 @@ static NativeGetPropCacheability CanAttachNativeGetProp(
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!holder);
|
||||
if (baseHolder) {
|
||||
if (!baseHolder->isNative()) {
|
||||
return CanAttachNone;
|
||||
}
|
||||
|
||||
if (prop.isNativeProperty()) {
|
||||
MOZ_ASSERT(baseHolder);
|
||||
holder.set(&baseHolder->as<NativeObject>());
|
||||
}
|
||||
shape.set(prop.maybeShape());
|
||||
shape.set(prop.shape());
|
||||
|
||||
if (IsCacheableGetPropReadSlot(obj, holder, prop)) {
|
||||
return CanAttachReadSlot;
|
||||
if (IsCacheableGetPropReadSlot(obj, holder, shape)) {
|
||||
return CanAttachReadSlot;
|
||||
}
|
||||
|
||||
// Idempotent ICs cannot call getters, see tryAttachIdempotentStub.
|
||||
if (pc && (resultFlags & GetPropertyResultFlags::Monitored)) {
|
||||
return IsCacheableGetPropCall(obj, holder, shape);
|
||||
}
|
||||
|
||||
return CanAttachNone;
|
||||
}
|
||||
|
||||
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc, resultFlags)) {
|
||||
return CanAttachReadSlot;
|
||||
}
|
||||
|
||||
// Idempotent ICs cannot call getters, see tryAttachIdempotentStub.
|
||||
if (pc && (resultFlags & GetPropertyResultFlags::Monitored)) {
|
||||
return IsCacheableGetPropCall(obj, holder, shape);
|
||||
if (!prop.isFound()) {
|
||||
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc, resultFlags)) {
|
||||
return CanAttachReadSlot;
|
||||
}
|
||||
}
|
||||
|
||||
return CanAttachNone;
|
||||
@ -2749,8 +2750,7 @@ AttachDecision GetNameIRGenerator::tryAttachGlobalNameValue(ObjOperandId objId,
|
||||
// prototype. Ignore the global lexical scope as it doesn't figure
|
||||
// into the prototype chain. We guard on the global lexical
|
||||
// scope's shape independently.
|
||||
if (!IsCacheableGetPropReadSlot(&globalLexical->global(), holder,
|
||||
PropertyResult(shape))) {
|
||||
if (!IsCacheableGetPropReadSlot(&globalLexical->global(), holder, shape)) {
|
||||
return AttachDecision::NoAction;
|
||||
}
|
||||
|
||||
@ -2889,7 +2889,7 @@ AttachDecision GetNameIRGenerator::tryAttachEnvironmentName(ObjOperandId objId,
|
||||
}
|
||||
|
||||
holder = &env->as<NativeObject>();
|
||||
if (!IsCacheableGetPropReadSlot(holder, holder, PropertyResult(shape))) {
|
||||
if (!IsCacheableGetPropReadSlot(holder, holder, shape)) {
|
||||
return AttachDecision::NoAction;
|
||||
}
|
||||
if (holder->getSlot(shape->slot()).isMagic()) {
|
||||
@ -3767,7 +3767,9 @@ void SetPropIRGenerator::trackAttached(const char* name) {
|
||||
|
||||
static bool IsCacheableSetPropCallNative(JSObject* obj, JSObject* holder,
|
||||
Shape* shape) {
|
||||
if (!shape || !IsCacheableProtoChain(obj, holder)) {
|
||||
MOZ_ASSERT(shape);
|
||||
|
||||
if (!IsCacheableProtoChain(obj, holder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3797,7 +3799,9 @@ static bool IsCacheableSetPropCallNative(JSObject* obj, JSObject* holder,
|
||||
|
||||
static bool IsCacheableSetPropCallScripted(JSObject* obj, JSObject* holder,
|
||||
Shape* shape) {
|
||||
if (!shape || !IsCacheableProtoChain(obj, holder)) {
|
||||
MOZ_ASSERT(shape);
|
||||
|
||||
if (!IsCacheableProtoChain(obj, holder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3833,11 +3837,11 @@ static bool CanAttachSetter(JSContext* cx, jsbytecode* pc, HandleObject obj,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prop.isNonNativeProperty()) {
|
||||
if (!prop.isNativeProperty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
propShape.set(prop.maybeShape());
|
||||
propShape.set(prop.shape());
|
||||
if (!IsCacheableSetPropCallScripted(obj, holder, propShape) &&
|
||||
!IsCacheableSetPropCallNative(obj, holder, propShape)) {
|
||||
return false;
|
||||
@ -4756,7 +4760,7 @@ AttachDecision InstanceOfIRGenerator::tryAttachStub() {
|
||||
jsid hasInstanceID = SYMBOL_TO_JSID(cx_->wellKnownSymbols().hasInstance);
|
||||
if (!LookupPropertyPure(cx_, fun, hasInstanceID, &hasInstanceHolder,
|
||||
&hasInstanceProp) ||
|
||||
!hasInstanceProp.isFound() || hasInstanceProp.isNonNativeProperty()) {
|
||||
!hasInstanceProp.isNativeProperty()) {
|
||||
trackAttached(IRGenerator::NotAttached);
|
||||
return AttachDecision::NoAction;
|
||||
}
|
||||
|
@ -2369,10 +2369,12 @@ bool js::LookupOwnPropertyPure(JSContext* cx, JSObject* obj, jsid id,
|
||||
if (obj->isNative()) {
|
||||
// Search for a native dense element, typed array element, or property.
|
||||
|
||||
if (JSID_IS_INT(id) &&
|
||||
obj->as<NativeObject>().containsDenseElement(JSID_TO_INT(id))) {
|
||||
propp->setDenseOrTypedArrayElement();
|
||||
return true;
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32_t index = JSID_TO_INT(id);
|
||||
if (obj->as<NativeObject>().containsDenseElement(index)) {
|
||||
propp->setDenseElement(index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->is<TypedArrayObject>()) {
|
||||
@ -2384,7 +2386,7 @@ bool js::LookupOwnPropertyPure(JSContext* cx, JSObject* obj, jsid id,
|
||||
|
||||
if (index.inspect()) {
|
||||
if (index.inspect().value() < obj->as<TypedArrayObject>().length()) {
|
||||
propp->setDenseOrTypedArrayElement();
|
||||
propp->setTypedArrayElement(index.inspect().value());
|
||||
} else {
|
||||
propp->setNotFound();
|
||||
if (isTypedArrayOutOfRange) {
|
||||
@ -2421,13 +2423,13 @@ bool js::LookupOwnPropertyPure(JSContext* cx, JSObject* obj, jsid id,
|
||||
static inline bool NativeGetPureInline(NativeObject* pobj, jsid id,
|
||||
PropertyResult prop, Value* vp,
|
||||
JSContext* cx) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
// For simplicity we ignore the TypedArray with string index case.
|
||||
if (!JSID_IS_INT(id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return pobj->getDenseOrTypedArrayElement<NoGC>(cx, JSID_TO_INT(id), vp);
|
||||
if (prop.isDenseElement()) {
|
||||
*vp = pobj->getDenseElement(prop.denseElementIndex());
|
||||
return true;
|
||||
}
|
||||
if (prop.isTypedArrayElement()) {
|
||||
size_t idx = prop.typedArrayElementIndex();
|
||||
return pobj->as<TypedArrayObject>().getElement<NoGC>(cx, idx, vp);
|
||||
}
|
||||
|
||||
// Fail if we have a custom getter.
|
||||
@ -2477,7 +2479,9 @@ bool js::GetOwnPropertyPure(JSContext* cx, JSObject* obj, jsid id, Value* vp,
|
||||
|
||||
static inline bool NativeGetGetterPureInline(PropertyResult prop,
|
||||
JSFunction** fp) {
|
||||
if (!prop.isDenseOrTypedArrayElement() && prop.shape()->hasGetterObject()) {
|
||||
MOZ_ASSERT(prop.isNativeProperty());
|
||||
|
||||
if (prop.shape()->hasGetterObject()) {
|
||||
Shape* shape = prop.shape();
|
||||
if (shape->getterObject()->is<JSFunction>()) {
|
||||
*fp = &shape->getterObject()->as<JSFunction>();
|
||||
@ -2531,8 +2535,7 @@ bool js::GetOwnNativeGetterPure(JSContext* cx, JSObject* obj, jsid id,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!prop || prop.isDenseOrTypedArrayElement() ||
|
||||
!prop.shape()->hasGetterObject()) {
|
||||
if (!prop || !prop.isNativeProperty() || !prop.shape()->hasGetterObject()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2557,8 +2560,7 @@ bool js::HasOwnDataPropertyPure(JSContext* cx, JSObject* obj, jsid id,
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = prop && !prop.isDenseOrTypedArrayElement() &&
|
||||
prop.shape()->isDataProperty();
|
||||
*result = prop && prop.isNativeProperty() && prop.shape()->isDataProperty();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -741,9 +741,12 @@ static MOZ_ALWAYS_INLINE bool CallResolveOp(JSContext* cx,
|
||||
MOZ_ASSERT_IF(obj->getClass()->getMayResolve(),
|
||||
obj->getClass()->getMayResolve()(cx->names(), id, obj));
|
||||
|
||||
if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
|
||||
propp.setDenseOrTypedArrayElement();
|
||||
return true;
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32_t index = JSID_TO_INT(id);
|
||||
if (obj->containsDenseElement(index)) {
|
||||
propp.setDenseElement(index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!obj->is<TypedArrayObject>());
|
||||
@ -765,10 +768,13 @@ static MOZ_ALWAYS_INLINE bool LookupOwnPropertyInline(
|
||||
typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp,
|
||||
bool* donep) {
|
||||
// Check for a native dense element.
|
||||
if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
|
||||
propp.setDenseOrTypedArrayElement();
|
||||
*donep = true;
|
||||
return true;
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32_t index = JSID_TO_INT(id);
|
||||
if (obj->containsDenseElement(index)) {
|
||||
propp.setDenseElement(index);
|
||||
*donep = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a typed array element. Integer lookups always finish here
|
||||
@ -784,9 +790,9 @@ static MOZ_ALWAYS_INLINE bool LookupOwnPropertyInline(
|
||||
}
|
||||
|
||||
if (index.inspect()) {
|
||||
if (index.inspect().value() <
|
||||
obj->template as<TypedArrayObject>().length()) {
|
||||
propp.setDenseOrTypedArrayElement();
|
||||
uint64_t idx = index.inspect().value();
|
||||
if (idx < obj->template as<TypedArrayObject>().length()) {
|
||||
propp.setTypedArrayElement(idx);
|
||||
} else {
|
||||
propp.setNotFound();
|
||||
}
|
||||
@ -840,9 +846,12 @@ static inline MOZ_MUST_USE bool NativeLookupOwnPropertyNoResolve(
|
||||
JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
MutableHandle<PropertyResult> result) {
|
||||
// Check for a native dense element.
|
||||
if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
|
||||
result.setDenseOrTypedArrayElement();
|
||||
return true;
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32_t index = JSID_TO_INT(id);
|
||||
if (obj->containsDenseElement(index)) {
|
||||
result.setDenseElement(index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a typed array element.
|
||||
@ -852,7 +861,7 @@ static inline MOZ_MUST_USE bool NativeLookupOwnPropertyNoResolve(
|
||||
|
||||
if (index) {
|
||||
if (index.value() < obj->as<TypedArrayObject>().length()) {
|
||||
result.setDenseOrTypedArrayElement();
|
||||
result.setTypedArrayElement(index.value());
|
||||
} else {
|
||||
result.setNotFound();
|
||||
}
|
||||
|
@ -1672,9 +1672,15 @@ static MOZ_ALWAYS_INLINE bool GetExistingProperty(
|
||||
static bool GetExistingPropertyValue(JSContext* cx, HandleNativeObject obj,
|
||||
HandleId id, Handle<PropertyResult> prop,
|
||||
MutableHandleValue vp) {
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
return obj->getDenseOrTypedArrayElement<CanGC>(cx, JSID_TO_INT(id), vp);
|
||||
if (prop.isDenseElement()) {
|
||||
vp.set(obj->getDenseElement(prop.denseElementIndex()));
|
||||
return true;
|
||||
}
|
||||
if (prop.isTypedArrayElement()) {
|
||||
size_t idx = prop.typedArrayElementIndex();
|
||||
return obj->as<TypedArrayObject>().getElement<CanGC>(cx, idx, vp);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!cx->isHelperThreadContext());
|
||||
|
||||
MOZ_ASSERT(prop.shape()->propid() == id);
|
||||
@ -1713,8 +1719,7 @@ static bool DefinePropertyIsRedundant(JSContext* cx, HandleNativeObject obj,
|
||||
if (desc.hasValue()) {
|
||||
// Get the current value of the existing property.
|
||||
RootedValue currentValue(cx);
|
||||
if (!prop.isDenseOrTypedArrayElement() &&
|
||||
prop.shape()->isDataProperty()) {
|
||||
if (prop.isNativeProperty() && prop.shape()->isDataProperty()) {
|
||||
// Inline GetExistingPropertyValue in order to omit a type
|
||||
// correctness assertion that's too strict for this particular
|
||||
// call site. For details, see bug 1125624 comments 13-16.
|
||||
@ -1733,13 +1738,13 @@ static bool DefinePropertyIsRedundant(JSContext* cx, HandleNativeObject obj,
|
||||
}
|
||||
|
||||
GetterOp existingGetterOp =
|
||||
prop.isDenseOrTypedArrayElement() ? nullptr : prop.shape()->getter();
|
||||
prop.isNativeProperty() ? prop.shape()->getter() : nullptr;
|
||||
if (desc.getter() != existingGetterOp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SetterOp existingSetterOp =
|
||||
prop.isDenseOrTypedArrayElement() ? nullptr : prop.shape()->setter();
|
||||
prop.isNativeProperty() ? prop.shape()->setter() : nullptr;
|
||||
if (desc.setter() != existingSetterOp) {
|
||||
return true;
|
||||
}
|
||||
@ -1887,7 +1892,7 @@ bool js::NativeDefineProperty(JSContext* cx, HandleNativeObject obj,
|
||||
// type for this property that doesn't match the value in the slot.
|
||||
// Update the type here, even though this DefineProperty call is
|
||||
// otherwise a no-op. (See bug 1125624 comment 13.)
|
||||
if (!prop.isDenseOrTypedArrayElement() && desc.hasValue()) {
|
||||
if (prop.isNativeProperty() && desc.hasValue()) {
|
||||
UpdateShapeTypeAndValue(cx, obj, prop.shape(), id, desc.value());
|
||||
}
|
||||
return result.succeed();
|
||||
@ -2344,9 +2349,12 @@ bool js::NativeGetOwnPropertyDescriptor(
|
||||
desc.setGetter(nullptr);
|
||||
desc.setSetter(nullptr);
|
||||
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
if (!obj->getDenseOrTypedArrayElement<CanGC>(cx, JSID_TO_INT(id),
|
||||
desc.value())) {
|
||||
if (prop.isDenseElement()) {
|
||||
desc.value().set(obj->getDenseElement(prop.denseElementIndex()));
|
||||
} else if (prop.isTypedArrayElement()) {
|
||||
size_t idx = prop.typedArrayElementIndex();
|
||||
if (!obj->as<TypedArrayObject>().getElement<CanGC>(cx, idx,
|
||||
desc.value())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@ -2557,9 +2565,14 @@ static MOZ_ALWAYS_INLINE bool NativeGetPropertyInline(
|
||||
if (prop) {
|
||||
// Steps 5-8. Special case for dense elements because
|
||||
// GetExistingProperty doesn't support those.
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
return pobj->template getDenseOrTypedArrayElement<allowGC>(
|
||||
cx, JSID_TO_INT(id), vp);
|
||||
if (prop.isDenseElement()) {
|
||||
vp.set(pobj->getDenseElement(prop.denseElementIndex()));
|
||||
return true;
|
||||
}
|
||||
if (prop.isTypedArrayElement()) {
|
||||
size_t idx = prop.typedArrayElementIndex();
|
||||
auto* tarr = &pobj->template as<TypedArrayObject>();
|
||||
return tarr->template getElement<allowGC>(cx, idx, vp);
|
||||
}
|
||||
|
||||
typename MaybeRooted<Shape*, allowGC>::RootType shape(cx, prop.shape());
|
||||
@ -2866,7 +2879,7 @@ static bool SetExistingProperty(JSContext* cx, HandleId id, HandleValue v,
|
||||
Handle<PropertyResult> prop,
|
||||
ObjectOpResult& result) {
|
||||
// Step 5 for dense elements.
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
if (prop.isDenseElement() || prop.isTypedArrayElement()) {
|
||||
// Step 5.a.
|
||||
if (pobj->denseElementsAreFrozen()) {
|
||||
return result.fail(JSMSG_READ_ONLY);
|
||||
@ -2874,14 +2887,13 @@ static bool SetExistingProperty(JSContext* cx, HandleId id, HandleValue v,
|
||||
|
||||
// Pure optimization for the common case:
|
||||
if (receiver.isObject() && pobj == &receiver.toObject()) {
|
||||
uint32_t index = JSID_TO_INT(id);
|
||||
|
||||
if (pobj->is<TypedArrayObject>()) {
|
||||
if (prop.isTypedArrayElement()) {
|
||||
Rooted<TypedArrayObject*> tobj(cx, &pobj->as<TypedArrayObject>());
|
||||
return SetTypedArrayElement(cx, tobj, index, v, result);
|
||||
size_t idx = prop.typedArrayElementIndex();
|
||||
return SetTypedArrayElement(cx, tobj, idx, v, result);
|
||||
}
|
||||
|
||||
return SetDenseElement(cx, pobj, index, v, result);
|
||||
return SetDenseElement(cx, pobj, prop.denseElementIndex(), v, result);
|
||||
}
|
||||
|
||||
// Steps 5.b-f.
|
||||
@ -3047,16 +3059,16 @@ bool js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
// Typed array elements are non-configurable.
|
||||
MOZ_ASSERT(!obj->is<TypedArrayObject>());
|
||||
// Typed array elements are non-configurable.
|
||||
MOZ_ASSERT(!prop.isTypedArrayElement());
|
||||
|
||||
// Step 5.
|
||||
if (prop.isDenseElement()) {
|
||||
if (!obj->maybeCopyElementsForWrite(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
obj->setDenseElementHole(cx, JSID_TO_INT(id));
|
||||
obj->setDenseElementHole(cx, prop.denseElementIndex());
|
||||
} else {
|
||||
if (!NativeObject::removeProperty(cx, obj, id)) {
|
||||
return false;
|
||||
|
@ -277,12 +277,12 @@ static inline uint8_t GetPropertyAttributes(JSObject* obj,
|
||||
PropertyResult prop) {
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
if (obj->is<TypedArrayObject>()) {
|
||||
return JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||
}
|
||||
if (prop.isDenseElement()) {
|
||||
return obj->as<NativeObject>().getElementsHeader()->elementAttributes();
|
||||
}
|
||||
if (prop.isTypedArrayElement()) {
|
||||
return JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||
}
|
||||
|
||||
return prop.shape()->attributes();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user