mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-14 15:37:55 +00:00
Bug 1132706 - Lazify hashing for insertions into the NewObjectCache; r=jonco
--HG-- extra : rebase_source : 9435fdbada6cc43d6e59cddef93d17572f423cba
This commit is contained in:
parent
847508c681
commit
d2a24551f7
@ -3329,6 +3329,14 @@ EnsureNewArrayElements(ExclusiveContext *cx, ArrayObject *obj, uint32_t length)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
NewArrayIsCachable(ExclusiveContext *cxArg, NewObjectKind newKind)
|
||||
{
|
||||
return cxArg->isJSContext() &&
|
||||
newKind == GenericObject &&
|
||||
!cxArg->asJSContext()->compartment()->hasObjectMetadataCallback();
|
||||
}
|
||||
|
||||
template <uint32_t maxLength>
|
||||
static MOZ_ALWAYS_INLINE ArrayObject *
|
||||
NewArray(ExclusiveContext *cxArg, uint32_t length,
|
||||
@ -3338,15 +3346,13 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
|
||||
MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
uint64_t gcNumber = 0;
|
||||
if (JSContext *cx = cxArg->maybeJSContext()) {
|
||||
bool isCachable = NewArrayIsCachable(cxArg, newKind);
|
||||
if (isCachable) {
|
||||
JSContext *cx = cxArg->asJSContext();
|
||||
JSRuntime *rt = cx->runtime();
|
||||
NewObjectCache &cache = rt->newObjectCache;
|
||||
if (newKind == GenericObject &&
|
||||
!cx->compartment()->hasObjectMetadataCallback() &&
|
||||
cache.lookupGlobal(&ArrayObject::class_, cx->global(), allocKind, &entry))
|
||||
{
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupGlobal(&ArrayObject::class_, cx->global(), allocKind, &entry)) {
|
||||
gc::InitialHeap heap = GetInitialHeap(newKind, &ArrayObject::class_);
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry, heap);
|
||||
if (obj) {
|
||||
@ -3361,8 +3367,6 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
} else {
|
||||
gcNumber = rt->gc.gcNumber();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3405,11 +3409,11 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
|
||||
if (newKind == SingletonObject && !JSObject::setSingleton(cxArg, arr))
|
||||
return nullptr;
|
||||
|
||||
if (entry != -1 &&
|
||||
cxArg->asJSContext()->runtime()->gc.gcNumber() == gcNumber)
|
||||
{
|
||||
cxArg->asJSContext()->runtime()->newObjectCache.fillGlobal(entry, &ArrayObject::class_,
|
||||
cxArg->global(), allocKind, arr);
|
||||
if (isCachable) {
|
||||
NewObjectCache &cache = cxArg->asJSContext()->runtime()->newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
cache.lookupGlobal(&ArrayObject::class_, cxArg->global(), allocKind, &entry);
|
||||
cache.fillGlobal(entry, &ArrayObject::class_, cxArg->global(), allocKind, arr);
|
||||
}
|
||||
|
||||
if (maxLength > 0 && !EnsureNewArrayElements(cxArg, arr, std::min(maxLength, length)))
|
||||
|
133
js/src/jsobj.cpp
133
js/src/jsobj.cpp
@ -1218,6 +1218,20 @@ NewObjectCache::fillProto(EntryIndex entry, const Class *clasp, js::TaggedProto
|
||||
return fill(entry, clasp, proto.raw(), kind, obj);
|
||||
}
|
||||
|
||||
static bool
|
||||
NewObjectWithTaggedProtoIsCachable(ExclusiveContext *cxArg, Handle<TaggedProto> proto,
|
||||
NewObjectKind newKind, const Class *clasp,
|
||||
HandleObject parentArg)
|
||||
{
|
||||
return cxArg->isJSContext() &&
|
||||
proto.isObject() &&
|
||||
newKind == GenericObject &&
|
||||
clasp->isNative() &&
|
||||
!cxArg->asJSContext()->compartment()->hasObjectMetadataCallback() &&
|
||||
(!parentArg || parentArg == proto.toObject()->getParent()) &&
|
||||
!proto.toObject()->is<GlobalObject>();
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::NewObjectWithGivenTaggedProto(ExclusiveContext *cxArg, const Class *clasp,
|
||||
Handle<TaggedProto> proto, HandleObject parentArg,
|
||||
@ -1226,25 +1240,16 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext *cxArg, const Class *clasp,
|
||||
if (CanBeFinalizedInBackground(allocKind, clasp))
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
uint64_t gcNumber = 0;
|
||||
if (JSContext *cx = cxArg->maybeJSContext()) {
|
||||
bool isCachable = NewObjectWithTaggedProtoIsCachable(cxArg, proto, newKind, clasp, parentArg);
|
||||
if (isCachable) {
|
||||
JSContext *cx = cxArg->asJSContext();
|
||||
JSRuntime *rt = cx->runtime();
|
||||
NewObjectCache &cache = rt->newObjectCache;
|
||||
if (proto.isObject() &&
|
||||
newKind == GenericObject &&
|
||||
clasp->isNative() &&
|
||||
!cx->compartment()->hasObjectMetadataCallback() &&
|
||||
(!parentArg || parentArg == proto.toObject()->getParent()) &&
|
||||
!proto.toObject()->is<GlobalObject>())
|
||||
{
|
||||
if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
|
||||
if (obj)
|
||||
return obj;
|
||||
} else {
|
||||
gcNumber = rt->gc.gcNumber();
|
||||
}
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1264,12 +1269,11 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext *cxArg, const Class *clasp,
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
if (entry != -1 && !obj->as<NativeObject>().hasDynamicSlots() &&
|
||||
cxArg->asJSContext()->runtime()->gc.gcNumber() == gcNumber)
|
||||
{
|
||||
cxArg->asJSContext()->runtime()->newObjectCache.fillProto(entry, clasp,
|
||||
proto, allocKind,
|
||||
&obj->as<NativeObject>());
|
||||
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
|
||||
NewObjectCache &cache = cxArg->asJSContext()->runtime()->newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
cache.lookupProto(clasp, proto.toObject(), allocKind, &entry);
|
||||
cache.fillProto(entry, clasp, proto, allocKind, &obj->as<NativeObject>());
|
||||
}
|
||||
|
||||
return obj;
|
||||
@ -1369,6 +1373,17 @@ FindProto(ExclusiveContext *cx, const js::Class *clasp, MutableHandleObject prot
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
NewObjectWithClassProtoIsCachable(ExclusiveContext *cxArg, HandleObject parent,
|
||||
JSProtoKey protoKey, NewObjectKind newKind, const Class *clasp)
|
||||
{
|
||||
return cxArg->isJSContext() &&
|
||||
parent->is<GlobalObject>() &&
|
||||
protoKey != JSProto_Null &&
|
||||
newKind == GenericObject &&
|
||||
clasp->isNative() &&
|
||||
!cxArg->asJSContext()->compartment()->hasObjectMetadataCallback();
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp,
|
||||
@ -1396,24 +1411,16 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp,
|
||||
*/
|
||||
JSProtoKey protoKey = ClassProtoKeyOrAnonymousOrNull(clasp);
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
uint64_t gcNumber = 0;
|
||||
if (JSContext *cx = cxArg->maybeJSContext()) {
|
||||
bool isCachable = NewObjectWithClassProtoIsCachable(cxArg, parent, protoKey, newKind, clasp);
|
||||
if (isCachable) {
|
||||
JSContext *cx = cxArg->asJSContext();
|
||||
JSRuntime *rt = cx->runtime();
|
||||
NewObjectCache &cache = rt->newObjectCache;
|
||||
if (parent->is<GlobalObject>() &&
|
||||
protoKey != JSProto_Null &&
|
||||
newKind == GenericObject &&
|
||||
clasp->isNative() &&
|
||||
!cx->compartment()->hasObjectMetadataCallback())
|
||||
{
|
||||
if (cache.lookupGlobal(clasp, &parent->as<GlobalObject>(), allocKind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
|
||||
if (obj)
|
||||
return obj;
|
||||
} else {
|
||||
gcNumber = rt->gc.gcNumber();
|
||||
}
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupGlobal(clasp, &parent->as<GlobalObject>(), allocKind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1430,17 +1437,29 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp,
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
if (entry != -1 && !obj->as<NativeObject>().hasDynamicSlots() &&
|
||||
cxArg->asJSContext()->runtime()->gc.gcNumber() == gcNumber)
|
||||
{
|
||||
cxArg->asJSContext()->runtime()->newObjectCache.fillGlobal(entry, clasp,
|
||||
&parent->as<GlobalObject>(),
|
||||
allocKind, &obj->as<NativeObject>());
|
||||
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
|
||||
NewObjectCache &cache = cxArg->asJSContext()->runtime()->newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
cache.lookupGlobal(clasp, &parent->as<GlobalObject>(), allocKind, &entry);
|
||||
cache.fillGlobal(entry, clasp, &parent->as<GlobalObject>(), allocKind,
|
||||
&obj->as<NativeObject>());
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static bool
|
||||
NewObjectWithGroupIsCachable(JSContext *cx, HandleObjectGroup group, HandleObject parent,
|
||||
NewObjectKind newKind)
|
||||
{
|
||||
return group->proto().isObject() &&
|
||||
parent == group->proto().toObject()->getParent() &&
|
||||
newKind == GenericObject &&
|
||||
group->clasp()->isNative() &&
|
||||
(!group->newScript() || group->newScript()->analyzed()) &&
|
||||
!cx->compartment()->hasObjectMetadataCallback();
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a plain object with the specified group. This bypasses getNewGroup to
|
||||
* avoid losing creation site information for objects made by scripted 'new'.
|
||||
@ -1455,24 +1474,15 @@ js::NewObjectWithGroupCommon(JSContext *cx, HandleObjectGroup group, HandleObjec
|
||||
if (CanBeFinalizedInBackground(allocKind, group->clasp()))
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
NewObjectCache &cache = cx->runtime()->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
uint64_t gcNumber = 0;
|
||||
if (group->proto().isObject() &&
|
||||
parent == group->proto().toObject()->getParent() &&
|
||||
newKind == GenericObject &&
|
||||
group->clasp()->isNative() &&
|
||||
(!group->newScript() || group->newScript()->analyzed()) &&
|
||||
!cx->compartment()->hasObjectMetadataCallback())
|
||||
{
|
||||
bool isCachable = NewObjectWithGroupIsCachable(cx, group, parent, newKind);
|
||||
if (isCachable) {
|
||||
NewObjectCache &cache = cx->runtime()->newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupGroup(group, allocKind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry,
|
||||
GetInitialHeap(newKind, group->clasp()));
|
||||
if (obj)
|
||||
return obj;
|
||||
} else {
|
||||
gcNumber = cx->runtime()->gc.gcNumber();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1480,9 +1490,10 @@ js::NewObjectWithGroupCommon(JSContext *cx, HandleObjectGroup group, HandleObjec
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
if (entry != -1 && !obj->as<NativeObject>().hasDynamicSlots() &&
|
||||
cx->runtime()->gc.gcNumber() == gcNumber)
|
||||
{
|
||||
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
|
||||
NewObjectCache &cache = cx->runtime()->newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
cache.lookupGroup(group, allocKind, &entry);
|
||||
cache.fillGroup(entry, group, allocKind, &obj->as<NativeObject>());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user