Bug 1688534 - Part 4: Add fast path for object literal without index or duplicate properties. r=tcampbell

Differential Revision: https://phabricator.services.mozilla.com/D103553
This commit is contained in:
Tooru Fujisawa 2021-02-02 17:37:51 +00:00
Родитель 16905203c9
Коммит cb096fbf7c
3 изменённых файлов: 69 добавлений и 37 удалений

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

@ -24,9 +24,10 @@
#include "vm/PlainObject.h" // PlainObject
#include "vm/Printer.h" // js::Fprinter
#include "gc/ObjectKind-inl.h" // gc::GetGCObjectKind
#include "vm/JSAtom-inl.h" // AtomToId
#include "vm/JSObject-inl.h" // NewBuiltinClassInstance
#include "gc/ObjectKind-inl.h" // gc::GetGCObjectKind
#include "vm/JSAtom-inl.h" // AtomToId
#include "vm/JSObject-inl.h" // NewBuiltinClassInstance
#include "vm/NativeObject-inl.h" // AddDataPropertyNonDelegate
namespace js {
@ -61,28 +62,29 @@ static void InterpretObjLiteralValue(
}
}
static JSObject* InterpretObjLiteralObj(
JSContext* cx, const frontend::CompilationAtomCache& atomCache,
const mozilla::Span<const uint8_t> literalInsns, ObjLiteralFlags flags,
uint32_t propertyCount) {
enum class PropertySetKind {
UniqueNames,
Normal,
};
template <PropertySetKind kind>
bool InterpretObjLiteralObj(JSContext* cx, HandlePlainObject obj,
const frontend::CompilationAtomCache& atomCache,
const mozilla::Span<const uint8_t> literalInsns,
ObjLiteralFlags flags) {
bool singleton = flags.contains(ObjLiteralFlag::Singleton);
ObjLiteralReader reader(literalInsns);
ObjLiteralInsn insn;
gc::AllocKind allocKind = gc::GetGCObjectKind(propertyCount);
RootedPlainObject obj(
cx, NewBuiltinClassInstance<PlainObject>(cx, allocKind, TenuredObject));
if (!obj) {
return nullptr;
}
RootedId propId(cx);
RootedValue propVal(cx);
while (reader.readInsn(&insn)) {
MOZ_ASSERT(insn.isValid());
MOZ_ASSERT_IF(kind == PropertySetKind::UniqueNames,
!insn.getKey().isArrayIndex());
if (insn.getKey().isArrayIndex()) {
if (kind == PropertySetKind::Normal && insn.getKey().isArrayIndex()) {
propId = INT_TO_JSID(insn.getKey().getArrayIndex());
} else {
JSAtom* jsatom =
@ -97,11 +99,42 @@ static JSObject* InterpretObjLiteralObj(
propVal.setUndefined();
}
if (!NativeDefineDataProperty(cx, obj, propId, propVal, JSPROP_ENUMERATE)) {
if (kind == PropertySetKind::UniqueNames) {
if (!AddDataPropertyNonDelegate(cx, obj, propId, propVal)) {
return false;
}
} else {
if (!NativeDefineDataProperty(cx, obj, propId, propVal,
JSPROP_ENUMERATE)) {
return false;
}
}
}
return true;
}
static JSObject* InterpretObjLiteralObj(
JSContext* cx, const frontend::CompilationAtomCache& atomCache,
const mozilla::Span<const uint8_t> literalInsns, ObjLiteralFlags flags,
uint32_t propertyCount) {
gc::AllocKind allocKind = gc::GetGCObjectKind(propertyCount);
RootedPlainObject obj(
cx, NewBuiltinClassInstance<PlainObject>(cx, allocKind, TenuredObject));
if (!obj) {
return nullptr;
}
if (!flags.contains(ObjLiteralFlag::HasIndexOrDuplicatePropName)) {
if (!InterpretObjLiteralObj<PropertySetKind::UniqueNames>(
cx, obj, atomCache, literalInsns, flags)) {
return nullptr;
}
} else {
if (!InterpretObjLiteralObj<PropertySetKind::Normal>(cx, obj, atomCache,
literalInsns, flags)) {
return nullptr;
}
}
return obj;
}

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

@ -864,6 +864,25 @@ inline bool IsPackedArray(JSObject* obj) {
return true;
}
MOZ_ALWAYS_INLINE bool AddDataPropertyNonDelegate(JSContext* cx,
HandlePlainObject obj,
HandleId id, HandleValue v) {
MOZ_ASSERT(!JSID_IS_INT(id));
MOZ_ASSERT(!obj->isDelegate());
// If we know this is a new property we can call addProperty instead of
// the slower putProperty.
Shape* shape = NativeObject::addEnumerableDataProperty(cx, obj, id);
if (!shape) {
return false;
}
obj->setSlot(shape->slot(), v);
MOZ_ASSERT(!obj->getClass()->getAddProperty());
return true;
}
} // namespace js
#endif /* vm_NativeObject_inl_h */

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

@ -1377,26 +1377,6 @@ static MOZ_ALWAYS_INLINE bool AddDataProperty(JSContext* cx,
return CallAddPropertyHook(cx, obj, id, v);
}
static MOZ_ALWAYS_INLINE bool AddDataPropertyNonDelegate(JSContext* cx,
HandlePlainObject obj,
HandleId id,
HandleValue v) {
MOZ_ASSERT(!JSID_IS_INT(id));
MOZ_ASSERT(!obj->isDelegate());
// If we know this is a new property we can call addProperty instead of
// the slower putProperty.
Shape* shape = NativeObject::addEnumerableDataProperty(cx, obj, id);
if (!shape) {
return false;
}
obj->setSlot(shape->slot(), v);
MOZ_ASSERT(!obj->getClass()->getAddProperty());
return true;
}
static bool IsConfigurable(unsigned attrs) {
return (attrs & JSPROP_PERMANENT) == 0;
}