Revert "Revert "Attempt fix regexp crash. Not working.""

This reverts commit 7f55d9bbf5cc0cc471750f232a7b5bf877aafebc.
This commit is contained in:
win7-7 2026-01-18 05:18:22 +02:00 committed by wuggy
commit 4a4ab4f90a
4 changed files with 81 additions and 51 deletions

View file

@ -217,6 +217,10 @@ js::CreateRegExpMatchResult(JSContext* cx, RegExpShared& re,
// Step 34b (reordered)
// Set the |indices| property.
if (hasIndices) {
fprintf(stderr,
"regexp indices store: arr=%p comp=%p zone=%p | indices=%p comp=%p zone=%p\n",
arr.get(), arr->compartment(), arr->zone(),
indices.get(), indices->compartment(), indices->zone());
arr->setSlot(3, ObjectValue(*indices));
}

View file

@ -859,8 +859,10 @@ class NativeObject : public ShapedObject
// Check requirements on values stored to this object.
MOZ_ALWAYS_INLINE void checkStoredValue(const Value& v) {
MOZ_ASSERT(IsObjectValueInCompartment(v, compartment()));
MOZ_ASSERT(AtomIsMarked(zoneFromAnyThread(), v));
if (!IsObjectValueInCompartment(v, compartment()))
MOZ_CRASH("compartment mismatch");
if (!AtomIsMarked(zoneFromAnyThread(), v))
MOZ_CRASH("AtomIsMarked failed");
}
MOZ_ALWAYS_INLINE void setSlot(uint32_t slot, const Value& value) {

View file

@ -1297,11 +1297,12 @@ RegExpShared::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
/* RegExpCompartment */
RegExpCompartment::RegExpCompartment(Zone* zone)
: optimizableRegExpPrototypeShape_(nullptr),
: perCompartment_(zone),
optimizableRegExpPrototypeShape_(nullptr),
optimizableRegExpInstanceShape_(nullptr)
{
for (auto& templateObj : matchResultTemplateObjects_) {
templateObj = nullptr;
{
MOZ_ALWAYS_TRUE(perCompartment_.init(4));
}
}
@ -1311,9 +1312,30 @@ RegExpCompartment::~RegExpCompartment()
}
ArrayObject*
RegExpCompartment::createMatchResultTemplateObject(JSContext* cx, ResultTemplateKind kind)
RegExpCompartment::getOrCreateMatchResultTemplateObject(JSContext* cx, ResultTemplateKind kind)
{
MOZ_ASSERT(!matchResultTemplateObjects_[kind]);
JSCompartment* comp = cx->compartment();
auto p = perCompartment_.lookupForAdd(comp);
if (!p) {
PerCompartmentData init;
if (!perCompartment_.add(p, comp, init))
return nullptr;
}
PerCompartmentData& data = p->value();
if (data.matchResultTemplateObjects_[kind])
return data.matchResultTemplateObjects_[kind];
return createMatchResultTemplateObject(cx, kind, data);
}
ArrayObject*
RegExpCompartment::createMatchResultTemplateObject(JSContext* cx,
ResultTemplateKind kind,
PerCompartmentData& data)
{
MOZ_ASSERT(!data.matchResultTemplateObjects_[kind]);
/* Create template array object */
RootedArrayObject templateObject(cx, NewDenseUnallocatedArray(cx, RegExpObject::MaxPairCount,
@ -1337,8 +1359,8 @@ RegExpCompartment::createMatchResultTemplateObject(JSContext* cx, ResultTemplate
return nullptr;
}
AddTypePropertyId(cx, templateObject, NameToId(cx->names().groups), TypeSet::AnyObjectType());
matchResultTemplateObjects_[kind].set(templateObject);
return matchResultTemplateObjects_[kind];
data.matchResultTemplateObjects_[kind].set(templateObject);
return data.matchResultTemplateObjects_[kind];
}
/* Set dummy index property */
@ -1377,9 +1399,8 @@ RegExpCompartment::createMatchResultTemplateObject(JSContext* cx, ResultTemplate
AddTypePropertyId(cx, templateObject, NameToId(cx->names().indices), TypeSet::AnyObjectType());
}
matchResultTemplateObjects_[kind].set(templateObject);
return matchResultTemplateObjects_[kind];
data.matchResultTemplateObjects_[kind].set(templateObject);
return data.matchResultTemplateObjects_[kind];
}
bool
@ -1397,22 +1418,21 @@ RegExpCompartment::init(JSContext* cx)
void
RegExpCompartment::sweep(JSRuntime* rt)
{
for (auto& templateObject : matchResultTemplateObjects_) {
if (templateObject && IsAboutToBeFinalized(&templateObject)) {
templateObject.set(nullptr);
}
}
for (auto iter = perCompartment_.all(); !iter.empty(); iter.popFront()) {
PerCompartmentData& data = iter.front().value();
if (optimizableRegExpPrototypeShape_ &&
IsAboutToBeFinalized(&optimizableRegExpPrototypeShape_))
{
optimizableRegExpPrototypeShape_.set(nullptr);
}
for (auto& templateObject : data.matchResultTemplateObjects_) {
if (templateObject && IsAboutToBeFinalized(&templateObject))
templateObject.set(nullptr);
}
if (optimizableRegExpInstanceShape_ &&
IsAboutToBeFinalized(&optimizableRegExpInstanceShape_))
{
optimizableRegExpInstanceShape_.set(nullptr);
if (data.optimizableRegExpPrototypeShape_ &&
IsAboutToBeFinalized(&data.optimizableRegExpPrototypeShape_))
data.optimizableRegExpPrototypeShape_.set(nullptr);
if (data.optimizableRegExpInstanceShape_ &&
IsAboutToBeFinalized(&data.optimizableRegExpInstanceShape_))
data.optimizableRegExpInstanceShape_.set(nullptr);
}
}

View file

@ -12,6 +12,7 @@
#ifndef vm_RegExpShared_h
#define vm_RegExpShared_h
#include "js/GCHashTable.h"
#include "mozilla/Assertions.h"
#include "mozilla/MemoryReporting.h"
@ -22,6 +23,7 @@
#include "gc/Barrier.h"
#include "gc/Heap.h"
#include "gc/Marking.h"
#include "jsalloc.h"
#include "js/UbiNode.h"
#include "js/Vector.h"
#include "irregexp/InfallibleVector.h"
@ -310,23 +312,31 @@ public:
enum ResultTemplateKind { Normal, WithIndices, Indices, NumKinds };
private:
/*
* The template objects that the result of re.exec() is based on, if
* there is a result. These are used in CreateRegExpMatchResult.
* There are three template objects, each of which is an ArrayObject
* with some additional properties. We decide which to use based on
* the |hasIndices| (/d) flag.
*
* Normal: Has |index|, |input|, and |groups| properties.
* Used for the result object if |hasIndices| is not set.
*
* WithIndices: Has |index|, |input|, |groups|, and |indices| properties.
* Used for the result object if |hasIndices| is set.
*
* Indices: Has a |groups| property. If |hasIndices| is set, used
* for the |.indices| property of the result object.
*/
ReadBarriered<ArrayObject*> matchResultTemplateObjects_[ResultTemplateKind::NumKinds];
struct PerCompartmentData {
ReadBarriered<ArrayObject*> matchResultTemplateObjects_[NumKinds];
ReadBarriered<Shape*> optimizableRegExpPrototypeShape_;
ReadBarriered<Shape*> optimizableRegExpInstanceShape_;
PerCompartmentData()
: optimizableRegExpPrototypeShape_(nullptr),
optimizableRegExpInstanceShape_(nullptr)
{
for (auto& t : matchResultTemplateObjects_)
t = nullptr;
}
};
using PerCompartmentMap =
GCHashMap<JSCompartment*, PerCompartmentData,
DefaultHasher<JSCompartment*>,
ZoneAllocPolicy>;
PerCompartmentMap perCompartment_; // <-- add this
ArrayObject* createMatchResultTemplateObject(JSContext* cx,
ResultTemplateKind kind,
PerCompartmentData& data);
/*
* The shape of RegExp.prototype object that satisfies following:
@ -349,19 +359,13 @@ private:
*/
ReadBarriered<Shape*> optimizableRegExpInstanceShape_;
ArrayObject* createMatchResultTemplateObject(JSContext* cx, ResultTemplateKind kind);
public:
explicit RegExpCompartment(Zone* zone);
void sweep(JSRuntime* rt);
/* Get or create template object used to base the result of .exec() on. */
ArrayObject* getOrCreateMatchResultTemplateObject(JSContext* cx, ResultTemplateKind kind = ResultTemplateKind::Normal) {
if (matchResultTemplateObjects_[kind])
return matchResultTemplateObjects_[kind];
return createMatchResultTemplateObject(cx, kind);
}
ArrayObject* getOrCreateMatchResultTemplateObject(JSContext* cx,
ResultTemplateKind kind = Normal);
Shape* getOptimizableRegExpPrototypeShape() {
return optimizableRegExpPrototypeShape_;