зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1091010 - Optimize accesses to TypedObject.length, r=nmatsakis.
This commit is contained in:
Родитель
91aaa3e40b
Коммит
55aad7d841
|
@ -1636,8 +1636,7 @@ OutlineTypedObject::attach(JSContext *cx, ArrayBufferObject &buffer, int32_t off
|
|||
MOZ_ASSERT(offset >= 0);
|
||||
MOZ_ASSERT((size_t) (offset + size()) <= buffer.byteLength());
|
||||
|
||||
if (typeDescr().is<SizedTypeDescr>())
|
||||
buffer.setHasSizedObjectViews();
|
||||
buffer.setHasTypedObjectViews();
|
||||
|
||||
if (!buffer.addView(cx, this))
|
||||
CrashAtUnhandlableOOM("TypedObject::attach");
|
||||
|
@ -2439,7 +2438,7 @@ InlineTransparentTypedObject::getOrCreateBuffer(JSContext *cx)
|
|||
JS_ALWAYS_TRUE(buffer->addView(cx, this));
|
||||
|
||||
buffer->setForInlineTypedObject();
|
||||
buffer->setHasSizedObjectViews();
|
||||
buffer->setHasTypedObjectViews();
|
||||
|
||||
if (!table->addBuffer(cx, this, buffer))
|
||||
return nullptr;
|
||||
|
|
|
@ -7262,7 +7262,7 @@ IonBuilder::checkTypedObjectIndexInBounds(int32_t elemSize,
|
|||
// If we are not loading the length from the object itself, only
|
||||
// optimize if the array buffer can't have been neutered.
|
||||
types::TypeObjectKey *globalType = types::TypeObjectKey::get(&script()->global());
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_SIZED_OBJECT_NEUTERED))
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED))
|
||||
return false;
|
||||
} else if (objPrediction.kind() == type::UnsizedArray) {
|
||||
// Note: unsized arrays will have their length set to zero if they are
|
||||
|
@ -8563,6 +8563,7 @@ IonBuilder::jsop_length_fastPath()
|
|||
if (obj->mightBeType(MIRType_Object)) {
|
||||
types::TemporaryTypeSet *objTypes = obj->resultTypeSet();
|
||||
|
||||
// Compute the length for array objects.
|
||||
if (objTypes &&
|
||||
objTypes->getKnownClass() == &ArrayObject::class_ &&
|
||||
!objTypes->hasObjectFlags(constraints(), types::OBJECT_FLAG_LENGTH_OVERFLOW))
|
||||
|
@ -8577,6 +8578,30 @@ IonBuilder::jsop_length_fastPath()
|
|||
current->push(length);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compute the length for array typed objects.
|
||||
TypedObjectPrediction prediction = typedObjectPrediction(obj);
|
||||
if (!prediction.isUseless()) {
|
||||
types::TypeObjectKey *globalType = types::TypeObjectKey::get(&script()->global());
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED))
|
||||
return false;
|
||||
|
||||
MInstruction *length;
|
||||
int32_t sizedLength;
|
||||
if (prediction.hasKnownArrayLength(&sizedLength)) {
|
||||
obj->setImplicitlyUsedUnchecked();
|
||||
length = MConstant::New(alloc(), Int32Value(sizedLength));
|
||||
} else if (prediction.kind() == type::UnsizedArray) {
|
||||
length = MTypedObjectUnsizedLength::New(alloc(), obj);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
current->pop();
|
||||
current->add(length);
|
||||
current->push(length);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -9308,7 +9333,7 @@ IonBuilder::getPropTryScalarPropOfTypedObject(bool *emitted, MDefinition *typedO
|
|||
|
||||
// Don't optimize if the typed object might be neutered.
|
||||
types::TypeObjectKey *globalType = types::TypeObjectKey::get(&script()->global());
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_SIZED_OBJECT_NEUTERED))
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED))
|
||||
return true;
|
||||
|
||||
// OK, perform the optimization.
|
||||
|
@ -9325,7 +9350,7 @@ IonBuilder::getPropTryComplexPropOfTypedObject(bool *emitted,
|
|||
{
|
||||
// Don't optimize if the typed object might be neutered.
|
||||
types::TypeObjectKey *globalType = types::TypeObjectKey::get(&script()->global());
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_SIZED_OBJECT_NEUTERED))
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED))
|
||||
return true;
|
||||
|
||||
// OK, perform the optimization
|
||||
|
@ -9984,7 +10009,7 @@ IonBuilder::setPropTryScalarPropOfTypedObject(bool *emitted,
|
|||
|
||||
// Don't optimize if the typed object might be neutered.
|
||||
types::TypeObjectKey *globalType = types::TypeObjectKey::get(&script()->global());
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_SIZED_OBJECT_NEUTERED))
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED))
|
||||
return true;
|
||||
|
||||
// OK! Perform the optimization.
|
||||
|
|
|
@ -484,10 +484,9 @@ enum MOZ_ENUM_TYPE(uint32_t) {
|
|||
|
||||
/*
|
||||
* For a global object, whether any array buffers in this compartment with
|
||||
* sized typed object views have been neutered. Sized typed objects have
|
||||
* different neutering checks from other array buffer views.
|
||||
* typed object views have been neutered.
|
||||
*/
|
||||
OBJECT_FLAG_SIZED_OBJECT_NEUTERED = 0x00400000,
|
||||
OBJECT_FLAG_TYPED_OBJECT_NEUTERED = 0x00400000,
|
||||
|
||||
/*
|
||||
* Whether objects with this type should be allocated directly in the
|
||||
|
|
|
@ -515,21 +515,21 @@ ArrayBufferObject::neuter(JSContext *cx, Handle<ArrayBufferObject*> buffer,
|
|||
return false;
|
||||
|
||||
// When neutering buffers where we don't know all views, the new data must
|
||||
// match the old data. All missing views are sized typed objects, which do
|
||||
// not have a length property to mutate when neutering.
|
||||
// match the old data. All missing views are typed objects, which do not
|
||||
// expect their data to ever change.
|
||||
MOZ_ASSERT_IF(buffer->forInlineTypedObject(),
|
||||
newContents.data() == buffer->dataPointer());
|
||||
|
||||
// When neutering a buffer with sized typed object views, any jitcode which
|
||||
// When neutering a buffer with typed object views, any jitcode which
|
||||
// accesses such views needs to be deoptimized so that neuter checks are
|
||||
// performed. This is done by setting a compartment wide flag indicating
|
||||
// that buffers with sized object views have been neutered.
|
||||
if (buffer->hasSizedObjectViews()) {
|
||||
// that buffers with typed object views have been neutered.
|
||||
if (buffer->hasTypedObjectViews()) {
|
||||
// Make sure the global object's type has been instantiated, so the
|
||||
// flag change will be observed.
|
||||
if (!cx->global()->getType(cx))
|
||||
CrashAtUnhandlableOOM("ArrayBufferObject::neuter");
|
||||
types::MarkTypeObjectFlags(cx, cx->global(), types::OBJECT_FLAG_SIZED_OBJECT_NEUTERED);
|
||||
types::MarkTypeObjectFlags(cx, cx->global(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED);
|
||||
}
|
||||
|
||||
// Neuter all views on the buffer, clear out the list of views and the
|
||||
|
|
|
@ -140,11 +140,11 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
// This array buffer was created lazily for a typed object with inline
|
||||
// data. This implies both that the typed object owns the buffer's data
|
||||
// and that the list of views sharing this buffer's data might be
|
||||
// incomplete. Any missing views will be sized typed objects.
|
||||
// incomplete. Any missing views will be typed objects.
|
||||
FOR_INLINE_TYPED_OBJECT = 0x10,
|
||||
|
||||
// Views of this buffer might include sized typed objects.
|
||||
SIZED_OBJECT_VIEWS = 0x20
|
||||
// Views of this buffer might include typed objects.
|
||||
TYPED_OBJECT_VIEWS = 0x20
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -325,8 +325,8 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
void setForInlineTypedObject() {
|
||||
setFlags(flags() | FOR_INLINE_TYPED_OBJECT);
|
||||
}
|
||||
void setHasSizedObjectViews() {
|
||||
setFlags(flags() | SIZED_OBJECT_VIEWS);
|
||||
void setHasTypedObjectViews() {
|
||||
setFlags(flags() | TYPED_OBJECT_VIEWS);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -342,7 +342,7 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
}
|
||||
|
||||
bool forInlineTypedObject() const { return flags() & FOR_INLINE_TYPED_OBJECT; }
|
||||
bool hasSizedObjectViews() const { return flags() & SIZED_OBJECT_VIEWS; }
|
||||
bool hasTypedObjectViews() const { return flags() & TYPED_OBJECT_VIEWS; }
|
||||
|
||||
void setIsAsmJSMalloced() { setFlags((flags() & ~KIND_MASK) | ASMJS_MALLOCED); }
|
||||
void setIsNeutered() { setFlags(flags() | NEUTERED); }
|
||||
|
|
Загрузка…
Ссылка в новой задаче