summaryrefslogtreecommitdiffstats
path: root/js/src/jit/MCallOptimize.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/MCallOptimize.cpp')
-rw-r--r--js/src/jit/MCallOptimize.cpp90
1 files changed, 67 insertions, 23 deletions
diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp
index 236354530..f2071dc6a 100644
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -30,6 +30,7 @@
#include "jit/shared/Lowering-shared-inl.h"
#include "vm/NativeObject-inl.h"
#include "vm/StringObject-inl.h"
+#include "vm/UnboxedObject-inl.h"
using mozilla::ArrayLength;
using mozilla::AssertedCast;
@@ -470,6 +471,11 @@ IonBuilder::inlineArray(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
+ if (templateObject->is<UnboxedArrayObject>()) {
+ if (templateObject->group()->unboxedLayout().nativeGroup())
+ return InliningStatus_NotInlined;
+ }
+
// Multiple arguments imply array initialization, not just construction.
if (callInfo.argc() >= 2) {
initLength = callInfo.argc();
@@ -517,7 +523,7 @@ IonBuilder::inlineArray(CallInfo& callInfo)
// Make sure initLength matches the template object's length. This is
// not guaranteed to be the case, for instance if we're inlining the
// MConstant may come from an outer script.
- if (initLength != templateObject->as<ArrayObject>().length())
+ if (initLength != GetAnyBoxedOrUnboxedArrayLength(templateObject))
return InliningStatus_NotInlined;
// Don't inline large allocations.
@@ -532,15 +538,16 @@ IonBuilder::inlineArray(CallInfo& callInfo)
MDefinition* array = current->peek(-1);
if (callInfo.argc() >= 2) {
+ JSValueType unboxedType = GetBoxedOrUnboxedType(templateObject);
for (uint32_t i = 0; i < initLength; i++) {
if (!alloc().ensureBallast())
return InliningStatus_Error;
MDefinition* value = callInfo.getArg(i);
- if (!initializeArrayElement(array, i, value, /* addResumePoint = */ false))
+ if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
return InliningStatus_Error;
}
- MInstruction* setLength = setInitializedLength(array, initLength);
+ MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
if (!resumeAfter(setLength))
return InliningStatus_Error;
}
@@ -573,7 +580,7 @@ IonBuilder::inlineArrayIsArray(CallInfo& callInfo)
if (!clasp || clasp->isProxy())
return InliningStatus_NotInlined;
- isArray = (clasp == &ArrayObject::class_);
+ isArray = (clasp == &ArrayObject::class_ || clasp == &UnboxedArrayObject::class_);
}
pushConstant(BooleanValue(isArray));
@@ -604,12 +611,12 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
OBJECT_FLAG_LENGTH_OVERFLOW |
OBJECT_FLAG_ITERATED;
- MDefinition* obj = callInfo.thisArg();
+ MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
TemporaryTypeSet* thisTypes = obj->resultTypeSet();
if (!thisTypes)
return InliningStatus_NotInlined;
const Class* clasp = thisTypes->getKnownClass(constraints());
- if (clasp != &ArrayObject::class_)
+ if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
return InliningStatus_NotInlined;
if (thisTypes->hasObjectFlags(constraints(), unhandledFlags)) {
trackOptimizationOutcome(TrackedOutcome::ArrayBadFlags);
@@ -622,9 +629,17 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
return InliningStatus_NotInlined;
}
+ JSValueType unboxedType = JSVAL_TYPE_MAGIC;
+ if (clasp == &UnboxedArrayObject::class_) {
+ unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
+ if (unboxedType == JSVAL_TYPE_MAGIC)
+ return InliningStatus_NotInlined;
+ }
+
callInfo.setImplicitlyUsedUnchecked();
- obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
+ if (clasp == &ArrayObject::class_)
+ obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
TemporaryTypeSet* returnTypes = getInlineReturnTypeSet();
bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_NON_PACKED);
@@ -635,7 +650,8 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
if (barrier != BarrierKind::NoBarrier)
returnType = MIRType::Value;
- MArrayPopShift* ins = MArrayPopShift::New(alloc(), obj, mode, needsHoleCheck, maybeUndefined);
+ MArrayPopShift* ins = MArrayPopShift::New(alloc(), obj, mode,
+ unboxedType, needsHoleCheck, maybeUndefined);
current->add(ins);
current->push(ins);
ins->setResultType(returnType);
@@ -684,7 +700,7 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
- MDefinition* obj = callInfo.thisArg();
+ MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
MDefinition* value = callInfo.getArg(0);
if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
&obj, nullptr, &value, /* canModify = */ false))
@@ -717,6 +733,13 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
+ JSValueType unboxedType = JSVAL_TYPE_MAGIC;
+ if (clasp == &UnboxedArrayObject::class_) {
+ unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
+ if (unboxedType == JSVAL_TYPE_MAGIC)
+ return InliningStatus_NotInlined;
+ }
+
callInfo.setImplicitlyUsedUnchecked();
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles ||
@@ -727,12 +750,13 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
value = valueDouble;
}
- obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
+ if (unboxedType == JSVAL_TYPE_MAGIC)
+ obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
if (NeedsPostBarrier(value))
current->add(MPostWriteBarrier::New(alloc(), obj, value));
- MArrayPush* ins = MArrayPush::New(alloc(), obj, value);
+ MArrayPush* ins = MArrayPush::New(alloc(), obj, value, unboxedType);
current->add(ins);
current->push(ins);
@@ -749,7 +773,7 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
- MDefinition* obj = callInfo.thisArg();
+ MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
// Ensure |this| and result are objects.
if (getInlineReturnType() != MIRType::Object)
@@ -773,9 +797,16 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
return InliningStatus_NotInlined;
const Class* clasp = thisTypes->getKnownClass(constraints());
- if (clasp != &ArrayObject::class_)
+ if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
return InliningStatus_NotInlined;
+ JSValueType unboxedType = JSVAL_TYPE_MAGIC;
+ if (clasp == &UnboxedArrayObject::class_) {
+ unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
+ if (unboxedType == JSVAL_TYPE_MAGIC)
+ return InliningStatus_NotInlined;
+ }
+
// Watch out for indexed properties on the object or its prototype.
if (ElementAccessHasExtraIndexedProperty(this, obj)) {
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
@@ -796,8 +827,15 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
if (!templateObj)
return InliningStatus_NotInlined;
- if (!templateObj->is<ArrayObject>())
- return InliningStatus_NotInlined;
+ if (unboxedType == JSVAL_TYPE_MAGIC) {
+ if (!templateObj->is<ArrayObject>())
+ return InliningStatus_NotInlined;
+ } else {
+ if (!templateObj->is<UnboxedArrayObject>())
+ return InliningStatus_NotInlined;
+ if (templateObj->as<UnboxedArrayObject>().elementType() != unboxedType)
+ return InliningStatus_NotInlined;
+ }
callInfo.setImplicitlyUsedUnchecked();
@@ -816,12 +854,16 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
end = MArrayLength::New(alloc(), elements);
current->add(end->toInstruction());
+ } else {
+ end = MUnboxedArrayLength::New(alloc(), obj);
+ current->add(end->toInstruction());
}
MArraySlice* ins = MArraySlice::New(alloc(), constraints(),
obj, begin, end,
templateObj,
- templateObj->group()->initialHeap(constraints()));
+ templateObj->group()->initialHeap(constraints()),
+ unboxedType);
current->add(ins);
current->push(ins);
@@ -1340,7 +1382,7 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
// Check if exist a template object in stub.
JSString* stringStr = nullptr;
JSString* stringSep = nullptr;
- ArrayObject* templateObject = nullptr;
+ JSObject* templateObject = nullptr;
if (!inspector->isOptimizableCallStringSplit(pc, &stringStr, &stringSep, &templateObject))
return InliningStatus_NotInlined;
@@ -1366,13 +1408,13 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
if (!key.maybeTypes()->hasType(TypeSet::StringType()))
return InliningStatus_NotInlined;
- uint32_t initLength = templateObject->length();
- if (templateObject->getDenseInitializedLength() != initLength)
+ uint32_t initLength = GetAnyBoxedOrUnboxedArrayLength(templateObject);
+ if (GetAnyBoxedOrUnboxedInitializedLength(templateObject) != initLength)
return InliningStatus_NotInlined;
Vector<MConstant*, 0, SystemAllocPolicy> arrayValues;
for (uint32_t i = 0; i < initLength; i++) {
- Value str = templateObject->getDenseElement(i);
+ Value str = GetAnyBoxedOrUnboxedDenseElement(templateObject, i);
MOZ_ASSERT(str.toString()->isAtom());
MConstant* value = MConstant::New(alloc().fallible(), str, constraints());
if (!value)
@@ -1403,6 +1445,8 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
return InliningStatus_Inlined;
}
+ JSValueType unboxedType = GetBoxedOrUnboxedType(templateObject);
+
// Store all values, no need to initialize the length after each as
// jsop_initelem_array is doing because we do not expect to bailout
// because the memory is supposed to be allocated by now.
@@ -1413,11 +1457,11 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
MConstant* value = arrayValues[i];
current->add(value);
- if (!initializeArrayElement(array, i, value, /* addResumePoint = */ false))
+ if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
return InliningStatus_Error;
}
- MInstruction* setLength = setInitializedLength(array, initLength);
+ MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
if (!resumeAfter(setLength))
return InliningStatus_Error;
@@ -2053,7 +2097,7 @@ IonBuilder::inlineDefineDataProperty(CallInfo& callInfo)
if (callInfo.argc() != 3)
return InliningStatus_NotInlined;
- MDefinition* obj = callInfo.getArg(0);
+ MDefinition* obj = convertUnboxedObjects(callInfo.getArg(0));
MDefinition* id = callInfo.getArg(1);
MDefinition* value = callInfo.getArg(2);