author | Tom Schuster <evilpies@gmail.com> |
Wed, 03 Mar 2021 10:12:55 +0000 | |
changeset 569467 | 0963e86271f75690c758d6f0716d8d0960d9d49e |
parent 569466 | 6f29f36ea34c503e320b8c307eee92345012aa81 |
child 569468 | 2ee3856bd2aebb4ae25455088809895fc408a4ac |
push id | 38260 |
push user | apavel@mozilla.com |
push date | Wed, 03 Mar 2021 21:50:27 +0000 |
treeherder | mozilla-central@46580fa5a4ce [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 1695736 |
milestone | 88.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
|
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/cacheir/getelem-undefined-null.js @@ -0,0 +1,52 @@ +function exists() { + var a = {'null': 1, 'undefined': 2}; + for (var i = 0; i < 100; i++) { + assertEq(a[null], 1); + assertEq(a[undefined], 2); + } +} + +function missing() { + var a = {}; + for (var i = 0; i < 100; i++) { + assertEq(a[null], undefined); + assertEq(a[undefined], undefined); + } +} + +function getter() { + var a = { + get null() { + return 1; + }, + get undefined() { + return 2; + } + } + for (var i = 0; i < 100; i++) { + assertEq(a[null], 1); + assertEq(a[undefined], 2); + } +} + +function primitive() { + var v = true; + for (var i = 0; i < 100; i++) { + assertEq(v[null], undefined); + assertEq(v[undefined], undefined); + } +} + +function mixed() { + var a = {'null': 'null', 'undefined': 'undefined'}; + for (var i = 0; i < 100; i++) { + var v = a[i % 2 ? null : undefined] + assertEq(a[v], i % 2 ? 'null' : 'undefined'); + } +} + +exists(); +missing() +getter(); +primitive(); +mixed();
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/cacheir/has-undefined-null.js @@ -0,0 +1,28 @@ +function exists() { + var a = {'null': 0, 'undefined': 0}; + for (var i = 0; i < 100; i++) { + assertEq(null in a, true); + assertEq(undefined in a, true); + } +} + +function missing() { + var a = {}; + for (var i = 0; i < 100; i++) { + assertEq(null in a, false); + assertEq(undefined in a, false); + } +} + +function mixed() { + var x = [{'null': 0}, {'undefined': 0}] + for (var i = 0; i < 100; i++) { + var a = x[i % 2]; + assertEq(null in a, i % 2 == 0); + assertEq(undefined in a, i % 2 == 1); + } +} + +exists(); +missing(); +mixed();
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/cacheir/setelem-undefined-null.js @@ -0,0 +1,50 @@ +function exists() { + var a = {'null': 0, 'undefined': 0}; + for (var i = 0; i < 100; i++) { + a[null] = i; + a[undefined] = i * 2; + assertEq(a['null'], i); + assertEq(a['undefined'], i * 2); + } +} + +function adding() { + for (var i = 0; i < 100; i++) { + var a = {}; + a[null] = i; + a[undefined] = i * 2; + assertEq(a['null'], i); + assertEq(a['undefined'], i * 2); + } +} + +function setter() { + var test = 0; + var a = { + set null(v) { + test = v; + }, + set undefined(v) { + test = v * 2; + } + } + for (var i = 0; i < 100; i++) { + a[null] = i; + assertEq(test, i); + a[undefined] = i; + assertEq(test, i * 2); + } +} + +function mixed() { + var a = {'null': void 0, 'undefined': void 0}; + for (var i = 0; i < 100; i++) { + a[i % 2 ? null : undefined] = i; + assertEq(a[i % 2 ? 'null' : 'undefined'], i) + } +} + +exists(); +adding() +setter(); +mixed();
--- a/js/src/jit/CacheIR.cpp +++ b/js/src/jit/CacheIR.cpp @@ -310,35 +310,36 @@ static ProxyStubType GetProxyStubType(JS return ProxyStubType::DOMShadowed; } MOZ_ASSERT(shadows == DOMProxyShadowsResult::DoesntShadow || shadows == DOMProxyShadowsResult::DoesntShadowUnique); return ProxyStubType::DOMUnshadowed; } -static bool ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, +static bool ValueToNameOrSymbolId(JSContext* cx, HandleValue idVal, MutableHandleId id, bool* nameOrSymbol) { *nameOrSymbol = false; - if (!idval.isString() && !idval.isSymbol()) { + if (!idVal.isString() && !idVal.isSymbol() && !idVal.isUndefined() && + !idVal.isNull()) { return true; } - if (!PrimitiveValueToId<CanGC>(cx, idval, id)) { + if (!PrimitiveValueToId<CanGC>(cx, idVal, id)) { return false; } - if (!JSID_IS_STRING(id) && !JSID_IS_SYMBOL(id)) { + if (!id.isAtom() && !id.isSymbol()) { id.set(JSID_VOID); return true; } uint32_t dummy; - if (JSID_IS_STRING(id) && JSID_TO_ATOM(id)->isIndex(&dummy)) { + if (id.isAtom() && id.toAtom()->isIndex(&dummy)) { id.set(JSID_VOID); return true; } *nameOrSymbol = true; return true; } @@ -2642,49 +2643,59 @@ void GetPropIRGenerator::trackAttached(c #ifdef JS_CACHEIR_SPEW if (const CacheIRSpewer::Guard& sp = CacheIRSpewer::Guard(*this, name)) { sp.valueProperty("base", val_); sp.valueProperty("property", idVal_); } #endif } -void IRGenerator::emitIdGuard(ValOperandId valId, jsid id) { - if (JSID_IS_SYMBOL(id)) { +void IRGenerator::emitIdGuard(ValOperandId valId, HandleValue idVal, jsid id) { + if (id.isSymbol()) { + MOZ_ASSERT(idVal.toSymbol() == id.toSymbol()); SymbolOperandId symId = writer.guardToSymbol(valId); - writer.guardSpecificSymbol(symId, JSID_TO_SYMBOL(id)); - } else { - MOZ_ASSERT(JSID_IS_ATOM(id)); - StringOperandId strId = writer.guardToString(valId); - writer.guardSpecificAtom(strId, JSID_TO_ATOM(id)); + writer.guardSpecificSymbol(symId, id.toSymbol()); + } else { + MOZ_ASSERT(id.isAtom()); + if (idVal.isUndefined()) { + MOZ_ASSERT(id.isAtom(cx_->names().undefined)); + writer.guardIsUndefined(valId); + } else if (idVal.isNull()) { + MOZ_ASSERT(id.isAtom(cx_->names().null)); + writer.guardIsNull(valId); + } else { + MOZ_ASSERT(idVal.isString()); + StringOperandId strId = writer.guardToString(valId); + writer.guardSpecificAtom(strId, id.toAtom()); + } } } void GetPropIRGenerator::maybeEmitIdGuard(jsid id) { if (cacheKind_ == CacheKind::GetProp || cacheKind_ == CacheKind::GetPropSuper) { // Constant PropertyName, no guards necessary. MOZ_ASSERT(&idVal_.toString()->asAtom() == JSID_TO_ATOM(id)); return; } MOZ_ASSERT(cacheKind_ == CacheKind::GetElem || cacheKind_ == CacheKind::GetElemSuper); - emitIdGuard(getElemKeyValueId(), id); + emitIdGuard(getElemKeyValueId(), idVal_, id); } void SetPropIRGenerator::maybeEmitIdGuard(jsid id) { if (cacheKind_ == CacheKind::SetProp) { // Constant PropertyName, no guards necessary. MOZ_ASSERT(&idVal_.toString()->asAtom() == JSID_TO_ATOM(id)); return; } MOZ_ASSERT(cacheKind_ == CacheKind::SetElem); - emitIdGuard(setElemKeyValueId(), id); + emitIdGuard(setElemKeyValueId(), idVal_, id); } GetNameIRGenerator::GetNameIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, ICState::Mode mode, HandleObject env, HandlePropertyName name) : IRGenerator(cx, script, pc, CacheKind::GetName, mode), env_(env), @@ -3244,17 +3255,17 @@ AttachDecision HasPropIRGenerator::tryAt return AttachDecision::NoAction; } if (!IsCacheableProtoChain(obj, holder)) { return AttachDecision::NoAction; } Maybe<ObjOperandId> tempId; - emitIdGuard(keyId, key); + emitIdGuard(keyId, idVal_, key); EmitReadSlotGuard(writer, obj, holder, objId, &tempId); writer.loadBooleanResult(true); writer.returnFromIC(); trackAttached("NativeHasProp"); return AttachDecision::Attach; } @@ -3279,17 +3290,17 @@ AttachDecision HasPropIRGenerator::tryAt trackAttached("TypedArrayObject"); return AttachDecision::Attach; } AttachDecision HasPropIRGenerator::tryAttachSlotDoesNotExist( JSObject* obj, ObjOperandId objId, jsid key, ValOperandId keyId) { bool hasOwn = (cacheKind_ == CacheKind::HasOwn); - emitIdGuard(keyId, key); + emitIdGuard(keyId, idVal_, key); if (hasOwn) { TestMatchingReceiver(writer, obj, objId); } else { Maybe<ObjOperandId> tempId; EmitReadSlotGuard(writer, obj, nullptr, objId, &tempId); } writer.loadBooleanResult(false); writer.returnFromIC(); @@ -3446,17 +3457,17 @@ AttachDecision CheckPrivateFieldIRGenera jsid key, ValOperandId keyId, bool hasOwn) { if (!obj->is<NativeObject>()) { return AttachDecision::NoAction; } Maybe<ObjOperandId> tempId; - emitIdGuard(keyId, key); + emitIdGuard(keyId, idVal_, key); EmitReadSlotGuard(writer, obj, obj, objId, &tempId); writer.loadBooleanResult(hasOwn); writer.returnFromIC(); trackAttached("NativeCheckPrivateField"); return AttachDecision::Attach; }
--- a/js/src/jit/CacheIR.h +++ b/js/src/jit/CacheIR.h @@ -1247,17 +1247,17 @@ class MOZ_RAII IRGenerator { IntPtrOperandId guardToIntPtrIndex(const Value& index, ValOperandId indexId, bool supportOOB); ObjOperandId guardDOMProxyExpandoObjectAndShape(JSObject* obj, ObjOperandId objId, const Value& expandoVal, JSObject* expandoObj); - void emitIdGuard(ValOperandId valId, jsid id); + void emitIdGuard(ValOperandId valId, HandleValue idVal, jsid id); OperandId emitNumericGuard(ValOperandId valId, Scalar::Type type); friend class CacheIRSpewer; public: explicit IRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, CacheKind cacheKind, ICState::Mode mode);