Bug 1132706 - Lazify hashing for insertions into the NewObjectCache; r=jonco

--HG--
extra : rebase_source : 9435fdbada6cc43d6e59cddef93d17572f423cba
This commit is contained in:
Terrence Cole 2015-02-13 11:36:40 -08:00
Родитель 847508c681
Коммит d2a24551f7
2 изменённых файлов: 90 добавлений и 75 удалений

Просмотреть файл

@ -3329,6 +3329,14 @@ EnsureNewArrayElements(ExclusiveContext *cx, ArrayObject *obj, uint32_t length)
return true; return true;
} }
static bool
NewArrayIsCachable(ExclusiveContext *cxArg, NewObjectKind newKind)
{
return cxArg->isJSContext() &&
newKind == GenericObject &&
!cxArg->asJSContext()->compartment()->hasObjectMetadataCallback();
}
template <uint32_t maxLength> template <uint32_t maxLength>
static MOZ_ALWAYS_INLINE ArrayObject * static MOZ_ALWAYS_INLINE ArrayObject *
NewArray(ExclusiveContext *cxArg, uint32_t length, NewArray(ExclusiveContext *cxArg, uint32_t length,
@ -3338,15 +3346,13 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_)); MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));
allocKind = GetBackgroundAllocKind(allocKind); allocKind = GetBackgroundAllocKind(allocKind);
NewObjectCache::EntryIndex entry = -1; bool isCachable = NewArrayIsCachable(cxArg, newKind);
uint64_t gcNumber = 0; if (isCachable) {
if (JSContext *cx = cxArg->maybeJSContext()) { JSContext *cx = cxArg->asJSContext();
JSRuntime *rt = cx->runtime(); JSRuntime *rt = cx->runtime();
NewObjectCache &cache = rt->newObjectCache; NewObjectCache &cache = rt->newObjectCache;
if (newKind == GenericObject && NewObjectCache::EntryIndex entry = -1;
!cx->compartment()->hasObjectMetadataCallback() && if (cache.lookupGlobal(&ArrayObject::class_, cx->global(), allocKind, &entry)) {
cache.lookupGlobal(&ArrayObject::class_, cx->global(), allocKind, &entry))
{
gc::InitialHeap heap = GetInitialHeap(newKind, &ArrayObject::class_); gc::InitialHeap heap = GetInitialHeap(newKind, &ArrayObject::class_);
JSObject *obj = cache.newObjectFromHit(cx, entry, heap); JSObject *obj = cache.newObjectFromHit(cx, entry, heap);
if (obj) { if (obj) {
@ -3361,8 +3367,6 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
} }
return arr; return arr;
} }
} else {
gcNumber = rt->gc.gcNumber();
} }
} }
@ -3405,11 +3409,11 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
if (newKind == SingletonObject && !JSObject::setSingleton(cxArg, arr)) if (newKind == SingletonObject && !JSObject::setSingleton(cxArg, arr))
return nullptr; return nullptr;
if (entry != -1 && if (isCachable) {
cxArg->asJSContext()->runtime()->gc.gcNumber() == gcNumber) NewObjectCache &cache = cxArg->asJSContext()->runtime()->newObjectCache;
{ NewObjectCache::EntryIndex entry = -1;
cxArg->asJSContext()->runtime()->newObjectCache.fillGlobal(entry, &ArrayObject::class_, cache.lookupGlobal(&ArrayObject::class_, cxArg->global(), allocKind, &entry);
cxArg->global(), allocKind, arr); cache.fillGlobal(entry, &ArrayObject::class_, cxArg->global(), allocKind, arr);
} }
if (maxLength > 0 && !EnsureNewArrayElements(cxArg, arr, std::min(maxLength, length))) if (maxLength > 0 && !EnsureNewArrayElements(cxArg, arr, std::min(maxLength, length)))

Просмотреть файл

@ -1218,6 +1218,20 @@ NewObjectCache::fillProto(EntryIndex entry, const Class *clasp, js::TaggedProto
return fill(entry, clasp, proto.raw(), kind, obj); 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 * JSObject *
js::NewObjectWithGivenTaggedProto(ExclusiveContext *cxArg, const Class *clasp, js::NewObjectWithGivenTaggedProto(ExclusiveContext *cxArg, const Class *clasp,
Handle<TaggedProto> proto, HandleObject parentArg, Handle<TaggedProto> proto, HandleObject parentArg,
@ -1226,25 +1240,16 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext *cxArg, const Class *clasp,
if (CanBeFinalizedInBackground(allocKind, clasp)) if (CanBeFinalizedInBackground(allocKind, clasp))
allocKind = GetBackgroundAllocKind(allocKind); allocKind = GetBackgroundAllocKind(allocKind);
NewObjectCache::EntryIndex entry = -1; bool isCachable = NewObjectWithTaggedProtoIsCachable(cxArg, proto, newKind, clasp, parentArg);
uint64_t gcNumber = 0; if (isCachable) {
if (JSContext *cx = cxArg->maybeJSContext()) { JSContext *cx = cxArg->asJSContext();
JSRuntime *rt = cx->runtime(); JSRuntime *rt = cx->runtime();
NewObjectCache &cache = rt->newObjectCache; NewObjectCache &cache = rt->newObjectCache;
if (proto.isObject() && NewObjectCache::EntryIndex entry = -1;
newKind == GenericObject && if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
clasp->isNative() && JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
!cx->compartment()->hasObjectMetadataCallback() && if (obj)
(!parentArg || parentArg == proto.toObject()->getParent()) && return obj;
!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();
}
} }
} }
@ -1264,12 +1269,11 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext *cxArg, const Class *clasp,
if (!obj) if (!obj)
return nullptr; return nullptr;
if (entry != -1 && !obj->as<NativeObject>().hasDynamicSlots() && if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
cxArg->asJSContext()->runtime()->gc.gcNumber() == gcNumber) NewObjectCache &cache = cxArg->asJSContext()->runtime()->newObjectCache;
{ NewObjectCache::EntryIndex entry = -1;
cxArg->asJSContext()->runtime()->newObjectCache.fillProto(entry, clasp, cache.lookupProto(clasp, proto.toObject(), allocKind, &entry);
proto, allocKind, cache.fillProto(entry, clasp, proto, allocKind, &obj->as<NativeObject>());
&obj->as<NativeObject>());
} }
return obj; return obj;
@ -1369,6 +1373,17 @@ FindProto(ExclusiveContext *cx, const js::Class *clasp, MutableHandleObject prot
return true; 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 * JSObject *
js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp, js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp,
@ -1396,24 +1411,16 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp,
*/ */
JSProtoKey protoKey = ClassProtoKeyOrAnonymousOrNull(clasp); JSProtoKey protoKey = ClassProtoKeyOrAnonymousOrNull(clasp);
NewObjectCache::EntryIndex entry = -1; bool isCachable = NewObjectWithClassProtoIsCachable(cxArg, parent, protoKey, newKind, clasp);
uint64_t gcNumber = 0; if (isCachable) {
if (JSContext *cx = cxArg->maybeJSContext()) { JSContext *cx = cxArg->asJSContext();
JSRuntime *rt = cx->runtime(); JSRuntime *rt = cx->runtime();
NewObjectCache &cache = rt->newObjectCache; NewObjectCache &cache = rt->newObjectCache;
if (parent->is<GlobalObject>() && NewObjectCache::EntryIndex entry = -1;
protoKey != JSProto_Null && if (cache.lookupGlobal(clasp, &parent->as<GlobalObject>(), allocKind, &entry)) {
newKind == GenericObject && JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
clasp->isNative() && if (obj)
!cx->compartment()->hasObjectMetadataCallback()) return obj;
{
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();
}
} }
} }
@ -1430,17 +1437,29 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp,
if (!obj) if (!obj)
return nullptr; return nullptr;
if (entry != -1 && !obj->as<NativeObject>().hasDynamicSlots() && if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
cxArg->asJSContext()->runtime()->gc.gcNumber() == gcNumber) NewObjectCache &cache = cxArg->asJSContext()->runtime()->newObjectCache;
{ NewObjectCache::EntryIndex entry = -1;
cxArg->asJSContext()->runtime()->newObjectCache.fillGlobal(entry, clasp, cache.lookupGlobal(clasp, &parent->as<GlobalObject>(), allocKind, &entry);
&parent->as<GlobalObject>(), cache.fillGlobal(entry, clasp, &parent->as<GlobalObject>(), allocKind,
allocKind, &obj->as<NativeObject>()); &obj->as<NativeObject>());
} }
return obj; 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 * Create a plain object with the specified group. This bypasses getNewGroup to
* avoid losing creation site information for objects made by scripted 'new'. * 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())) if (CanBeFinalizedInBackground(allocKind, group->clasp()))
allocKind = GetBackgroundAllocKind(allocKind); allocKind = GetBackgroundAllocKind(allocKind);
NewObjectCache &cache = cx->runtime()->newObjectCache; bool isCachable = NewObjectWithGroupIsCachable(cx, group, parent, newKind);
if (isCachable) {
NewObjectCache::EntryIndex entry = -1; NewObjectCache &cache = cx->runtime()->newObjectCache;
uint64_t gcNumber = 0; NewObjectCache::EntryIndex entry = -1;
if (group->proto().isObject() &&
parent == group->proto().toObject()->getParent() &&
newKind == GenericObject &&
group->clasp()->isNative() &&
(!group->newScript() || group->newScript()->analyzed()) &&
!cx->compartment()->hasObjectMetadataCallback())
{
if (cache.lookupGroup(group, allocKind, &entry)) { if (cache.lookupGroup(group, allocKind, &entry)) {
JSObject *obj = cache.newObjectFromHit(cx, entry, JSObject *obj = cache.newObjectFromHit(cx, entry,
GetInitialHeap(newKind, group->clasp())); GetInitialHeap(newKind, group->clasp()));
if (obj) if (obj)
return obj; return obj;
} else {
gcNumber = cx->runtime()->gc.gcNumber();
} }
} }
@ -1480,9 +1490,10 @@ js::NewObjectWithGroupCommon(JSContext *cx, HandleObjectGroup group, HandleObjec
if (!obj) if (!obj)
return nullptr; return nullptr;
if (entry != -1 && !obj->as<NativeObject>().hasDynamicSlots() && if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
cx->runtime()->gc.gcNumber() == gcNumber) NewObjectCache &cache = cx->runtime()->newObjectCache;
{ NewObjectCache::EntryIndex entry = -1;
cache.lookupGroup(group, allocKind, &entry);
cache.fillGroup(entry, group, allocKind, &obj->as<NativeObject>()); cache.fillGroup(entry, group, allocKind, &obj->as<NativeObject>());
} }