mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 832972 - Reduce cost of exact stack rooting during name operations, clean up some GC allocation methods, r=terrence.
This commit is contained in:
parent
6aced240ae
commit
5c1084be65
108
js/src/gc/Root.h
108
js/src/gc/Root.h
@ -801,10 +801,94 @@ class SkipRoot
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
/* Interface substitute for Rooted<T> which does not root the variable's memory. */
|
||||
template <typename T>
|
||||
class FakeRooted : public RootedBase<T>
|
||||
{
|
||||
public:
|
||||
FakeRooted(JSContext *cx
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: ptr(RootMethods<T>::initial())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
FakeRooted(JSContext *cx, T initial
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: ptr(initial)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
FakeRooted(JSContext *cx, const Unrooted<S> &initial
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: ptr(static_cast<S>(initial))
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
operator T() const { return ptr; }
|
||||
T operator->() const { return ptr; }
|
||||
T *address() { return &ptr; }
|
||||
const T *address() const { return &ptr; }
|
||||
T &get() { return ptr; }
|
||||
const T &get() const { return ptr; }
|
||||
|
||||
T &operator=(T value) {
|
||||
JS_ASSERT(!RootMethods<T>::poisoned(value));
|
||||
ptr = value;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool operator!=(const T &other) { return ptr != other; }
|
||||
bool operator==(const T &other) { return ptr == other; }
|
||||
|
||||
private:
|
||||
T ptr;
|
||||
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
FakeRooted(const FakeRooted &) MOZ_DELETE;
|
||||
};
|
||||
|
||||
/* Interface substitute for MutableHandle<T> which is not required to point to rooted memory. */
|
||||
template <typename T>
|
||||
class FakeMutableHandle : public js::MutableHandleBase<T>
|
||||
{
|
||||
public:
|
||||
FakeMutableHandle(T *t) {
|
||||
ptr = t;
|
||||
}
|
||||
|
||||
void set(T v) {
|
||||
JS_ASSERT(!js::RootMethods<T>::poisoned(v));
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
T *address() const { return ptr; }
|
||||
T get() const { return *ptr; }
|
||||
|
||||
operator T() const { return get(); }
|
||||
T operator->() const { return get(); }
|
||||
|
||||
private:
|
||||
FakeMutableHandle() {}
|
||||
|
||||
T *ptr;
|
||||
|
||||
template <typename S>
|
||||
void operator=(S v) MOZ_DELETE;
|
||||
};
|
||||
|
||||
/*
|
||||
* Types for a variable that either should or shouldn't be rooted, depending on
|
||||
* the template parameter Rooted. Used for implementing functions that can
|
||||
* operate on either rooted or unrooted data.
|
||||
*
|
||||
* The toHandle() and toMutableHandle() functions are for calling functions
|
||||
* which require handle types and are only called in the ALLOW_GC case. These
|
||||
* allow the calling code to type check.
|
||||
*/
|
||||
enum AllowGC {
|
||||
DONT_ALLOW_GC = 0,
|
||||
@ -818,15 +902,35 @@ class MaybeRooted
|
||||
template <typename T> class MaybeRooted<T, ALLOW_GC>
|
||||
{
|
||||
public:
|
||||
typedef Rooted<T> RootType;
|
||||
typedef Handle<T> HandleType;
|
||||
typedef Rooted<T> RootType;
|
||||
typedef MutableHandle<T> MutableHandleType;
|
||||
|
||||
static inline Handle<T> toHandle(HandleType v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline MutableHandle<T> toMutableHandle(MutableHandleType v) {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class MaybeRooted<T, DONT_ALLOW_GC>
|
||||
{
|
||||
public:
|
||||
typedef T RootType;
|
||||
typedef T HandleType;
|
||||
typedef FakeRooted<T> RootType;
|
||||
typedef FakeMutableHandle<T> MutableHandleType;
|
||||
|
||||
static inline Handle<T> toHandle(HandleType v) {
|
||||
JS_NOT_REACHED("Bad conversion");
|
||||
return Handle<T>::fromMarkedLocation(NULL);
|
||||
}
|
||||
|
||||
static inline MutableHandle<T> toMutableHandle(MutableHandleType v) {
|
||||
JS_NOT_REACHED("Bad conversion");
|
||||
return MutableHandle<T>::fromMarkedLocation(NULL);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
@ -323,7 +323,7 @@ IonCode::New(JSContext *cx, uint8_t *code, uint32_t bufferSize, JSC::ExecutableP
|
||||
{
|
||||
AssertCanGC();
|
||||
|
||||
IonCode *codeObj = gc::NewGCThing<IonCode>(cx, gc::FINALIZE_IONCODE, sizeof(IonCode));
|
||||
IonCode *codeObj = gc::NewGCThing<IonCode, ALLOW_GC>(cx, gc::FINALIZE_IONCODE, sizeof(IonCode));
|
||||
if (!codeObj) {
|
||||
pool->release();
|
||||
return NULL;
|
||||
|
@ -392,7 +392,7 @@ struct GetNativePropertyStub
|
||||
JS_ASSERT_IF(expando, expando->isNative() && expando->getProto() == NULL);
|
||||
|
||||
masm.loadValue(expandoAddr, tempVal);
|
||||
if (expando && expando->nativeLookupNoAllocation(propName)) {
|
||||
if (expando && expando->nativeLookup(cx, propName)) {
|
||||
// Reference object has an expando that doesn't define the name.
|
||||
// Check incoming object's expando and make sure it's an object.
|
||||
|
||||
|
@ -116,7 +116,7 @@ InvokeFunction(JSContext *cx, HandleFunction fun0, uint32_t argc, Value *argv, V
|
||||
JSObject *
|
||||
NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize)
|
||||
{
|
||||
return gc::NewGCThing<JSObject>(cx, allocKind, thingSize);
|
||||
return gc::NewGCThing<JSObject, ALLOW_GC>(cx, allocKind, thingSize);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -106,7 +106,7 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_)
|
||||
JS_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
|
||||
Entry *entry = &entries[entry_];
|
||||
|
||||
JSObject *obj = js_TryNewGCObject(cx, entry->kind);
|
||||
JSObject *obj = js_NewGCObject<DONT_ALLOW_GC>(cx, entry->kind);
|
||||
if (obj) {
|
||||
copyCachedToObject(obj, reinterpret_cast<JSObject *>(&entry->templateObject));
|
||||
Probes::createObject(cx, obj);
|
||||
|
@ -1449,6 +1449,7 @@ RunLastDitchGC(JSContext *cx, gcreason::Reason reason)
|
||||
GC(rt, GC_NORMAL, reason);
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
/* static */ void *
|
||||
ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
||||
{
|
||||
@ -1458,7 +1459,9 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
||||
JSRuntime *rt = comp->rt;
|
||||
JS_ASSERT(!rt->isHeapBusy());
|
||||
|
||||
bool runGC = rt->gcIncrementalState != NO_INCREMENTAL && comp->gcBytes > comp->gcTriggerBytes;
|
||||
bool runGC = rt->gcIncrementalState != NO_INCREMENTAL &&
|
||||
comp->gcBytes > comp->gcTriggerBytes &&
|
||||
allowGC;
|
||||
for (;;) {
|
||||
if (JS_UNLIKELY(runGC)) {
|
||||
PrepareCompartmentForGC(comp);
|
||||
@ -1492,6 +1495,9 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
}
|
||||
|
||||
if (!allowGC)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* We failed to allocate. Run the GC if we haven't done it already.
|
||||
* Otherwise report OOM.
|
||||
@ -1501,10 +1507,17 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
||||
runGC = true;
|
||||
}
|
||||
|
||||
JS_ASSERT(allowGC);
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template void *
|
||||
ArenaLists::refillFreeList<DONT_ALLOW_GC>(JSContext *cx, AllocKind thingKind);
|
||||
|
||||
template void *
|
||||
ArenaLists::refillFreeList<ALLOW_GC>(JSContext *cx, AllocKind thingKind);
|
||||
|
||||
JSGCTraceKind
|
||||
js_GetGCThingTraceKind(void *thing)
|
||||
{
|
||||
@ -4769,6 +4782,6 @@ js_NewGCXML(JSContext *cx)
|
||||
if (!cx->runningWithTrustedPrincipals())
|
||||
++sE4XObjectsCreated;
|
||||
|
||||
return NewGCThing<JSXML>(cx, js::gc::FINALIZE_XML, sizeof(JSXML));
|
||||
return NewGCThing<JSXML, ALLOW_GC>(cx, js::gc::FINALIZE_XML, sizeof(JSXML));
|
||||
}
|
||||
#endif
|
||||
|
@ -411,6 +411,7 @@ struct ArenaLists {
|
||||
return freeLists[thingKind].allocate(thingSize);
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static void *refillFreeList(JSContext *cx, AllocKind thingKind);
|
||||
|
||||
void checkEmptyFreeLists() {
|
||||
|
@ -476,11 +476,13 @@ class GCCompartmentGroupIter {
|
||||
* in the partially initialized thing.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
template <typename T, AllowGC allowGC>
|
||||
inline T *
|
||||
NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (allowGC)
|
||||
AssertCanGC();
|
||||
|
||||
JS_ASSERT(thingSize == js::gc::Arena::thingSize(kind));
|
||||
JS_ASSERT_IF(cx->compartment == cx->runtime->atomsCompartment,
|
||||
kind == FINALIZE_STRING ||
|
||||
@ -493,16 +495,17 @@ NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
|
||||
JS_OOM_POSSIBLY_FAIL_REPORT(cx);
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (cx->runtime->needZealousGC())
|
||||
if (cx->runtime->needZealousGC() && allowGC)
|
||||
js::gc::RunDebugGC(cx);
|
||||
#endif
|
||||
|
||||
MaybeCheckStackRoots(cx, /* relax = */ false);
|
||||
if (allowGC)
|
||||
MaybeCheckStackRoots(cx, /* relax = */ false);
|
||||
|
||||
JSCompartment *comp = cx->compartment;
|
||||
T *t = static_cast<T *>(comp->arenas.allocateFromFreeList(kind, thingSize));
|
||||
if (!t)
|
||||
t = static_cast<T *>(js::gc::ArenaLists::refillFreeList(cx, kind));
|
||||
t = static_cast<T *>(js::gc::ArenaLists::refillFreeList<allowGC>(cx, kind));
|
||||
|
||||
JS_ASSERT_IF(t && comp->wasGCStarted() && (comp->isGCMarking() || comp->isGCSweeping()),
|
||||
t->arenaHeader()->allocatedDuringIncremental);
|
||||
@ -515,36 +518,6 @@ NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Alternate form which allocates a GC thing if doing so cannot trigger a GC. */
|
||||
template <typename T>
|
||||
inline T *
|
||||
TryNewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(thingSize == js::gc::Arena::thingSize(kind));
|
||||
JS_ASSERT_IF(cx->compartment == cx->runtime->atomsCompartment,
|
||||
kind == js::gc::FINALIZE_STRING || kind == js::gc::FINALIZE_SHORT_STRING);
|
||||
JS_ASSERT(!cx->runtime->isHeapBusy());
|
||||
JS_ASSERT(!cx->runtime->noGCOrAllocationCheck);
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (cx->runtime->needZealousGC())
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
JSCompartment *comp = cx->compartment;
|
||||
T *t = static_cast<T *>(comp->arenas.allocateFromFreeList(kind, thingSize));
|
||||
JS_ASSERT_IF(t && comp->wasGCStarted() && (comp->isGCMarking() || comp->isGCSweeping()),
|
||||
t->arenaHeader()->allocatedDuringIncremental);
|
||||
|
||||
#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)
|
||||
if (cx->runtime->gcVerifyPostData && IsNurseryAllocable(kind) && !IsAtomsCompartment(comp))
|
||||
comp->gcNursery.insertPointer(t);
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Instances of this class set the |JSRuntime::suppressGC| flag for the duration
|
||||
* that they are live. Use of this class is highly discouraged. Please carefully
|
||||
@ -577,67 +550,52 @@ class AutoSuppressGC
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline JSObject *
|
||||
js_NewGCObject(JSContext *cx, js::gc::AllocKind kind)
|
||||
{
|
||||
JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
|
||||
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 js::gc::TryNewGCThing<JSObject>(cx, kind, js::gc::Arena::thingSize(kind));
|
||||
return js::gc::NewGCThing<JSObject, allowGC>(cx, kind, js::gc::Arena::thingSize(kind));
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline JSString *
|
||||
js_NewGCString(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSString>(cx, js::gc::FINALIZE_STRING, sizeof(JSString));
|
||||
}
|
||||
|
||||
inline JSString *
|
||||
js_TryNewGCString(JSContext *cx)
|
||||
{
|
||||
return js::gc::TryNewGCThing<JSString>(cx, js::gc::FINALIZE_STRING, sizeof(JSString));
|
||||
return js::gc::NewGCThing<JSString, allowGC>(cx, js::gc::FINALIZE_STRING, sizeof(JSString));
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline JSShortString *
|
||||
js_NewGCShortString(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSShortString>(cx, js::gc::FINALIZE_SHORT_STRING, sizeof(JSShortString));
|
||||
}
|
||||
|
||||
inline JSShortString *
|
||||
js_TryNewGCShortString(JSContext *cx)
|
||||
{
|
||||
return js::gc::TryNewGCThing<JSShortString>(cx, js::gc::FINALIZE_SHORT_STRING, sizeof(JSShortString));
|
||||
return js::gc::NewGCThing<JSShortString, allowGC>(cx, js::gc::FINALIZE_SHORT_STRING, sizeof(JSShortString));
|
||||
}
|
||||
|
||||
inline JSExternalString *
|
||||
js_NewGCExternalString(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSExternalString>(cx, js::gc::FINALIZE_EXTERNAL_STRING,
|
||||
sizeof(JSExternalString));
|
||||
return js::gc::NewGCThing<JSExternalString, js::ALLOW_GC>(cx, js::gc::FINALIZE_EXTERNAL_STRING,
|
||||
sizeof(JSExternalString));
|
||||
}
|
||||
|
||||
inline JSScript *
|
||||
js_NewGCScript(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSScript>(cx, js::gc::FINALIZE_SCRIPT, sizeof(JSScript));
|
||||
return js::gc::NewGCThing<JSScript, js::ALLOW_GC>(cx, js::gc::FINALIZE_SCRIPT, sizeof(JSScript));
|
||||
}
|
||||
|
||||
inline js::UnrootedShape
|
||||
js_NewGCShape(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<js::Shape>(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape));
|
||||
return js::gc::NewGCThing<js::Shape, js::ALLOW_GC>(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape));
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline js::UnrootedBaseShape
|
||||
js_NewGCBaseShape(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<js::BaseShape>(cx, js::gc::FINALIZE_BASE_SHAPE, sizeof(js::BaseShape));
|
||||
return js::gc::NewGCThing<js::BaseShape, allowGC>(cx, js::gc::FINALIZE_BASE_SHAPE, sizeof(js::BaseShape));
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
|
@ -2279,7 +2279,7 @@ TypeCompartment::newTypeObject(JSContext *cx, Class *clasp, Handle<TaggedProto>
|
||||
{
|
||||
JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
|
||||
|
||||
TypeObject *object = gc::NewGCThing<TypeObject>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
|
||||
TypeObject *object = gc::NewGCThing<TypeObject, ALLOW_GC>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
|
||||
if (!object)
|
||||
return NULL;
|
||||
new(object) TypeObject(clasp, proto, clasp == &FunctionClass, unknown);
|
||||
|
@ -340,9 +340,9 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, HandleValue lval, HandleValu
|
||||
((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape)) {
|
||||
#ifdef DEBUG
|
||||
if (entry->isOwnPropertyHit()) {
|
||||
JS_ASSERT(obj->nativeLookupNoAllocation(shape->propid()) == shape);
|
||||
JS_ASSERT(obj->nativeLookup(cx, shape->propid()) == shape);
|
||||
} else {
|
||||
JS_ASSERT(obj2->nativeLookupNoAllocation(shape->propid()) == shape);
|
||||
JS_ASSERT(obj2->nativeLookup(cx, shape->propid()) == shape);
|
||||
JS_ASSERT(entry->isPrototypePropertyHit());
|
||||
JS_ASSERT(entry->kshape != entry->pshape);
|
||||
JS_ASSERT(!shape->hasSlot());
|
||||
@ -409,6 +409,16 @@ FetchName(JSContext *cx, HandleObject obj, HandleObject obj2, HandlePropertyName
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
FetchNameNoGC(JSContext *cx, JSObject *pobj, Shape *shape, MutableHandleValue vp)
|
||||
{
|
||||
if (!shape || !pobj->isNative() || !shape->isDataDescriptor() || !shape->hasDefaultGetter())
|
||||
return false;
|
||||
|
||||
vp.set(pobj->nativeGetSlot(shape->slot()));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetIntrinsicOperation(JSContext *cx, JSScript *script, jsbytecode *pc, MutableHandleValue vp)
|
||||
{
|
||||
@ -427,8 +437,8 @@ SetIntrinsicOperation(JSContext *cx, JSScript *script, jsbytecode *pc, HandleVal
|
||||
inline bool
|
||||
NameOperation(JSContext *cx, jsbytecode *pc, MutableHandleValue vp)
|
||||
{
|
||||
RootedObject obj(cx, cx->stack.currentScriptedScopeChain());
|
||||
RootedPropertyName name(cx, cx->stack.currentScript()->getName(pc));
|
||||
JSObject *obj = cx->stack.currentScriptedScopeChain();
|
||||
PropertyName *name = cx->stack.currentScript()->getName(pc);
|
||||
|
||||
/*
|
||||
* Skip along the scope chain to the enclosing global object. This is
|
||||
@ -442,16 +452,26 @@ NameOperation(JSContext *cx, jsbytecode *pc, MutableHandleValue vp)
|
||||
if (IsGlobalOp(JSOp(*pc)))
|
||||
obj = &obj->global();
|
||||
|
||||
RootedShape shape(cx);
|
||||
RootedObject scope(cx), pobj(cx);
|
||||
if (!LookupName(cx, name, obj, &scope, &pobj, &shape))
|
||||
Shape *shape = NULL;
|
||||
JSObject *scope = NULL, *pobj = NULL;
|
||||
if (LookupNameNoGC(cx, name, obj, &scope, &pobj, &shape)) {
|
||||
if (FetchNameNoGC(cx, pobj, shape, vp))
|
||||
return true;
|
||||
JS_ASSERT(!cx->isExceptionPending());
|
||||
}
|
||||
|
||||
RootedObject objRoot(cx, obj), scopeRoot(cx), pobjRoot(cx);
|
||||
RootedPropertyName nameRoot(cx, name);
|
||||
RootedShape shapeRoot(cx);
|
||||
|
||||
if (!LookupName(cx, nameRoot, objRoot, &scopeRoot, &pobjRoot, &shapeRoot))
|
||||
return false;
|
||||
|
||||
/* Kludge to allow (typeof foo == "undefined") tests. */
|
||||
JSOp op2 = JSOp(pc[JSOP_NAME_LENGTH]);
|
||||
if (op2 == JSOP_TYPEOF)
|
||||
return FetchName<true>(cx, scope, pobj, name, shape, vp);
|
||||
return FetchName<false>(cx, scope, pobj, name, shape, vp);
|
||||
return FetchName<true>(cx, scopeRoot, pobjRoot, nameRoot, shapeRoot, vp);
|
||||
return FetchName<false>(cx, scopeRoot, pobjRoot, nameRoot, shapeRoot, vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -532,7 +532,7 @@ js::Int32ToString(JSContext *cx, int32_t si)
|
||||
if (JSFlatString *str = c->dtoaCache.lookup(10, si))
|
||||
return str;
|
||||
|
||||
JSShortString *str = js_NewGCShortString(cx);
|
||||
JSShortString *str = js_NewGCShortString<ALLOW_GC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
@ -1287,7 +1287,7 @@ js::IndexToString(JSContext *cx, uint32_t index)
|
||||
if (JSFlatString *str = c->dtoaCache.lookup(10, index))
|
||||
return str;
|
||||
|
||||
JSShortString *str = js_NewGCShortString(cx);
|
||||
JSShortString *str = js_NewGCShortString<ALLOW_GC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
|
@ -3184,7 +3184,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
|
||||
* - Otherwise no property was resolved. Set *propp = NULL and *recursedp = false
|
||||
* and return true.
|
||||
*/
|
||||
static JSBool
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
MutableHandleObject objp, MutableHandleShape propp, bool *recursedp)
|
||||
{
|
||||
@ -3242,7 +3242,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
}
|
||||
|
||||
if (JSID_IS_INT(id) && objp->containsDenseElement(JSID_TO_INT(id))) {
|
||||
MarkDenseElementFound(propp);
|
||||
MarkDenseElementFound<ALLOW_GC>(propp);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3255,20 +3255,27 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
return true;
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static JS_ALWAYS_INLINE bool
|
||||
LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
LookupPropertyWithFlagsInline(JSContext *cx,
|
||||
typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
|
||||
typename MaybeRooted<jsid, allowGC>::HandleType id,
|
||||
unsigned flags,
|
||||
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
|
||||
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (allowGC)
|
||||
AssertCanGC();
|
||||
|
||||
/* Search scopes starting with obj and following the prototype link. */
|
||||
RootedObject current(cx, obj);
|
||||
typename MaybeRooted<JSObject*, allowGC>::RootType current(cx, obj);
|
||||
|
||||
while (true) {
|
||||
/* Search for a native dense element or property. */
|
||||
{
|
||||
if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) {
|
||||
objp.set(current);
|
||||
MarkDenseElementFound(propp);
|
||||
MarkDenseElementFound<allowGC>(propp);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3282,9 +3289,20 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi
|
||||
|
||||
/* Try obj's class resolve hook if id was not found in obj's scope. */
|
||||
if (current->getClass()->resolve != JS_ResolveStub) {
|
||||
bool recursed;
|
||||
if (!CallResolveOp(cx, current, id, flags, objp, propp, &recursed))
|
||||
if (!allowGC)
|
||||
return false;
|
||||
bool recursed;
|
||||
if (!CallResolveOp(cx,
|
||||
MaybeRooted<JSObject*, allowGC>::toHandle(current),
|
||||
MaybeRooted<jsid, allowGC>::toHandle(id),
|
||||
flags,
|
||||
MaybeRooted<JSObject*, allowGC>::toMutableHandle(objp),
|
||||
MaybeRooted<Shape*, allowGC>::toMutableHandle(propp),
|
||||
&recursed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recursed)
|
||||
break;
|
||||
if (propp) {
|
||||
@ -3296,15 +3314,18 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi
|
||||
}
|
||||
}
|
||||
|
||||
RootedObject proto(cx);
|
||||
if (!JSObject::getProto(cx, current, &proto))
|
||||
return false;
|
||||
typename MaybeRooted<JSObject*, allowGC>::RootType proto(cx, current->getProto());
|
||||
|
||||
if (!proto)
|
||||
break;
|
||||
if (!proto->isNative()) {
|
||||
if (!JSObject::lookupGeneric(cx, proto, id, objp, propp))
|
||||
if (!allowGC)
|
||||
return false;
|
||||
return true;
|
||||
return JSObject::lookupGeneric(cx,
|
||||
MaybeRooted<JSObject*, allowGC>::toHandle(proto),
|
||||
MaybeRooted<jsid, allowGC>::toHandle(id),
|
||||
MaybeRooted<JSObject*, allowGC>::toMutableHandle(objp),
|
||||
MaybeRooted<Shape*, allowGC>::toMutableHandle(propp));
|
||||
}
|
||||
|
||||
current = proto;
|
||||
@ -3319,7 +3340,7 @@ JS_FRIEND_API(JSBool)
|
||||
baseops::LookupProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp,
|
||||
MutableHandleShape propp)
|
||||
{
|
||||
return LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp);
|
||||
return LookupPropertyWithFlagsInline<ALLOW_GC>(cx, obj, id, cx->resolveFlags, objp, propp);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
@ -3330,14 +3351,14 @@ baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
|
||||
return LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp);
|
||||
return LookupPropertyWithFlagsInline<ALLOW_GC>(cx, obj, id, cx->resolveFlags, objp, propp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
MutableHandleObject objp, MutableHandleShape propp)
|
||||
{
|
||||
return LookupPropertyWithFlagsInline(cx, obj, id, flags, objp, propp);
|
||||
return LookupPropertyWithFlagsInline<ALLOW_GC>(cx, obj, id, flags, objp, propp);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -3361,6 +3382,32 @@ js::LookupName(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::LookupNameNoGC(JSContext *cx, PropertyName *name, JSObject *scopeChain,
|
||||
JSObject **objp, JSObject **pobjp, Shape **propp)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
|
||||
JS_ASSERT(!*objp && !*pobjp && !*propp);
|
||||
|
||||
for (JSObject *scope = scopeChain; scope; scope = scope->enclosingScope()) {
|
||||
if (scope->getOps()->lookupGeneric)
|
||||
return false;
|
||||
if (!LookupPropertyWithFlagsInline<DONT_ALLOW_GC>(cx, scope, NameToId(name),
|
||||
cx->resolveFlags, pobjp, propp))
|
||||
{
|
||||
JS_ASSERT(!cx->isExceptionPending());
|
||||
return false;
|
||||
}
|
||||
if (*propp) {
|
||||
*objp = scope;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::LookupNameWithGlobalDefault(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
|
||||
MutableHandleObject objp)
|
||||
@ -3481,7 +3528,7 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
/* This call site is hot -- use the always-inlined variant of LookupPropertyWithFlags(). */
|
||||
RootedObject obj2(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, &obj2, &shape))
|
||||
if (!LookupPropertyWithFlagsInline<ALLOW_GC>(cx, obj, id, cx->resolveFlags, &obj2, &shape))
|
||||
return false;
|
||||
|
||||
if (!shape) {
|
||||
@ -4116,8 +4163,10 @@ baseops::DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
|
||||
}
|
||||
|
||||
bool
|
||||
js::HasDataProperty(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
|
||||
js::HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
|
||||
if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
|
||||
*vp = obj->getDenseElement(JSID_TO_INT(id));
|
||||
return true;
|
||||
|
@ -1272,6 +1272,10 @@ extern bool
|
||||
LookupName(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
|
||||
MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp);
|
||||
|
||||
extern bool
|
||||
LookupNameNoGC(JSContext *cx, PropertyName *name, JSObject *scopeChain,
|
||||
JSObject **objp, JSObject **pobjp, Shape **propp);
|
||||
|
||||
/*
|
||||
* Like LookupName except returns the global object if 'name' is not found in
|
||||
* any preceding non-global scope.
|
||||
@ -1341,13 +1345,12 @@ GetMethod(JSContext *cx, HandleObject obj, PropertyName *name, unsigned getHow,
|
||||
* store the property value in *vp.
|
||||
*/
|
||||
extern bool
|
||||
HasDataProperty(JSContext *cx, HandleObject obj, HandleId id, Value *vp);
|
||||
HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
||||
|
||||
inline bool
|
||||
HasDataProperty(JSContext *cx, HandleObject obj, PropertyName *name, Value *vp)
|
||||
HasDataProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return HasDataProperty(cx, obj, id, vp);
|
||||
return HasDataProperty(cx, obj, NameToId(name), vp);
|
||||
}
|
||||
|
||||
extern JSBool
|
||||
|
@ -969,7 +969,7 @@ JSObject::create(JSContext *cx, js::gc::AllocKind kind,
|
||||
JS_ASSERT(js::gc::GetGCKindSlots(kind, type->clasp) == shape->numFixedSlots());
|
||||
JS_ASSERT(cx->compartment == type->compartment());
|
||||
|
||||
JSObject *obj = js_NewGCObject(cx, kind);
|
||||
JSObject *obj = js_NewGCObject<js::ALLOW_GC>(cx, kind);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
@ -1014,7 +1014,7 @@ JSObject::createArray(JSContext *cx, js::gc::AllocKind kind,
|
||||
|
||||
uint32_t capacity = js::gc::GetGCKindSlots(kind) - js::ObjectElements::VALUES_PER_HEADER;
|
||||
|
||||
JSObject *obj = js_NewGCObject(cx, kind);
|
||||
JSObject *obj = js_NewGCObject<js::ALLOW_GC>(cx, kind);
|
||||
if (!obj) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
@ -1695,7 +1695,7 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
|
||||
JS_ASSERT(proto);
|
||||
|
||||
RootedId id(cx, NameToId(ClassName(key, cx)));
|
||||
JS_ASSERT(!global->nativeLookupNoAllocation(id));
|
||||
JS_ASSERT(!global->nativeLookup(cx, id));
|
||||
|
||||
/* Set these first in case AddTypePropertyId looks for this class. */
|
||||
global->setSlot(key, ObjectValue(*ctor));
|
||||
|
@ -172,7 +172,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
|
||||
if (pobj->lastProperty() == entry->pshape) {
|
||||
#ifdef DEBUG
|
||||
Rooted<PropertyName*> name(cx, GetNameFromBytecode(cx, script, pc, op));
|
||||
JS_ASSERT(pobj->nativeContainsNoAllocation(name));
|
||||
JS_ASSERT(pobj->nativeContains(cx, name));
|
||||
#endif
|
||||
*pobjp = pobj;
|
||||
return NULL;
|
||||
|
@ -75,20 +75,20 @@ ShapeTable::init(JSRuntime *rt, UnrootedShape lastProp)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Shape::makeOwnBaseShape(JSContext *cx, HandleShape shape)
|
||||
bool
|
||||
Shape::makeOwnBaseShape(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(!shape->base()->isOwned());
|
||||
assertSameCompartmentDebugOnly(cx, shape->compartment());
|
||||
JS_ASSERT(!base()->isOwned());
|
||||
assertSameCompartmentDebugOnly(cx, compartment());
|
||||
|
||||
UnrootedBaseShape nbase = js_NewGCBaseShape(cx);
|
||||
UnrootedBaseShape nbase = js_NewGCBaseShape<DONT_ALLOW_GC>(cx);
|
||||
if (!nbase)
|
||||
return false;
|
||||
|
||||
new (nbase) BaseShape(StackBaseShape(shape));
|
||||
nbase->setOwned(shape->base()->toUnowned());
|
||||
new (nbase) BaseShape(StackBaseShape(this));
|
||||
nbase->setOwned(base()->toUnowned());
|
||||
|
||||
shape->base_ = nbase;
|
||||
this->base_ = nbase;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -115,9 +115,9 @@ Shape::handoffTableTo(UnrootedShape shape)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Shape::hashify(JSContext *cx, HandleShape shape)
|
||||
Shape::hashify(JSContext *cx, Shape *shape)
|
||||
{
|
||||
AssertCanGC();
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(!shape->hasTable());
|
||||
|
||||
if (!shape->ensureOwnBaseShape(cx))
|
||||
@ -738,7 +738,7 @@ JSObject::putProperty(JSContext *cx, HandleObject obj, HandleId id,
|
||||
JSObject::changeProperty(JSContext *cx, HandleObject obj, RawShape shape, unsigned attrs, unsigned mask,
|
||||
PropertyOp getter, StrictPropertyOp setter)
|
||||
{
|
||||
JS_ASSERT(obj->nativeContainsNoAllocation(*shape));
|
||||
JS_ASSERT(obj->nativeContains(cx, shape));
|
||||
|
||||
attrs |= shape->attrs & mask;
|
||||
|
||||
@ -857,7 +857,7 @@ JSObject::removeProperty(JSContext *cx, jsid id_)
|
||||
*/
|
||||
UnrootedShape aprop = self->lastProperty();
|
||||
for (int n = 50; --n >= 0 && aprop->parent; aprop = aprop->parent)
|
||||
JS_ASSERT_IF(aprop != shape, self->nativeContainsNoAllocation(*aprop));
|
||||
JS_ASSERT_IF(aprop != shape, self->nativeContains(cx, aprop));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -935,7 +935,7 @@ JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *n
|
||||
JS_ASSERT(cx->compartment == oldShape->compartment());
|
||||
JS_ASSERT_IF(oldShape != lastProperty(),
|
||||
inDictionaryMode() &&
|
||||
nativeLookupNoAllocation(oldShape->propidRef()) == oldShape);
|
||||
nativeLookup(cx, oldShape->propidRef()) == oldShape);
|
||||
|
||||
JSObject *self = this;
|
||||
|
||||
@ -1140,7 +1140,7 @@ BaseShape::getUnowned(JSContext *cx, const StackBaseShape &base)
|
||||
|
||||
StackBaseShape::AutoRooter root(cx, &base);
|
||||
|
||||
UnrootedBaseShape nbase_ = js_NewGCBaseShape(cx);
|
||||
UnrootedBaseShape nbase_ = js_NewGCBaseShape<ALLOW_GC>(cx);
|
||||
if (!nbase_)
|
||||
return NULL;
|
||||
|
||||
|
@ -498,8 +498,6 @@ class Shape : public js::gc::Cell
|
||||
static inline UnrootedShape search(JSContext *cx, Shape *start, jsid id,
|
||||
Shape ***pspp, bool adding = false);
|
||||
|
||||
static inline UnrootedShape searchNoAllocation(UnrootedShape start, jsid id);
|
||||
|
||||
inline void removeFromDictionary(JSObject *obj);
|
||||
inline void insertIntoDictionary(HeapPtrShape *dictp);
|
||||
|
||||
@ -512,7 +510,7 @@ class Shape : public js::gc::Cell
|
||||
static UnrootedShape replaceLastProperty(JSContext *cx, const StackBaseShape &base,
|
||||
TaggedProto proto, HandleShape shape);
|
||||
|
||||
static bool hashify(JSContext *cx, HandleShape shape);
|
||||
static bool hashify(JSContext *cx, Shape *shape);
|
||||
void handoffTableTo(UnrootedShape newShape);
|
||||
|
||||
inline void setParent(UnrootedShape p);
|
||||
@ -520,11 +518,10 @@ class Shape : public js::gc::Cell
|
||||
bool ensureOwnBaseShape(JSContext *cx) {
|
||||
if (base()->isOwned())
|
||||
return true;
|
||||
RootedShape self(cx, this);
|
||||
return makeOwnBaseShape(cx, self);
|
||||
return makeOwnBaseShape(cx);
|
||||
}
|
||||
|
||||
static bool makeOwnBaseShape(JSContext *cx, HandleShape shape);
|
||||
bool makeOwnBaseShape(JSContext *cx);
|
||||
|
||||
public:
|
||||
bool hasTable() const { return base()->hasTable(); }
|
||||
@ -1055,14 +1052,7 @@ namespace js {
|
||||
inline UnrootedShape
|
||||
Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
|
||||
{
|
||||
AssertCanGC();
|
||||
#ifdef DEBUG
|
||||
{
|
||||
SkipRoot skip0(cx, &start);
|
||||
SkipRoot skip1(cx, &id);
|
||||
MaybeCheckStackRoots(cx);
|
||||
}
|
||||
#endif
|
||||
AutoAssertNoGC nogc;
|
||||
|
||||
if (start->inDictionary()) {
|
||||
*pspp = start->table().search(id, adding);
|
||||
@ -1078,14 +1068,10 @@ Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
|
||||
|
||||
if (start->numLinearSearches() == LINEAR_SEARCHES_MAX) {
|
||||
if (start->isBigEnoughForAShapeTable()) {
|
||||
RootedShape startRoot(cx, start);
|
||||
RootedId idRoot(cx, id);
|
||||
if (Shape::hashify(cx, startRoot)) {
|
||||
Shape **spp = startRoot->table().search(idRoot, adding);
|
||||
if (Shape::hashify(cx, start)) {
|
||||
Shape **spp = start->table().search(id, adding);
|
||||
return SHAPE_FETCH(spp);
|
||||
}
|
||||
start = startRoot;
|
||||
id = idRoot;
|
||||
}
|
||||
/*
|
||||
* No table built -- there weren't enough entries, or OOM occurred.
|
||||
@ -1104,22 +1090,6 @@ Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
/* static */ inline UnrootedShape
|
||||
Shape::searchNoAllocation(UnrootedShape start, jsid id)
|
||||
{
|
||||
if (start->hasTable()) {
|
||||
Shape **spp = start->table().search(id, false);
|
||||
return SHAPE_FETCH(spp);
|
||||
}
|
||||
|
||||
for (UnrootedShape shape = start; shape; shape = shape->parent) {
|
||||
if (shape->propidRef() == id)
|
||||
return shape;
|
||||
}
|
||||
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
template<> struct RootKind<Shape *> : SpecificRootKind<Shape *, THING_ROOT_SHAPE> {};
|
||||
template<> struct RootKind<BaseShape *> : SpecificRootKind<BaseShape *, THING_ROOT_BASE_SHAPE> {};
|
||||
|
||||
|
@ -507,8 +507,9 @@ MarkNonNativePropertyFound(MutableHandleShape propp)
|
||||
propp.set(reinterpret_cast<Shape*>(1));
|
||||
}
|
||||
|
||||
template <AllowGC allowGC>
|
||||
static inline void
|
||||
MarkDenseElementFound(MutableHandleShape propp)
|
||||
MarkDenseElementFound(typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
|
||||
{
|
||||
propp.set(reinterpret_cast<Shape*>(1));
|
||||
}
|
||||
|
@ -1990,8 +1990,7 @@ InterpretDollar(RegExpStatics *res, const jschar *dp, const jschar *ep,
|
||||
static bool
|
||||
FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t *sizep)
|
||||
{
|
||||
RootedObject base(cx, rdata.elembase);
|
||||
if (base) {
|
||||
if (rdata.elembase) {
|
||||
/*
|
||||
* The base object is used when replace was passed a lambda which looks like
|
||||
* 'function(a) { return b[a]; }' for the base object b. b will not change
|
||||
@ -1999,8 +1998,8 @@ FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t
|
||||
* to accessing a scripted getter or a value with a scripted toString.
|
||||
*/
|
||||
JS_ASSERT(rdata.lambda);
|
||||
JS_ASSERT(!base->getOps()->lookupProperty);
|
||||
JS_ASSERT(!base->getOps()->getProperty);
|
||||
JS_ASSERT(!rdata.elembase->getOps()->lookupProperty);
|
||||
JS_ASSERT(!rdata.elembase->getOps()->getProperty);
|
||||
|
||||
Value match;
|
||||
if (!res->createLastMatch(cx, &match))
|
||||
@ -2017,8 +2016,7 @@ FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t
|
||||
}
|
||||
|
||||
Value v;
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
if (HasDataProperty(cx, base, id, &v) && v.isString()) {
|
||||
if (HasDataProperty(cx, rdata.elembase, AtomToId(atom), &v) && v.isString()) {
|
||||
rdata.repstr = v.toString()->ensureLinear(cx);
|
||||
if (!rdata.repstr)
|
||||
return false;
|
||||
|
@ -1305,7 +1305,7 @@ class GetPropCompiler : public PICStubCompiler
|
||||
// that will complicate property lookups on them.
|
||||
JS_ASSERT_IF(expando, expando->isNative() && expando->getProto() == NULL);
|
||||
|
||||
if (expando && expando->nativeLookupNoAllocation(name) == NULL) {
|
||||
if (expando && expando->nativeLookup(cx, name) == NULL) {
|
||||
Jump expandoGuard = masm.testObject(Assembler::NotEqual, expandoAddress);
|
||||
if (!shapeMismatches.append(expandoGuard))
|
||||
return error();
|
||||
|
@ -43,63 +43,31 @@ Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
|
||||
inline js::UnrootedShape
|
||||
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyId pid)
|
||||
{
|
||||
RootedId id(cx, pid.asId());
|
||||
return nativeLookup(cx, id);
|
||||
return nativeLookup(cx, pid.asId());
|
||||
}
|
||||
|
||||
inline js::UnrootedShape
|
||||
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyName *name)
|
||||
{
|
||||
return nativeLookup(cx, PropertyId(name));
|
||||
}
|
||||
|
||||
inline js::UnrootedShape
|
||||
js::ObjectImpl::nativeLookupNoAllocation(PropertyId pid)
|
||||
{
|
||||
return nativeLookupNoAllocation(pid.asId());
|
||||
}
|
||||
|
||||
inline js::UnrootedShape
|
||||
js::ObjectImpl::nativeLookupNoAllocation(PropertyName *name)
|
||||
{
|
||||
return nativeLookupNoAllocation(PropertyId(name));
|
||||
return nativeLookup(cx, NameToId(name));
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::ObjectImpl::nativeContains(JSContext *cx, JS::Handle<jsid> id)
|
||||
js::ObjectImpl::nativeContains(JSContext *cx, jsid id)
|
||||
{
|
||||
return nativeLookup(cx, id) != NULL;
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::ObjectImpl::nativeContains(JSContext *cx, JS::Handle<PropertyName*> name)
|
||||
js::ObjectImpl::nativeContains(JSContext *cx, PropertyName *name)
|
||||
{
|
||||
return nativeLookup(cx, name) != NULL;
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::ObjectImpl::nativeContains(JSContext *cx, JS::Handle<Shape*> shape)
|
||||
js::ObjectImpl::nativeContains(JSContext *cx, Shape *shape)
|
||||
{
|
||||
RootedId id(cx, shape->propid());
|
||||
return nativeLookup(cx, id) == shape;
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::ObjectImpl::nativeContainsNoAllocation(jsid id)
|
||||
{
|
||||
return nativeLookupNoAllocation(id) != NULL;
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::ObjectImpl::nativeContainsNoAllocation(PropertyName *name)
|
||||
{
|
||||
return nativeLookupNoAllocation(name) != NULL;
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::ObjectImpl::nativeContainsNoAllocation(Shape &shape)
|
||||
{
|
||||
return nativeLookupNoAllocation(shape.propid()) == &shape;
|
||||
return nativeLookup(cx, shape->propid()) == shape;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -264,21 +264,14 @@ js::ObjectImpl::slotInRange(uint32_t slot, SentinelAllowed sentinel) const
|
||||
MOZ_NEVER_INLINE
|
||||
#endif
|
||||
UnrootedShape
|
||||
js::ObjectImpl::nativeLookup(JSContext *cx, HandleId id)
|
||||
js::ObjectImpl::nativeLookup(JSContext *cx, jsid id)
|
||||
{
|
||||
AssertCanGC();
|
||||
AutoAssertNoGC nogc;
|
||||
MOZ_ASSERT(isNative());
|
||||
Shape **spp;
|
||||
return Shape::search(cx, lastProperty(), id, &spp);
|
||||
}
|
||||
|
||||
UnrootedShape
|
||||
js::ObjectImpl::nativeLookupNoAllocation(jsid id)
|
||||
{
|
||||
MOZ_ASSERT(isNative());
|
||||
return Shape::searchNoAllocation(lastProperty(), id);
|
||||
}
|
||||
|
||||
void
|
||||
js::ObjectImpl::markChildren(JSTracer *trc)
|
||||
{
|
||||
|
@ -1209,21 +1209,13 @@ class ObjectImpl : public gc::Cell
|
||||
/* Compute dynamicSlotsCount() for this object. */
|
||||
inline uint32_t numDynamicSlots() const;
|
||||
|
||||
UnrootedShape nativeLookup(JSContext *cx, HandleId id);
|
||||
UnrootedShape nativeLookup(JSContext *cx, jsid id);
|
||||
inline UnrootedShape nativeLookup(JSContext *cx, PropertyId pid);
|
||||
inline UnrootedShape nativeLookup(JSContext *cx, PropertyName *name);
|
||||
|
||||
UnrootedShape nativeLookupNoAllocation(jsid id);
|
||||
inline UnrootedShape nativeLookupNoAllocation(PropertyId pid);
|
||||
inline UnrootedShape nativeLookupNoAllocation(PropertyName *name);
|
||||
|
||||
inline bool nativeContains(JSContext *cx, Handle<jsid> id);
|
||||
inline bool nativeContains(JSContext *cx, Handle<PropertyName*> name);
|
||||
inline bool nativeContains(JSContext *cx, Handle<Shape*> shape);
|
||||
|
||||
inline bool nativeContainsNoAllocation(jsid id);
|
||||
inline bool nativeContainsNoAllocation(PropertyName *name);
|
||||
inline bool nativeContainsNoAllocation(Shape &shape);
|
||||
inline bool nativeContains(JSContext *cx, jsid id);
|
||||
inline bool nativeContains(JSContext *cx, PropertyName* name);
|
||||
inline bool nativeContains(JSContext *cx, Shape* shape);
|
||||
|
||||
inline JSClass *getJSClass() const;
|
||||
inline bool hasClass(const Class *c) const;
|
||||
|
@ -331,17 +331,17 @@ RegExpObject::init(JSContext *cx, HandleAtom source, RegExpFlag flags)
|
||||
JS_ASSERT(!self->nativeEmpty());
|
||||
}
|
||||
|
||||
JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().lastIndex))->slot() ==
|
||||
JS_ASSERT(self->nativeLookup(cx, NameToId(cx->names().lastIndex))->slot() ==
|
||||
LAST_INDEX_SLOT);
|
||||
JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().source))->slot() ==
|
||||
JS_ASSERT(self->nativeLookup(cx, NameToId(cx->names().source))->slot() ==
|
||||
SOURCE_SLOT);
|
||||
JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().global))->slot() ==
|
||||
JS_ASSERT(self->nativeLookup(cx, NameToId(cx->names().global))->slot() ==
|
||||
GLOBAL_FLAG_SLOT);
|
||||
JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().ignoreCase))->slot() ==
|
||||
JS_ASSERT(self->nativeLookup(cx, NameToId(cx->names().ignoreCase))->slot() ==
|
||||
IGNORE_CASE_FLAG_SLOT);
|
||||
JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().multiline))->slot() ==
|
||||
JS_ASSERT(self->nativeLookup(cx, NameToId(cx->names().multiline))->slot() ==
|
||||
MULTILINE_FLAG_SLOT);
|
||||
JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().sticky))->slot() ==
|
||||
JS_ASSERT(self->nativeLookup(cx, NameToId(cx->names().sticky))->slot() ==
|
||||
STICKY_FLAG_SLOT);
|
||||
|
||||
/*
|
||||
|
@ -27,8 +27,8 @@ NewShortString(JSContext *cx, Latin1Chars chars)
|
||||
size_t len = chars.length();
|
||||
JS_ASSERT(JSShortString::lengthFits(len));
|
||||
UnrootedInlineString str = JSInlineString::lengthFits(len)
|
||||
? JSInlineString::new_(cx)
|
||||
: JSShortString::new_(cx);
|
||||
? JSInlineString::new_<ALLOW_GC>(cx)
|
||||
: JSShortString::new_<ALLOW_GC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
@ -51,8 +51,8 @@ NewShortString(JSContext *cx, StableTwoByteChars chars)
|
||||
*/
|
||||
JS_ASSERT(JSShortString::lengthFits(len));
|
||||
JSInlineString *str = JSInlineString::lengthFits(len)
|
||||
? JSInlineString::new_(cx)
|
||||
: JSShortString::new_(cx);
|
||||
? JSInlineString::new_<ALLOW_GC>(cx)
|
||||
: JSShortString::new_<ALLOW_GC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
@ -74,8 +74,8 @@ NewShortString(JSContext *cx, TwoByteChars chars)
|
||||
*/
|
||||
JS_ASSERT(JSShortString::lengthFits(len));
|
||||
JSInlineString *str = JSInlineString::lengthFits(len)
|
||||
? JSInlineString::tryNew_(cx)
|
||||
: JSShortString::tryNew_(cx);
|
||||
? JSInlineString::new_<DONT_ALLOW_GC>(cx)
|
||||
: JSShortString::new_<DONT_ALLOW_GC>(cx);
|
||||
if (!str) {
|
||||
jschar tmp[JSShortString::MAX_SHORT_LENGTH];
|
||||
PodCopy(tmp, chars.start().get(), len);
|
||||
@ -186,7 +186,7 @@ JSRope::newStringMaybeAllowGC(JSContext *cx,
|
||||
{
|
||||
if (!validateLength(cx, length))
|
||||
return NULL;
|
||||
JSRope *str = (JSRope *) (allowGC ? js_NewGCString(cx) : js_TryNewGCString(cx));
|
||||
JSRope *str = (JSRope *) js_NewGCString<allowGC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->init(left, right, length);
|
||||
@ -243,7 +243,7 @@ JSDependentString::new_(JSContext *cx, JSLinearString *baseArg, const jschar *ch
|
||||
if (JSShortString::lengthFits(length))
|
||||
return js::NewShortString(cx, js::TwoByteChars(chars, length));
|
||||
|
||||
JSDependentString *str = (JSDependentString *)js_NewGCString(cx);
|
||||
JSDependentString *str = (JSDependentString *)js_NewGCString<js::ALLOW_GC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->init(base, chars, length);
|
||||
@ -293,23 +293,18 @@ JSStableString::new_(JSContext *cx, const jschar *chars, size_t length)
|
||||
|
||||
if (!validateLength(cx, length))
|
||||
return NULL;
|
||||
JSStableString *str = (JSStableString *)js_NewGCString(cx);
|
||||
JSStableString *str = (JSStableString *)js_NewGCString<js::ALLOW_GC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
str->init(chars, length);
|
||||
return str;
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
JS_ALWAYS_INLINE JSInlineString *
|
||||
JSInlineString::new_(JSContext *cx)
|
||||
{
|
||||
return (JSInlineString *)js_NewGCString(cx);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSInlineString *
|
||||
JSInlineString::tryNew_(JSContext *cx)
|
||||
{
|
||||
return (JSInlineString *)js_TryNewGCString(cx);
|
||||
return (JSInlineString *)js_NewGCString<allowGC>(cx);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE jschar *
|
||||
@ -328,16 +323,11 @@ JSInlineString::resetLength(size_t length)
|
||||
JS_ASSERT(lengthFits(length) || (isShort() && JSShortString::lengthFits(length)));
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
JS_ALWAYS_INLINE JSShortString *
|
||||
JSShortString::new_(JSContext *cx)
|
||||
{
|
||||
return js_NewGCShortString(cx);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSShortString *
|
||||
JSShortString::tryNew_(JSContext *cx)
|
||||
{
|
||||
return js_TryNewGCShortString(cx);
|
||||
return js_NewGCShortString<allowGC>(cx);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE void
|
||||
|
@ -319,7 +319,7 @@ ConcatStringsMaybeAllowGC(JSContext *cx,
|
||||
return NULL;
|
||||
|
||||
if (JSShortString::lengthFits(wholeLength)) {
|
||||
JSShortString *str = allowGC ? js_NewGCShortString(cx) : js_TryNewGCShortString(cx);
|
||||
JSShortString *str = js_NewGCShortString<allowGC>(cx);
|
||||
if (!str)
|
||||
return NULL;
|
||||
const jschar *leftChars = left->getChars(cx);
|
||||
|
@ -656,8 +656,8 @@ class JSInlineString : public JSFlatString
|
||||
static const size_t MAX_INLINE_LENGTH = NUM_INLINE_CHARS - 1;
|
||||
|
||||
public:
|
||||
template <js::AllowGC allowGC>
|
||||
static inline JSInlineString *new_(JSContext *cx);
|
||||
static inline JSInlineString *tryNew_(JSContext *cx);
|
||||
|
||||
inline jschar *init(size_t length);
|
||||
|
||||
@ -688,8 +688,8 @@ class JSShortString : public JSInlineString
|
||||
jschar inlineStorageExtension[INLINE_EXTENSION_CHARS];
|
||||
|
||||
public:
|
||||
template <js::AllowGC allowGC>
|
||||
static inline JSShortString *new_(JSContext *cx);
|
||||
static inline JSShortString *tryNew_(JSContext *cx);
|
||||
|
||||
static const size_t MAX_SHORT_LENGTH = JSString::NUM_INLINE_CHARS +
|
||||
INLINE_EXTENSION_CHARS
|
||||
|
@ -40,7 +40,7 @@ StringObject::init(JSContext *cx, HandleString str)
|
||||
}
|
||||
}
|
||||
|
||||
JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().length))->slot() == LENGTH_SLOT);
|
||||
JS_ASSERT(self->nativeLookup(cx, NameToId(cx->names().length))->slot() == LENGTH_SLOT);
|
||||
|
||||
self->setStringThis(str);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user