зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1245965 - Remove the NewObjectCache. r=terrence
This commit is contained in:
Родитель
02e277f76d
Коммит
6df1030632
|
@ -42,6 +42,7 @@ ecma_5/Object/15.2.3.6-redefinition-1-of-4.js
|
|||
ecma_5/Object/15.2.3.6-redefinition-2-of-4.js
|
||||
ecma_5/Object/15.2.3.6-redefinition-3-of-4.js
|
||||
ecma_5/Object/15.2.3.6-redefinition-4-of-4.js
|
||||
ecma_6/extensions/array-isArray-proxy-recursion.js
|
||||
ecma_6/String/normalize-generateddata-part0.js
|
||||
ecma_6/String/normalize-generateddata-part1-not-listed.js
|
||||
ecma_6/String/normalize-generateddata-part1.js
|
||||
|
@ -50,6 +51,7 @@ ecma_6/String/normalize-generateddata-part3.js
|
|||
js1_5/GC/regress-203278-2.js
|
||||
js1_5/GC/regress-203278-3.js
|
||||
js1_5/GC/regress-278725.js
|
||||
js1_5/Regress/regress-203278-1.js
|
||||
js1_5/Regress/regress-312588.js
|
||||
js1_5/Regress/regress-360969-01.js
|
||||
js1_5/Regress/regress-360969-02.js
|
||||
|
@ -58,3 +60,5 @@ js1_5/Regress/regress-360969-04.js
|
|||
js1_5/Regress/regress-360969-05.js
|
||||
js1_5/Regress/regress-360969-06.js
|
||||
js1_8_5/extensions/clone-complex-object.js
|
||||
js1_8_5/extensions/clone-many-transferables.js
|
||||
js1_8_5/extensions/clone-object.js
|
||||
|
|
|
@ -685,10 +685,6 @@ js::Nursery::doCollection(JSRuntime* rt, JS::gcreason::Reason reason,
|
|||
}
|
||||
maybeEndProfile(ProfileKey::MarkDebugger);
|
||||
|
||||
maybeStartProfile(ProfileKey::ClearNewObjectCache);
|
||||
rt->contextFromMainThread()->caches.newObjectCache.clearNurseryObjects(rt);
|
||||
maybeEndProfile(ProfileKey::ClearNewObjectCache);
|
||||
|
||||
// Most of the work is done here. This loop iterates over objects that have
|
||||
// been moved to the major heap. If these objects have any outgoing pointers
|
||||
// to the nursery, then those nursery objects get moved as well, until no
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
_(CheckHashTables, "ckTbls") \
|
||||
_(MarkRuntime, "mkRntm") \
|
||||
_(MarkDebugger, "mkDbgr") \
|
||||
_(ClearNewObjectCache, "clrNOC") \
|
||||
_(CollectToFP, "collct") \
|
||||
_(ObjectsTenuredCallback, "tenCB") \
|
||||
_(SweepArrayBufferViewList, "swpABO") \
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
|
||||
#include "vm/ArgumentsObject-inl.h"
|
||||
#include "vm/ArrayObject-inl.h"
|
||||
#include "vm/Caches-inl.h"
|
||||
#include "vm/Interpreter-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
#include "vm/UnboxedObject-inl.h"
|
||||
|
@ -3382,31 +3381,6 @@ NewArray(ExclusiveContext* cxArg, uint32_t length,
|
|||
if (!proto && !GetBuiltinPrototype(cxArg, JSProto_Array, &proto))
|
||||
return nullptr;
|
||||
|
||||
Rooted<TaggedProto> taggedProto(cxArg, TaggedProto(proto));
|
||||
bool isCachable = NewObjectWithTaggedProtoIsCachable(cxArg, taggedProto, newKind, &ArrayObject::class_);
|
||||
if (isCachable) {
|
||||
JSContext* cx = cxArg->asJSContext();
|
||||
NewObjectCache& cache = cx->caches.newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupProto(&ArrayObject::class_, proto, allocKind, &entry)) {
|
||||
gc::InitialHeap heap = GetInitialHeap(newKind, &ArrayObject::class_);
|
||||
AutoSetNewObjectMetadata metadata(cx);
|
||||
JSObject* obj = cache.newObjectFromHit(cx, entry, heap);
|
||||
if (obj) {
|
||||
/* Fixup the elements pointer and length, which may be incorrect. */
|
||||
ArrayObject* arr = &obj->as<ArrayObject>();
|
||||
arr->setFixedElements();
|
||||
arr->setLength(cx, length);
|
||||
if (maxLength > 0 &&
|
||||
!EnsureNewArrayElements(cx, arr, std::min(maxLength, length)))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RootedObjectGroup group(cxArg, ObjectGroup::defaultNewGroup(cxArg, &ArrayObject::class_,
|
||||
TaggedProto(proto)));
|
||||
if (!group)
|
||||
|
@ -3439,13 +3413,6 @@ NewArray(ExclusiveContext* cxArg, uint32_t length,
|
|||
if (newKind == SingletonObject && !JSObject::setSingleton(cxArg, arr))
|
||||
return nullptr;
|
||||
|
||||
if (isCachable) {
|
||||
NewObjectCache& cache = cxArg->asJSContext()->caches.newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
cache.lookupProto(&ArrayObject::class_, proto, allocKind, &entry);
|
||||
cache.fillProto(entry, &ArrayObject::class_, taggedProto, allocKind, arr);
|
||||
}
|
||||
|
||||
if (maxLength > 0 && !EnsureNewArrayElements(cxArg, arr, std::min(maxLength, length)))
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -3597,7 +3597,6 @@ GCRuntime::purgeRuntime(AutoLockForExclusiveAccess& lock)
|
|||
JSContext* cx = rt->contextFromMainThread();
|
||||
cx->caches.gsnCache.purge();
|
||||
cx->caches.envCoordinateNameCache.purge();
|
||||
cx->caches.newObjectCache.purge();
|
||||
cx->caches.nativeIterCache.purge();
|
||||
cx->caches.uncompressedSourceCache.purge();
|
||||
if (cx->caches.evalCache.initialized())
|
||||
|
@ -5492,7 +5491,6 @@ GCRuntime::compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget,
|
|||
|
||||
// Clear caches that can contain cell pointers.
|
||||
JSContext* cx = rt->contextFromMainThread();
|
||||
cx->caches.newObjectCache.purge();
|
||||
cx->caches.nativeIterCache.purge();
|
||||
if (cx->caches.evalCache.initialized())
|
||||
cx->caches.evalCache.clear();
|
||||
|
|
118
js/src/jsobj.cpp
118
js/src/jsobj.cpp
|
@ -62,7 +62,6 @@
|
|||
|
||||
#include "vm/ArrayObject-inl.h"
|
||||
#include "vm/BooleanObject-inl.h"
|
||||
#include "vm/Caches-inl.h"
|
||||
#include "vm/Interpreter-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
#include "vm/NumberObject-inl.h"
|
||||
|
@ -683,26 +682,6 @@ NewObject(ExclusiveContext* cx, HandleObjectGroup group, gc::AllocKind kind,
|
|||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
NewObjectCache::fillProto(EntryIndex entry, const Class* clasp, js::TaggedProto proto,
|
||||
gc::AllocKind kind, NativeObject* obj)
|
||||
{
|
||||
MOZ_ASSERT_IF(proto.isObject(), !proto.toObject()->is<GlobalObject>());
|
||||
MOZ_ASSERT(obj->taggedProto() == proto);
|
||||
return fill(entry, clasp, proto.raw(), kind, obj);
|
||||
}
|
||||
|
||||
bool
|
||||
js::NewObjectWithTaggedProtoIsCachable(ExclusiveContext* cxArg, Handle<TaggedProto> proto,
|
||||
NewObjectKind newKind, const Class* clasp)
|
||||
{
|
||||
return cxArg->isJSContext() &&
|
||||
proto.isObject() &&
|
||||
newKind == GenericObject &&
|
||||
clasp->isNative() &&
|
||||
!proto.toObject()->is<GlobalObject>();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
|
||||
Handle<TaggedProto> proto,
|
||||
|
@ -712,42 +691,11 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
|
|||
if (CanBeFinalizedInBackground(allocKind, clasp))
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
bool isCachable = NewObjectWithTaggedProtoIsCachable(cxArg, proto, newKind, clasp);
|
||||
if (isCachable) {
|
||||
JSContext* cx = cxArg->asJSContext();
|
||||
NewObjectCache& cache = cx->caches.newObjectCache;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
RootedObjectGroup group(cxArg, ObjectGroup::defaultNewGroup(cxArg, clasp, proto, nullptr));
|
||||
if (!group)
|
||||
return nullptr;
|
||||
|
||||
RootedObject obj(cxArg, NewObject(cxArg, group, allocKind, newKind, initialShapeFlags));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
|
||||
NewObjectCache& cache = cxArg->asJSContext()->caches.newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
cache.lookupProto(clasp, proto.toObject(), allocKind, &entry);
|
||||
cache.fillProto(entry, clasp, proto, allocKind, &obj->as<NativeObject>());
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static bool
|
||||
NewObjectIsCachable(ExclusiveContext* cxArg, NewObjectKind newKind, const Class* clasp)
|
||||
{
|
||||
return cxArg->isJSContext() &&
|
||||
newKind == GenericObject &&
|
||||
clasp->isNative();
|
||||
return NewObject(cxArg, group, allocKind, newKind, initialShapeFlags);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -760,20 +708,6 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext* cx, const Class* clasp, Hand
|
|||
if (CanBeFinalizedInBackground(allocKind, clasp))
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
Handle<GlobalObject*> global = cx->global();
|
||||
|
||||
bool isCachable = NewObjectIsCachable(cx, newKind, clasp);
|
||||
if (isCachable) {
|
||||
NewObjectCache& cache = cx->asJSContext()->caches.newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupGlobal(clasp, global, allocKind, &entry)) {
|
||||
gc::InitialHeap heap = GetInitialHeap(newKind, clasp);
|
||||
JSObject* obj = cache.newObjectFromHit(cx->asJSContext(), entry, heap);
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the appropriate proto for clasp. Built-in classes have a cached
|
||||
// proto on cx->global(); all others get %ObjectPrototype%.
|
||||
JSProtoKey protoKey = JSCLASS_CACHED_PROTO_KEY(clasp);
|
||||
|
@ -788,30 +722,7 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext* cx, const Class* clasp, Hand
|
|||
if (!group)
|
||||
return nullptr;
|
||||
|
||||
JSObject* obj = NewObject(cx, group, allocKind, newKind);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
|
||||
NewObjectCache& cache = cx->asJSContext()->caches.newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
cache.lookupGlobal(clasp, global, allocKind, &entry);
|
||||
cache.fillGlobal(entry, clasp, global, allocKind,
|
||||
&obj->as<NativeObject>());
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static bool
|
||||
NewObjectWithGroupIsCachable(ExclusiveContext* cx, HandleObjectGroup group,
|
||||
NewObjectKind newKind)
|
||||
{
|
||||
return group->proto().isObject() &&
|
||||
newKind == GenericObject &&
|
||||
group->clasp()->isNative() &&
|
||||
(!group->newScript() || group->newScript()->analyzed()) &&
|
||||
cx->isJSContext();
|
||||
return NewObject(cx, group, allocKind, newKind);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -826,30 +737,7 @@ js::NewObjectWithGroupCommon(ExclusiveContext* cx, HandleObjectGroup group,
|
|||
if (CanBeFinalizedInBackground(allocKind, group->clasp()))
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
bool isCachable = NewObjectWithGroupIsCachable(cx, group, newKind);
|
||||
if (isCachable) {
|
||||
NewObjectCache& cache = cx->asJSContext()->caches.newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupGroup(group, allocKind, &entry)) {
|
||||
JSObject* obj = cache.newObjectFromHit(cx->asJSContext(), entry,
|
||||
GetInitialHeap(newKind, group->clasp()));
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
JSObject* obj = NewObject(cx, group, allocKind, newKind);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
|
||||
NewObjectCache& cache = cx->asJSContext()->caches.newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
cache.lookupGroup(group, allocKind, &entry);
|
||||
cache.fillGroup(entry, group, allocKind, &obj->as<NativeObject>());
|
||||
}
|
||||
|
||||
return obj;
|
||||
return NewObject(cx, group, allocKind, newKind);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -73,7 +73,6 @@ extern const Class JSONClass;
|
|||
extern const Class MathClass;
|
||||
|
||||
class GlobalObject;
|
||||
class NewObjectCache;
|
||||
|
||||
// Forward declarations, required for later friend declarations.
|
||||
bool PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result);
|
||||
|
@ -103,7 +102,6 @@ class JSObject : public js::gc::Cell
|
|||
private:
|
||||
friend class js::Shape;
|
||||
friend class js::GCMarker;
|
||||
friend class js::NewObjectCache;
|
||||
friend class js::Nursery;
|
||||
friend class js::gc::RelocationOverlay;
|
||||
friend bool js::PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result);
|
||||
|
@ -1128,10 +1126,6 @@ GetInitialHeap(NewObjectKind newKind, const Class* clasp)
|
|||
return gc::DefaultHeap;
|
||||
}
|
||||
|
||||
bool
|
||||
NewObjectWithTaggedProtoIsCachable(ExclusiveContext* cxArg, Handle<TaggedProto> proto,
|
||||
NewObjectKind newKind, const Class* clasp);
|
||||
|
||||
// ES6 9.1.15 GetPrototypeFromConstructor.
|
||||
extern bool
|
||||
GetPrototypeFromConstructor(JSContext* cx, js::HandleObject newTarget, js::MutableHandleObject proto);
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef vm_Caches_inl_h
|
||||
#define vm_Caches_inl_h
|
||||
|
||||
#include "vm/Caches.h"
|
||||
|
||||
#include "jscompartment.h"
|
||||
|
||||
#include "gc/Allocator.h"
|
||||
#include "gc/GCTrace.h"
|
||||
#include "vm/Probes.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
inline bool
|
||||
NewObjectCache::lookupProto(const Class* clasp, JSObject* proto, gc::AllocKind kind, EntryIndex* pentry)
|
||||
{
|
||||
MOZ_ASSERT(!proto->is<GlobalObject>());
|
||||
return lookup(clasp, proto, kind, pentry);
|
||||
}
|
||||
|
||||
inline bool
|
||||
NewObjectCache::lookupGlobal(const Class* clasp, GlobalObject* global, gc::AllocKind kind, EntryIndex* pentry)
|
||||
{
|
||||
return lookup(clasp, global, kind, pentry);
|
||||
}
|
||||
|
||||
inline void
|
||||
NewObjectCache::fillGlobal(EntryIndex entry, const Class* clasp, GlobalObject* global,
|
||||
gc::AllocKind kind, NativeObject* obj)
|
||||
{
|
||||
//MOZ_ASSERT(global == obj->getGlobal());
|
||||
return fill(entry, clasp, global, kind, obj);
|
||||
}
|
||||
|
||||
inline NativeObject*
|
||||
NewObjectCache::newObjectFromHit(JSContext* cx, EntryIndex entryIndex, gc::InitialHeap heap)
|
||||
{
|
||||
MOZ_ASSERT(unsigned(entryIndex) < mozilla::ArrayLength(entries));
|
||||
Entry* entry = &entries[entryIndex];
|
||||
|
||||
NativeObject* templateObj = reinterpret_cast<NativeObject*>(&entry->templateObject);
|
||||
|
||||
// Do an end run around JSObject::group() to avoid doing AutoUnprotectCell
|
||||
// on the templateObj, which is not a GC thing and can't use runtimeFromAnyThread.
|
||||
ObjectGroup* group = templateObj->group_;
|
||||
|
||||
MOZ_ASSERT(!group->hasUnanalyzedPreliminaryObjects());
|
||||
|
||||
if (group->shouldPreTenure())
|
||||
heap = gc::TenuredHeap;
|
||||
|
||||
if (cx->runtime()->gc.upcomingZealousGC())
|
||||
return nullptr;
|
||||
|
||||
NativeObject* obj = static_cast<NativeObject*>(Allocate<JSObject, NoGC>(cx, entry->kind, 0,
|
||||
heap, group->clasp()));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
copyCachedToObject(obj, templateObj, entry->kind);
|
||||
|
||||
if (group->clasp()->shouldDelayMetadataBuilder())
|
||||
cx->compartment()->setObjectPendingMetadata(cx, obj);
|
||||
else
|
||||
obj = static_cast<NativeObject*>(SetNewObjectMetadata(cx, obj));
|
||||
|
||||
probes::CreateObject(cx, obj);
|
||||
gc::TraceCreateObject(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* vm_Caches_inl_h */
|
|
@ -4,13 +4,14 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "vm/Caches-inl.h"
|
||||
#include "vm/Caches.h"
|
||||
|
||||
#include "mozilla/PodOperations.h"
|
||||
|
||||
using namespace js;
|
||||
#include "jscntxt.h"
|
||||
#include "jsmath.h"
|
||||
|
||||
using mozilla::PodZero;
|
||||
using namespace js;
|
||||
|
||||
MathCache*
|
||||
ContextCaches::createMathCache(JSContext* cx)
|
||||
|
@ -35,18 +36,3 @@ ContextCaches::init()
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
NewObjectCache::clearNurseryObjects(JSRuntime* rt)
|
||||
{
|
||||
for (unsigned i = 0; i < mozilla::ArrayLength(entries); ++i) {
|
||||
Entry& e = entries[i];
|
||||
NativeObject* obj = reinterpret_cast<NativeObject*>(&e.templateObject);
|
||||
if (IsInsideNursery(e.key) ||
|
||||
rt->gc.nursery.isInside(obj->slots_) ||
|
||||
rt->gc.nursery.isInside(obj->elements_))
|
||||
{
|
||||
PodZero(&e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,137 +149,6 @@ class NativeIterCache
|
|||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Cache for speeding up repetitive creation of objects in the VM.
|
||||
* When an object is created which matches the criteria in the 'key' section
|
||||
* below, an entry is filled with the resulting object.
|
||||
*/
|
||||
class NewObjectCache
|
||||
{
|
||||
/* Statically asserted to be equal to sizeof(JSObject_Slots16) */
|
||||
static const unsigned MAX_OBJ_SIZE = 4 * sizeof(void*) + 16 * sizeof(Value);
|
||||
|
||||
static void staticAsserts() {
|
||||
JS_STATIC_ASSERT(NewObjectCache::MAX_OBJ_SIZE == sizeof(JSObject_Slots16));
|
||||
JS_STATIC_ASSERT(gc::AllocKind::OBJECT_LAST == gc::AllocKind::OBJECT16_BACKGROUND);
|
||||
}
|
||||
|
||||
struct Entry
|
||||
{
|
||||
/* Class of the constructed object. */
|
||||
const Class* clasp;
|
||||
|
||||
/*
|
||||
* Key with one of three possible values:
|
||||
*
|
||||
* - Global for the object. The object must have a standard class for
|
||||
* which the global's prototype can be determined, and the object's
|
||||
* parent will be the global.
|
||||
*
|
||||
* - Prototype for the object (cannot be global). The object's parent
|
||||
* will be the prototype's parent.
|
||||
*
|
||||
* - Type for the object. The object's parent will be the type's
|
||||
* prototype's parent.
|
||||
*/
|
||||
gc::Cell* key;
|
||||
|
||||
/* Allocation kind for the constructed object. */
|
||||
gc::AllocKind kind;
|
||||
|
||||
/* Number of bytes to copy from the template object. */
|
||||
uint32_t nbytes;
|
||||
|
||||
/*
|
||||
* Template object to copy from, with the initial values of fields,
|
||||
* fixed slots (undefined) and private data (nullptr).
|
||||
*/
|
||||
char templateObject[MAX_OBJ_SIZE];
|
||||
};
|
||||
|
||||
Entry entries[41]; // TODO: reconsider size
|
||||
|
||||
public:
|
||||
|
||||
typedef int EntryIndex;
|
||||
|
||||
NewObjectCache() { mozilla::PodZero(this); }
|
||||
void purge() { mozilla::PodZero(this); }
|
||||
|
||||
/* Remove any cached items keyed on moved objects. */
|
||||
void clearNurseryObjects(JSRuntime* rt);
|
||||
|
||||
/*
|
||||
* Get the entry index for the given lookup, return whether there was a hit
|
||||
* on an existing entry.
|
||||
*/
|
||||
inline bool lookupProto(const Class* clasp, JSObject* proto, gc::AllocKind kind, EntryIndex* pentry);
|
||||
inline bool lookupGlobal(const Class* clasp, js::GlobalObject* global, gc::AllocKind kind,
|
||||
EntryIndex* pentry);
|
||||
|
||||
bool lookupGroup(js::ObjectGroup* group, gc::AllocKind kind, EntryIndex* pentry) {
|
||||
return lookup(group->clasp(), group, kind, pentry);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a new object from a cache hit produced by a lookup method, or
|
||||
* nullptr if returning the object could possibly trigger GC (does not
|
||||
* indicate failure).
|
||||
*/
|
||||
inline NativeObject* newObjectFromHit(JSContext* cx, EntryIndex entry, js::gc::InitialHeap heap);
|
||||
|
||||
/* Fill an entry after a cache miss. */
|
||||
void fillProto(EntryIndex entry, const Class* clasp, js::TaggedProto proto,
|
||||
gc::AllocKind kind, NativeObject* obj);
|
||||
|
||||
inline void fillGlobal(EntryIndex entry, const Class* clasp, js::GlobalObject* global,
|
||||
gc::AllocKind kind, NativeObject* obj);
|
||||
|
||||
void fillGroup(EntryIndex entry, js::ObjectGroup* group, gc::AllocKind kind,
|
||||
NativeObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(obj->group() == group);
|
||||
return fill(entry, group->clasp(), group, kind, obj);
|
||||
}
|
||||
|
||||
/* Invalidate any entries which might produce an object with shape/proto. */
|
||||
void invalidateEntriesForShape(JSContext* cx, HandleShape shape, HandleObject proto);
|
||||
|
||||
private:
|
||||
EntryIndex makeIndex(const Class* clasp, gc::Cell* key, gc::AllocKind kind) {
|
||||
uintptr_t hash = (uintptr_t(clasp) ^ uintptr_t(key)) + size_t(kind);
|
||||
return hash % mozilla::ArrayLength(entries);
|
||||
}
|
||||
|
||||
bool lookup(const Class* clasp, gc::Cell* key, gc::AllocKind kind, EntryIndex* pentry) {
|
||||
*pentry = makeIndex(clasp, key, kind);
|
||||
Entry* entry = &entries[*pentry];
|
||||
|
||||
/* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
|
||||
return entry->clasp == clasp && entry->key == key;
|
||||
}
|
||||
|
||||
void fill(EntryIndex entry_, const Class* clasp, gc::Cell* key, gc::AllocKind kind,
|
||||
NativeObject* obj) {
|
||||
MOZ_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
|
||||
MOZ_ASSERT(entry_ == makeIndex(clasp, key, kind));
|
||||
Entry* entry = &entries[entry_];
|
||||
|
||||
entry->clasp = clasp;
|
||||
entry->key = key;
|
||||
entry->kind = kind;
|
||||
|
||||
entry->nbytes = gc::Arena::thingSize(kind);
|
||||
js_memcpy(&entry->templateObject, obj, entry->nbytes);
|
||||
}
|
||||
|
||||
static void copyCachedToObject(NativeObject* dst, NativeObject* src, gc::AllocKind kind) {
|
||||
js_memcpy(dst, src, gc::Arena::thingSize(kind));
|
||||
Shape::writeBarrierPost(&dst->shape_, nullptr, dst->shape_);
|
||||
ObjectGroup::writeBarrierPost(&dst->group_, nullptr, dst->group_);
|
||||
}
|
||||
};
|
||||
|
||||
class MathCache;
|
||||
|
||||
class ContextCaches
|
||||
|
@ -291,7 +160,6 @@ class ContextCaches
|
|||
public:
|
||||
js::GSNCache gsnCache;
|
||||
js::EnvironmentCoordinateNameCache envCoordinateNameCache;
|
||||
js::NewObjectCache newObjectCache;
|
||||
js::NativeIterCache nativeIterCache;
|
||||
js::UncompressedSourceCache uncompressedSourceCache;
|
||||
js::EvalCache evalCache;
|
||||
|
|
|
@ -307,8 +307,6 @@ struct Class;
|
|||
class GCMarker;
|
||||
class Shape;
|
||||
|
||||
class NewObjectCache;
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline bool
|
||||
IsObjectValueInCompartment(Value v, JSCompartment* comp);
|
||||
|
@ -534,7 +532,6 @@ class NativeObject : public ShapedObject
|
|||
protected:
|
||||
friend class GCMarker;
|
||||
friend class Shape;
|
||||
friend class NewObjectCache;
|
||||
|
||||
void invalidateSlotRange(uint32_t start, uint32_t length) {
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "jscompartmentinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/Caches-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
@ -1530,35 +1529,6 @@ EmptyShape::getInitialShape(ExclusiveContext* cx, const Class* clasp, TaggedProt
|
|||
return getInitialShape(cx, clasp, proto, GetGCKindSlots(kind, clasp), objectFlags);
|
||||
}
|
||||
|
||||
void
|
||||
NewObjectCache::invalidateEntriesForShape(JSContext* cx, HandleShape shape, HandleObject proto)
|
||||
{
|
||||
const Class* clasp = shape->getObjectClass();
|
||||
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
|
||||
if (CanBeFinalizedInBackground(kind, clasp))
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
|
||||
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, clasp, TaggedProto(proto)));
|
||||
if (!group) {
|
||||
purge();
|
||||
cx->recoverFromOutOfMemory();
|
||||
return;
|
||||
}
|
||||
|
||||
EntryIndex entry;
|
||||
for (CompartmentsInZoneIter comp(shape->zone()); !comp.done(); comp.next()) {
|
||||
if (GlobalObject* global = comp->unsafeUnbarrieredMaybeGlobal()) {
|
||||
if (lookupGlobal(clasp, global, kind, &entry))
|
||||
PodZero(&entries[entry]);
|
||||
}
|
||||
}
|
||||
if (!proto->is<GlobalObject>() && lookupProto(clasp, proto, kind, &entry))
|
||||
PodZero(&entries[entry]);
|
||||
if (lookupGroup(group, kind, &entry))
|
||||
PodZero(&entries[entry]);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
EmptyShape::insertInitialShape(ExclusiveContext* cx, HandleShape shape, HandleObject proto)
|
||||
{
|
||||
|
@ -1583,21 +1553,6 @@ EmptyShape::insertInitialShape(ExclusiveContext* cx, HandleShape shape, HandleOb
|
|||
#endif
|
||||
|
||||
entry.shape = ReadBarrieredShape(shape);
|
||||
|
||||
/*
|
||||
* This affects the shape that will be produced by the various NewObject
|
||||
* methods, so clear any cache entry referring to the old shape. This is
|
||||
* not required for correctness: the NewObject must always check for a
|
||||
* nativeEmpty() result and generate the appropriate properties if found.
|
||||
* Clearing the cache entry avoids this duplicate regeneration.
|
||||
*
|
||||
* Clearing is not necessary when this context is running off the main
|
||||
* thread, as it will not use the new object cache for allocations.
|
||||
*/
|
||||
if (cx->isJSContext()) {
|
||||
JSContext* ncx = cx->asJSContext();
|
||||
ncx->caches.newObjectCache.invalidateEntriesForShape(ncx, shape, proto);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include "gc/Barrier.h"
|
||||
#include "gc/Zone.h"
|
||||
|
||||
#include "vm/Caches-inl.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
/* static */ void
|
||||
|
|
Загрузка…
Ссылка в новой задаче