Bug 1090636, part 15 - Optimize away the HasOwnProperty call in SetPropertyByDefining, in the common case. No change in behavior, theoretically. r=efaust.

--HG--
extra : rebase_source : 6c8840025cabcd9041bfe4c05c50925c28229f4f
This commit is contained in:
Jason Orendorff 2014-11-12 11:46:38 -06:00
Родитель 3be561fab8
Коммит 8a476b9eb4
1 изменённых файлов: 25 добавлений и 11 удалений

Просмотреть файл

@ -1932,15 +1932,29 @@ MaybeReportUndeclaredVarAssignment(JSContext *cx, JSString *propname)
template <ExecutionMode mode>
static bool
SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
HandleObject receiver, HandleId id, HandleValue v, bool strict)
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
// the same thing except faster in the non-proxy case. (Once
// SetPropertyHelper is better-behaved, we will be able to optimize away
// even the HasOwnProperty call.)
// the same thing except faster in the non-proxy case. Sometimes we can
// even optimize away the HasOwnProperty call.
bool existing;
if (mode == ParallelExecution) {
if (receiver == obj) {
// The common case. The caller has necessarily done a property lookup
// on obj and passed us the answer as objHasOwn.
#ifdef DEBUG
// 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);
}
#endif
existing = objHasOwn;
} else if (mode == ParallelExecution) {
// Not the fastest possible implementation, but the fastest possible
// without refactoring LookupPropertyPure or duplicating code.
NativeObject *npobj;
@ -2026,8 +2040,8 @@ SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
template <ExecutionMode mode>
static bool
SetNonexistentProperty(typename ExecutionModeTraits<mode>::ContextType cxArg,
HandleObject receiver, HandleId id, baseops::QualifiedBool qualified,
HandleValue v, bool strict)
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>());
@ -2040,7 +2054,7 @@ SetNonexistentProperty(typename ExecutionModeTraits<mode>::ContextType cxArg,
return false;
}
return SetPropertyByDefining<mode>(cxArg, receiver, id, v, strict);
return SetPropertyByDefining<mode>(cxArg, obj, receiver, id, v, strict, false);
}
/*
@ -2238,7 +2252,7 @@ SetExistingProperty(typename ExecutionModeTraits<mode>::ContextType cxArg,
}
// Shadow pobj[id] by defining a new data property receiver[id].
return SetPropertyByDefining<mode>(cxArg, receiver, id, vp, strict);
return SetPropertyByDefining<mode>(cxArg, obj, receiver, id, vp, strict, obj == pobj);
}
template <ExecutionMode mode>
@ -2309,7 +2323,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
RootedObject proto(cxArg, done ? nullptr : pobj->getProto());
if (!proto) {
// Step 4.d.i (and step 5).
return SetNonexistentProperty<mode>(cxArg, receiver, id, qualified, vp, strict);
return SetNonexistentProperty<mode>(cxArg, obj, receiver, id, qualified, vp, strict);
}
// Step 4.c.i. If the prototype is also native, this step is a
@ -2329,7 +2343,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
if (!JSObject::lookupGeneric(cxArg->asJSContext(), proto, id, &pobj, &shape))
return false;
if (!shape) {
return SetNonexistentProperty<mode>(cxArg, receiver, id, qualified, vp,
return SetNonexistentProperty<mode>(cxArg, obj, receiver, id, qualified, vp,
strict);
}
}