author | Nicholas Nethercote <nnethercote@mozilla.com> |
Wed, 07 Jan 2015 13:47:10 -0800 | |
changeset 222579 | e95a4191ea5eddc3e1543fa26633bef16a008d38 |
parent 222578 | 51e4e9fcde248895ce6713cdb52cb7e2713f9425 |
child 222580 | 5e04df19d58130e890eeb47e52e26eddebead1a9 |
push id | 28068 |
push user | cbook@mozilla.com |
push date | Thu, 08 Jan 2015 13:16:34 +0000 |
treeherder | mozilla-central@2880e05d5e32 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sfink |
bugs | 1117017 |
milestone | 37.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/jsiter.cpp | file | annotate | diff | comparison | revisions |
--- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -4,16 +4,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* JavaScript iterators. */ #include "jsiter.h" #include "mozilla/ArrayUtils.h" +#include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" #include "mozilla/PodOperations.h" #include "jsarray.h" #include "jsatom.h" #include "jscntxt.h" #include "jsgc.h" #include "jsobj.h" @@ -40,16 +41,17 @@ #include "vm/Stack-inl.h" #include "vm/String-inl.h" using namespace js; using namespace js::gc; using JS::ForOfIterator; using mozilla::ArrayLength; +using mozilla::Maybe; #ifdef JS_MORE_DETERMINISTIC using mozilla::PodCopy; #endif using mozilla::PodZero; typedef Rooted<PropertyIteratorObject*> RootedPropertyIteratorObject; static const gc::AllocKind ITERATOR_FINALIZE_KIND = gc::FINALIZE_OBJECT2_BACKGROUND; @@ -91,53 +93,60 @@ NewKeyValuePair(JSContext *cx, jsid id, if (!aobj) return false; rval.setObject(*aobj); return true; } static inline bool Enumerate(JSContext *cx, HandleObject pobj, jsid id, - bool enumerable, unsigned flags, IdSet& ht, AutoIdVector *props) + bool enumerable, unsigned flags, Maybe<IdSet>& ht, AutoIdVector *props) { // We implement __proto__ using a property on |Object.prototype|, but // because __proto__ is highly deserving of removal, we don't want it to // show up in property enumeration, even if only for |Object.prototype| // (think introspection by Prototype-like frameworks that add methods to // the built-in prototypes). So exclude __proto__ if the object where the // property was found has no [[Prototype]] and might be |Object.prototype|. if (MOZ_UNLIKELY(!pobj->getTaggedProto().isObject() && JSID_IS_ATOM(id, cx->names().proto))) return true; if (!(flags & JSITER_OWNONLY) || pobj->is<ProxyObject>() || pobj->getOps()->enumerate) { + if (!ht) { + ht.emplace(cx); + // Most of the time there are only a handful of entries. + if (!ht->init(5)) + return false; + } + // If we've already seen this, we definitely won't add it. - IdSet::AddPtr p = ht.lookupForAdd(id); + IdSet::AddPtr p = ht->lookupForAdd(id); if (MOZ_UNLIKELY(!!p)) return true; // It's not necessary to add properties to the hash table at the end of // the prototype chain, but custom enumeration behaviors might return // duplicated properties, so always add in such cases. - if ((pobj->is<ProxyObject>() || pobj->getProto() || pobj->getOps()->enumerate) && !ht.add(p, id)) + if ((pobj->is<ProxyObject>() || pobj->getProto() || pobj->getOps()->enumerate) && !ht->add(p, id)) return false; } // Symbol-keyed properties and nonenumerable properties are skipped unless // the caller specifically asks for them. A caller can also filter out // non-symbols by asking for JSITER_SYMBOLSONLY. if (JSID_IS_SYMBOL(id) ? !(flags & JSITER_SYMBOLS) : (flags & JSITER_SYMBOLSONLY)) return true; if (!enumerable && !(flags & JSITER_HIDDEN)) return true; return props->append(id); } static bool -EnumerateNativeProperties(JSContext *cx, HandleNativeObject pobj, unsigned flags, IdSet &ht, +EnumerateNativeProperties(JSContext *cx, HandleNativeObject pobj, unsigned flags, Maybe<IdSet> &ht, AutoIdVector *props) { bool enumerateSymbols; if (flags & JSITER_SYMBOLSONLY) { enumerateSymbols = true; } else { /* Collect any dense elements from this object. */ size_t initlen = pobj->getDenseInitializedLength(); @@ -268,21 +277,19 @@ struct SortComparatorIds } }; #endif /* JS_MORE_DETERMINISTIC */ static bool Snapshot(JSContext *cx, HandleObject pobj_, unsigned flags, AutoIdVector *props) { - // ~90% of the time this table ends up with 3 or fewer elements. - IdSet ht(cx); - if (!ht.init(3)) - return false; - + // We initialize |ht| lazily (in Enumerate()) because it ends up unused + // anywhere from 67--99.9% of the time. + Maybe<IdSet> ht; RootedObject pobj(cx, pobj_); do { if (JSNewEnumerateOp enumerate = pobj->getOps()->enumerate) { // This hook has the full control over what gets enumerated. AutoIdVector properties(cx); if (!enumerate(cx, pobj, properties)) return false;