diff options
Diffstat (limited to 'js/src/vm')
-rw-r--r-- | js/src/vm/ArrayBufferObject.cpp | 4 | ||||
-rw-r--r-- | js/src/vm/ArrayBufferObject.h | 17 | ||||
-rw-r--r-- | js/src/vm/Debugger.cpp | 8 | ||||
-rw-r--r-- | js/src/vm/EnvironmentObject.cpp | 12 | ||||
-rw-r--r-- | js/src/vm/EnvironmentObject.h | 2 | ||||
-rw-r--r-- | js/src/vm/GeneratorObject.cpp | 10 | ||||
-rw-r--r-- | js/src/vm/Interpreter-inl.h | 32 | ||||
-rw-r--r-- | js/src/vm/Interpreter.cpp | 67 | ||||
-rw-r--r-- | js/src/vm/JSONParser.h | 9 | ||||
-rw-r--r-- | js/src/vm/NativeObject-inl.h | 55 | ||||
-rw-r--r-- | js/src/vm/NativeObject.cpp | 142 | ||||
-rw-r--r-- | js/src/vm/NativeObject.h | 2 | ||||
-rw-r--r-- | js/src/vm/ObjectGroup.cpp | 2 | ||||
-rw-r--r-- | js/src/vm/Opcodes.h | 16 | ||||
-rw-r--r-- | js/src/vm/SavedStacks.h | 51 | ||||
-rw-r--r-- | js/src/vm/Scope.h | 96 | ||||
-rw-r--r-- | js/src/vm/Shape-inl.h | 8 | ||||
-rw-r--r-- | js/src/vm/Shape.cpp | 7 | ||||
-rw-r--r-- | js/src/vm/Shape.h | 65 | ||||
-rw-r--r-- | js/src/vm/SharedMem.h | 4 | ||||
-rw-r--r-- | js/src/vm/String.h | 2 | ||||
-rw-r--r-- | js/src/vm/TaggedProto.h | 22 | ||||
-rw-r--r-- | js/src/vm/UnboxedObject.cpp | 12 | ||||
-rw-r--r-- | js/src/vm/UnboxedObject.h | 4 |
24 files changed, 293 insertions, 356 deletions
diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 1de3d3b1e..5d355ada9 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -352,7 +352,7 @@ ArrayBufferObject::detach(JSContext* cx, Handle<ArrayBufferObject*> buffer, // Update all views of the buffer to account for the buffer having been // detached, and clear the buffer's data and list of views. - auto& innerViews = cx->compartment()->innerViews; + auto& innerViews = cx->compartment()->innerViews.get(); if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(buffer)) { for (size_t i = 0; i < views->length(); i++) NoteViewBufferWasDetached((*views)[i], newContents, cx); @@ -427,7 +427,7 @@ ArrayBufferObject::changeContents(JSContext* cx, BufferContents newContents, setNewData(cx->runtime()->defaultFreeOp(), newContents, ownsState); // Update all views. - auto& innerViews = cx->compartment()->innerViews; + auto& innerViews = cx->compartment()->innerViews.get(); if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(this)) { for (size_t i = 0; i < views->length(); i++) changeViewContents(cx, (*views)[i], oldDataPointer, newContents); diff --git a/js/src/vm/ArrayBufferObject.h b/js/src/vm/ArrayBufferObject.h index e6dbd3096..87dce34ba 100644 --- a/js/src/vm/ArrayBufferObject.h +++ b/js/src/vm/ArrayBufferObject.h @@ -541,7 +541,6 @@ class InnerViewTable typedef Vector<ArrayBufferViewObject*, 1, SystemAllocPolicy> ViewVector; friend class ArrayBufferObject; - friend class WeakCacheBase<InnerViewTable>; private: struct MapGCPolicy { @@ -602,23 +601,15 @@ class InnerViewTable size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); }; -template <> -class WeakCacheBase<InnerViewTable> +template <typename Wrapper> +class MutableWrappedPtrOperations<InnerViewTable, Wrapper> + : public WrappedPtrOperations<InnerViewTable, Wrapper> { InnerViewTable& table() { - return static_cast<JS::WeakCache<InnerViewTable>*>(this)->get(); - } - const InnerViewTable& table() const { - return static_cast<const JS::WeakCache<InnerViewTable>*>(this)->get(); + return static_cast<Wrapper*>(this)->get(); } public: - InnerViewTable::ViewVector* maybeViewsUnbarriered(ArrayBufferObject* obj) { - return table().maybeViewsUnbarriered(obj); - } - void removeViews(ArrayBufferObject* obj) { table().removeViews(obj); } - void sweepAfterMinorGC() { table().sweepAfterMinorGC(); } - bool needsSweepAfterMinorGC() const { return table().needsSweepAfterMinorGC(); } size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) { return table().sizeOfExcludingThis(mallocSizeOf); } diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 1c875c606..0c021ff0e 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -10098,12 +10098,14 @@ DebuggerObject::forceLexicalInitializationByName(JSContext* cx, HandleDebuggerOb RootedObject globalLexical(cx, &referent->lexicalEnvironment()); RootedObject pobj(cx); - RootedShape shape(cx); - if (!LookupProperty(cx, globalLexical, id, &pobj, &shape)) + Rooted<PropertyResult> prop(cx); + if (!LookupProperty(cx, globalLexical, id, &pobj, &prop)) return false; result = false; - if (shape) { + if (prop) { + MOZ_ASSERT(prop.isNativeProperty()); + Shape* shape = prop.shape(); Value v = globalLexical->as<NativeObject>().getSlot(shape->slot()); if (shape->hasSlot() && v.isMagic() && v.whyMagic() == JS_UNINITIALIZED_LEXICAL) { globalLexical->as<NativeObject>().setSlot(shape->slot(), UndefinedValue()); diff --git a/js/src/vm/EnvironmentObject.cpp b/js/src/vm/EnvironmentObject.cpp index bffa32f6b..4e74b95ab 100644 --- a/js/src/vm/EnvironmentObject.cpp +++ b/js/src/vm/EnvironmentObject.cpp @@ -518,14 +518,14 @@ ModuleEnvironmentObject::fixEnclosingEnvironmentAfterCompartmentMerge(GlobalObje /* static */ bool ModuleEnvironmentObject::lookupProperty(JSContext* cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, MutableHandle<PropertyResult> propp) { const IndirectBindingMap& bindings = obj->as<ModuleEnvironmentObject>().importBindings(); Shape* shape; ModuleEnvironmentObject* env; if (bindings.lookup(id, &env, &shape)) { objp.set(env); - propp.set(shape); + propp.setNativeProperty(shape); return true; } @@ -688,13 +688,13 @@ CheckUnscopables(JSContext *cx, HandleObject obj, HandleId id, bool *scopable) static bool with_LookupProperty(JSContext* cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, MutableHandle<PropertyResult> propp) { // SpiderMonkey-specific: consider internal '.generator' and '.this' names // to be unscopable. if (IsUnscopableDotName(cx, id)) { objp.set(nullptr); - propp.set(nullptr); + propp.setNotFound(); return true; } @@ -708,7 +708,7 @@ with_LookupProperty(JSContext* cx, HandleObject obj, HandleId id, return false; if (!scopable) { objp.set(nullptr); - propp.set(nullptr); + propp.setNotFound(); } } return true; @@ -1104,7 +1104,7 @@ ReportRuntimeLexicalErrorId(JSContext* cx, unsigned errorNumber, HandleId id) static bool lexicalError_LookupProperty(JSContext* cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) + MutableHandleObject objp, MutableHandle<PropertyResult> propp) { ReportRuntimeLexicalErrorId(cx, obj->as<RuntimeLexicalErrorObject>().errorNumber(), id); return false; diff --git a/js/src/vm/EnvironmentObject.h b/js/src/vm/EnvironmentObject.h index 0277e7c65..752eb5c65 100644 --- a/js/src/vm/EnvironmentObject.h +++ b/js/src/vm/EnvironmentObject.h @@ -407,7 +407,7 @@ class ModuleEnvironmentObject : public EnvironmentObject private: static bool lookupProperty(JSContext* cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp); + MutableHandleObject objp, MutableHandle<PropertyResult> propp); static bool hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp); static bool getProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id, MutableHandleValue vp); diff --git a/js/src/vm/GeneratorObject.cpp b/js/src/vm/GeneratorObject.cpp index 018e5a481..9265a1b62 100644 --- a/js/src/vm/GeneratorObject.cpp +++ b/js/src/vm/GeneratorObject.cpp @@ -363,12 +363,14 @@ js::CheckStarGeneratorResumptionValue(JSContext* cx, HandleValue v) // It should have `value` data property, but the type doesn't matter JSObject* ignored; - Shape* shape; - if (!LookupPropertyPure(cx, obj, NameToId(cx->names().value), &ignored, &shape)) + PropertyResult prop; + if (!LookupPropertyPure(cx, obj, NameToId(cx->names().value), &ignored, &prop)) return false; - if (!shape) + if (!prop) return false; - if (!shape->hasDefaultGetter()) + if (!prop.isNativeProperty()) + return false; + if (!prop.shape()->hasDefaultGetter()) return false; return true; diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h index 2e94a2ab2..5c2320d3f 100644 --- a/js/src/vm/Interpreter-inl.h +++ b/js/src/vm/Interpreter-inl.h @@ -78,17 +78,18 @@ IsUninitializedLexical(const Value& val) } static inline bool -IsUninitializedLexicalSlot(HandleObject obj, HandleShape shape) +IsUninitializedLexicalSlot(HandleObject obj, Handle<PropertyResult> prop) { - MOZ_ASSERT(shape); + MOZ_ASSERT(prop); if (obj->is<WithEnvironmentObject>()) return false; - // We check for IsImplicitDenseOrTypedArrayElement even though the shape - // is always a non-indexed property because proxy hooks may return a - // "non-native property found" shape, which happens to be encoded in the - // same way as the "dense element" shape. See MarkNonNativePropertyFound. - if (IsImplicitDenseOrTypedArrayElement(shape) || - !shape->hasSlot() || + + // Proxy hooks may return a non-native property. + if (prop.isNonNativeProperty()) + return false; + + Shape* shape = prop.shape(); + if (!shape->hasSlot() || !shape->hasDefaultGetter() || !shape->hasDefaultSetter()) { @@ -174,9 +175,9 @@ GetLengthProperty(const Value& lval, MutableHandleValue vp) template <bool TypeOf> inline bool FetchName(JSContext* cx, HandleObject obj, HandleObject obj2, HandlePropertyName name, - HandleShape shape, MutableHandleValue vp) + Handle<PropertyResult> prop, MutableHandleValue vp) { - if (!shape) { + if (!prop) { if (TypeOf) { vp.setUndefined(); return true; @@ -190,6 +191,7 @@ FetchName(JSContext* cx, HandleObject obj, HandleObject obj2, HandlePropertyName if (!GetProperty(cx, obj, obj, id, vp)) return false; } else { + RootedShape shape(cx, prop.shape()); RootedObject normalized(cx, obj); if (normalized->is<WithEnvironmentObject>() && !shape->hasDefaultGetter()) normalized = &normalized->as<WithEnvironmentObject>().object(); @@ -213,9 +215,13 @@ FetchName(JSContext* cx, HandleObject obj, HandleObject obj2, HandlePropertyName } inline bool -FetchNameNoGC(JSObject* pobj, Shape* shape, MutableHandleValue vp) +FetchNameNoGC(JSObject* pobj, PropertyResult prop, MutableHandleValue vp) { - if (!shape || !pobj->isNative() || !shape->isDataDescriptor() || !shape->hasDefaultGetter()) + if (!prop || !pobj->isNative()) + return false; + + Shape* shape = prop.shape(); + if (!shape->isDataDescriptor() || !shape->hasDefaultGetter()) return false; vp.set(pobj->as<NativeObject>().getSlot(shape->slot())); @@ -361,7 +367,7 @@ DefVarOperation(JSContext* cx, HandleObject varobj, HandlePropertyName dn, unsig } #endif - RootedShape prop(cx); + Rooted<PropertyResult> prop(cx); RootedObject obj2(cx); if (!LookupProperty(cx, varobj, dn, &obj2, &prop)) return false; diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 93542e4d7..cf58e2d60 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -210,27 +210,27 @@ GetNameOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableHan if (IsGlobalOp(JSOp(*pc)) && !fp->script()->hasNonSyntacticScope()) obj = &obj->global().lexicalEnvironment(); - Shape* shape = nullptr; + PropertyResult prop; JSObject* env = nullptr; JSObject* pobj = nullptr; - if (LookupNameNoGC(cx, name, obj, &env, &pobj, &shape)) { - if (FetchNameNoGC(pobj, shape, vp)) + if (LookupNameNoGC(cx, name, obj, &env, &pobj, &prop)) { + if (FetchNameNoGC(pobj, prop, vp)) return true; } RootedObject objRoot(cx, obj), envRoot(cx), pobjRoot(cx); RootedPropertyName nameRoot(cx, name); - RootedShape shapeRoot(cx); + Rooted<PropertyResult> propRoot(cx); - if (!LookupName(cx, nameRoot, objRoot, &envRoot, &pobjRoot, &shapeRoot)) + if (!LookupName(cx, nameRoot, objRoot, &envRoot, &pobjRoot, &propRoot)) return false; /* Kludge to allow (typeof foo == "undefined") tests. */ JSOp op2 = JSOp(pc[JSOP_GETNAME_LENGTH]); if (op2 == JSOP_TYPEOF) - return FetchName<true>(cx, envRoot, pobjRoot, nameRoot, shapeRoot, vp); + return FetchName<true>(cx, envRoot, pobjRoot, nameRoot, propRoot, vp); - return FetchName<false>(cx, envRoot, pobjRoot, nameRoot, shapeRoot, vp); + return FetchName<false>(cx, envRoot, pobjRoot, nameRoot, propRoot, vp); } static inline bool @@ -238,12 +238,12 @@ GetImportOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableH { RootedObject obj(cx, fp->environmentChain()), env(cx), pobj(cx); RootedPropertyName name(cx, fp->script()->getName(pc)); - RootedShape shape(cx); + Rooted<PropertyResult> prop(cx); - MOZ_ALWAYS_TRUE(LookupName(cx, name, obj, &env, &pobj, &shape)); + MOZ_ALWAYS_TRUE(LookupName(cx, name, obj, &env, &pobj, &prop)); MOZ_ASSERT(env && env->is<ModuleEnvironmentObject>()); MOZ_ASSERT(env->as<ModuleEnvironmentObject>().hasImportBinding(name)); - return FetchName<false>(cx, env, pobj, name, shape, vp); + return FetchName<false>(cx, env, pobj, name, prop, vp); } static bool @@ -1613,11 +1613,7 @@ GetSuperEnvFunction(JSContext* cx, InterpreterRegs& regs) */ template<typename T> -class ReservedRootedBase { -}; - -template<typename T> -class ReservedRooted : public ReservedRootedBase<T> +class ReservedRooted : public RootedBase<T, ReservedRooted<T>> { Rooted<T>* savedRoot; @@ -1645,14 +1641,6 @@ class ReservedRooted : public ReservedRootedBase<T> DECLARE_POINTER_ASSIGN_OPS(ReservedRooted, T) }; -template <> -class ReservedRootedBase<Value> : public ValueOperations<ReservedRooted<Value>> -{}; - -template <> -class ReservedRootedBase<Scope*> : public ScopeCastOperation<ReservedRooted<Scope*>> -{}; - static MOZ_NEVER_INLINE bool Interpret(JSContext* cx, RunState& state) { @@ -2128,6 +2116,16 @@ CASE(JSOP_IFNE) } END_CASE(JSOP_IFNE) +CASE(JSOP_COALESCE) +{ + MutableHandleValue res = REGS.stackHandleAt(-1); + bool cond = !res.isNullOrUndefined(); + if (cond) { + ADVANCE_AND_DISPATCH(GET_JUMP_OFFSET(REGS.pc)); + } +} +END_CASE(JSOP_COALESCE) + CASE(JSOP_OR) { bool cond = ToBoolean(REGS.stackHandleAt(-1)); @@ -4390,12 +4388,12 @@ bool js::GetEnvironmentName(JSContext* cx, HandleObject envChain, HandlePropertyName name, MutableHandleValue vp) { - RootedShape shape(cx); + Rooted<PropertyResult> prop(cx); RootedObject obj(cx), pobj(cx); - if (!LookupName(cx, name, envChain, &obj, &pobj, &shape)) + if (!LookupName(cx, name, envChain, &obj, &pobj, &prop)) return false; - if (!shape) + if (!prop) return ReportIsNotDefined(cx, name); if (!GetProperty(cx, obj, obj, name, vp)) @@ -4417,12 +4415,12 @@ bool js::GetEnvironmentNameForTypeOf(JSContext* cx, HandleObject envChain, HandlePropertyName name, MutableHandleValue vp) { - RootedShape shape(cx); + Rooted<PropertyResult> prop(cx); RootedObject obj(cx), pobj(cx); - if (!LookupName(cx, name, envChain, &obj, &pobj, &shape)) + if (!LookupName(cx, name, envChain, &obj, &pobj, &prop)) return false; - if (!shape) { + if (!prop) { vp.set(UndefinedValue()); return true; } @@ -4480,9 +4478,9 @@ js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain, /* ES5 10.5 (NB: with subsequent errata). */ RootedPropertyName name(cx, fun->explicitName()->asPropertyName()); - RootedShape shape(cx); + Rooted<PropertyResult> prop(cx); RootedObject pobj(cx); - if (!LookupProperty(cx, parent, name, &pobj, &shape)) + if (!LookupProperty(cx, parent, name, &pobj, &prop)) return false; RootedValue rval(cx, ObjectValue(*fun)); @@ -4496,7 +4494,7 @@ js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain, : JSPROP_ENUMERATE | JSPROP_PERMANENT; /* Steps 5d, 5f. */ - if (!shape || pobj != parent) { + if (!prop || pobj != parent) { if (!DefineProperty(cx, parent, name, rval, nullptr, nullptr, attrs)) return false; @@ -4514,6 +4512,7 @@ js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain, */ MOZ_ASSERT(parent->isNative() || parent->is<DebugEnvironmentProxy>()); if (parent->is<GlobalObject>()) { + Shape* shape = prop.shape(); if (shape->configurable()) { if (!DefineProperty(cx, parent, name, rval, nullptr, nullptr, attrs)) return false; @@ -4718,8 +4717,8 @@ js::DeleteNameOperation(JSContext* cx, HandlePropertyName name, HandleObject sco MutableHandleValue res) { RootedObject scope(cx), pobj(cx); - RootedShape shape(cx); - if (!LookupName(cx, name, scopeObj, &scope, &pobj, &shape)) + Rooted<PropertyResult> prop(cx); + if (!LookupName(cx, name, scopeObj, &scope, &pobj, &prop)) return false; if (!scope) { diff --git a/js/src/vm/JSONParser.h b/js/src/vm/JSONParser.h index 6f91391db..70ed86f58 100644 --- a/js/src/vm/JSONParser.h +++ b/js/src/vm/JSONParser.h @@ -255,10 +255,13 @@ class MOZ_STACK_CLASS JSONParser : public JSONParserBase void operator=(const JSONParser& other) = delete; }; -template <typename CharT> -struct RootedBase<JSONParser<CharT>> { +template <typename CharT, typename Wrapper> +class MutableWrappedPtrOperations<JSONParser<CharT>, Wrapper> + : public WrappedPtrOperations<JSONParser<CharT>, Wrapper> +{ + public: bool parse(MutableHandleValue vp) { - return static_cast<Rooted<JSONParser<CharT>>*>(this)->get().parse(vp); + return static_cast<Wrapper*>(this)->get().parse(vp); } }; diff --git a/js/src/vm/NativeObject-inl.h b/js/src/vm/NativeObject-inl.h index 2bb70b7d9..004b308f0 100644 --- a/js/src/vm/NativeObject-inl.h +++ b/js/src/vm/NativeObject-inl.h @@ -290,7 +290,7 @@ NativeObject::setSlotWithType(ExclusiveContext* cx, Shape* shape, inline void NativeObject::updateShapeAfterMovingGC() { - Shape* shape = shape_.unbarrieredGet(); + Shape* shape = shape_; if (IsForwarded(shape)) shape_.unsafeSet(Forwarded(shape)); } @@ -382,8 +382,8 @@ NewNativeObjectWithClassProto(ExclusiveContext* cx, const Class* clasp, HandleOb * *recursedp = false and return true. */ static MOZ_ALWAYS_INLINE bool -CallResolveOp(JSContext* cx, HandleNativeObject obj, HandleId id, MutableHandleShape propp, - bool* recursedp) +CallResolveOp(JSContext* cx, HandleNativeObject obj, HandleId id, + MutableHandle<PropertyResult> propp, bool* recursedp) { // Avoid recursion on (obj, id) already being resolved on cx. AutoResolving resolving(cx, obj, id); @@ -407,13 +407,18 @@ CallResolveOp(JSContext* cx, HandleNativeObject obj, HandleId id, MutableHandleS obj->getClass()->getMayResolve()(cx->names(), id, obj)); if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) { - MarkDenseOrTypedArrayElementFound<CanGC>(propp); + propp.setDenseOrTypedArrayElement(); return true; } MOZ_ASSERT(!obj->is<TypedArrayObject>()); - propp.set(obj->lookup(cx, id)); + RootedShape shape(cx, obj->lookup(cx, id)); + if (shape) + propp.setNativeProperty(shape); + else + propp.setNotFound(); + return true; } @@ -444,12 +449,12 @@ static MOZ_ALWAYS_INLINE bool LookupOwnPropertyInline(ExclusiveContext* cx, typename MaybeRooted<NativeObject*, allowGC>::HandleType obj, typename MaybeRooted<jsid, allowGC>::HandleType id, - typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp, + typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp, bool* donep) { // Check for a native dense element. if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) { - MarkDenseOrTypedArrayElementFound<allowGC>(propp); + propp.setDenseOrTypedArrayElement(); *donep = true; return true; } @@ -460,11 +465,10 @@ LookupOwnPropertyInline(ExclusiveContext* cx, if (obj->template is<TypedArrayObject>()) { uint64_t index; if (IsTypedArrayIndex(id, &index)) { - if (index < obj->template as<TypedArrayObject>().length()) { - MarkDenseOrTypedArrayElementFound<allowGC>(propp); - } else { - propp.set(nullptr); - } + if (index < obj->template as<TypedArrayObject>().length()) + propp.setDenseOrTypedArrayElement(); + else + propp.setNotFound(); *donep = true; return true; } @@ -472,7 +476,7 @@ LookupOwnPropertyInline(ExclusiveContext* cx, // Check for a native property. if (Shape* shape = obj->lookup(cx, id)) { - propp.set(shape); + propp.setNativeProperty(shape); *donep = true; return true; } @@ -486,14 +490,14 @@ LookupOwnPropertyInline(ExclusiveContext* cx, if (!CallResolveOp(cx->asJSContext(), MaybeRooted<NativeObject*, allowGC>::toHandle(obj), MaybeRooted<jsid, allowGC>::toHandle(id), - MaybeRooted<Shape*, allowGC>::toMutableHandle(propp), + MaybeRooted<PropertyResult, allowGC>::toMutableHandle(propp), &recursed)) { return false; } if (recursed) { - propp.set(nullptr); + propp.setNotFound(); *donep = true; return true; } @@ -504,7 +508,7 @@ LookupOwnPropertyInline(ExclusiveContext* cx, } } - propp.set(nullptr); + propp.setNotFound(); *donep = false; return true; } @@ -515,11 +519,11 @@ LookupOwnPropertyInline(ExclusiveContext* cx, */ static inline void NativeLookupOwnPropertyNoResolve(ExclusiveContext* cx, HandleNativeObject obj, HandleId id, - MutableHandleShape result) + MutableHandle<PropertyResult> result) { // Check for a native dense element. if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) { - MarkDenseOrTypedArrayElementFound<CanGC>(result); + result.setDenseOrTypedArrayElement(); return; } @@ -528,15 +532,18 @@ NativeLookupOwnPropertyNoResolve(ExclusiveContext* cx, HandleNativeObject obj, H uint64_t index; if (IsTypedArrayIndex(id, &index)) { if (index < obj->as<TypedArrayObject>().length()) - MarkDenseOrTypedArrayElementFound<CanGC>(result); + result.setDenseOrTypedArrayElement(); else - result.set(nullptr); + result.setNotFound(); return; } } // Check for a native property. - result.set(obj->lookup(cx, id)); + if (Shape* shape = obj->lookup(cx, id)) + result.setNativeProperty(shape); + else + result.setNotFound(); } template <AllowGC allowGC> @@ -545,7 +552,7 @@ LookupPropertyInline(ExclusiveContext* cx, typename MaybeRooted<NativeObject*, allowGC>::HandleType obj, typename MaybeRooted<jsid, allowGC>::HandleType id, typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp, - typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp) + typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp) { /* NB: The logic of this procedure is implicitly reflected in * BaselineIC.cpp's |EffectlesslyLookupProperty| logic. @@ -578,14 +585,14 @@ LookupPropertyInline(ExclusiveContext* cx, MaybeRooted<JSObject*, allowGC>::toHandle(proto), MaybeRooted<jsid, allowGC>::toHandle(id), MaybeRooted<JSObject*, allowGC>::toMutableHandle(objp), - MaybeRooted<Shape*, allowGC>::toMutableHandle(propp)); + MaybeRooted<PropertyResult, allowGC>::toMutableHandle(propp)); } current = &proto->template as<NativeObject>(); } objp.set(nullptr); - propp.set(nullptr); + propp.setNotFound(); return true; } diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp index 3625d86f5..53f7c0bfa 100644 --- a/js/src/vm/NativeObject.cpp +++ b/js/src/vm/NativeObject.cpp @@ -1044,7 +1044,7 @@ bool js::NativeLookupOwnProperty(ExclusiveContext* cx, typename MaybeRooted<NativeObject*, allowGC>::HandleType obj, typename MaybeRooted<jsid, allowGC>::HandleType id, - typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp) + typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp) { bool done; return LookupOwnPropertyInline<allowGC>(cx, obj, id, propp, &done); @@ -1052,11 +1052,11 @@ js::NativeLookupOwnProperty(ExclusiveContext* cx, template bool js::NativeLookupOwnProperty<CanGC>(ExclusiveContext* cx, HandleNativeObject obj, HandleId id, - MutableHandleShape propp); + MutableHandle<PropertyResult> propp); template bool js::NativeLookupOwnProperty<NoGC>(ExclusiveContext* cx, NativeObject* const& obj, const jsid& id, - FakeMutableHandle<Shape*> propp); + FakeMutableHandle<PropertyResult> propp); /*** [[DefineOwnProperty]] ***********************************************************************/ @@ -1279,19 +1279,20 @@ GetExistingProperty(JSContext* cx, static bool GetExistingPropertyValue(ExclusiveContext* cx, HandleNativeObject obj, HandleId id, - HandleShape shape, MutableHandleValue vp) + Handle<PropertyResult> prop, MutableHandleValue vp) { - if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (prop.isDenseOrTypedArrayElement()) { vp.set(obj->getDenseOrTypedArrayElement(JSID_TO_INT(id))); return true; } if (!cx->shouldBeJSContext()) return false; - MOZ_ASSERT(shape->propid() == id); - MOZ_ASSERT(obj->contains(cx, shape)); + MOZ_ASSERT(prop.shape()->propid() == id); + MOZ_ASSERT(obj->contains(cx, prop.shape())); RootedValue receiver(cx, ObjectValue(*obj)); + RootedShape shape(cx, prop.shape()); return GetExistingProperty<CanGC>(cx->asJSContext(), receiver, obj, shape, vp); } @@ -1302,7 +1303,7 @@ GetExistingPropertyValue(ExclusiveContext* cx, HandleNativeObject obj, HandleId */ static bool DefinePropertyIsRedundant(ExclusiveContext* cx, HandleNativeObject obj, HandleId id, - HandleShape shape, unsigned shapeAttrs, + Handle<PropertyResult> prop, unsigned shapeAttrs, Handle<PropertyDescriptor> desc, bool *redundant) { *redundant = false; @@ -1319,16 +1320,16 @@ DefinePropertyIsRedundant(ExclusiveContext* cx, HandleNativeObject obj, HandleId if (desc.hasValue()) { // Get the current value of the existing property. RootedValue currentValue(cx); - if (!IsImplicitDenseOrTypedArrayElement(shape) && - shape->hasSlot() && - shape->hasDefaultGetter()) + if (!prop.isDenseOrTypedArrayElement() && + prop.shape()->hasSlot() && + prop.shape()->hasDefaultGetter()) { // Inline GetExistingPropertyValue in order to omit a type // correctness assertion that's too strict for this particular // call site. For details, see bug 1125624 comments 13-16. - currentValue.set(obj->getSlot(shape->slot())); + currentValue.set(obj->getSlot(prop.shape()->slot())); } else { - if (!GetExistingPropertyValue(cx, obj, id, shape, ¤tValue)) + if (!GetExistingPropertyValue(cx, obj, id, prop, ¤tValue)) return false; } @@ -1339,22 +1340,24 @@ DefinePropertyIsRedundant(ExclusiveContext* cx, HandleNativeObject obj, HandleId } GetterOp existingGetterOp = - IsImplicitDenseOrTypedArrayElement(shape) ? nullptr : shape->getter(); + prop.isDenseOrTypedArrayElement() ? nullptr : prop.shape()->getter(); if (desc.getter() != existingGetterOp) return true; SetterOp existingSetterOp = - IsImplicitDenseOrTypedArrayElement(shape) ? nullptr : shape->setter(); + prop.isDenseOrTypedArrayElement() ? nullptr : prop.shape()->setter(); if (desc.setter() != existingSetterOp) return true; } else { - if (desc.hasGetterObject()) { - if (!(shapeAttrs & JSPROP_GETTER) || desc.getterObject() != shape->getterObject()) - return true; + if (desc.hasGetterObject() && + (!(shapeAttrs & JSPROP_GETTER) || desc.getterObject() != prop.shape()->getterObject())) + { + return true; } - if (desc.hasSetterObject()) { - if (!(shapeAttrs & JSPROP_SETTER) || desc.setterObject() != shape->setterObject()) - return true; + if (desc.hasSetterObject() && + (!(shapeAttrs & JSPROP_SETTER) || desc.setterObject() != prop.shape()->setterObject())) + { + return true; } } @@ -1421,14 +1424,14 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId } // 9.1.6.1 OrdinaryDefineOwnProperty steps 1-2. - RootedShape shape(cx); + Rooted<PropertyResult> prop(cx); if (desc_.attributes() & JSPROP_RESOLVING) { // We are being called from a resolve or enumerate hook to reify a // lazily-resolved property. To avoid reentering the resolve hook and // recursing forever, skip the resolve hook when doing this lookup. - NativeLookupOwnPropertyNoResolve(cx, obj, id, &shape); + NativeLookupOwnPropertyNoResolve(cx, obj, id, &prop); } else { - if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape)) + if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &prop)) return false; } @@ -1443,7 +1446,7 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId Rooted<PropertyDescriptor> desc(cx, desc_); // Step 2. - if (!shape) { + if (!prop) { if (!obj->nonProxyIsExtensible()) return result.fail(JSMSG_CANT_DEFINE_PROP_OBJECT_NOT_EXTENSIBLE); @@ -1455,21 +1458,20 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId return result.succeed(); } - MOZ_ASSERT(shape); - // Steps 3-4. (Step 3 is a special case of step 4.) We use shapeAttrs as a // stand-in for shape in many places below, since shape might not be a // pointer to a real Shape (see IsImplicitDenseOrTypedArrayElement). - unsigned shapeAttrs = GetShapeAttributes(obj, shape); + unsigned shapeAttrs = GetPropertyAttributes(obj, prop); bool redundant; - if (!DefinePropertyIsRedundant(cx, obj, id, shape, shapeAttrs, desc, &redundant)) + if (!DefinePropertyIsRedundant(cx, obj, id, prop, shapeAttrs, desc, &redundant)) return false; if (redundant) { // In cases involving JSOP_NEWOBJECT and JSOP_INITPROP, obj can have a // type for this property that doesn't match the value in the slot. // Update the type here, even though this DefineProperty call is // otherwise a no-op. (See bug 1125624 comment 13.) - if (!IsImplicitDenseOrTypedArrayElement(shape) && desc.hasValue()) { + if (!prop.isDenseOrTypedArrayElement() && desc.hasValue()) { + RootedShape shape(cx, prop.shape()); if (!UpdateShapeTypeAndValue(cx, obj, shape, desc.value())) return false; } @@ -1512,24 +1514,24 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId MOZ_ASSERT(!desc.hasSetterObject()); if (IsDataDescriptor(shapeAttrs)) { RootedValue currentValue(cx); - if (!GetExistingPropertyValue(cx, obj, id, shape, ¤tValue)) + if (!GetExistingPropertyValue(cx, obj, id, prop, ¤tValue)) return false; desc.setValue(currentValue); desc.setWritable(IsWritable(shapeAttrs)); } else { - desc.setGetterObject(shape->getterObject()); - desc.setSetterObject(shape->setterObject()); + desc.setGetterObject(prop.shape()->getterObject()); + desc.setSetterObject(prop.shape()->setterObject()); } } else if (desc.isDataDescriptor() != IsDataDescriptor(shapeAttrs)) { // Step 7. if (!IsConfigurable(shapeAttrs) && !skipRedefineChecks) return result.fail(JSMSG_CANT_REDEFINE_PROP); - if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (prop.isDenseOrTypedArrayElement()) { MOZ_ASSERT(!obj->is<TypedArrayObject>()); if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id))) return false; - shape = obj->lookup(cx, id); + prop.setNativeProperty(obj->lookup(cx, id)); } // Fill in desc fields with default values (steps 7.b.i and 7.c.i). @@ -1541,15 +1543,15 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId return result.fail(JSMSG_CANT_REDEFINE_PROP); if (frozen || !desc.hasValue()) { - if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (prop.isDenseOrTypedArrayElement()) { MOZ_ASSERT(!obj->is<TypedArrayObject>()); if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id))) return false; - shape = obj->lookup(cx, id); + prop.setNativeProperty(obj->lookup(cx, id)); } RootedValue currentValue(cx); - if (!GetExistingPropertyValue(cx, obj, id, shape, ¤tValue)) + if (!GetExistingPropertyValue(cx, obj, id, prop, ¤tValue)) return false; if (!desc.hasValue()) { @@ -1571,32 +1573,32 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId desc.setWritable(IsWritable(shapeAttrs)); } else { // Step 9. - MOZ_ASSERT(shape->isAccessorDescriptor()); + MOZ_ASSERT(prop.shape()->isAccessorDescriptor()); MOZ_ASSERT(desc.isAccessorDescriptor()); // The spec says to use SameValue, but since the values in // question are objects, we can just compare pointers. if (desc.hasSetterObject()) { if (!IsConfigurable(shapeAttrs) && - desc.setterObject() != shape->setterObject() && + desc.setterObject() != prop.shape()->setterObject() && !skipRedefineChecks) { return result.fail(JSMSG_CANT_REDEFINE_PROP); } } else { // Fill in desc.[[Set]] from shape. - desc.setSetterObject(shape->setterObject()); + desc.setSetterObject(prop.shape()->setterObject()); } if (desc.hasGetterObject()) { if (!IsConfigurable(shapeAttrs) && - desc.getterObject() != shape->getterObject() && + desc.getterObject() != prop.shape()->getterObject() && !skipRedefineChecks) { return result.fail(JSMSG_CANT_REDEFINE_PROP); } } else { // Fill in desc.[[Get]] from shape. - desc.setGetterObject(shape->getterObject()); + desc.setGetterObject(prop.shape()->getterObject()); } } @@ -1681,18 +1683,18 @@ bool js::NativeHasProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool* foundp) { RootedNativeObject pobj(cx, obj); - RootedShape shape(cx); + Rooted<PropertyResult> prop(cx); // This loop isn't explicit in the spec algorithm. See the comment on step // 7.a. below. for (;;) { // Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.) bool done; - if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &shape, &done)) + if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &prop, &done)) return false; // Step 4. - if (shape) { + if (prop) { *foundp = true; return true; } @@ -1733,15 +1735,15 @@ bool js::NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, HandleId id, MutableHandle<PropertyDescriptor> desc) { - RootedShape shape(cx); - if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape)) + Rooted<PropertyResult> prop(cx); + if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &prop)) return false; - if (!shape) { + if (!prop) { desc.object().set(nullptr); return true; } - desc.setAttributes(GetShapeAttributes(obj, shape)); + desc.setAttributes(GetPropertyAttributes(obj, prop)); if (desc.isAccessorDescriptor()) { MOZ_ASSERT(desc.isShared()); @@ -1754,13 +1756,13 @@ js::NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, Handle // than return true with desc incomplete, we fill out the missing // getter or setter with a null, following CompletePropertyDescriptor. if (desc.hasGetterObject()) { - desc.setGetterObject(shape->getterObject()); + desc.setGetterObject(prop.shape()->getterObject()); } else { desc.setGetterObject(nullptr); desc.attributesRef() |= JSPROP_GETTER; } if (desc.hasSetterObject()) { - desc.setSetterObject(shape->setterObject()); + desc.setSetterObject(prop.shape()->setterObject()); } else { desc.setSetterObject(nullptr); desc.attributesRef() |= JSPROP_SETTER; @@ -1776,9 +1778,10 @@ js::NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, Handle desc.setSetter(nullptr); desc.attributesRef() &= ~JSPROP_SHARED; - if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (prop.isDenseOrTypedArrayElement()) { desc.value().set(obj->getDenseOrTypedArrayElement(JSID_TO_INT(id))); } else { + RootedShape shape(cx, prop.shape()); if (!NativeGetExistingProperty(cx, obj, obj, shape, desc.value())) return false; } @@ -2058,23 +2061,25 @@ NativeGetPropertyInline(JSContext* cx, typename MaybeRooted<Value, allowGC>::MutableHandleType vp) { typename MaybeRooted<NativeObject*, allowGC>::RootType pobj(cx, obj); - typename MaybeRooted<Shape*, allowGC>::RootType shape(cx); + typename MaybeRooted<PropertyResult, allowGC>::RootType prop(cx); // This loop isn't explicit in the spec algorithm. See the comment on step // 4.d below. for (;;) { // Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.) bool done; - if (!LookupOwnPropertyInline<allowGC>(cx, pobj, id, &shape, &done)) + if (!LookupOwnPropertyInline<allowGC>(cx, pobj, id, &prop, &done)) return false; - if (shape) { + if (prop) { // Steps 5-8. Special case for dense elements because // GetExistingProperty doesn't support those. - if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (prop.isDenseOrTypedArrayElement()) { vp.set(pobj->getDenseOrTypedArrayElement(JSID_TO_INT(id))); return true; } + + typename MaybeRooted<Shape*, allowGC>::RootType shape(cx, prop.shape()); return GetExistingProperty<allowGC>(cx, receiver, pobj, shape, vp); } @@ -2366,11 +2371,11 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde */ static bool SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue v, - HandleValue receiver, HandleNativeObject pobj, HandleShape shape, + HandleValue receiver, HandleNativeObject pobj, Handle<PropertyResult> prop, ObjectOpResult& result) { // Step 5 for dense elements. - if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (prop.isDenseOrTypedArrayElement()) { // Step 5.a. if (pobj->getElementsHeader()->isFrozen()) return result.fail(JSMSG_READ_ONLY); @@ -2384,6 +2389,7 @@ SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleVa } // Step 5 for all other properties. + RootedShape shape(cx, prop.shape()); if (shape->isDataDescriptor()) { // Step 5.a. if (!shape->writable()) @@ -2441,7 +2447,7 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle // Step numbers below reference ES6 rev 27 9.1.9, the [[Set]] internal // method for ordinary objects. We substitute our own names for these names // used in the spec: O -> pobj, P -> id, ownDesc -> shape. - RootedShape shape(cx); + Rooted<PropertyResult> prop(cx); RootedNativeObject pobj(cx, obj); // This loop isn't explicit in the spec algorithm. See the comment on step @@ -2450,12 +2456,12 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle for (;;) { // Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.) bool done; - if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &shape, &done)) + if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &prop, &done)) return false; - if (shape) { + if (prop) { // Steps 5-6. - return SetExistingProperty(cx, obj, id, v, receiver, pobj, shape, result); + return SetExistingProperty(cx, obj, id, v, receiver, pobj, prop, result); } // Steps 4.a-b. The check for 'done' on this next line is tricky. @@ -2513,12 +2519,12 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id, ObjectOpResult& result) { // Steps 2-3. - RootedShape shape(cx); - if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape)) + Rooted<PropertyResult> prop(cx); + if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &prop)) return false; // Step 4. - if (!shape) { + if (!prop) { // If no property call the class's delProperty hook, passing succeeded // as the result parameter. This always succeeds when there is no hook. return CallJSDeletePropertyOp(cx, obj->getClass()->getDelProperty(), obj, id, result); @@ -2527,7 +2533,7 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id, cx->runtime()->gc.poke(); // Step 6. Non-configurable property. - if (GetShapeAttributes(obj, shape) & JSPROP_PERMANENT) + if (GetPropertyAttributes(obj, prop) & JSPROP_PERMANENT) return result.failCantDelete(); if (!CallJSDeletePropertyOp(cx, obj->getClass()->getDelProperty(), obj, id, result)) @@ -2536,7 +2542,7 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id, return true; // Step 5. - if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (prop.isDenseOrTypedArrayElement()) { // Typed array elements are non-configurable. MOZ_ASSERT(!obj->is<TypedArrayObject>()); diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h index 657fc8d57..abc84c9fd 100644 --- a/js/src/vm/NativeObject.h +++ b/js/src/vm/NativeObject.h @@ -1459,7 +1459,7 @@ extern bool NativeLookupOwnProperty(ExclusiveContext* cx, typename MaybeRooted<NativeObject*, allowGC>::HandleType obj, typename MaybeRooted<jsid, allowGC>::HandleType id, - typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp); + typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp); /* * Get a property from `receiver`, after having already done a lookup and found diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp index f2a3305cf..741531f01 100644 --- a/js/src/vm/ObjectGroup.cpp +++ b/js/src/vm/ObjectGroup.cpp @@ -421,7 +421,7 @@ struct ObjectGroupCompartment::NewEntry } static inline bool match(const ObjectGroupCompartment::NewEntry& key, const Lookup& lookup) { - TaggedProto proto = key.group.unbarrieredGet()->proto().unbarrieredGet(); + TaggedProto proto = key.group.unbarrieredGet()->proto(); JSObject* assoc = key.associated; MOZ_ASSERT(proto.hasUniqueId()); MOZ_ASSERT_IF(assoc, assoc->zone()->hasUniqueId(assoc)); diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index 58b5d7577..8328dfc99 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -2315,7 +2315,7 @@ * Operands: * Stack: => */ \ - macro(JSOP_JUMPTARGET, 230, "jumptarget", NULL, 1, 0, 0, JOF_BYTE)\ + macro(JSOP_JUMPTARGET, 230, "jumptarget", NULL, 1, 0, 0, JOF_BYTE) \ /* * Like JSOP_CALL, but tells the function that the return value is ignored. * stack. @@ -2325,14 +2325,22 @@ * Stack: callee, this, args[0], ..., args[argc-1] => rval * nuses: (argc+2) */ \ - macro(JSOP_CALL_IGNORES_RV, 231, "call-ignores-rv", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) - + macro(JSOP_CALL_IGNORES_RV, 231, "call-ignores-rv", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \ + /* + * If the value on top of the stack is not null or undefined, jumps to a 32-bit offset from the + * current bytecode. + * + * Category: Statements + * Type: Jumps + * Operands: int32_t offset + * Stack: cond => cond + */ \ + macro(JSOP_COALESCE, 232, "coalesce", NULL, 5, 1, 1, JOF_JUMP|JOF_DETECTING) /* * In certain circumstances it may be useful to "pad out" the opcode space to * a power of two. Use this macro to do so. */ #define FOR_EACH_TRAILING_UNUSED_OPCODE(macro) \ - macro(232) \ macro(233) \ macro(234) \ macro(235) \ diff --git a/js/src/vm/SavedStacks.h b/js/src/vm/SavedStacks.h index c6bda2831..3ea6c4087 100644 --- a/js/src/vm/SavedStacks.h +++ b/js/src/vm/SavedStacks.h @@ -265,24 +265,6 @@ class SavedStacks { uint32_t column; }; - template <typename Outer> - struct LocationValueOperations { - JSAtom* source() const { return loc().source; } - size_t line() const { return loc().line; } - uint32_t column() const { return loc().column; } - private: - const LocationValue& loc() const { return static_cast<const Outer*>(this)->get(); } - }; - - template <typename Outer> - struct MutableLocationValueOperations : public LocationValueOperations<Outer> { - void setSource(JSAtom* v) { loc().source = v; } - void setLine(size_t v) { loc().line = v; } - void setColumn(uint32_t v) { loc().column = v; } - private: - LocationValue& loc() { return static_cast<Outer*>(this)->get(); } - }; - private: struct PCLocationHasher : public DefaultHasher<PCKey> { using ScriptPtrHasher = DefaultHasher<JSScript*>; @@ -313,15 +295,32 @@ class SavedStacks { MutableHandle<LocationValue> locationp); }; -template <> -class RootedBase<SavedStacks::LocationValue> - : public SavedStacks::MutableLocationValueOperations<JS::Rooted<SavedStacks::LocationValue>> -{}; +template <typename Wrapper> +struct WrappedPtrOperations<SavedStacks::LocationValue, Wrapper> +{ + JSAtom* source() const { return loc().source; } + size_t line() const { return loc().line; } + uint32_t column() const { return loc().column; } + + private: + const SavedStacks::LocationValue& loc() const { + return static_cast<const Wrapper*>(this)->get(); + } +}; + +template <typename Wrapper> +struct MutableWrappedPtrOperations<SavedStacks::LocationValue, Wrapper> + : public WrappedPtrOperations<SavedStacks::LocationValue, Wrapper> +{ + void setSource(JSAtom* v) { loc().source = v; } + void setLine(size_t v) { loc().line = v; } + void setColumn(uint32_t v) { loc().column = v; } -template <> -class MutableHandleBase<SavedStacks::LocationValue> - : public SavedStacks::MutableLocationValueOperations<JS::MutableHandle<SavedStacks::LocationValue>> -{}; + private: + SavedStacks::LocationValue& loc() { + return static_cast<Wrapper*>(this)->get(); + } +}; UTF8CharsZ BuildUTF8StackString(JSContext* cx, HandleObject stack); diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h index 4f0edcc13..fc1419bb8 100644 --- a/js/src/vm/Scope.h +++ b/js/src/vm/Scope.h @@ -22,6 +22,7 @@ namespace js { class ModuleObject; +class Scope; enum class BindingKind : uint8_t { @@ -224,6 +225,21 @@ class BindingLocation }; // +// Allow using is<T> and as<T> on Rooted<Scope*> and Handle<Scope*>. +// +template <typename Wrapper> +class WrappedPtrOperations<Scope*, Wrapper> +{ + public: + template <class U> + JS::Handle<U*> as() const { + const Wrapper& self = *static_cast<const Wrapper*>(this); + MOZ_ASSERT_IF(self, self->template is<U>()); + return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address())); + } +}; + +// // The base class of all Scopes. // class Scope : public js::gc::TenuredCell @@ -1338,10 +1354,10 @@ class MOZ_STACK_CLASS ScopeIter // Specializations of Rooted containers for the iterators. // -template <typename Outer> -class BindingIterOperations +template <typename Wrapper> +class WrappedPtrOperations<BindingIter, Wrapper> { - const BindingIter& iter() const { return static_cast<const Outer*>(this)->get(); } + const BindingIter& iter() const { return static_cast<const Wrapper*>(this)->get(); } public: bool done() const { return iter().done(); } @@ -1361,19 +1377,20 @@ class BindingIterOperations uint32_t nextEnvironmentSlot() const { return iter().nextEnvironmentSlot(); } }; -template <typename Outer> -class MutableBindingIterOperations : public BindingIterOperations<Outer> +template <typename Wrapper> +class MutableWrappedPtrOperations<BindingIter, Wrapper> + : public WrappedPtrOperations<BindingIter, Wrapper> { - BindingIter& iter() { return static_cast<Outer*>(this)->get(); } + BindingIter& iter() { return static_cast<Wrapper*>(this)->get(); } public: void operator++(int) { iter().operator++(1); } }; -template <typename Outer> -class ScopeIterOperations +template <typename Wrapper> +class WrappedPtrOperations<ScopeIter, Wrapper> { - const ScopeIter& iter() const { return static_cast<const Outer*>(this)->get(); } + const ScopeIter& iter() const { return static_cast<const Wrapper*>(this)->get(); } public: bool done() const { return iter().done(); } @@ -1384,69 +1401,16 @@ class ScopeIterOperations bool hasSyntacticEnvironment() const { return iter().hasSyntacticEnvironment(); } }; -template <typename Outer> -class MutableScopeIterOperations : public ScopeIterOperations<Outer> +template <typename Wrapper> +class MutableWrappedPtrOperations<ScopeIter, Wrapper> + : public WrappedPtrOperations<ScopeIter, Wrapper> { - ScopeIter& iter() { return static_cast<Outer*>(this)->get(); } + ScopeIter& iter() { return static_cast<Wrapper*>(this)->get(); } public: void operator++(int) { iter().operator++(1); } }; -#define SPECIALIZE_ROOTING_CONTAINERS(Iter, BaseIter) \ - template <> \ - class RootedBase<Iter> \ - : public Mutable##BaseIter##Operations<JS::Rooted<Iter>> \ - { }; \ - \ - template <> \ - class MutableHandleBase<Iter> \ - : public Mutable##BaseIter##Operations<JS::MutableHandle<Iter>> \ - { }; \ - \ - template <> \ - class HandleBase<Iter> \ - : public BaseIter##Operations<JS::Handle<Iter>> \ - { }; \ - \ - template <> \ - class PersistentRootedBase<Iter> \ - : public Mutable##BaseIter##Operations<JS::PersistentRooted<Iter>> \ - { } - -SPECIALIZE_ROOTING_CONTAINERS(BindingIter, BindingIter); -SPECIALIZE_ROOTING_CONTAINERS(PositionalFormalParameterIter, BindingIter); -SPECIALIZE_ROOTING_CONTAINERS(ScopeIter, ScopeIter); - -#undef SPECIALIZE_ROOTING_CONTAINERS - -// -// Allow using is<T> and as<T> on Rooted<Scope*> and Handle<Scope*>. -// - -template <typename Outer> -struct ScopeCastOperation -{ - template <class U> - JS::Handle<U*> as() const { - const Outer& self = *static_cast<const Outer*>(this); - MOZ_ASSERT_IF(self, self->template is<U>()); - return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address())); - } -}; - -template <> -class RootedBase<Scope*> : public ScopeCastOperation<JS::Rooted<Scope*>> -{ }; - -template <> -class HandleBase<Scope*> : public ScopeCastOperation<JS::Handle<Scope*>> -{ }; - -template <> -class MutableHandleBase<Scope*> : public ScopeCastOperation<JS::MutableHandle<Scope*>> -{ }; - } // namespace js namespace JS { diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h index 32754740a..7b7561220 100644 --- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -123,7 +123,7 @@ Shape::new_(ExclusiveContext* cx, Handle<StackShape> other, uint32_t nfixed) inline void Shape::updateBaseShapeAfterMovingGC() { - BaseShape* base = base_.unbarrieredGet(); + BaseShape* base = base_; if (IsForwarded(base)) base_.unsafeSet(Forwarded(base)); } @@ -191,17 +191,17 @@ AutoRooterGetterSetter::AutoRooterGetterSetter(ExclusiveContext* cx, uint8_t att } static inline uint8_t -GetShapeAttributes(JSObject* obj, Shape* shape) +GetPropertyAttributes(JSObject* obj, PropertyResult prop) { MOZ_ASSERT(obj->isNative()); - if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (prop.isDenseOrTypedArrayElement()) { if (obj->is<TypedArrayObject>()) return JSPROP_ENUMERATE | JSPROP_PERMANENT; return obj->as<NativeObject>().getElementsHeader()->elementAttributes(); } - return shape->attributes(); + return prop.shape()->attributes(); } } /* namespace js */ diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 7cdf382ed..c71cef5a7 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1771,3 +1771,10 @@ JS::ubi::Concrete<js::BaseShape>::size(mozilla::MallocSizeOf mallocSizeOf) const { return js::gc::Arena::thingSize(get().asTenured().getAllocKind()); } + +void +PropertyResult::trace(JSTracer* trc) +{ + if (isNativeProperty()) + TraceRoot(trc, &shape_, "PropertyResult::shape_"); +} diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 52b9197da..bb813997f 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -1264,9 +1264,10 @@ struct InitialShapeEntry bool needsSweep() { Shape* ushape = shape.unbarrieredGet(); - JSObject* protoObj = proto.proto().raw(); + TaggedProto uproto = proto.proto().unbarrieredGet(); + JSObject* protoObj = uproto.raw(); return (gc::IsAboutToBeFinalizedUnbarriered(&ushape) || - (proto.proto().isObject() && gc::IsAboutToBeFinalizedUnbarriered(&protoObj))); + (uproto.isObject() && gc::IsAboutToBeFinalizedUnbarriered(&protoObj))); } }; @@ -1356,9 +1357,10 @@ struct StackShape void trace(JSTracer* trc); }; -template <typename Outer> -class StackShapeOperations { - const StackShape& ss() const { return static_cast<const Outer*>(this)->get(); } +template <typename Wrapper> +class WrappedPtrOperations<StackShape, Wrapper> +{ + const StackShape& ss() const { return static_cast<const Wrapper*>(this)->get(); } public: bool hasSlot() const { return ss().hasSlot(); } @@ -1370,9 +1372,11 @@ class StackShapeOperations { uint8_t attrs() const { return ss().attrs; } }; -template <typename Outer> -class MutableStackShapeOperations : public StackShapeOperations<Outer> { - StackShape& ss() { return static_cast<Outer*>(this)->get(); } +template <typename Wrapper> +class MutableWrappedPtrOperations<StackShape, Wrapper> + : public WrappedPtrOperations<StackShape, Wrapper> +{ + StackShape& ss() { return static_cast<Wrapper*>(this)->get(); } public: void updateGetterSetter(GetterOp rawGetter, SetterOp rawSetter) { @@ -1383,19 +1387,6 @@ class MutableStackShapeOperations : public StackShapeOperations<Outer> { void setAttrs(uint8_t attrs) { ss().attrs = attrs; } }; -template <> -class RootedBase<StackShape> : public MutableStackShapeOperations<JS::Rooted<StackShape>> -{}; - -template <> -class HandleBase<StackShape> : public StackShapeOperations<JS::Handle<StackShape>> -{}; - -template <> -class MutableHandleBase<StackShape> - : public MutableStackShapeOperations<JS::MutableHandle<StackShape>> -{}; - inline Shape::Shape(const StackShape& other, uint32_t nfixed) : base_(other.base), @@ -1550,38 +1541,6 @@ Shape::matches(const StackShape& other) const other.rawGetter, other.rawSetter); } -// Property lookup hooks on objects are required to return a non-nullptr shape -// to signify that the property has been found. For cases where the property is -// not actually represented by a Shape, use a dummy value. This includes all -// properties of non-native objects, and dense elements for native objects. -// Use separate APIs for these two cases. - -template <AllowGC allowGC> -static inline void -MarkNonNativePropertyFound(typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp) -{ - propp.set(reinterpret_cast<Shape*>(1)); -} - -template <AllowGC allowGC> -static inline void -MarkDenseOrTypedArrayElementFound(typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp) -{ - propp.set(reinterpret_cast<Shape*>(1)); -} - -static inline bool -IsImplicitDenseOrTypedArrayElement(Shape* prop) -{ - return prop == reinterpret_cast<Shape*>(1); -} - -static inline bool -IsImplicitNonNativeProperty(Shape* prop) -{ - return prop == reinterpret_cast<Shape*>(1); -} - Shape* ReshapeForAllocKind(JSContext* cx, Shape* shape, TaggedProto proto, gc::AllocKind allocKind); diff --git a/js/src/vm/SharedMem.h b/js/src/vm/SharedMem.h index fe8dad304..8e5bae492 100644 --- a/js/src/vm/SharedMem.h +++ b/js/src/vm/SharedMem.h @@ -11,8 +11,8 @@ template<typename T> class SharedMem { - static_assert(mozilla::IsPointer<T>::value, - "SharedMem encapsulates pointer types"); + // static_assert(mozilla::IsPointer<T>::value, + // "SharedMem encapsulates pointer types"); enum Sharedness { IsUnshared, diff --git a/js/src/vm/String.h b/js/src/vm/String.h index 0937ac24d..4c43439cd 100644 --- a/js/src/vm/String.h +++ b/js/src/vm/String.h @@ -521,7 +521,7 @@ class JSString : public js::gc::TenuredCell } static MOZ_ALWAYS_INLINE void writeBarrierPre(JSString* thing) { - if (isNullLike(thing) || thing->isPermanentAtom()) + if (!thing || thing->isPermanentAtom()) return; TenuredCell::writeBarrierPre(thing); diff --git a/js/src/vm/TaggedProto.h b/js/src/vm/TaggedProto.h index de3e86a7f..10b8c1171 100644 --- a/js/src/vm/TaggedProto.h +++ b/js/src/vm/TaggedProto.h @@ -68,20 +68,16 @@ struct InternalBarrierMethods<TaggedProto> static void readBarrier(const TaggedProto& proto); - static bool isMarkableTaggedPointer(TaggedProto proto) { - return proto.isObject(); - } - static bool isMarkable(TaggedProto proto) { return proto.isObject(); } }; -template<class Outer> -class TaggedProtoOperations +template <class Wrapper> +class WrappedPtrOperations<TaggedProto, Wrapper> { const TaggedProto& value() const { - return static_cast<const Outer*>(this)->get(); + return static_cast<const Wrapper*>(this)->get(); } public: @@ -95,18 +91,6 @@ class TaggedProtoOperations uint64_t uniqueId() const { return value().uniqueId(); } }; -template <> -class HandleBase<TaggedProto> : public TaggedProtoOperations<Handle<TaggedProto>> -{}; - -template <> -class RootedBase<TaggedProto> : public TaggedProtoOperations<Rooted<TaggedProto>> -{}; - -template <> -class BarrieredBaseMixins<TaggedProto> : public TaggedProtoOperations<GCPtr<TaggedProto>> -{}; - // If the TaggedProto is a JSObject pointer, convert to that type and call |f| // with the pointer. If the TaggedProto is lazy, calls F::defaultValue. template <typename F, typename... Args> diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp index 4912e65db..a28f6a95a 100644 --- a/js/src/vm/UnboxedObject.cpp +++ b/js/src/vm/UnboxedObject.cpp @@ -720,10 +720,10 @@ UnboxedPlainObject::createWithProperties(ExclusiveContext* cx, HandleObjectGroup /* static */ bool UnboxedPlainObject::obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id, MutableHandleObject objp, - MutableHandleShape propp) + MutableHandle<PropertyResult> propp) { if (obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id)) { - MarkNonNativePropertyFound<CanGC>(propp); + propp.setNonNativeProperty(); objp.set(obj); return true; } @@ -731,7 +731,7 @@ UnboxedPlainObject::obj_lookupProperty(JSContext* cx, HandleObject obj, RootedObject proto(cx, obj->staticPrototype()); if (!proto) { objp.set(nullptr); - propp.set(nullptr); + propp.setNotFound(); return true; } @@ -1411,10 +1411,10 @@ UnboxedArrayObject::containsProperty(ExclusiveContext* cx, jsid id) /* static */ bool UnboxedArrayObject::obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id, MutableHandleObject objp, - MutableHandleShape propp) + MutableHandle<PropertyResult> propp) { if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) { - MarkNonNativePropertyFound<CanGC>(propp); + propp.setNonNativeProperty(); objp.set(obj); return true; } @@ -1422,7 +1422,7 @@ UnboxedArrayObject::obj_lookupProperty(JSContext* cx, HandleObject obj, RootedObject proto(cx, obj->staticPrototype()); if (!proto) { objp.set(nullptr); - propp.set(nullptr); + propp.setNotFound(); return true; } diff --git a/js/src/vm/UnboxedObject.h b/js/src/vm/UnboxedObject.h index 8622be8a7..6fc482ec7 100644 --- a/js/src/vm/UnboxedObject.h +++ b/js/src/vm/UnboxedObject.h @@ -242,7 +242,7 @@ class UnboxedPlainObject : public JSObject static bool obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id, MutableHandleObject objp, - MutableHandleShape propp); + MutableHandle<PropertyResult> propp); static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id, Handle<PropertyDescriptor> desc, @@ -378,7 +378,7 @@ class UnboxedArrayObject : public JSObject static bool obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id, MutableHandleObject objp, - MutableHandleShape propp); + MutableHandle<PropertyResult> propp); static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id, Handle<PropertyDescriptor> desc, |