Bug 1118107 - Convert ThreadSafeContext -> ExclusiveContext and remove PJS paths in object ops. (r=lth)

This commit is contained in:
Shu-yu Guo 2015-01-09 00:06:03 -08:00
parent 50c6db483c
commit 7e86f97c24
19 changed files with 262 additions and 788 deletions

View File

@ -2388,7 +2388,7 @@ CodeGenerator::visitMaybeToDoubleElement(LMaybeToDoubleElement *lir)
masm.bind(&done);
}
typedef bool (*CopyElementsForWriteFn)(ThreadSafeContext *, NativeObject *);
typedef bool (*CopyElementsForWriteFn)(ExclusiveContext *, NativeObject *);
static const VMFunction CopyElementsForWriteInfo =
FunctionInfo<CopyElementsForWriteFn>(NativeObject::CopyElementsForWrite);

View File

@ -2631,7 +2631,7 @@ IsPropertyAddInlineable(NativeObject *obj, HandleId id, ConstantOrRegister val,
}
static SetPropertyIC::NativeSetPropCacheability
CanAttachNativeSetProp(ThreadSafeContext *cx, HandleObject obj, HandleId id, ConstantOrRegister val,
CanAttachNativeSetProp(JSContext *cx, HandleObject obj, HandleId id, ConstantOrRegister val,
bool needsTypeBarrier, MutableHandleNativeObject holder,
MutableHandleShape shape, bool *checkTypeset)
{

View File

@ -503,7 +503,7 @@ SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValu
}
if (MOZ_LIKELY(!obj->getOps()->setProperty)) {
return baseops::SetPropertyHelper<SequentialExecution>(
return baseops::SetPropertyHelper(
cx, obj.as<NativeObject>(), obj.as<NativeObject>(), id,
(op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)

View File

@ -475,7 +475,7 @@ array_length_setter(JSContext *cx, HandleObject obj, HandleId id, bool strict, M
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
MOZ_ASSERT(arr->lengthIsWritable(),
"setter shouldn't be called if property is non-writable");
return ArraySetLength<SequentialExecution>(cx, arr, id, JSPROP_PERMANENT, vp, strict);
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, strict);
}
struct ReverseIndexComparator
@ -487,64 +487,39 @@ struct ReverseIndexComparator
}
};
template <ExecutionMode mode>
bool
js::CanonicalizeArrayLengthValue(typename ExecutionModeTraits<mode>::ContextType cx,
HandleValue v, uint32_t *newLen)
js::CanonicalizeArrayLengthValue(JSContext *cx, HandleValue v, uint32_t *newLen)
{
double d;
if (mode == ParallelExecution) {
if (v.isObject())
return false;
if (!ToUint32(cx, v, newLen))
return false;
if (!NonObjectToUint32(cx, v, newLen))
return false;
if (!NonObjectToNumber(cx, v, &d))
return false;
} else {
if (!ToUint32(cx->asJSContext(), v, newLen))
return false;
if (!ToNumber(cx->asJSContext(), v, &d))
return false;
}
if (!ToNumber(cx, v, &d))
return false;
if (d == *newLen)
return true;
if (cx->isJSContext())
JS_ReportErrorNumber(cx->asJSContext(), js_GetErrorMessage, nullptr,
JSMSG_BAD_ARRAY_LENGTH);
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
template bool
js::CanonicalizeArrayLengthValue<SequentialExecution>(JSContext *cx,
HandleValue v, uint32_t *newLen);
template bool
js::CanonicalizeArrayLengthValue<ParallelExecution>(ForkJoinContext *cx,
HandleValue v, uint32_t *newLen);
/* ES6 20130308 draft 8.4.2.4 ArraySetLength */
template <ExecutionMode mode>
bool
js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
Handle<ArrayObject*> arr, HandleId id,
js::ArraySetLength(JSContext *cx, Handle<ArrayObject*> arr, HandleId id,
unsigned attrs, HandleValue value, bool setterIsStrict)
{
MOZ_ASSERT(cxArg->isThreadLocal(arr));
MOZ_ASSERT(id == NameToId(cxArg->names().length));
MOZ_ASSERT(id == NameToId(cx->names().length));
if (!arr->maybeCopyElementsForWrite(cxArg))
if (!arr->maybeCopyElementsForWrite(cx))
return false;
/* Steps 1-2 are irrelevant in our implementation. */
/* Steps 3-5. */
uint32_t newLen;
if (!CanonicalizeArrayLengthValue<mode>(cxArg, value, &newLen))
if (!CanonicalizeArrayLengthValue(cx, value, &newLen))
return false;
// Abort if we're being asked to change enumerability or configurability.
@ -559,18 +534,14 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
if (!(attrs & JSPROP_PERMANENT) || (attrs & JSPROP_ENUMERATE)) {
if (!setterIsStrict)
return true;
// Bail for strict mode in parallel execution, as we need to go back
// to sequential mode to throw the error.
if (mode == ParallelExecution)
return false;
return Throw(cxArg->asJSContext(), id, JSMSG_CANT_REDEFINE_PROP);
return Throw(cx, id, JSMSG_CANT_REDEFINE_PROP);
}
/* Steps 6-7. */
bool lengthIsWritable = arr->lengthIsWritable();
#ifdef DEBUG
{
RootedShape lengthShape(cxArg, arr->lookupPure(id));
RootedShape lengthShape(cx, arr->lookupPure(id));
MOZ_ASSERT(lengthShape);
MOZ_ASSERT(lengthShape->writable() == lengthIsWritable);
}
@ -583,17 +554,12 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
if (newLen == oldLen)
return true;
if (!cxArg->isJSContext())
return false;
if (setterIsStrict) {
return JS_ReportErrorFlagsAndNumber(cxArg->asJSContext(),
JSREPORT_ERROR, js_GetErrorMessage, nullptr,
return JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, nullptr,
JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
}
return JSObject::reportReadOnly(cxArg->asJSContext(), id,
JSREPORT_STRICT | JSREPORT_WARNING);
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
}
/* Step 8. */
@ -615,7 +581,7 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
// fix this inefficiency by moving indexed storage to be entirely
// separate from non-indexed storage.
if (!arr->isIndexed()) {
if (!arr->maybeCopyElementsForWrite(cxArg))
if (!arr->maybeCopyElementsForWrite(cx))
return false;
uint32_t oldCapacity = arr->getDenseCapacity();
@ -624,7 +590,7 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
if (oldInitializedLength > newLen)
arr->setDenseInitializedLength(newLen);
if (oldCapacity > newLen)
arr->shrinkElements(cxArg, newLen);
arr->shrinkElements(cx, newLen);
// We've done the work of deleting any dense elements needing
// deletion, and there are no sparse elements. Thus we can skip
@ -632,13 +598,6 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
break;
}
// Bail from parallel execution if need to perform step 15, which is
// unsafe and isn't a common case.
if (mode == ParallelExecution)
return false;
JSContext *cx = cxArg->asJSContext();
// Step 15.
//
// Attempt to delete all elements above the new length, from greatest
@ -747,26 +706,15 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
// API call on the floor here. Given that getter/setter will go away in
// the long run, with accessors replacing them both internally and at the
// API level, just run with this.
RootedShape lengthShape(cxArg, mode == ParallelExecution
? arr->lookupPure(id)
: arr->lookup(cxArg->asJSContext(), id));
if (!NativeObject::changeProperty<mode>(cxArg, arr, lengthShape, attrs,
JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_SHARED,
array_length_getter, array_length_setter))
RootedShape lengthShape(cx, arr->lookup(cx, id));
if (!NativeObject::changeProperty(cx, arr, lengthShape, attrs,
JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_SHARED,
array_length_getter, array_length_setter))
{
return false;
}
if (mode == ParallelExecution) {
// Overflowing int32 requires changing TI state.
if (newLen > INT32_MAX)
return false;
arr->setLengthInt32(newLen);
} else {
JSContext *cx = cxArg->asJSContext();
arr->setLength(cx, newLen);
}
arr->setLength(cx, newLen);
// All operations past here until the |!succeeded| code must be infallible,
// so that all element fields remain properly synchronized.
@ -787,15 +735,12 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
// the already-required range check for |index < capacity| by making
// capacity of arrays with non-writable length never exceed the length.
if (arr->getDenseCapacity() > newLen) {
arr->shrinkElements(cxArg, newLen);
arr->shrinkElements(cx, newLen);
arr->getElementsHeader()->capacity = newLen;
}
}
if (setterIsStrict && !succeeded) {
// We can't have arrived here under ParallelExecution, as we have
// returned from the function before step 15 above.
JSContext *cx = cxArg->asJSContext();
RootedId elementId(cx);
if (!IndexToId(cx, newLen - 1, &elementId))
return false;
@ -805,17 +750,8 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
return true;
}
template bool
js::ArraySetLength<SequentialExecution>(JSContext *cx, Handle<ArrayObject*> arr,
HandleId id, unsigned attrs, HandleValue value,
bool setterIsStrict);
template bool
js::ArraySetLength<ParallelExecution>(ForkJoinContext *cx, Handle<ArrayObject*> arr,
HandleId id, unsigned attrs, HandleValue value,
bool setterIsStrict);
bool
js::WouldDefinePastNonwritableLength(ThreadSafeContext *cx,
js::WouldDefinePastNonwritableLength(ExclusiveContext *cx,
HandleObject obj, uint32_t index, bool strict,
bool *definesPast)
{
@ -840,9 +776,6 @@ js::WouldDefinePastNonwritableLength(ThreadSafeContext *cx,
// Error in strict mode code or warn with strict option.
unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_STRICT | JSREPORT_WARNING);
if (cx->isForkJoinContext())
return cx->asForkJoinContext()->reportError(flags);
if (!cx->isJSContext())
return true;
@ -2064,8 +1997,6 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp)
}
} else {
FastInvokeGuard fig(cx, fval);
MOZ_ASSERT(!InParallelSection(),
"Array.sort() can't currently be used from parallel code");
JS_ALWAYS_TRUE(vec.resize(n * 2));
if (!MergeSort(vec.begin(), n, vec.begin() + n,
SortComparatorFunction(cx, fval, fig)))
@ -3057,7 +2988,6 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
uint32_t to = 0;
/* Step 9. */
MOZ_ASSERT(!InParallelSection());
FastInvokeGuard fig(cx, ObjectValue(*callable));
InvokeArgs &args2 = fig.args();
RootedValue kValue(cx);

View File

@ -107,20 +107,16 @@ NewDenseCopyOnWriteArray(JSContext *cx, HandleArrayObject templateObject, gc::In
* increase the length of the array.
*/
extern bool
WouldDefinePastNonwritableLength(ThreadSafeContext *cx,
WouldDefinePastNonwritableLength(ExclusiveContext *cx,
HandleObject obj, uint32_t index, bool strict,
bool *definesPast);
/*
* Canonicalize |vp| to a uint32_t value potentially suitable for use as an
* array length.
*
* For parallel execution we can only canonicalize non-object values.
*/
template <ExecutionMode mode>
extern bool
CanonicalizeArrayLengthValue(typename ExecutionModeTraits<mode>::ContextType cx,
HandleValue v, uint32_t *canonicalized);
CanonicalizeArrayLengthValue(JSContext *cx, HandleValue v, uint32_t *canonicalized);
extern bool
GetLengthProperty(JSContext *cx, HandleObject obj, uint32_t *lengthp);

View File

@ -160,11 +160,6 @@ struct ThreadSafeContext : ContextFriendFields,
{
friend struct StackBaseShape;
friend class Activation;
friend UnownedBaseShape *BaseShape::lookupUnowned(ThreadSafeContext *cx,
const StackBaseShape &base);
friend Shape *NativeObject::lookupChildProperty(ThreadSafeContext *cx,
HandleNativeObject obj, HandleShape parent,
StackShape &child);
public:
enum ContextKind {

View File

@ -908,7 +908,7 @@ DefinePropertyOnArray(JSContext *cx, Handle<ArrayObject*> arr, HandleId id, cons
RootedValue v(cx);
if (desc.hasValue()) {
uint32_t newLen;
if (!CanonicalizeArrayLengthValue<SequentialExecution>(cx, desc.value(), &newLen))
if (!CanonicalizeArrayLengthValue(cx, desc.value(), &newLen))
return false;
v.setNumber(newLen);
} else {
@ -932,7 +932,7 @@ DefinePropertyOnArray(JSContext *cx, Handle<ArrayObject*> arr, HandleId id, cons
attrs = attrs | JSPROP_READONLY;
}
return ArraySetLength<SequentialExecution>(cx, arr, id, attrs, v, throwError);
return ArraySetLength(cx, arr, id, attrs, v, throwError);
}
/* Step 3. */
@ -3117,7 +3117,7 @@ js::HasOwnProperty(JSContext *cx, HandleObject obj, HandleId id, bool *resultp)
}
static MOZ_ALWAYS_INLINE bool
LookupPropertyPureInline(ThreadSafeContext *cx, JSObject *obj, jsid id, NativeObject **objp,
LookupPropertyPureInline(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObject **objp,
Shape **propp)
{
if (!obj->isNative())
@ -3197,7 +3197,7 @@ NativeGetPureInline(NativeObject *pobj, Shape *shape, Value *vp)
}
bool
js::LookupPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, NativeObject **objp,
js::LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObject **objp,
Shape **propp)
{
return LookupPropertyPureInline(cx, obj, id, objp, propp);
@ -3214,7 +3214,7 @@ js::LookupPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, NativeObje
* - The property has a getter.
*/
bool
js::GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, Value *vp)
js::GetPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, Value *vp)
{
/* Deal with native objects. */
NativeObject *obj2;
@ -3258,7 +3258,7 @@ js::GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, Value *vp)
static bool
MOZ_ALWAYS_INLINE
GetElementPure(ThreadSafeContext *cx, JSObject *obj, uint32_t index, Value *vp)
GetElementPure(ExclusiveContext *cx, JSObject *obj, uint32_t index, Value *vp)
{
if (index <= JSID_INT_MAX)
return GetPropertyPure(cx, obj, INT_TO_JSID(index), vp);
@ -3271,7 +3271,7 @@ GetElementPure(ThreadSafeContext *cx, JSObject *obj, uint32_t index, Value *vp)
* side-effect might have occurred.
*/
bool
js::GetObjectElementOperationPure(ThreadSafeContext *cx, JSObject *obj, const Value &prop,
js::GetObjectElementOperationPure(ExclusiveContext *cx, JSObject *obj, const Value &prop,
Value *vp)
{
uint32_t index;
@ -3290,15 +3290,8 @@ js::GetObjectElementOperationPure(ThreadSafeContext *cx, JSObject *obj, const Va
}
bool
JSObject::reportReadOnly(ThreadSafeContext *cxArg, jsid id, unsigned report)
JSObject::reportReadOnly(JSContext *cx, jsid id, unsigned report)
{
if (cxArg->isForkJoinContext())
return cxArg->asForkJoinContext()->reportError(report);
if (!cxArg->isJSContext())
return true;
JSContext *cx = cxArg->asJSContext();
RootedValue val(cx, IdToValue(id));
return js_ReportValueErrorFlags(cx, report, JSMSG_READ_ONLY,
JSDVG_IGNORE_STACK, val, js::NullPtr(),
@ -3306,15 +3299,8 @@ JSObject::reportReadOnly(ThreadSafeContext *cxArg, jsid id, unsigned report)
}
bool
JSObject::reportNotConfigurable(ThreadSafeContext *cxArg, jsid id, unsigned report)
JSObject::reportNotConfigurable(JSContext *cx, jsid id, unsigned report)
{
if (cxArg->isForkJoinContext())
return cxArg->asForkJoinContext()->reportError(report);
if (!cxArg->isJSContext())
return true;
JSContext *cx = cxArg->asJSContext();
RootedValue val(cx, IdToValue(id));
return js_ReportValueErrorFlags(cx, report, JSMSG_CANT_DELETE,
JSDVG_IGNORE_STACK, val, js::NullPtr(),
@ -3322,15 +3308,8 @@ JSObject::reportNotConfigurable(ThreadSafeContext *cxArg, jsid id, unsigned repo
}
bool
JSObject::reportNotExtensible(ThreadSafeContext *cxArg, unsigned report)
JSObject::reportNotExtensible(JSContext *cx, unsigned report)
{
if (cxArg->isForkJoinContext())
return cxArg->asForkJoinContext()->reportError(report);
if (!cxArg->isJSContext())
return true;
JSContext *cx = cxArg->asJSContext();
RootedValue val(cx, ObjectValue(*this));
return js_ReportValueErrorFlags(cx, report, JSMSG_OBJECT_NOT_EXTENSIBLE,
JSDVG_IGNORE_STACK, val, js::NullPtr(),

View File

@ -568,9 +568,9 @@ class JSObject : public js::gc::Cell
bool *foundp);
public:
static bool reportReadOnly(js::ThreadSafeContext *cx, jsid id, unsigned report = JSREPORT_ERROR);
bool reportNotConfigurable(js::ThreadSafeContext *cx, jsid id, unsigned report = JSREPORT_ERROR);
bool reportNotExtensible(js::ThreadSafeContext *cx, unsigned report = JSREPORT_ERROR);
static bool reportReadOnly(JSContext *cx, jsid id, unsigned report = JSREPORT_ERROR);
bool reportNotConfigurable(JSContext *cx, jsid id, unsigned report = JSREPORT_ERROR);
bool reportNotExtensible(JSContext *cx, unsigned report = JSREPORT_ERROR);
/*
* Get the property with the given id, then call it as a function with the
@ -1096,14 +1096,14 @@ js_FindVariableScope(JSContext *cx, JSFunction **funp);
namespace js {
bool
LookupPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, NativeObject **objp,
LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObject **objp,
Shape **propp);
bool
GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, Value *vp);
GetPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, Value *vp);
inline bool
GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, PropertyName *name, Value *vp)
GetPropertyPure(ExclusiveContext *cx, JSObject *obj, PropertyName *name, Value *vp)
{
return GetPropertyPure(cx, obj, NameToId(name), vp);
}
@ -1127,7 +1127,7 @@ extern bool
IsDelegateOfObject(JSContext *cx, HandleObject protoObj, JSObject* obj, bool *result);
bool
GetObjectElementOperationPure(ThreadSafeContext *cx, JSObject *obj, const Value &prop, Value *vp);
GetObjectElementOperationPure(ExclusiveContext *cx, JSObject *obj, const Value &prop, Value *vp);
/* Wrap boolean, number or string as Boolean, Number or String object. */
extern JSObject *

View File

@ -193,36 +193,6 @@ PropertyTree::getChild(ExclusiveContext *cx, Shape *parentArg, StackShape &unroo
return shape;
}
Shape *
PropertyTree::lookupChild(ThreadSafeContext *cx, Shape *parent, const StackShape &child)
{
/* Keep this in sync with the logic of getChild above. */
Shape *shape = nullptr;
MOZ_ASSERT(parent);
KidsPointer *kidp = &parent->kids;
if (kidp->isShape()) {
Shape *kid = kidp->toShape();
if (kid->matches(child))
shape = kid;
} else if (kidp->isHash()) {
if (KidsHash::Ptr p = kidp->toHash()->readonlyThreadsafeLookup(child))
shape = *p;
} else {
return nullptr;
}
if (shape) {
DebugOnly<JS::Zone *> zone = shape->arenaHeader()->zone;
MOZ_ASSERT(!zone->needsIncrementalBarrier());
MOZ_ASSERT(!(zone->isGCSweeping() && !shape->isMarked() &&
!shape->arenaHeader()->allocatedDuringIncremental));
}
return shape;
}
void
Shape::sweep()
{

View File

@ -97,7 +97,6 @@ class PropertyTree
JSCompartment *compartment() { return compartment_; }
Shape *getChild(ExclusiveContext *cx, Shape *parent, StackShape &child);
Shape *lookupChild(ThreadSafeContext *cx, Shape *parent, const StackShape &child);
};
} /* namespace js */

View File

@ -324,11 +324,8 @@ SetNameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, HandleObject s
if (scope->isUnqualifiedVarObj()) {
MOZ_ASSERT(!scope->getOps()->setProperty);
RootedId id(cx, NameToId(name));
return baseops::SetPropertyHelper<SequentialExecution>(cx,
scope.as<NativeObject>(),
scope.as<NativeObject>(),
id, baseops::Unqualified, &valCopy,
strict);
return baseops::SetPropertyHelper(cx, scope.as<NativeObject>(), scope.as<NativeObject>(),
id, baseops::Unqualified, &valCopy, strict);
}
return JSObject::setProperty(cx, scope, scope, name, &valCopy, strict);

View File

@ -312,12 +312,8 @@ SetObjectProperty(JSContext *cx, JSOp op, HandleValue lval, HandleId id, Mutable
bool strict = op == JSOP_STRICTSETPROP;
if (MOZ_LIKELY(!obj->getOps()->setProperty)) {
if (!baseops::SetPropertyHelper<SequentialExecution>(cx,
obj.as<NativeObject>(),
obj.as<NativeObject>(),
id,
baseops::Qualified,
rref, strict))
if (!baseops::SetPropertyHelper(cx, obj.as<NativeObject>(), obj.as<NativeObject>(),
id, baseops::Qualified, rref, strict))
{
return false;
}

View File

@ -32,8 +32,7 @@ NativeObject::fixedData(size_t nslots) const
NativeObject::changePropertyAttributes(JSContext *cx, HandleNativeObject obj,
HandleShape shape, unsigned attrs)
{
return !!changeProperty<SequentialExecution>(cx, obj, shape, attrs, 0,
shape->getter(), shape->setter());
return !!changeProperty(cx, obj, shape, attrs, 0, shape->getter(), shape->setter());
}
inline void
@ -76,15 +75,6 @@ NativeObject::clearShouldConvertDoubleElements()
getElementsHeader()->clearShouldConvertDoubleElements();
}
inline bool
NativeObject::setDenseElementIfHasType(uint32_t index, const Value &val)
{
if (!types::HasTypePropertyId(this, JSID_VOID, val))
return false;
setDenseElementMaybeConvertDouble(index, val);
return true;
}
inline void
NativeObject::setDenseElementWithType(ExclusiveContext *cx, uint32_t index,
const Value &val)
@ -138,7 +128,7 @@ NativeObject::markDenseElementsNotPacked(ExclusiveContext *cx)
}
inline void
NativeObject::ensureDenseInitializedLengthNoPackedCheck(ThreadSafeContext *cx, uint32_t index,
NativeObject::ensureDenseInitializedLengthNoPackedCheck(ExclusiveContext *cx, uint32_t index,
uint32_t extra)
{
MOZ_ASSERT(cx->isThreadLocal(this));
@ -172,16 +162,8 @@ NativeObject::ensureDenseInitializedLength(ExclusiveContext *cx, uint32_t index,
ensureDenseInitializedLengthNoPackedCheck(cx, index, extra);
}
inline void
NativeObject::ensureDenseInitializedLengthPreservePackedFlag(ThreadSafeContext *cx,
uint32_t index, uint32_t extra)
{
MOZ_ASSERT(!writeToIndexWouldMarkNotPacked(index));
ensureDenseInitializedLengthNoPackedCheck(cx, index, extra);
}
NativeObject::EnsureDenseResult
NativeObject::extendDenseElements(ThreadSafeContext *cx,
NativeObject::extendDenseElements(ExclusiveContext *cx,
uint32_t requiredCapacity, uint32_t extra)
{
MOZ_ASSERT(cx->isThreadLocal(this));
@ -221,10 +203,13 @@ NativeObject::extendDenseElements(ThreadSafeContext *cx,
}
inline NativeObject::EnsureDenseResult
NativeObject::ensureDenseElementsNoPackedCheck(ThreadSafeContext *cx, uint32_t index, uint32_t extra)
NativeObject::ensureDenseElements(ExclusiveContext *cx, uint32_t index, uint32_t extra)
{
MOZ_ASSERT(isNative());
if (writeToIndexWouldMarkNotPacked(index))
markDenseElementsNotPacked(cx);
if (!maybeCopyElementsForWrite(cx))
return ED_FAILED;
@ -262,22 +247,6 @@ NativeObject::ensureDenseElementsNoPackedCheck(ThreadSafeContext *cx, uint32_t i
return ED_OK;
}
inline NativeObject::EnsureDenseResult
NativeObject::ensureDenseElements(ExclusiveContext *cx, uint32_t index, uint32_t extra)
{
if (writeToIndexWouldMarkNotPacked(index))
markDenseElementsNotPacked(cx);
return ensureDenseElementsNoPackedCheck(cx, index, extra);
}
inline NativeObject::EnsureDenseResult
NativeObject::ensureDenseElementsPreservePackedFlag(ThreadSafeContext *cx, uint32_t index,
uint32_t extra)
{
MOZ_ASSERT(!writeToIndexWouldMarkNotPacked(index));
return ensureDenseElementsNoPackedCheck(cx, index, extra);
}
inline Value
NativeObject::getDenseOrTypedArrayElement(uint32_t idx)
{

View File

@ -318,7 +318,7 @@ PropDesc::trace(JSTracer *trc)
}
/* static */ inline bool
NativeObject::updateSlotsForSpan(ThreadSafeContext *cx,
NativeObject::updateSlotsForSpan(ExclusiveContext *cx,
HandleNativeObject obj, size_t oldSpan, size_t newSpan)
{
MOZ_ASSERT(cx->isThreadLocal(obj));
@ -348,7 +348,7 @@ NativeObject::updateSlotsForSpan(ThreadSafeContext *cx,
}
/* static */ bool
NativeObject::setLastProperty(ThreadSafeContext *cx, HandleNativeObject obj, HandleShape shape)
NativeObject::setLastProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleShape shape)
{
MOZ_ASSERT(cx->isThreadLocal(obj));
MOZ_ASSERT(!obj->inDictionaryMode());
@ -391,7 +391,7 @@ NativeObject::setLastPropertyShrinkFixedSlots(Shape *shape)
}
/* static */ bool
NativeObject::setSlotSpan(ThreadSafeContext *cx, HandleNativeObject obj, uint32_t span)
NativeObject::setSlotSpan(ExclusiveContext *cx, HandleNativeObject obj, uint32_t span)
{
MOZ_ASSERT(cx->isThreadLocal(obj));
MOZ_ASSERT(obj->inDictionaryMode());
@ -410,7 +410,7 @@ NativeObject::setSlotSpan(ThreadSafeContext *cx, HandleNativeObject obj, uint32_
// This will not run the garbage collector. If a nursery cannot accomodate the slot array
// an attempt will be made to place the array in the tenured area.
static HeapSlot *
AllocateSlots(ThreadSafeContext *cx, JSObject *obj, uint32_t nslots)
AllocateSlots(ExclusiveContext *cx, JSObject *obj, uint32_t nslots)
{
if (cx->isJSContext())
return cx->asJSContext()->runtime()->gc.nursery.allocateSlots(obj, nslots);
@ -422,7 +422,7 @@ AllocateSlots(ThreadSafeContext *cx, JSObject *obj, uint32_t nslots)
//
// If this returns null then the old slots will be left alone.
static HeapSlot *
ReallocateSlots(ThreadSafeContext *cx, JSObject *obj, HeapSlot *oldSlots,
ReallocateSlots(ExclusiveContext *cx, JSObject *obj, HeapSlot *oldSlots,
uint32_t oldCount, uint32_t newCount)
{
if (cx->isJSContext()) {
@ -433,7 +433,7 @@ ReallocateSlots(ThreadSafeContext *cx, JSObject *obj, HeapSlot *oldSlots,
}
/* static */ bool
NativeObject::growSlots(ThreadSafeContext *cx, HandleNativeObject obj, uint32_t oldCount, uint32_t newCount)
NativeObject::growSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t oldCount, uint32_t newCount)
{
MOZ_ASSERT(cx->isThreadLocal(obj));
MOZ_ASSERT(newCount > oldCount);
@ -467,7 +467,7 @@ NativeObject::growSlots(ThreadSafeContext *cx, HandleNativeObject obj, uint32_t
}
static void
FreeSlots(ThreadSafeContext *cx, HeapSlot *slots)
FreeSlots(ExclusiveContext *cx, HeapSlot *slots)
{
// Note: threads without a JSContext do not have access to GGC nursery allocated things.
if (cx->isJSContext())
@ -476,7 +476,7 @@ FreeSlots(ThreadSafeContext *cx, HeapSlot *slots)
}
/* static */ void
NativeObject::shrinkSlots(ThreadSafeContext *cx, HandleNativeObject obj,
NativeObject::shrinkSlots(ExclusiveContext *cx, HandleNativeObject obj,
uint32_t oldCount, uint32_t newCount)
{
MOZ_ASSERT(cx->isThreadLocal(obj));
@ -700,7 +700,7 @@ NativeObject::maybeDensifySparseElements(js::ExclusiveContext *cx, HandleNativeO
// This will not run the garbage collector. If a nursery cannot accomodate the element array
// an attempt will be made to place the array in the tenured area.
static ObjectElements *
AllocateElements(ThreadSafeContext *cx, JSObject *obj, uint32_t nelems)
AllocateElements(ExclusiveContext *cx, JSObject *obj, uint32_t nelems)
{
if (cx->isJSContext())
return cx->asJSContext()->runtime()->gc.nursery.allocateElements(obj, nelems);
@ -710,7 +710,7 @@ AllocateElements(ThreadSafeContext *cx, JSObject *obj, uint32_t nelems)
// This will not run the garbage collector. If a nursery cannot accomodate the element array
// an attempt will be made to place the array in the tenured area.
static ObjectElements *
ReallocateElements(ThreadSafeContext *cx, JSObject *obj, ObjectElements *oldHeader,
ReallocateElements(ExclusiveContext *cx, JSObject *obj, ObjectElements *oldHeader,
uint32_t oldCount, uint32_t newCount)
{
if (cx->isJSContext()) {
@ -808,7 +808,7 @@ NativeObject::goodAllocated(uint32_t reqAllocated, uint32_t length = 0)
}
bool
NativeObject::growElements(ThreadSafeContext *cx, uint32_t reqCapacity)
NativeObject::growElements(ExclusiveContext *cx, uint32_t reqCapacity)
{
MOZ_ASSERT(nonProxyIsExtensible());
MOZ_ASSERT(canHaveNonEmptyElements());
@ -872,7 +872,7 @@ NativeObject::growElements(ThreadSafeContext *cx, uint32_t reqCapacity)
}
void
NativeObject::shrinkElements(ThreadSafeContext *cx, uint32_t reqCapacity)
NativeObject::shrinkElements(ExclusiveContext *cx, uint32_t reqCapacity)
{
MOZ_ASSERT(cx->isThreadLocal(this));
MOZ_ASSERT(canHaveNonEmptyElements());
@ -906,7 +906,7 @@ NativeObject::shrinkElements(ThreadSafeContext *cx, uint32_t reqCapacity)
}
/* static */ bool
NativeObject::CopyElementsForWrite(ThreadSafeContext *cx, NativeObject *obj)
NativeObject::CopyElementsForWrite(ExclusiveContext *cx, NativeObject *obj)
{
MOZ_ASSERT(obj->denseElementsAreCopyOnWrite());
@ -940,7 +940,7 @@ NativeObject::CopyElementsForWrite(ThreadSafeContext *cx, NativeObject *obj)
}
/* static */ bool
NativeObject::allocSlot(ThreadSafeContext *cx, HandleNativeObject obj, uint32_t *slotp)
NativeObject::allocSlot(ExclusiveContext *cx, HandleNativeObject obj, uint32_t *slotp)
{
MOZ_ASSERT(cx->isThreadLocal(obj));
@ -1033,18 +1033,13 @@ NativeObject::addDataProperty(ExclusiveContext *cx, HandlePropertyName name,
* value to be stored before the call-out through the hook. Optimize to do
* both while saving cycles for classes that stub their addProperty hook.
*/
template <ExecutionMode mode>
static inline bool
CallAddPropertyHook(typename ExecutionModeTraits<mode>::ExclusiveContextType cxArg,
HandleNativeObject obj, HandleShape shape, HandleValue nominal)
CallAddPropertyHook(ExclusiveContext *cx, HandleNativeObject obj, HandleShape shape,
HandleValue nominal)
{
if (JSPropertyOp addProperty = obj->getClass()->addProperty) {
MOZ_ASSERT(addProperty != JS_PropertyStub);
if (mode == ParallelExecution)
return false;
ExclusiveContext *cx = cxArg->asExclusiveContext();
if (!cx->shouldBeJSContext())
return false;
@ -1064,35 +1059,22 @@ CallAddPropertyHook(typename ExecutionModeTraits<mode>::ExclusiveContextType cxA
return true;
}
template <ExecutionMode mode>
static inline bool
CallAddPropertyHookDense(typename ExecutionModeTraits<mode>::ExclusiveContextType cxArg,
HandleNativeObject obj, uint32_t index, HandleValue nominal)
CallAddPropertyHookDense(ExclusiveContext *cx, HandleNativeObject obj, uint32_t index,
HandleValue nominal)
{
/* Inline addProperty for array objects. */
if (obj->is<ArrayObject>()) {
ArrayObject *arr = &obj->as<ArrayObject>();
uint32_t length = arr->length();
if (index >= length) {
if (mode == ParallelExecution) {
/* We cannot deal with overflows in parallel. */
if (length > INT32_MAX)
return false;
arr->setLengthInt32(index + 1);
} else {
arr->setLength(cxArg->asExclusiveContext(), index + 1);
}
}
if (index >= length)
arr->setLength(cx, index + 1);
return true;
}
if (JSPropertyOp addProperty = obj->getClass()->addProperty) {
MOZ_ASSERT(addProperty != JS_PropertyStub);
if (mode == ParallelExecution)
return false;
ExclusiveContext *cx = cxArg->asExclusiveContext();
if (!cx->shouldBeJSContext())
return false;
@ -1114,19 +1096,12 @@ CallAddPropertyHookDense(typename ExecutionModeTraits<mode>::ExclusiveContextTyp
return true;
}
template <ExecutionMode mode>
static bool
UpdateShapeTypeAndValue(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
NativeObject *obj, Shape *shape, const Value &value)
UpdateShapeTypeAndValue(ExclusiveContext *cx, NativeObject *obj, Shape *shape, const Value &value)
{
jsid id = shape->propid();
if (shape->hasSlot()) {
if (mode == ParallelExecution) {
if (!obj->setSlotIfHasType(shape, value, /* overwriting = */ false))
return false;
} else {
obj->setSlotWithType(cx->asExclusiveContext(), shape, value, /* overwriting = */ false);
}
obj->setSlotWithType(cx, shape, value, /* overwriting = */ false);
// Per the acquired properties analysis, when the shape of a partially
// initialized object is changed to its fully initialized shape, its
@ -1136,35 +1111,19 @@ UpdateShapeTypeAndValue(typename ExecutionModeTraits<mode>::ExclusiveContextType
obj->setType(newScript->initializedType());
}
}
if (!shape->hasSlot() || !shape->hasDefaultGetter() || !shape->hasDefaultSetter()) {
if (mode == ParallelExecution) {
if (!types::IsTypePropertyIdMarkedNonData(obj, id))
return false;
} else {
types::MarkTypePropertyNonData(cx->asExclusiveContext(), obj, id);
}
}
if (!shape->writable()) {
if (mode == ParallelExecution) {
if (!types::IsTypePropertyIdMarkedNonWritable(obj, id))
return false;
} else {
types::MarkTypePropertyNonWritable(cx->asExclusiveContext(), obj, id);
}
}
if (!shape->hasSlot() || !shape->hasDefaultGetter() || !shape->hasDefaultSetter())
types::MarkTypePropertyNonData(cx, obj, id);
if (!shape->writable())
types::MarkTypePropertyNonWritable(cx, obj, id);
return true;
}
template <ExecutionMode mode>
static bool
NativeSet(typename ExecutionModeTraits<mode>::ContextType cx,
HandleNativeObject obj, HandleObject receiver,
NativeSet(JSContext *cx, HandleNativeObject obj, HandleObject receiver,
HandleShape shape, bool strict, MutableHandleValue vp);
template <ExecutionMode mode>
static inline bool
DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
HandleNativeObject obj, HandleId id,
DefinePropertyOrElement(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
unsigned attrs, HandleValue value,
bool callSetterAfterwards, bool setterIsStrict)
@ -1188,34 +1147,22 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
return true;
NativeObject::EnsureDenseResult result;
if (mode == ParallelExecution) {
if (obj->writeToIndexWouldMarkNotPacked(index))
return false;
result = obj->ensureDenseElementsPreservePackedFlag(cx, index, 1);
} else {
result = obj->ensureDenseElements(cx->asExclusiveContext(), index, 1);
}
result = obj->ensureDenseElements(cx, index, 1);
if (result == NativeObject::ED_FAILED)
return false;
if (result == NativeObject::ED_OK) {
if (mode == ParallelExecution) {
if (!obj->setDenseElementIfHasType(index, value))
return false;
} else {
obj->setDenseElementWithType(cx->asExclusiveContext(), index, value);
}
return CallAddPropertyHookDense<mode>(cx, obj, index, value);
obj->setDenseElementWithType(cx, index, value);
return CallAddPropertyHookDense(cx, obj, index, value);
}
}
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (id == NameToId(cx->names().length)) {
if (mode == SequentialExecution && !cx->shouldBeJSContext())
if (!cx->shouldBeJSContext())
return false;
return ArraySetLength<mode>(ExecutionModeTraits<mode>::toContextType(cx), arr, id,
attrs, value, setterIsStrict);
return ArraySetLength(cx->asJSContext(), arr, id, attrs, value, setterIsStrict);
}
uint32_t index;
@ -1236,12 +1183,12 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
}
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
RootedShape shape(cx, NativeObject::putProperty<mode>(cx, obj, id, getter, setter,
SHAPE_INVALID_SLOT, attrs, 0));
RootedShape shape(cx, NativeObject::putProperty(cx, obj, id, getter, setter,
SHAPE_INVALID_SLOT, attrs, 0));
if (!shape)
return false;
if (!UpdateShapeTypeAndValue<mode>(cx, obj, shape, value))
if (!UpdateShapeTypeAndValue(cx, obj, shape, value))
return false;
/*
@ -1249,33 +1196,28 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
* and investigate converting the object to dense indexes.
*/
if (JSID_IS_INT(id)) {
if (mode == ParallelExecution)
return false;
if (!obj->maybeCopyElementsForWrite(cx))
return false;
ExclusiveContext *ncx = cx->asExclusiveContext();
uint32_t index = JSID_TO_INT(id);
NativeObject::removeDenseElementForSparseIndex(ncx, obj, index);
NativeObject::EnsureDenseResult result = NativeObject::maybeDensifySparseElements(ncx, obj);
NativeObject::removeDenseElementForSparseIndex(cx, obj, index);
NativeObject::EnsureDenseResult result = NativeObject::maybeDensifySparseElements(cx, obj);
if (result == NativeObject::ED_FAILED)
return false;
if (result == NativeObject::ED_OK) {
MOZ_ASSERT(!setter);
return CallAddPropertyHookDense<mode>(cx, obj, index, value);
return CallAddPropertyHookDense(cx, obj, index, value);
}
}
if (!CallAddPropertyHook<mode>(cx, obj, shape, value))
if (!CallAddPropertyHook(cx, obj, shape, value))
return false;
if (callSetterAfterwards && setter) {
if (!cx->shouldBeJSContext())
return false;
RootedValue nvalue(cx, value);
return NativeSet<mode>(ExecutionModeTraits<mode>::toContextType(cx),
obj, obj, shape, setterIsStrict, &nvalue);
return NativeSet(cx->asJSContext(), obj, obj, shape, setterIsStrict, &nvalue);
}
return true;
}
@ -1432,14 +1374,14 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
if (!CheckAccessorRedefinition(cx, obj, shape, getter, setter, id, attrs))
return false;
attrs = ApplyOrDefaultAttributes(attrs, shape);
shape = NativeObject::changeProperty<SequentialExecution>(cx, obj, shape, attrs,
JSPROP_GETTER | JSPROP_SETTER,
(attrs & JSPROP_GETTER)
? getter
: shape->getter(),
(attrs & JSPROP_SETTER)
? setter
: shape->setter());
shape = NativeObject::changeProperty(cx, obj, shape, attrs,
JSPROP_GETTER | JSPROP_SETTER,
(attrs & JSPROP_GETTER)
? getter
: shape->getter(),
(attrs & JSPROP_SETTER)
? setter
: shape->setter());
if (!shape)
return false;
shouldDefine = false;
@ -1507,8 +1449,8 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
/* Keep everything from the shape that isn't the things we're changing */
unsigned attrMask = ~(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
shape = NativeObject::changeProperty<SequentialExecution>(cx, obj, shape, attrs, attrMask,
shape->getter(), shape->setter());
shape = NativeObject::changeProperty(cx, obj, shape, attrs, attrMask,
shape->getter(), shape->setter());
if (!shape)
return false;
if (shape->hasSlot())
@ -1529,15 +1471,15 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
// cleared the IGNORE flags by now. Since we can never get here with JSPROP_IGNORE_VALUE
// relevant, just clear it.
attrs = ApplyOrDefaultAttributes(attrs) & ~JSPROP_IGNORE_VALUE;
return DefinePropertyOrElement<SequentialExecution>(cx, obj, id, getter, setter,
attrs, value, false, false);
return DefinePropertyOrElement(cx, obj, id, getter, setter,
attrs, value, false, false);
}
MOZ_ASSERT(shape);
JS_ALWAYS_TRUE(UpdateShapeTypeAndValue<SequentialExecution>(cx, obj, shape, updateValue));
JS_ALWAYS_TRUE(UpdateShapeTypeAndValue(cx, obj, shape, updateValue));
return CallAddPropertyHook<SequentialExecution>(cx, obj, shape, updateValue);
return CallAddPropertyHook(cx, obj, shape, updateValue);
}
static bool
@ -1904,11 +1846,9 @@ MaybeReportUndeclaredVarAssignment(JSContext *cx, JSString *propname)
* This implements ES6 draft rev 28, 9.1.9 [[Set]] steps 5.c-f, but it
* is really old code and there are a few barnacles.
*/
template <ExecutionMode mode>
static bool
SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
HandleNativeObject obj, HandleObject receiver, HandleId id,
HandleValue v, bool strict, bool objHasOwn)
SetPropertyByDefining(JSContext *cx, HandleNativeObject obj, HandleObject receiver,
HandleId id, HandleValue v, bool strict, bool objHasOwn)
{
// Step 5.c-d: Test whether receiver has an existing own property
// receiver[id]. The spec calls [[GetOwnProperty]]; js::HasOwnProperty is
@ -1922,23 +1862,13 @@ SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
// Check that objHasOwn is correct. This could fail if receiver or a
// native object on its prototype chain has a nondeterministic resolve
// hook. We shouldn't have any that are quite that badly behaved.
if (mode == SequentialExecution) {
if (!HasOwnProperty(cxArg->asJSContext(), receiver, id, &existing))
return false;
MOZ_ASSERT(existing == objHasOwn);
}
if (!HasOwnProperty(cx, receiver, id, &existing))
return false;
MOZ_ASSERT(existing == objHasOwn);
#endif
existing = objHasOwn;
} else if (mode == ParallelExecution) {
// Not the fastest possible implementation, but the fastest possible
// without refactoring LookupPropertyPure or duplicating code.
NativeObject *npobj;
Shape *shape;
if (!LookupPropertyPure(cxArg, receiver, id, &npobj, &shape))
return false;
existing = (npobj == receiver);
} else {
if (!HasOwnProperty(cxArg->asJSContext(), receiver, id, &existing))
if (!HasOwnProperty(cx, receiver, id, &existing))
return false;
}
@ -1947,41 +1877,25 @@ SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
// enforced by [[DefineOwnProperty]], but we haven't implemented that yet.)
if (!existing) {
bool extensible;
if (mode == ParallelExecution) {
if (receiver->is<ProxyObject>())
return false;
extensible = receiver->nonProxyIsExtensible();
} else {
if (!JSObject::isExtensible(cxArg->asJSContext(), receiver, &extensible))
return false;
}
if (!JSObject::isExtensible(cx, receiver, &extensible))
return false;
if (!extensible) {
// Error in strict mode code, warn with extra warnings option,
// otherwise do nothing.
if (strict)
return receiver->reportNotExtensible(cxArg);
if (mode == SequentialExecution &&
cxArg->asJSContext()->compartment()->options().extraWarnings(cxArg->asJSContext()))
{
return receiver->reportNotExtensible(cxArg, JSREPORT_STRICT | JSREPORT_WARNING);
}
return receiver->reportNotExtensible(cx);
if (cx->compartment()->options().extraWarnings(cx))
return receiver->reportNotExtensible(cx, JSREPORT_STRICT | JSREPORT_WARNING);
return true;
}
}
// Invalidate SpiderMonkey-specific caches or bail.
const Class *clasp = receiver->getClass();
if (mode == ParallelExecution) {
if (receiver->isDelegate())
return false;
if (clasp->getProperty || !types::HasTypePropertyId(receiver, id, v))
return false;
} else {
// Purge the property cache of now-shadowed id in receiver's scope chain.
if (!PurgeScopeChain(cxArg->asJSContext(), receiver, id))
return false;
}
// Purge the property cache of now-shadowed id in receiver's scope chain.
if (!PurgeScopeChain(cx, receiver, id))
return false;
// Step 5.e-f. Define the new data property.
unsigned attrs =
@ -1992,15 +1906,11 @@ SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
JSStrictPropertyOp setter = clasp->setProperty;
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
if (!receiver->is<NativeObject>()) {
if (mode == ParallelExecution)
return false;
return JSObject::defineGeneric(cxArg->asJSContext(), receiver, id, v, getter, setter,
attrs);
}
Rooted<NativeObject*> nativeReceiver(cxArg, &receiver->as<NativeObject>());
return DefinePropertyOrElement<mode>(cxArg, nativeReceiver, id, getter, setter,
attrs, v, true, strict);
if (!receiver->is<NativeObject>())
return JSObject::defineGeneric(cx, receiver, id, v, getter, setter, attrs);
Rooted<NativeObject*> nativeReceiver(cx, &receiver->as<NativeObject>());
return DefinePropertyOrElement(cx, nativeReceiver, id, getter, setter, attrs, v, true, strict);
}
/*
@ -2012,49 +1922,33 @@ SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
*
* Note that receiver is not necessarily native.
*/
template <ExecutionMode mode>
static bool
SetNonexistentProperty(typename ExecutionModeTraits<mode>::ContextType cxArg,
HandleNativeObject obj, HandleObject receiver, HandleId id,
SetNonexistentProperty(JSContext *cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
baseops::QualifiedBool qualified, HandleValue v, bool strict)
{
// We should never add properties to lexical blocks.
MOZ_ASSERT(!receiver->is<BlockObject>());
if (receiver->isUnqualifiedVarObj() && !qualified) {
if (mode == ParallelExecution)
return false;
if (!MaybeReportUndeclaredVarAssignment(cxArg->asJSContext(), JSID_TO_STRING(id)))
if (!MaybeReportUndeclaredVarAssignment(cx, JSID_TO_STRING(id)))
return false;
}
return SetPropertyByDefining<mode>(cxArg, obj, receiver, id, v, strict, false);
return SetPropertyByDefining(cx, obj, receiver, id, v, strict, false);
}
/*
* Set an existing own property obj[index] that's a dense element or typed
* array element.
*/
template <ExecutionMode mode>
static bool
SetDenseOrTypedArrayElement(typename ExecutionModeTraits<mode>::ContextType cxArg,
HandleNativeObject obj, uint32_t index, MutableHandleValue vp,
bool strict)
SetDenseOrTypedArrayElement(JSContext *cx, HandleNativeObject obj, uint32_t index,
MutableHandleValue vp, bool strict)
{
if (IsAnyTypedArray(obj)) {
double d;
if (mode == ParallelExecution) {
// Bail if converting the value might invoke user-defined
// conversions.
if (vp.isObject())
return false;
if (!NonObjectToNumber(cxArg, vp, &d))
return false;
} else {
if (!ToNumber(cxArg->asJSContext(), vp, &d))
return false;
}
if (!ToNumber(cx, vp, &d))
return false;
// Silently do nothing for out-of-bounds sets, for consistency with
// current behavior. (ES6 currently says to throw for this in
@ -2070,22 +1964,15 @@ SetDenseOrTypedArrayElement(typename ExecutionModeTraits<mode>::ContextType cxAr
}
bool definesPast;
if (!WouldDefinePastNonwritableLength(cxArg, obj, index, strict, &definesPast))
if (!WouldDefinePastNonwritableLength(cx, obj, index, strict, &definesPast))
return false;
if (definesPast) {
/* Bail out of parallel execution if we are strict to throw. */
if (mode == ParallelExecution)
return !strict;
if (definesPast)
return true;
}
if (!obj->maybeCopyElementsForWrite(cxArg))
if (!obj->maybeCopyElementsForWrite(cx))
return false;
if (mode == ParallelExecution)
return obj->setDenseElementIfHasType(index, vp);
obj->setDenseElementWithType(cxArg->asJSContext(), index, vp);
obj->setDenseElementWithType(cx, index, vp);
return true;
}
@ -2093,36 +1980,24 @@ SetDenseOrTypedArrayElement(typename ExecutionModeTraits<mode>::ContextType cxAr
* Finish assignment to a shapeful property of a native object obj. This
* conforms to no standard and there is a lot of legacy baggage here.
*/
template <ExecutionMode mode>
static bool
NativeSet(typename ExecutionModeTraits<mode>::ContextType cxArg, HandleNativeObject obj,
HandleObject receiver, HandleShape shape, bool strict, MutableHandleValue vp)
NativeSet(JSContext *cx, HandleNativeObject obj, HandleObject receiver,
HandleShape shape, bool strict, MutableHandleValue vp)
{
MOZ_ASSERT(cxArg->isThreadLocal(obj));
MOZ_ASSERT(obj->isNative());
if (shape->hasSlot()) {
/* If shape has a stub setter, just store vp. */
if (shape->hasDefaultSetter()) {
if (mode == ParallelExecution) {
if (!obj->setSlotIfHasType(shape, vp))
return false;
} else {
// Global properties declared with 'var' will be initially
// defined with an undefined value, so don't treat the initial
// assignments to such properties as overwrites.
bool overwriting = !obj->is<GlobalObject>() || !obj->getSlot(shape->slot()).isUndefined();
obj->setSlotWithType(cxArg->asExclusiveContext(), shape, vp, overwriting);
}
// Global properties declared with 'var' will be initially
// defined with an undefined value, so don't treat the initial
// assignments to such properties as overwrites.
bool overwriting = !obj->is<GlobalObject>() || !obj->getSlot(shape->slot()).isUndefined();
obj->setSlotWithType(cx, shape, vp, overwriting);
return true;
}
}
if (mode == ParallelExecution)
return false;
JSContext *cx = cxArg->asJSContext();
if (!shape->hasSlot()) {
/*
* Allow API consumers to create shared properties with stub setters.
@ -2161,26 +2036,19 @@ NativeSet(typename ExecutionModeTraits<mode>::ContextType cxArg, HandleNativeObj
* It is necessary to pass both id and shape because shape could be an implicit
* dense or typed array element (i.e. not actually a pointer to a Shape).
*/
template <ExecutionMode mode>
static bool
SetExistingProperty(typename ExecutionModeTraits<mode>::ContextType cxArg,
HandleNativeObject obj, HandleObject receiver, HandleId id,
SetExistingProperty(JSContext *cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
HandleNativeObject pobj, HandleShape shape, MutableHandleValue vp, bool strict)
{
if (IsImplicitDenseOrTypedArrayElement(shape)) {
/* ES5 8.12.4 [[Put]] step 2, for a dense data property on pobj. */
if (pobj == receiver)
return SetDenseOrTypedArrayElement<mode>(cxArg, pobj, JSID_TO_INT(id), vp, strict);
return SetDenseOrTypedArrayElement(cx, pobj, JSID_TO_INT(id), vp, strict);
} else {
/* ES5 8.12.4 [[Put]] step 2. */
if (shape->isAccessorDescriptor()) {
if (shape->hasDefaultSetter()) {
/* Bail out of parallel execution if we are strict to throw. */
if (mode == ParallelExecution)
return !strict;
return js_ReportGetterOnlyAssignment(cxArg->asJSContext(), strict);
}
if (shape->hasDefaultSetter())
return js_ReportGetterOnlyAssignment(cx, strict);
} else {
MOZ_ASSERT(shape->isDataDescriptor());
@ -2188,13 +2056,8 @@ SetExistingProperty(typename ExecutionModeTraits<mode>::ContextType cxArg,
/*
* Error in strict mode code, warn with extra warnings
* options, otherwise do nothing.
*
* Bail out of parallel execution if we are strict to throw.
*/
if (mode == ParallelExecution)
return !strict;
JSContext *cx = cxArg->asJSContext();
if (strict)
return JSObject::reportReadOnly(cx, id, JSREPORT_ERROR);
if (cx->compartment()->options().extraWarnings(cx))
@ -2204,46 +2067,36 @@ SetExistingProperty(typename ExecutionModeTraits<mode>::ContextType cxArg,
}
if (pobj == receiver) {
if (pobj->is<ArrayObject>() && id == NameToId(cxArg->names().length)) {
Rooted<ArrayObject*> arr(cxArg, &pobj->as<ArrayObject>());
return ArraySetLength<mode>(cxArg, arr, id, shape->attributes(), vp, strict);
if (pobj->is<ArrayObject>() && id == NameToId(cx->names().length)) {
Rooted<ArrayObject*> arr(cx, &pobj->as<ArrayObject>());
return ArraySetLength(cx, arr, id, shape->attributes(), vp, strict);
}
return NativeSet<mode>(cxArg, obj, receiver, shape, strict, vp);
return NativeSet(cx, obj, receiver, shape, strict, vp);
}
// pobj[id] is not an own property of receiver. Call the setter or shadow it.
if (!shape->shadowable() &&
!(pobj->is<ArrayObject>() && id == NameToId(cxArg->names().length)))
!(pobj->is<ArrayObject>() && id == NameToId(cx->names().length)))
{
// Weird special case: slotless property with default setter.
if (shape->hasDefaultSetter() && !shape->hasGetterValue())
return true;
// We're setting an accessor property.
if (mode == ParallelExecution)
return false;
return shape->set(cxArg->asJSContext(), obj, receiver, strict, vp);
return shape->set(cx, obj, receiver, strict, vp);
}
}
// Shadow pobj[id] by defining a new data property receiver[id].
return SetPropertyByDefining<mode>(cxArg, obj, receiver, id, vp, strict, obj == pobj);
return SetPropertyByDefining(cx, obj, receiver, id, vp, strict, obj == pobj);
}
template <ExecutionMode mode>
bool
baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg,
HandleNativeObject obj, HandleObject receiver, HandleId id,
QualifiedBool qualified, MutableHandleValue vp, bool strict)
baseops::SetPropertyHelper(JSContext *cx, HandleNativeObject obj, HandleObject receiver,
HandleId id, QualifiedBool qualified, MutableHandleValue vp,
bool strict)
{
MOZ_ASSERT(cxArg->isThreadLocal(obj));
// Fire watchpoints, if any.
if (MOZ_UNLIKELY(obj->watched())) {
if (mode == ParallelExecution)
return false;
JSContext *cx = cxArg->asJSContext();
WatchpointMap *wpmap = cx->compartment()->watchpointMap;
if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
return false;
@ -2252,37 +2105,24 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
// 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, V -> *vp, ownDesc -> shape.
RootedShape shape(cxArg);
RootedNativeObject pobj(cxArg, obj);
RootedShape shape(cx);
RootedNativeObject pobj(cx, obj);
// This loop isn't explicit in the spec algorithm. See the comment on step
// 4.c.i below.
for (;;) {
// Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.)
bool done;
if (mode == ParallelExecution) {
// Use the loop in LookupPropertyPure instead of this loop.
// It amounts to the same thing.
NativeObject *ancestor;
if (!LookupPropertyPure(cxArg, pobj, id, &ancestor, shape.address()))
return false;
done = true;
if (shape)
pobj = ancestor;
} else {
RootedObject ancestor(cxArg);
if (!LookupOwnPropertyInline<CanGC>(cxArg->asJSContext(), pobj, id, &ancestor,
&shape, &done))
{
return false;
}
if (!done || ancestor != pobj)
shape = nullptr;
}
RootedObject ancestor(cx);
if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &ancestor, &shape, &done))
return false;
if (!done || ancestor != pobj)
shape = nullptr;
if (shape) {
// Steps 5-6.
return SetExistingProperty<mode>(cxArg, obj, receiver, id, pobj, shape, vp, strict);
return SetExistingProperty(cx, obj, receiver, id, pobj, shape, vp, strict);
}
// Steps 4.a-b. The check for 'done' on this next line is tricky.
@ -2295,10 +2135,10 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
// lookup (in LookupPropertyPure above).
// What they all have in common is we do not want to keep walking
// the prototype chain.
RootedObject proto(cxArg, done ? nullptr : pobj->getProto());
RootedObject proto(cx, done ? nullptr : pobj->getProto());
if (!proto) {
// Step 4.d.i (and step 5).
return SetNonexistentProperty<mode>(cxArg, obj, receiver, id, qualified, vp, strict);
return SetNonexistentProperty(cx, obj, receiver, id, qualified, vp, strict);
}
// Step 4.c.i. If the prototype is also native, this step is a
@ -2307,40 +2147,23 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
// we're going to end up anyway. But if pobj is non-native,
// that optimization would be incorrect.
if (!proto->isNative()) {
if (mode == ParallelExecution)
return false;
// Unqualified assignments are not specified to go through [[Set]]
// at all, but they do go through this function. So check for
// unqualified assignment to a nonexistent global (a strict error).
if (!qualified) {
RootedObject pobj(cxArg);
if (!JSObject::lookupGeneric(cxArg->asJSContext(), proto, id, &pobj, &shape))
RootedObject pobj(cx);
if (!JSObject::lookupGeneric(cx, proto, id, &pobj, &shape))
return false;
if (!shape) {
return SetNonexistentProperty<mode>(cxArg, obj, receiver, id, qualified, vp,
strict);
}
if (!shape)
return SetNonexistentProperty(cx, obj, receiver, id, qualified, vp, strict);
}
return JSObject::setGeneric(cxArg->asJSContext(), proto, receiver, id, vp,
strict);
return JSObject::setGeneric(cx, proto, receiver, id, vp, strict);
}
pobj = &proto->as<NativeObject>();
}
}
template bool
baseops::SetPropertyHelper<SequentialExecution>(JSContext *cx, HandleNativeObject obj,
HandleObject receiver, HandleId id,
QualifiedBool qualified,
MutableHandleValue vp, bool strict);
template bool
baseops::SetPropertyHelper<ParallelExecution>(ForkJoinContext *cx, HandleNativeObject obj,
HandleObject receiver, HandleId id,
QualifiedBool qualified,
MutableHandleValue vp, bool strict);
bool
baseops::SetElementHelper(JSContext *cx, HandleNativeObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, bool strict)
@ -2348,8 +2171,7 @@ baseops::SetElementHelper(JSContext *cx, HandleNativeObject obj, HandleObject re
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return baseops::SetPropertyHelper<SequentialExecution>(cx, obj, receiver, id, Qualified, vp,
strict);
return baseops::SetPropertyHelper(cx, obj, receiver, id, Qualified, vp, strict);
}
bool

View File

@ -86,10 +86,8 @@ class ArrayObject;
* |setterIsStrict| indicates whether invalid changes will cause a TypeError
* to be thrown.
*/
template <ExecutionMode mode>
extern bool
ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cx,
Handle<ArrayObject*> obj, HandleId id,
ArraySetLength(JSContext *cx, Handle<ArrayObject*> obj, HandleId id,
unsigned attrs, HandleValue value, bool setterIsStrict);
/*
@ -187,10 +185,8 @@ class ObjectElements
friend class ArrayObject;
friend class Nursery;
template <ExecutionMode mode>
friend bool
ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cx,
Handle<ArrayObject*> obj, HandleId id,
ArraySetLength(JSContext *cx, Handle<ArrayObject*> obj, HandleId id,
unsigned attrs, HandleValue value, bool setterIsStrict);
/* See Flags enum above. */
@ -403,7 +399,7 @@ class NativeObject : public JSObject
* Update the last property, keeping the number of allocated slots in sync
* with the object's new slot span.
*/
static bool setLastProperty(ThreadSafeContext *cx,
static bool setLastProperty(ExclusiveContext *cx,
HandleNativeObject obj, HandleShape shape);
// As for setLastProperty(), but allows the number of fixed slots to
@ -420,7 +416,7 @@ class NativeObject : public JSObject
#endif
Shape *
replaceWithNewEquivalentShape(ThreadSafeContext *cx,
replaceWithNewEquivalentShape(ExclusiveContext *cx,
Shape *existingShape, Shape *newShape = nullptr,
bool accessorShape = false);
@ -436,9 +432,9 @@ class NativeObject : public JSObject
* Update the slot span directly for a dictionary object, and allocate
* slots to cover the new span if necessary.
*/
static bool setSlotSpan(ThreadSafeContext *cx, HandleNativeObject obj, uint32_t span);
static bool setSlotSpan(ExclusiveContext *cx, HandleNativeObject obj, uint32_t span);
bool toDictionaryMode(ThreadSafeContext *cx);
bool toDictionaryMode(ExclusiveContext *cx);
private:
friend class Nursery;
@ -534,7 +530,7 @@ class NativeObject : public JSObject
}
public:
bool generateOwnShape(ThreadSafeContext *cx, Shape *newShape = nullptr) {
bool generateOwnShape(ExclusiveContext *cx, Shape *newShape = nullptr) {
return replaceWithNewEquivalentShape(cx, lastProperty(), newShape);
}
@ -579,9 +575,9 @@ class NativeObject : public JSObject
* The number of allocated slots is not stored explicitly, and changes to
* the slots must track changes in the slot span.
*/
static bool growSlots(ThreadSafeContext *cx, HandleNativeObject obj, uint32_t oldCount,
static bool growSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t oldCount,
uint32_t newCount);
static void shrinkSlots(ThreadSafeContext *cx, HandleNativeObject obj, uint32_t oldCount,
static void shrinkSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t oldCount,
uint32_t newCount);
bool hasDynamicSlots() const { return !!slots_; }
@ -633,32 +629,16 @@ class NativeObject : public JSObject
* after calling object-parameter-free shape methods, avoiding coupling
* logic across the object vs. shape module wall.
*/
static bool allocSlot(ThreadSafeContext *cx, HandleNativeObject obj, uint32_t *slotp);
static bool allocSlot(ExclusiveContext *cx, HandleNativeObject obj, uint32_t *slotp);
void freeSlot(uint32_t slot);
private:
static Shape *getChildPropertyOnDictionary(ThreadSafeContext *cx, HandleNativeObject obj,
static Shape *getChildPropertyOnDictionary(ExclusiveContext *cx, HandleNativeObject obj,
HandleShape parent, StackShape &child);
static Shape *getChildProperty(ExclusiveContext *cx, HandleNativeObject obj,
HandleShape parent, StackShape &child);
template <ExecutionMode mode>
static inline Shape *
getOrLookupChildProperty(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
HandleNativeObject obj, HandleShape parent, StackShape &child)
{
if (mode == ParallelExecution)
return lookupChildProperty(cx, obj, parent, child);
return getChildProperty(cx->asExclusiveContext(), obj, parent, child);
}
public:
/*
* XXX: This should be private, but is public because it needs to be a
* friend of ThreadSafeContext to get to the propertyTree on cx->compartment_.
*/
static Shape *lookupChildProperty(ThreadSafeContext *cx, HandleNativeObject obj,
HandleShape parent, StackShape &child);
/* Add a property whose id is not yet in this scope. */
static Shape *addProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
JSPropertyOp getter, JSStrictPropertyOp setter,
@ -672,26 +652,21 @@ class NativeObject : public JSObject
uint32_t slot, unsigned attrs);
/* Add or overwrite a property for id in this scope. */
template <ExecutionMode mode>
static Shape *
putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
HandleNativeObject obj, HandleId id,
putProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags);
template <ExecutionMode mode>
static inline Shape *
putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
HandleObject obj, PropertyName *name,
putProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags);
/* Change the given property into a sibling with the same id in this scope. */
template <ExecutionMode mode>
static Shape *
changeProperty(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
HandleNativeObject obj, HandleShape shape, unsigned attrs, unsigned mask,
changeProperty(ExclusiveContext *cx, HandleNativeObject obj,
HandleShape shape, unsigned attrs, unsigned mask,
JSPropertyOp getter, JSStrictPropertyOp setter);
static inline bool changePropertyAttributes(JSContext *cx, HandleNativeObject obj,
@ -711,10 +686,8 @@ class NativeObject : public JSObject
* 1. getter and setter must be normalized based on flags (see jsscope.cpp).
* 2. Checks for non-extensibility must be done by callers.
*/
template <ExecutionMode mode>
static Shape *
addPropertyInternal(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
HandleNativeObject obj, HandleId id,
addPropertyInternal(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, unsigned attrs, unsigned flags, Shape **spp,
bool allowDictionary);
@ -803,7 +776,7 @@ class NativeObject : public JSObject
static const uint32_t MAX_FIXED_SLOTS = 16;
protected:
static inline bool updateSlotsForSpan(ThreadSafeContext *cx,
static inline bool updateSlotsForSpan(ExclusiveContext *cx,
HandleNativeObject obj, size_t oldSpan, size_t newSpan);
public:
@ -903,7 +876,7 @@ class NativeObject : public JSObject
}
/* Accessors for elements. */
bool ensureElements(ThreadSafeContext *cx, uint32_t capacity) {
bool ensureElements(ExclusiveContext *cx, uint32_t capacity) {
MOZ_ASSERT(!denseElementsAreCopyOnWrite());
if (capacity > getDenseCapacity())
return growElements(cx, capacity);
@ -911,24 +884,24 @@ class NativeObject : public JSObject
}
static uint32_t goodAllocated(uint32_t n, uint32_t length);
bool growElements(ThreadSafeContext *cx, uint32_t newcap);
void shrinkElements(ThreadSafeContext *cx, uint32_t cap);
bool growElements(ExclusiveContext *cx, uint32_t newcap);
void shrinkElements(ExclusiveContext *cx, uint32_t cap);
void setDynamicElements(ObjectElements *header) {
MOZ_ASSERT(!hasDynamicElements());
elements_ = header->elements();
MOZ_ASSERT(hasDynamicElements());
}
static bool CopyElementsForWrite(ThreadSafeContext *cx, NativeObject *obj);
static bool CopyElementsForWrite(ExclusiveContext *cx, NativeObject *obj);
bool maybeCopyElementsForWrite(ThreadSafeContext *cx) {
bool maybeCopyElementsForWrite(ExclusiveContext *cx) {
if (denseElementsAreCopyOnWrite())
return CopyElementsForWrite(cx, this);
return true;
}
private:
inline void ensureDenseInitializedLengthNoPackedCheck(ThreadSafeContext *cx,
inline void ensureDenseInitializedLengthNoPackedCheck(ExclusiveContext *cx,
uint32_t index, uint32_t extra);
public:
@ -941,8 +914,6 @@ class NativeObject : public JSObject
inline void ensureDenseInitializedLength(ExclusiveContext *cx,
uint32_t index, uint32_t extra);
inline void ensureDenseInitializedLengthPreservePackedFlag(ThreadSafeContext *cx,
uint32_t index, uint32_t extra);
void setDenseElement(uint32_t index, const Value &val) {
MOZ_ASSERT(index < getDenseInitializedLength());
MOZ_ASSERT(!denseElementsAreCopyOnWrite());
@ -962,7 +933,6 @@ class NativeObject : public JSObject
setDenseElement(index, val);
}
inline bool setDenseElementIfHasType(uint32_t index, const Value &val);
inline void setDenseElementWithType(ExclusiveContext *cx, uint32_t index,
const Value &val);
inline void initDenseElementWithType(ExclusiveContext *cx, uint32_t index,
@ -1068,17 +1038,11 @@ class NativeObject : public JSObject
*/
enum EnsureDenseResult { ED_OK, ED_FAILED, ED_SPARSE };
private:
inline EnsureDenseResult ensureDenseElementsNoPackedCheck(ThreadSafeContext *cx,
uint32_t index, uint32_t extra);
public:
inline EnsureDenseResult ensureDenseElements(ExclusiveContext *cx,
uint32_t index, uint32_t extra);
inline EnsureDenseResult ensureDenseElementsPreservePackedFlag(ThreadSafeContext *cx,
uint32_t index, uint32_t extra);
inline EnsureDenseResult extendDenseElements(ThreadSafeContext *cx,
inline EnsureDenseResult extendDenseElements(ExclusiveContext *cx,
uint32_t requiredCapacity, uint32_t extra);
/* Convert a single dense element to a sparse property. */
@ -1321,15 +1285,12 @@ enum QualifiedBool {
Qualified = 1
};
template <ExecutionMode mode>
extern bool
SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cx,
HandleNativeObject obj,
HandleObject receiver, HandleId id, QualifiedBool qualified,
MutableHandleValue vp, bool strict);
SetPropertyHelper(JSContext *cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
QualifiedBool qualified, MutableHandleValue vp, bool strict);
extern bool
SetElementHelper(JSContext *cx, HandleNativeObject obj, HandleObject Receiver, uint32_t index,
SetElementHelper(JSContext *cx, HandleNativeObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, bool strict);
extern bool
@ -1419,8 +1380,8 @@ JSObject::setGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject recei
{
if (obj->getOps()->setGeneric)
return nonNativeSetProperty(cx, obj, receiver, id, vp, strict);
return js::baseops::SetPropertyHelper<js::SequentialExecution>(
cx, obj.as<js::NativeObject>(), receiver, id, js::baseops::Qualified, vp, strict);
return js::baseops::SetPropertyHelper(cx, obj.as<js::NativeObject>(),
receiver, id, js::baseops::Qualified, vp, strict);
}
/* static */ inline bool

View File

@ -336,10 +336,8 @@ DeclEnvObject::createTemplateObject(JSContext *cx, HandleFunction fun, gc::Initi
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
if (!NativeObject::putProperty<SequentialExecution>(cx, obj, id, getter, setter, lambdaSlot(),
attrs, 0)) {
if (!NativeObject::putProperty(cx, obj, id, getter, setter, lambdaSlot(), attrs, 0))
return nullptr;
}
MOZ_ASSERT(!obj->hasDynamicSlots());
return &obj->as<DeclEnvObject>();
@ -715,14 +713,14 @@ StaticBlockObject::addVar(ExclusiveContext *cx, Handle<StaticBlockObject*> block
uint32_t slot = JSSLOT_FREE(&BlockObject::class_) + index;
uint32_t readonly = constant ? JSPROP_READONLY : 0;
uint32_t propFlags = readonly | JSPROP_ENUMERATE | JSPROP_PERMANENT;
return NativeObject::addPropertyInternal<SequentialExecution>(cx, block, id,
/* getter = */ nullptr,
/* setter = */ nullptr,
slot,
propFlags,
/* attrs = */ 0,
spp,
/* allowDictionary = */ false);
return NativeObject::addPropertyInternal(cx, block, id,
/* getter = */ nullptr,
/* setter = */ nullptr,
slot,
propFlags,
/* attrs = */ 0,
spp,
/* allowDictionary = */ false);
}
const Class BlockObject::class_ = {

View File

@ -24,7 +24,7 @@
namespace js {
inline
StackBaseShape::StackBaseShape(ThreadSafeContext *cx, const Class *clasp,
StackBaseShape::StackBaseShape(ExclusiveContext *cx, const Class *clasp,
JSObject *parent, JSObject *metadata, uint32_t objectFlags)
: flags(objectFlags),
clasp(clasp),
@ -55,33 +55,6 @@ Shape::search(ExclusiveContext *cx, jsid id)
return search(cx, this, id, &_);
}
inline Shape *
Shape::searchThreadLocal(ThreadSafeContext *cx, Shape *start, jsid id,
Shape ***pspp, bool adding)
{
/*
* Note that adding is a best-effort attempt to claim an entry in a shape
* table. In the sequential case, this can be done either when the object
* is in dictionary mode, or when it has been hashified.
*
* In parallel, an object that is in dictionary mode may be thread
* local. That is, it was converted to a dictionary in the current thread,
* with all its shapes cloned into the current thread, and its shape table
* allocated thread locally. In that case, we may add to the
* table. Otherwise it is not allowed.
*/
MOZ_ASSERT_IF(adding, cx->isThreadLocal(start) && start->inDictionary());
if (start->inDictionary()) {
*pspp = start->table().search(id, adding);
return SHAPE_FETCH(*pspp);
}
*pspp = nullptr;
return searchNoHashify(start, id);
}
inline bool
Shape::set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict,
MutableHandleValue vp)
@ -206,7 +179,7 @@ EmptyShape::ensureInitialCustomShape(ExclusiveContext *cx, Handle<ObjectSubclass
}
inline
AutoRooterGetterSetter::Inner::Inner(ThreadSafeContext *cx, uint8_t attrs,
AutoRooterGetterSetter::Inner::Inner(ExclusiveContext *cx, uint8_t attrs,
PropertyOp *pgetter_, StrictPropertyOp *psetter_)
: CustomAutoRooter(cx), attrs(attrs),
pgetter(pgetter_), psetter(psetter_)
@ -216,7 +189,7 @@ AutoRooterGetterSetter::Inner::Inner(ThreadSafeContext *cx, uint8_t attrs,
}
inline
AutoRooterGetterSetter::AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t attrs,
AutoRooterGetterSetter::AutoRooterGetterSetter(ExclusiveContext *cx, uint8_t attrs,
PropertyOp *pgetter, StrictPropertyOp *psetter
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
{
@ -226,7 +199,7 @@ AutoRooterGetterSetter::AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t at
}
inline
AutoRooterGetterSetter::AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t attrs,
AutoRooterGetterSetter::AutoRooterGetterSetter(ExclusiveContext *cx, uint8_t attrs,
JSNative *pgetter, JSNative *psetter
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
{

View File

@ -34,7 +34,7 @@ using mozilla::PodZero;
using mozilla::RotateLeft;
bool
ShapeTable::init(ThreadSafeContext *cx, Shape *lastProp)
ShapeTable::init(ExclusiveContext *cx, Shape *lastProp)
{
uint32_t sizeLog2 = CeilingLog2Size(entryCount);
uint32_t size = JS_BIT(sizeLog2);
@ -103,7 +103,7 @@ Shape::insertIntoDictionary(HeapPtrShape *dictp)
}
bool
Shape::makeOwnBaseShape(ThreadSafeContext *cx)
Shape::makeOwnBaseShape(ExclusiveContext *cx)
{
MOZ_ASSERT(!base()->isOwned());
MOZ_ASSERT(cx->isThreadLocal(this));
@ -142,7 +142,7 @@ Shape::handoffTableTo(Shape *shape)
}
/* static */ bool
Shape::hashify(ThreadSafeContext *cx, Shape *shape)
Shape::hashify(ExclusiveContext *cx, Shape *shape)
{
MOZ_ASSERT(!shape->hasTable());
@ -262,7 +262,7 @@ ShapeTable::fixupAfterMovingGC()
#endif
bool
ShapeTable::change(int log2Delta, ThreadSafeContext *cx)
ShapeTable::change(int log2Delta, ExclusiveContext *cx)
{
MOZ_ASSERT(entries);
@ -301,7 +301,7 @@ ShapeTable::change(int log2Delta, ThreadSafeContext *cx)
}
bool
ShapeTable::grow(ThreadSafeContext *cx)
ShapeTable::grow(ExclusiveContext *cx)
{
MOZ_ASSERT(needsToGrow());
@ -345,7 +345,7 @@ Shape::replaceLastProperty(ExclusiveContext *cx, StackBaseShape &base,
* one of lastProperty() or lastProperty()->parent.
*/
/* static */ Shape *
NativeObject::getChildPropertyOnDictionary(ThreadSafeContext *cx, HandleNativeObject obj,
NativeObject::getChildPropertyOnDictionary(ExclusiveContext *cx, HandleNativeObject obj,
HandleShape parent, StackShape &child)
{
/*
@ -417,28 +417,8 @@ NativeObject::getChildProperty(ExclusiveContext *cx,
return shape;
}
/* static */ Shape *
NativeObject::lookupChildProperty(ThreadSafeContext *cx,
HandleNativeObject obj, HandleShape parent, StackShape &unrootedChild)
{
RootedGeneric<StackShape*> child(cx, &unrootedChild);
MOZ_ASSERT(cx->isThreadLocal(obj));
RootedShape shape(cx, getChildPropertyOnDictionary(cx, obj, parent, *child));
if (!obj->inDictionaryMode()) {
shape = cx->compartment_->propertyTree.lookupChild(cx, parent, *child);
if (!shape)
return nullptr;
if (!setLastProperty(cx, obj, shape))
return nullptr;
}
return shape;
}
bool
js::NativeObject::toDictionaryMode(ThreadSafeContext *cx)
js::NativeObject::toDictionaryMode(ExclusiveContext *cx)
{
MOZ_ASSERT(!inDictionaryMode());
@ -522,8 +502,8 @@ NativeObject::addProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
if (obj->inDictionaryMode())
spp = obj->lastProperty()->table().search(id, true);
return addPropertyInternal<SequentialExecution>(cx, obj, id, getter, setter, slot, attrs,
flags, spp, allowDictionary);
return addPropertyInternal(cx, obj, id, getter, setter, slot, attrs, flags, spp,
allowDictionary);
}
static bool
@ -538,19 +518,8 @@ ShouldConvertToDictionary(JSObject *obj)
return obj->lastProperty()->entryCount() >= PropertyTree::MAX_HEIGHT;
}
template <ExecutionMode mode>
static inline UnownedBaseShape *
GetOrLookupUnownedBaseShape(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
StackBaseShape &base)
{
if (mode == ParallelExecution)
return BaseShape::lookupUnowned(cx, base);
return BaseShape::getUnowned(cx->asExclusiveContext(), base);
}
template <ExecutionMode mode>
/* static */ Shape *
NativeObject::addPropertyInternal(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
NativeObject::addPropertyInternal(ExclusiveContext *cx,
HandleNativeObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, unsigned attrs,
@ -610,14 +579,14 @@ NativeObject::addPropertyInternal(typename ExecutionModeTraits<mode>::ExclusiveC
} else {
StackBaseShape base(last->base());
base.flags |= BaseShape::INDEXED;
nbase = GetOrLookupUnownedBaseShape<mode>(cx, base);
nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return nullptr;
}
StackShape child(nbase, id, slot, attrs, flags);
child.updateGetterSetter(getter, setter);
shape = getOrLookupChildProperty<mode>(cx, obj, last, child);
shape = getChildProperty(cx, obj, last, child);
}
if (shape) {
@ -641,21 +610,6 @@ NativeObject::addPropertyInternal(typename ExecutionModeTraits<mode>::ExclusiveC
return nullptr;
}
template /* static */ Shape *
NativeObject::addPropertyInternal<SequentialExecution>(ExclusiveContext *cx,
HandleNativeObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, Shape **spp,
bool allowDictionary);
template /* static */ Shape *
NativeObject::addPropertyInternal<ParallelExecution>(ForkJoinContext *cx,
HandleNativeObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags, Shape **spp,
bool allowDictionary);
JSObject *
js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
gc::AllocKind allocKind, HandleShape shape, NewObjectKind newKind)
@ -695,7 +649,7 @@ js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
if (indexed) {
StackBaseShape base(nbase);
base.flags |= BaseShape::INDEXED;
nbase = GetOrLookupUnownedBaseShape<SequentialExecution>(cx, base);
nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return nullptr;
}
@ -717,7 +671,7 @@ js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
* enforce all restrictions from ECMA-262 v5 8.12.9 [[DefineOwnProperty]].
*/
static inline bool
CheckCanChangeAttrs(ThreadSafeContext *cx, JSObject *obj, Shape *shape, unsigned *attrsp)
CheckCanChangeAttrs(ExclusiveContext *cx, JSObject *obj, Shape *shape, unsigned *attrsp)
{
if (shape->configurable())
return true;
@ -737,10 +691,8 @@ CheckCanChangeAttrs(ThreadSafeContext *cx, JSObject *obj, Shape *shape, unsigned
return true;
}
template <ExecutionMode mode>
/* static */ Shape *
NativeObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
HandleNativeObject obj, HandleId id,
NativeObject::putProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, unsigned attrs, unsigned flags)
{
@ -771,11 +723,7 @@ NativeObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextTy
* shape table.
*/
Shape **spp;
RootedShape shape(cx, (mode == ParallelExecution
? Shape::searchThreadLocal(cx, obj->lastProperty(), id, &spp,
cx->isThreadLocal(obj->lastProperty()))
: Shape::search(cx->asExclusiveContext(), obj->lastProperty(), id,
&spp, true)));
RootedShape shape(cx, Shape::search(cx, obj->lastProperty(), id, &spp, true));
if (!shape) {
/*
* You can't add properties to a non-extensible object, but you can change
@ -783,14 +731,8 @@ NativeObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextTy
*/
bool extensible;
if (mode == ParallelExecution) {
if (obj->is<ProxyObject>())
return nullptr;
extensible = obj->nonProxyIsExtensible();
} else {
if (!JSObject::isExtensible(cx->asExclusiveContext(), obj, &extensible))
return nullptr;
}
if (!JSObject::isExtensible(cx, obj, &extensible))
return nullptr;
if (!extensible) {
if (cx->isJSContext())
@ -798,8 +740,8 @@ NativeObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextTy
return nullptr;
}
return addPropertyInternal<mode>(cx, obj, id, getter, setter, slot, attrs, flags,
spp, true);
return addPropertyInternal(cx, obj, id, getter, setter, slot, attrs, flags,
spp, true);
}
/* Property exists: search must have returned a valid *spp. */
@ -825,7 +767,7 @@ NativeObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextTy
StackBaseShape base(obj->lastProperty()->base());
if (indexed)
base.flags |= BaseShape::INDEXED;
nbase = GetOrLookupUnownedBaseShape<mode>(cx, base);
nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return nullptr;
}
@ -901,7 +843,7 @@ NativeObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextTy
*/
StackBaseShape base(obj->lastProperty()->base());
UnownedBaseShape *nbase = GetOrLookupUnownedBaseShape<mode>(cx, base);
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return nullptr;
@ -911,7 +853,7 @@ NativeObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextTy
StackShape child(nbase, id, slot, attrs, flags);
child.updateGetterSetter(getter, setter);
RootedShape parent(cx, shape->parent);
Shape *newShape = getOrLookupChildProperty<mode>(cx, obj, parent, child);
Shape *newShape = getChildProperty(cx, obj, parent, child);
if (!newShape) {
obj->checkShapeConsistency();
@ -940,23 +882,9 @@ NativeObject::putProperty(typename ExecutionModeTraits<mode>::ExclusiveContextTy
return shape;
}
template /* static */ Shape *
NativeObject::putProperty<SequentialExecution>(ExclusiveContext *cx,
HandleNativeObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags);
template /* static */ Shape *
NativeObject::putProperty<ParallelExecution>(ForkJoinContext *cx,
HandleNativeObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, unsigned attrs,
unsigned flags);
template <ExecutionMode mode>
/* static */ Shape *
NativeObject::changeProperty(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
HandleNativeObject obj, HandleShape shape, unsigned attrs,
NativeObject::changeProperty(ExclusiveContext *cx, HandleNativeObject obj,
HandleShape shape, unsigned attrs,
unsigned mask, PropertyOp getter, StrictPropertyOp setter)
{
MOZ_ASSERT(cx->isThreadLocal(obj));
@ -971,12 +899,7 @@ NativeObject::changeProperty(typename ExecutionModeTraits<mode>::ExclusiveContex
MOZ_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) ||
!(attrs & JSPROP_SHARED));
if (mode == ParallelExecution) {
if (!types::IsTypePropertyIdMarkedNonData(obj, shape->propid()))
return nullptr;
} else {
types::MarkTypePropertyNonData(cx->asExclusiveContext(), obj, shape->propid());
}
types::MarkTypePropertyNonData(cx, obj, shape->propid());
if (!CheckCanChangeAttrs(cx, obj, shape, &attrs))
return nullptr;
@ -991,24 +914,13 @@ NativeObject::changeProperty(typename ExecutionModeTraits<mode>::ExclusiveContex
* putProperty won't re-allocate it.
*/
RootedId propid(cx, shape->propid());
Shape *newShape = putProperty<mode>(cx, obj, propid, getter, setter,
shape->maybeSlot(), attrs, shape->flags);
Shape *newShape = putProperty(cx, obj, propid, getter, setter,
shape->maybeSlot(), attrs, shape->flags);
obj->checkShapeConsistency();
return newShape;
}
template /* static */ Shape *
NativeObject::changeProperty<SequentialExecution>(ExclusiveContext *cx,
HandleNativeObject obj, HandleShape shape,
unsigned attrs, unsigned mask,
PropertyOp getter, StrictPropertyOp setter);
template /* static */ Shape *
NativeObject::changeProperty<ParallelExecution>(ForkJoinContext *cx,
HandleNativeObject obj, HandleShape shape,
unsigned attrs, unsigned mask,
PropertyOp getter, StrictPropertyOp setter);
bool
NativeObject::removeProperty(ExclusiveContext *cx, jsid id_)
{
@ -1175,17 +1087,14 @@ NativeObject::rollbackProperties(ExclusiveContext *cx, HandleNativeObject obj, u
}
Shape *
NativeObject::replaceWithNewEquivalentShape(ThreadSafeContext *cx, Shape *oldShape, Shape *newShape,
NativeObject::replaceWithNewEquivalentShape(ExclusiveContext *cx, Shape *oldShape, Shape *newShape,
bool accessorShape)
{
MOZ_ASSERT(cx->isThreadLocal(this));
MOZ_ASSERT(cx->isThreadLocal(oldShape));
MOZ_ASSERT(cx->isInsideCurrentCompartment(oldShape));
MOZ_ASSERT_IF(oldShape != lastProperty(),
inDictionaryMode() &&
((cx->isExclusiveContext()
? lookup(cx->asExclusiveContext(), oldShape->propidRef())
: lookupPure(oldShape->propidRef())) == oldShape));
inDictionaryMode() && lookup(cx, oldShape->propidRef()) == oldShape);
NativeObject *self = this;
@ -1473,18 +1382,6 @@ BaseShape::getUnowned(ExclusiveContext *cx, StackBaseShape &base)
return nbase;
}
/* static */ UnownedBaseShape *
BaseShape::lookupUnowned(ThreadSafeContext *cx, const StackBaseShape &base)
{
BaseShapeSet &table = cx->compartment_->baseShapes;
if (!table.initialized())
return nullptr;
BaseShapeSet::Ptr p = table.readonlyThreadsafeLookup(&base);
return *p;
}
void
BaseShape::assertConsistency()
{

View File

@ -180,15 +180,15 @@ struct ShapeTable {
* and returns false. This will make any extant pointers into the
* table invalid. Don't call this unless needsToGrow() is true.
*/
bool grow(ThreadSafeContext *cx);
bool grow(ExclusiveContext *cx);
/*
* NB: init and change are fallible but do not report OOM, so callers can
* cope or ignore. They do however use the context's calloc method in
* order to update the malloc counter on success.
*/
bool init(ThreadSafeContext *cx, Shape *lastProp);
bool change(int log2Delta, ThreadSafeContext *cx);
bool init(ExclusiveContext *cx, Shape *lastProp);
bool change(int log2Delta, ExclusiveContext *cx);
Shape **search(jsid id, bool adding);
#ifdef JSGC_COMPACTING
@ -431,12 +431,6 @@ class BaseShape : public gc::TenuredCell
*/
static UnownedBaseShape* getUnowned(ExclusiveContext *cx, StackBaseShape &base);
/*
* Lookup base shapes from the compartment's baseShapes table, returning
* nullptr if not found.
*/
static UnownedBaseShape *lookupUnowned(ThreadSafeContext *cx, const StackBaseShape &base);
/* Get the canonical base shape. */
inline UnownedBaseShape* unowned();
@ -533,7 +527,7 @@ struct StackBaseShape : public DefaultHasher<ReadBarrieredUnownedBaseShape>
compartment(base->compartment())
{}
inline StackBaseShape(ThreadSafeContext *cx, const Class *clasp,
inline StackBaseShape(ExclusiveContext *cx, const Class *clasp,
JSObject *parent, JSObject *metadata, uint32_t objectFlags);
explicit inline StackBaseShape(Shape *shape);
@ -621,8 +615,6 @@ class Shape : public gc::TenuredCell
static inline Shape *search(ExclusiveContext *cx, Shape *start, jsid id,
Shape ***pspp, bool adding = false);
static inline Shape *searchThreadLocal(ThreadSafeContext *cx, Shape *start, jsid id,
Shape ***pspp, bool adding = false);
static inline Shape *searchNoHashify(Shape *start, jsid id);
void removeFromDictionary(NativeObject *obj);
@ -639,7 +631,7 @@ class Shape : public gc::TenuredCell
* is thread local, which is the case when we clone the entire shape
* lineage in preparation for converting an object to dictionary mode.
*/
static bool hashify(ThreadSafeContext *cx, Shape *shape);
static bool hashify(ExclusiveContext *cx, Shape *shape);
void handoffTableTo(Shape *newShape);
void setParent(Shape *p) {
@ -650,13 +642,13 @@ class Shape : public gc::TenuredCell
parent = p;
}
bool ensureOwnBaseShape(ThreadSafeContext *cx) {
bool ensureOwnBaseShape(ExclusiveContext *cx) {
if (base()->isOwned())
return true;
return makeOwnBaseShape(cx);
}
bool makeOwnBaseShape(ThreadSafeContext *cx);
bool makeOwnBaseShape(ExclusiveContext *cx);
public:
bool hasTable() const { return base()->hasTable(); }
@ -1058,7 +1050,7 @@ class AutoRooterGetterSetter
class Inner : private JS::CustomAutoRooter
{
public:
inline Inner(ThreadSafeContext *cx, uint8_t attrs,
inline Inner(ExclusiveContext *cx, uint8_t attrs,
PropertyOp *pgetter_, StrictPropertyOp *psetter_);
private:
@ -1070,10 +1062,10 @@ class AutoRooterGetterSetter
};
public:
inline AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t attrs,
inline AutoRooterGetterSetter(ExclusiveContext *cx, uint8_t attrs,
PropertyOp *pgetter, StrictPropertyOp *psetter
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
inline AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t attrs,
inline AutoRooterGetterSetter(ExclusiveContext *cx, uint8_t attrs,
JSNative *pgetter, JSNative *psetter
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);