mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1118107 - Convert ThreadSafeContext -> ExclusiveContext and remove PJS paths in object ops. (r=lth)
This commit is contained in:
parent
50c6db483c
commit
7e86f97c24
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
|
@ -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 *
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_ = {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user