Bug 1847714 part 2 - Use createArrayWithFixedElements for regexp match result object. r=iain

This lets us get rid of the template object in later patches.

This patch also adds an optimization for the common case of less than 14 elements by
supporting array capacities of 2/6/14 elements instead of always using 14.

Differential Revision: https://phabricator.services.mozilla.com/D185651
This commit is contained in:
Jan de Mooij 2023-08-09 07:22:23 +00:00
Родитель 7e76ca7a02
Коммит 641cf896e2
1 изменённых файлов: 55 добавлений и 14 удалений

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

@ -2452,11 +2452,6 @@ static JitCode* GenerateRegExpMatchStubShared(JSContext* cx,
const TemplateNativeObject& nativeTemplateObj =
templateObj.asTemplateNativeObject();
// The template object should have enough space for the maximum number of
// pairs this stub can handle.
MOZ_ASSERT(ObjectElements::VALUES_PER_HEADER + RegExpObject::MaxPairCount ==
gc::GetGCKindSlots(templateObj.getAllocKind()));
TempAllocator temp(&cx->tempLifoAlloc());
JitContext jcx(cx);
StackMacroAssembler masm(cx, temp);
@ -2499,15 +2494,64 @@ static JitCode* GenerateRegExpMatchStubShared(JSContext* cx,
Address(shared, RegExpShared::offsetOfFlags()),
Imm32(int32_t(JS::RegExpFlag::HasIndices)), &oolEntry);
Address pairCountAddress =
RegExpPairCountAddress(masm, inputOutputDataStartOffset);
// Construct the result.
Register object = temp1;
Label matchResultJoin;
masm.createGCObject(object, temp2, templateObj, gc::Heap::Default, &oolEntry);
masm.bind(&matchResultJoin);
{
// In most cases, the array will have just 1-2 elements, so we optimize for
// that by emitting separate code paths for capacity 2/6/14 (= 4/8/16 slots
// because two slots are used for the elements header).
// Load the array length in temp2 and the shape in temp3.
Label allocated;
masm.load32(pairCountAddress, temp2);
masm.movePtr(ImmGCPtr(nativeTemplateObj.shape()), temp3);
auto emitAllocObject = [&](size_t elementCapacity) {
gc::AllocKind kind = GuessArrayGCKind(elementCapacity);
MOZ_ASSERT(CanChangeToBackgroundAllocKind(kind, &ArrayObject::class_));
kind = ForegroundToBackgroundAllocKind(kind);
#ifdef DEBUG
// Assert all of the available slots are used for |elementCapacity|
// elements.
size_t usedSlots = ObjectElements::VALUES_PER_HEADER + elementCapacity;
MOZ_ASSERT(usedSlots == GetGCKindSlots(kind));
#endif
constexpr size_t numUsedDynamicSlots = 3;
constexpr size_t numDynamicSlots = 6;
MOZ_ASSERT(nativeTemplateObj.numFixedSlots() == 0);
MOZ_ASSERT(nativeTemplateObj.numDynamicSlots() == numDynamicSlots);
MOZ_ASSERT(nativeTemplateObj.slotSpan() == numUsedDynamicSlots);
constexpr size_t arrayLength = 1;
masm.createArrayWithFixedElements(object, temp3, temp2, temp3,
arrayLength, elementCapacity,
numUsedDynamicSlots, numDynamicSlots,
kind, gc::Heap::Default, &oolEntry);
};
Label moreThan2;
masm.branch32(Assembler::Above, temp2, Imm32(2), &moreThan2);
emitAllocObject(2);
masm.jump(&allocated);
Label moreThan6;
masm.bind(&moreThan2);
masm.branch32(Assembler::Above, temp2, Imm32(6), &moreThan6);
emitAllocObject(6);
masm.jump(&allocated);
masm.bind(&moreThan6);
static_assert(RegExpObject::MaxPairCount == 14);
emitAllocObject(RegExpObject::MaxPairCount);
masm.bind(&allocated);
}
MOZ_ASSERT(nativeTemplateObj.numFixedSlots() == 0);
// Dynamic slot count is always two less than a power of 2.
MOZ_ASSERT(nativeTemplateObj.numDynamicSlots() == 6);
static_assert(RegExpRealm::MatchResultObjectIndexSlot == 0,
"First slot holds the 'index' property");
static_assert(RegExpRealm::MatchResultObjectInputSlot == 1,
@ -2566,9 +2610,6 @@ static JitCode* GenerateRegExpMatchStubShared(JSContext* cx,
"MatchPair consists of two int32 values representing the start"
"and the end offset of the match");
Address pairCountAddress =
RegExpPairCountAddress(masm, inputOutputDataStartOffset);
int32_t pairsVectorStartOffset =
RegExpPairsVectorStartOffset(inputOutputDataStartOffset);