summaryrefslogtreecommitdiff
path: root/js/src/vm
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm')
-rw-r--r--js/src/vm/ArrayBufferObject.cpp4
-rw-r--r--js/src/vm/ArrayBufferObject.h17
-rw-r--r--js/src/vm/Debugger.cpp8
-rw-r--r--js/src/vm/EnvironmentObject.cpp12
-rw-r--r--js/src/vm/EnvironmentObject.h2
-rw-r--r--js/src/vm/GeneratorObject.cpp10
-rw-r--r--js/src/vm/Interpreter-inl.h32
-rw-r--r--js/src/vm/Interpreter.cpp67
-rw-r--r--js/src/vm/JSONParser.h9
-rw-r--r--js/src/vm/NativeObject-inl.h55
-rw-r--r--js/src/vm/NativeObject.cpp142
-rw-r--r--js/src/vm/NativeObject.h2
-rw-r--r--js/src/vm/ObjectGroup.cpp2
-rw-r--r--js/src/vm/Opcodes.h16
-rw-r--r--js/src/vm/SavedStacks.h51
-rw-r--r--js/src/vm/Scope.h96
-rw-r--r--js/src/vm/Shape-inl.h8
-rw-r--r--js/src/vm/Shape.cpp7
-rw-r--r--js/src/vm/Shape.h65
-rw-r--r--js/src/vm/SharedMem.h4
-rw-r--r--js/src/vm/String.h2
-rw-r--r--js/src/vm/TaggedProto.h22
-rw-r--r--js/src/vm/UnboxedObject.cpp12
-rw-r--r--js/src/vm/UnboxedObject.h4
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, &currentValue))
+ if (!GetExistingPropertyValue(cx, obj, id, prop, &currentValue))
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, &currentValue))
+ if (!GetExistingPropertyValue(cx, obj, id, prop, &currentValue))
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, &currentValue))
+ if (!GetExistingPropertyValue(cx, obj, id, prop, &currentValue))
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,