author | Tom Schuster <evilpies@gmail.com> |
Fri, 13 Apr 2018 13:56:55 +0200 | |
changeset 414692 | 0a19791ab7735a3b5d96a070284e9c6f3441c527 |
parent 414691 | eebf6569ce4ad9d7025a70775c69f3c524b73201 |
child 414693 | 8ce15c227c6600eb6235a6e99c4a1f7882be3227 |
push id | 33876 |
push user | dluca@mozilla.com |
push date | Fri, 20 Apr 2018 23:00:46 +0000 |
treeherder | mozilla-central@39ccabfd7d07 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 1453932 |
milestone | 61.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
|
--- a/js/public/TrackedOptimizationInfo.h +++ b/js/public/TrackedOptimizationInfo.h @@ -32,16 +32,17 @@ namespace JS { _(SetProp_CommonSetter) \ _(SetProp_TypedObject) \ _(SetProp_DefiniteSlot) \ _(SetProp_Unboxed) \ _(SetProp_InlineAccess) \ _(SetProp_InlineCache) \ \ _(GetElem_TypedObject) \ + _(GetElem_CallSiteObject) \ _(GetElem_Dense) \ _(GetElem_TypedArray) \ _(GetElem_String) \ _(GetElem_Arguments) \ _(GetElem_ArgumentsInlinedConstant) \ _(GetElem_ArgumentsInlinedSwitch) \ _(GetElem_InlineCache) \ \
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/ion/template-tag-callsiteobject.js @@ -0,0 +1,26 @@ +function tagA(strings) { + assertEq(strings.length, 2); + assertEq(strings[0], "a"); + assertEq(strings[1], ""); +} + +function tagAB(strings) { + assertEq(strings.length, 2); + assertEq(strings[0], "a"); + assertEq(strings[1], "b"); +} + +var data = [1, 2, 3]; +function tag(strings, value1, value2) { + return strings[0] + value1 + strings[1] + value2 + strings[2]; +} + +function complex() { + return tag`${data[0]} ${data[1] + data[2]}`; +} + +for (var i = 0; i < 20; i++) { + tagA`a${0}`; + tagAB`a${0}b`; + assertEq(complex(), "1 5"); +}
--- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -7791,16 +7791,21 @@ IonBuilder::jsop_getelem() if (!forceInlineCaches()) { // Note: no trackOptimizationAttempt call is needed, getElemTryGetProp // will call it. MOZ_TRY(getElemTryGetProp(&emitted, obj, index)); if (emitted) return Ok(); + trackOptimizationAttempt(TrackedStrategy::GetElem_CallSiteObject); + MOZ_TRY(getElemTryCallSiteObject(&emitted, obj, index)); + if (emitted) + return Ok(); + trackOptimizationAttempt(TrackedStrategy::GetElem_Dense); MOZ_TRY(getElemTryDense(&emitted, obj, index)); if (emitted) return Ok(); trackOptimizationAttempt(TrackedStrategy::GetElem_TypedArray); MOZ_TRY(getElemTryTypedArray(&emitted, obj, index)); if (emitted) @@ -8239,16 +8244,62 @@ IonBuilder::getElemTryTypedArray(bool* e MOZ_TRY(jsop_getelem_typed(obj, index, arrayType)); trackOptimizationSuccess(); *emitted = true; return Ok(); } AbortReasonOr<Ok> +IonBuilder::getElemTryCallSiteObject(bool* emitted, MDefinition* obj, MDefinition* index) +{ + MOZ_ASSERT(*emitted == false); + + if (!obj->isConstant() || obj->type() != MIRType::Object) { + trackOptimizationOutcome(TrackedOutcome::NotObject); + return Ok(); + } + + if (!index->isConstant() || index->type() != MIRType::Int32) { + trackOptimizationOutcome(TrackedOutcome::IndexType); + return Ok(); + } + + JSObject* cst = &obj->toConstant()->toObject(); + if (!cst->is<ArrayObject>()) { + trackOptimizationOutcome(TrackedOutcome::GenericFailure); + return Ok(); + } + + // Technically this code would work with any kind of frozen array, + // in pratice only CallSiteObjects can be constant and frozen. + + ArrayObject* array = &cst->as<ArrayObject>(); + if (array->lengthIsWritable() || array->hasEmptyElements() || !array->denseElementsAreFrozen()) { + trackOptimizationOutcome(TrackedOutcome::GenericFailure); + return Ok(); + } + + int32_t idx = index->toConstant()->toInt32(); + if (idx < 0 || !array->containsDenseElement(uint32_t(idx))) { + trackOptimizationOutcome(TrackedOutcome::OutOfBounds); + return Ok(); + } + + obj->setImplicitlyUsedUnchecked(); + index->setImplicitlyUsedUnchecked(); + + pushConstant(array->getDenseElement(uint32_t(idx))); + + trackOptimizationSuccess(); + *emitted = true; + return Ok(); +} + +AbortReasonOr<Ok> IonBuilder::getElemTryString(bool* emitted, MDefinition* obj, MDefinition* index) { MOZ_ASSERT(*emitted == false); if (obj->type() != MIRType::String || !IsNumberType(index->type())) { trackOptimizationOutcome(TrackedOutcome::AccessNotString); return Ok(); }
--- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -415,16 +415,17 @@ class IonBuilder uint32_t elemSize); AbortReasonOr<Ok> initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value, bool addResumePointAndIncrementInitializedLength); // jsop_getelem() helpers. AbortReasonOr<Ok> getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index); AbortReasonOr<Ok> getElemTryGetProp(bool* emitted, MDefinition* obj, MDefinition* index); AbortReasonOr<Ok> getElemTryTypedArray(bool* emitted, MDefinition* obj, MDefinition* index); + AbortReasonOr<Ok> getElemTryCallSiteObject(bool* emitted, MDefinition* obj, MDefinition* index); AbortReasonOr<Ok> getElemTryTypedObject(bool* emitted, MDefinition* obj, MDefinition* index); AbortReasonOr<Ok> getElemTryString(bool* emitted, MDefinition* obj, MDefinition* index); AbortReasonOr<Ok> getElemTryArguments(bool* emitted, MDefinition* obj, MDefinition* index); AbortReasonOr<Ok> getElemTryArgumentsInlinedConstant(bool* emitted, MDefinition* obj, MDefinition* index); AbortReasonOr<Ok> getElemTryArgumentsInlinedIndex(bool* emitted, MDefinition* obj, MDefinition* index); AbortReasonOr<Ok> getElemAddCache(MDefinition* obj, MDefinition* index);