mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Address bug 699446 review comments, r=luke.
This commit is contained in:
parent
540d7ac81a
commit
e4d3f5339b
@ -3876,11 +3876,13 @@ NewArray(JSContext *cx, jsuint length, JSObject *proto)
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
#endif
|
||||
|
||||
JSObject *parent = GetCurrentGlobal(cx);
|
||||
GlobalObject *parent = GetCurrentGlobal(cx);
|
||||
|
||||
NewObjectCache::Entry *entry = NULL;
|
||||
if (cx->compartment->newObjectCache.lookup(&ArrayClass, parent, kind, &entry)) {
|
||||
JSObject *obj = NewObjectFromCacheHit(cx, entry);
|
||||
NewObjectCache &cache = cx->compartment->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupGlobal(&ArrayClass, parent, kind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
/* Fixup the elements pointer and length, which may be incorrect. */
|
||||
@ -3909,8 +3911,8 @@ NewArray(JSContext *cx, jsuint length, JSObject *proto)
|
||||
|
||||
obj->initializeDenseArray(shape, type, length);
|
||||
|
||||
if (entry)
|
||||
entry->fill(&ArrayClass, parent, kind, obj);
|
||||
if (entry != -1)
|
||||
cache.fillGlobal(entry, &ArrayClass, parent, kind, obj);
|
||||
|
||||
if (allocateCapacity && !EnsureNewArrayElements(cx, obj, length))
|
||||
return NULL;
|
||||
|
@ -367,9 +367,6 @@ class CellIter: public CellIterImpl
|
||||
inline void EmptyArenaOp(Arena *arena) {}
|
||||
inline void EmptyCellOp(Cell *t) {}
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* Allocates a new GC thing. After a successful allocation the caller must
|
||||
* fully initialize the thing before calling any function that can potentially
|
||||
@ -423,55 +420,58 @@ TryNewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
|
||||
return static_cast<T *>(t);
|
||||
}
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
inline JSObject *
|
||||
js_NewGCObject(JSContext *cx, js::gc::AllocKind kind)
|
||||
{
|
||||
JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
|
||||
return NewGCThing<JSObject>(cx, kind, js::gc::Arena::thingSize(kind));
|
||||
return js::gc::NewGCThing<JSObject>(cx, kind, js::gc::Arena::thingSize(kind));
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
js_TryNewGCObject(JSContext *cx, js::gc::AllocKind kind)
|
||||
{
|
||||
JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
|
||||
return TryNewGCThing<JSObject>(cx, kind, js::gc::Arena::thingSize(kind));
|
||||
return js::gc::TryNewGCThing<JSObject>(cx, kind, js::gc::Arena::thingSize(kind));
|
||||
}
|
||||
|
||||
inline JSString *
|
||||
js_NewGCString(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<JSString>(cx, js::gc::FINALIZE_STRING, sizeof(JSString));
|
||||
return js::gc::NewGCThing<JSString>(cx, js::gc::FINALIZE_STRING, sizeof(JSString));
|
||||
}
|
||||
|
||||
inline JSShortString *
|
||||
js_NewGCShortString(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<JSShortString>(cx, js::gc::FINALIZE_SHORT_STRING, sizeof(JSShortString));
|
||||
return js::gc::NewGCThing<JSShortString>(cx, js::gc::FINALIZE_SHORT_STRING, sizeof(JSShortString));
|
||||
}
|
||||
|
||||
inline JSExternalString *
|
||||
js_NewGCExternalString(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<JSExternalString>(cx, js::gc::FINALIZE_EXTERNAL_STRING,
|
||||
sizeof(JSExternalString));
|
||||
return js::gc::NewGCThing<JSExternalString>(cx, js::gc::FINALIZE_EXTERNAL_STRING,
|
||||
sizeof(JSExternalString));
|
||||
}
|
||||
|
||||
inline JSScript *
|
||||
js_NewGCScript(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<JSScript>(cx, js::gc::FINALIZE_SCRIPT, sizeof(JSScript));
|
||||
return js::gc::NewGCThing<JSScript>(cx, js::gc::FINALIZE_SCRIPT, sizeof(JSScript));
|
||||
}
|
||||
|
||||
inline js::Shape *
|
||||
js_NewGCShape(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<js::Shape>(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape));
|
||||
return js::gc::NewGCThing<js::Shape>(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape));
|
||||
}
|
||||
|
||||
inline js::BaseShape *
|
||||
js_NewGCBaseShape(JSContext *cx)
|
||||
{
|
||||
return NewGCThing<js::BaseShape>(cx, js::gc::FINALIZE_BASE_SHAPE, sizeof(js::BaseShape));
|
||||
return js::gc::NewGCThing<js::BaseShape>(cx, js::gc::FINALIZE_BASE_SHAPE, sizeof(js::BaseShape));
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
|
@ -1974,7 +1974,7 @@ TypeObject *
|
||||
TypeCompartment::newTypeObject(JSContext *cx, JSScript *script,
|
||||
JSProtoKey key, JSObject *proto, bool unknown)
|
||||
{
|
||||
TypeObject *object = NewGCThing<TypeObject>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
|
||||
TypeObject *object = gc::NewGCThing<TypeObject>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
|
||||
if (!object)
|
||||
return NULL;
|
||||
new(object) TypeObject(proto, key == JSProto_Function, unknown);
|
||||
|
@ -2942,10 +2942,12 @@ js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
|
||||
if (CanBeFinalizedInBackground(kind, clasp))
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
|
||||
NewObjectCache::Entry *entry = NULL;
|
||||
NewObjectCache &cache = cx->compartment->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (proto && (!parent || parent == proto->getParent()) && !proto->isGlobal()) {
|
||||
if (cx->compartment->newObjectCache.lookup(clasp, proto, kind, &entry))
|
||||
return NewObjectFromCacheHit(cx, entry);
|
||||
if (cache.lookupProto(clasp, proto, kind, &entry))
|
||||
return cache.newObjectFromHit(cx, entry);
|
||||
}
|
||||
|
||||
types::TypeObject *type = proto ? proto->getNewType(cx) : cx->compartment->getEmptyType(cx);
|
||||
@ -2963,8 +2965,8 @@ js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (entry && !obj->hasDynamicSlots())
|
||||
entry->fill(clasp, proto, kind, obj);
|
||||
if (entry != -1 && !obj->hasDynamicSlots())
|
||||
cache.fillProto(entry, clasp, proto, kind, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -2993,10 +2995,12 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
|
||||
*/
|
||||
JSProtoKey protoKey = GetClassProtoKey(clasp);
|
||||
|
||||
NewObjectCache::Entry *entry = NULL;
|
||||
NewObjectCache &cache = cx->compartment->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (parent->isGlobal() && protoKey != JSProto_Null) {
|
||||
if (cx->compartment->newObjectCache.lookup(clasp, parent, kind, &entry))
|
||||
return NewObjectFromCacheHit(cx, entry);
|
||||
if (cache.lookupGlobal(clasp, parent->asGlobal(), kind, &entry))
|
||||
return cache.newObjectFromHit(cx, entry);
|
||||
}
|
||||
|
||||
if (!FindProto(cx, clasp, parent, &proto))
|
||||
@ -3010,8 +3014,8 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (entry && !obj->hasDynamicSlots())
|
||||
entry->fill(clasp, parent, kind, obj);
|
||||
if (entry != -1 && !obj->hasDynamicSlots())
|
||||
cache.fillGlobal(entry, clasp, parent->asGlobal(), kind, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -3025,18 +3029,20 @@ js::NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent,
|
||||
if (CanBeFinalizedInBackground(kind, &ObjectClass))
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
|
||||
NewObjectCache::Entry *entry = NULL;
|
||||
NewObjectCache &cache = cx->compartment->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (parent == type->proto->getParent()) {
|
||||
if (cx->compartment->newObjectCache.lookup(&ObjectClass, type, kind, &entry))
|
||||
return NewObjectFromCacheHit(cx, entry);
|
||||
if (cache.lookupType(&ObjectClass, type, kind, &entry))
|
||||
return cache.newObjectFromHit(cx, entry);
|
||||
}
|
||||
|
||||
JSObject *obj = NewObject(cx, &ObjectClass, type, parent, kind);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (entry && !obj->hasDynamicSlots())
|
||||
entry->fill(&ObjectClass, type, kind, obj);
|
||||
if (entry != -1 && !obj->hasDynamicSlots())
|
||||
cache.fillType(entry, &ObjectClass, type, kind, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
@ -1596,7 +1596,7 @@ MarkStandardClassInitializedNoProto(JSObject *obj, js::Class *clasp);
|
||||
* When an object is created which matches the criteria in the 'key' section
|
||||
* below, an entry is filled with the resulting object.
|
||||
*/
|
||||
struct NewObjectCache
|
||||
class NewObjectCache
|
||||
{
|
||||
struct Entry
|
||||
{
|
||||
@ -1629,31 +1629,45 @@ struct NewObjectCache
|
||||
* fixed slots (undefined) and private data (NULL).
|
||||
*/
|
||||
JSObject_Slots16 templateObject;
|
||||
|
||||
inline void fill(Class *clasp, gc::Cell *key, gc::AllocKind kind, JSObject *obj);
|
||||
};
|
||||
|
||||
Entry entries[41];
|
||||
|
||||
void reset() { PodZero(this); }
|
||||
|
||||
bool lookup(Class *clasp, gc::Cell *key, gc::AllocKind kind, Entry **pentry)
|
||||
{
|
||||
jsuword hash = (jsuword(clasp) ^ jsuword(key)) + kind;
|
||||
Entry *entry = *pentry = &entries[hash % JS_ARRAY_LENGTH(entries)];
|
||||
|
||||
/* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
|
||||
return (entry->clasp == clasp && entry->key == key);
|
||||
}
|
||||
|
||||
void invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject *proto);
|
||||
|
||||
void staticAsserts() {
|
||||
JS_STATIC_ASSERT(gc::FINALIZE_OBJECT_LAST == gc::FINALIZE_OBJECT16_BACKGROUND);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef int EntryIndex;
|
||||
|
||||
void reset() { PodZero(this); }
|
||||
|
||||
/*
|
||||
* Get the entry index for the given lookup, return whether there was a hit
|
||||
* on an existing entry.
|
||||
*/
|
||||
inline bool lookupProto(Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry);
|
||||
inline bool lookupGlobal(Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry);
|
||||
inline bool lookupType(Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, EntryIndex *pentry);
|
||||
|
||||
/* Return a new object from a cache hit produced by a lookup method. */
|
||||
inline JSObject *newObjectFromHit(JSContext *cx, EntryIndex entry);
|
||||
|
||||
/* Fill an entry after a cache miss. */
|
||||
inline void fillProto(EntryIndex entry, Class *clasp, JSObject *proto, gc::AllocKind kind, JSObject *obj);
|
||||
inline void fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj);
|
||||
inline void fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, JSObject *obj);
|
||||
|
||||
/* Invalidate any entries which might produce an object with shape/proto. */
|
||||
void invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject *proto);
|
||||
|
||||
private:
|
||||
inline bool lookup(Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry);
|
||||
inline void fill(EntryIndex entry, Class *clasp, gc::Cell *key, gc::AllocKind kind, JSObject *obj);
|
||||
};
|
||||
|
||||
}
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
|
||||
|
@ -1544,22 +1544,81 @@ class AutoPropertyDescriptorRooter : private AutoGCRooter, public PropertyDescri
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
};
|
||||
|
||||
inline void
|
||||
NewObjectCache::Entry::fill(Class *clasp, gc::Cell *key, gc::AllocKind kind, JSObject *obj)
|
||||
inline bool
|
||||
NewObjectCache::lookup(Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry)
|
||||
{
|
||||
jsuword hash = (jsuword(clasp) ^ jsuword(key)) + kind;
|
||||
*pentry = hash % js::ArrayLength(entries);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
inline bool
|
||||
NewObjectCache::lookupProto(Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry)
|
||||
{
|
||||
JS_ASSERT(!proto->isGlobal());
|
||||
return lookup(clasp, proto, kind, pentry);
|
||||
}
|
||||
|
||||
inline bool
|
||||
NewObjectCache::lookupGlobal(Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
|
||||
{
|
||||
return lookup(clasp, global, kind, pentry);
|
||||
}
|
||||
|
||||
inline bool
|
||||
NewObjectCache::lookupType(Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, EntryIndex *pentry)
|
||||
{
|
||||
return lookup(clasp, type, kind, pentry);
|
||||
}
|
||||
|
||||
inline void
|
||||
NewObjectCache::fill(EntryIndex entry_, Class *clasp, gc::Cell *key, gc::AllocKind kind, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(unsigned(entry_) < ArrayLength(entries));
|
||||
Entry *entry = &entries[entry_];
|
||||
|
||||
JS_ASSERT(!obj->hasDynamicSlots() && !obj->hasDynamicElements());
|
||||
|
||||
this->clasp = clasp;
|
||||
this->key = key;
|
||||
this->kind = kind;
|
||||
entry->clasp = clasp;
|
||||
entry->key = key;
|
||||
entry->kind = kind;
|
||||
|
||||
nbytes = obj->structSize();
|
||||
memcpy(&templateObject, obj, nbytes);
|
||||
entry->nbytes = obj->structSize();
|
||||
memcpy(&entry->templateObject, obj, entry->nbytes);
|
||||
}
|
||||
|
||||
inline void
|
||||
NewObjectCache::fillProto(EntryIndex entry, Class *clasp, JSObject *proto, gc::AllocKind kind, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(!proto->isGlobal());
|
||||
JS_ASSERT(obj->getProto() == proto);
|
||||
return fill(entry, clasp, proto, kind, obj);
|
||||
}
|
||||
|
||||
inline void
|
||||
NewObjectCache::fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(global == obj->getGlobal());
|
||||
return fill(entry, clasp, global, kind, obj);
|
||||
}
|
||||
|
||||
inline void
|
||||
NewObjectCache::fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->type() == type);
|
||||
return fill(entry, clasp, type, kind, obj);
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
NewObjectFromCacheHit(JSContext *cx, NewObjectCache::Entry *entry)
|
||||
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_)
|
||||
{
|
||||
JS_ASSERT(unsigned(entry_) < ArrayLength(entries));
|
||||
Entry *entry = &entries[entry_];
|
||||
|
||||
JSObject *obj = js_TryNewGCObject(cx, entry->kind);
|
||||
if (obj) {
|
||||
memcpy(obj, &entry->templateObject, entry->nbytes);
|
||||
|
@ -1399,23 +1399,22 @@ EmptyShape::lookupInitialShape(JSContext *cx, Class *clasp, JSObject *proto, JSO
|
||||
void
|
||||
NewObjectCache::invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject *proto)
|
||||
{
|
||||
NewObjectCache::Entry *entry = NULL;
|
||||
|
||||
Class *clasp = shape->getObjectClass();
|
||||
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
|
||||
if (CanBeFinalizedInBackground(kind, clasp))
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
|
||||
JSObject *global = shape->getObjectParent()->getGlobal();
|
||||
GlobalObject *global = shape->getObjectParent()->getGlobal();
|
||||
types::TypeObject *type = proto->getNewType(cx);
|
||||
|
||||
if (lookup(clasp, global, kind, &entry))
|
||||
PodZero(entry);
|
||||
if (lookup(clasp, proto, kind, &entry))
|
||||
PodZero(entry);
|
||||
if (lookup(clasp, type, kind, &entry))
|
||||
PodZero(entry);
|
||||
EntryIndex entry;
|
||||
if (lookupGlobal(clasp, global, kind, &entry))
|
||||
PodZero(&entries[entry]);
|
||||
if (!proto->isGlobal() && lookupProto(clasp, proto, kind, &entry))
|
||||
PodZero(&entries[entry]);
|
||||
if (lookupType(clasp, type, kind, &entry))
|
||||
PodZero(&entries[entry]);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
|
Loading…
Reference in New Issue
Block a user