Bug 1351107 - Move RegExpFlags, RegExpShared, and RegExpCompartment into vm/RegExpShared.h so that users requiring only those types don't have to import everything RegExpObject requires. r=arai

--HG--
rename : js/src/vm/RegExpObject.h => js/src/vm/RegExpShared.h
This commit is contained in:
Jeff Walden 2017-04-19 16:30:18 -07:00
Родитель b87d68dcc0
Коммит ad5d6337ea
7 изменённых файлов: 385 добавлений и 340 удалений

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

@ -13,6 +13,7 @@
#include "mozilla/Maybe.h"
#include "mozilla/TypeTraits.h"
#include "jscompartment.h"
#include "jsiter.h"
#include "jspubtd.h"

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

@ -27,7 +27,7 @@
#include "js/UniquePtr.h"
#include "js/Vector.h"
#include "vm/ErrorReporting.h"
#include "vm/RegExpObject.h"
#include "vm/RegExpShared.h"
#include "vm/String.h"
#include "vm/Unicode.h"
@ -200,7 +200,7 @@ struct Token
u.atom = atom;
}
void setRegExpFlags(js::RegExpFlag flags) {
void setRegExpFlags(RegExpFlag flags) {
MOZ_ASSERT(type == TOK_REGEXP);
MOZ_ASSERT((flags & AllFlags) == flags);
u.reflags = flags;
@ -226,7 +226,7 @@ struct Token
return u.atom;
}
js::RegExpFlag regExpFlags() const {
RegExpFlag regExpFlags() const {
MOZ_ASSERT(type == TOK_REGEXP);
MOZ_ASSERT((u.reflags & AllFlags) == u.reflags);
return u.reflags;

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

@ -18,7 +18,6 @@
#include "gc/Barrier.h"
#include "gc/NurseryAwareHashMap.h"
#include "gc/Zone.h"
#include "vm/GlobalObject.h"
#include "vm/PIC.h"
#include "vm/SavedStacks.h"
#include "vm/TemplateRegistry.h"
@ -35,6 +34,7 @@ namespace gc {
template <typename Node, typename Derived> class ComponentFinder;
} // namespace gc
class GlobalObject;
class LexicalEnvironmentObject;
class ScriptSourceObject;
struct NativeIterator;

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

@ -995,7 +995,7 @@ RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pa
re->canStringMatch = true;
CompileOptions options(cx);
TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
LifoAllocScope scope(&cx->tempLifoAlloc());

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

@ -4,6 +4,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* JavaScript RegExp objects. */
#ifndef vm_RegExpObject_h
#define vm_RegExpObject_h
@ -14,66 +16,35 @@
#include "builtin/SelfHostingDefines.h"
#include "gc/Marking.h"
#include "gc/Zone.h"
#include "js/GCHashTable.h"
#include "proxy/Proxy.h"
#include "vm/ArrayObject.h"
#include "vm/RegExpShared.h"
#include "vm/Shape.h"
namespace JS { struct Zone; }
/*
* JavaScript Regular Expressions
*
* There are several engine concepts associated with a single logical regexp:
*
* RegExpObject - The JS-visible object whose .[[Class]] equals "RegExp"
*
* RegExpShared - The compiled representation of the regexp.
*
* RegExpCompartment - Owns all RegExpShared instances in a compartment.
*
* To save memory, a RegExpShared is not created for a RegExpObject until it is
* needed for execution. When a RegExpShared needs to be created, it is looked
* up in a per-compartment table to allow reuse between objects. Lastly, on GC,
* every RegExpShared that is not in active use is discarded.
* RegExpObject:
* The JS-visible object whose .[[Class]] equals "RegExp".
* RegExpShared:
* The compiled representation of the regexp (lazily created, cleared
* during some forms of GC).
* RegExpCompartment:
* Owns all RegExpShared instances in a compartment.
*/
namespace js {
struct MatchPair;
class MatchPairs;
class RegExpShared;
class RegExpStatics;
using RootedRegExpShared = JS::Rooted<RegExpShared*>;
using HandleRegExpShared = JS::Handle<RegExpShared*>;
using MutableHandleRegExpShared = JS::MutableHandle<RegExpShared*>;
namespace frontend { class TokenStream; }
enum RegExpFlag : uint8_t
{
IgnoreCaseFlag = 0x01,
GlobalFlag = 0x02,
MultilineFlag = 0x04,
StickyFlag = 0x08,
UnicodeFlag = 0x10,
NoFlags = 0x00,
AllFlags = 0x1f
};
static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG &&
GlobalFlag == REGEXP_GLOBAL_FLAG &&
MultilineFlag == REGEXP_MULTILINE_FLAG &&
StickyFlag == REGEXP_STICKY_FLAG &&
UnicodeFlag == REGEXP_UNICODE_FLAG,
"Flag values should be in sync with self-hosted JS");
enum RegExpRunStatus
{
RegExpRunStatus_Error,
RegExpRunStatus_Success,
RegExpRunStatus_Success_NotFound
};
extern RegExpObject*
RegExpAlloc(JSContext* cx, HandleObject proto = nullptr);
@ -81,273 +52,6 @@ RegExpAlloc(JSContext* cx, HandleObject proto = nullptr);
extern JSObject*
CloneRegExpObject(JSContext* cx, JSObject* regexp);
/*
* A RegExpShared is the compiled representation of a regexp. A RegExpShared is
* potentially pointed to by multiple RegExpObjects. Additionally, C++ code may
* have pointers to RegExpShareds on the stack. The RegExpShareds are kept in a
* table so that they can be reused when compiling the same regex string.
*
* During a GC, RegExpShared instances are marked and swept like GC things.
* Usually, RegExpObjects clear their pointers to their RegExpShareds rather
* than explicitly tracing them, so that the RegExpShared and any jitcode can
* be reclaimed quicker. However, the RegExpShareds are traced through by
* objects when we are preserving jitcode in their zone, to avoid the same
* recompilation inefficiencies as normal Ion and baseline compilation.
*/
class RegExpShared : public gc::TenuredCell
{
public:
enum CompilationMode {
Normal,
MatchOnly
};
enum ForceByteCodeEnum {
DontForceByteCode,
ForceByteCode
};
private:
friend class RegExpCompartment;
friend class RegExpStatics;
typedef frontend::TokenStream TokenStream;
struct RegExpCompilation
{
ReadBarriered<jit::JitCode*> jitCode;
uint8_t* byteCode;
RegExpCompilation() : byteCode(nullptr) {}
bool compiled(ForceByteCodeEnum force = DontForceByteCode) const {
return byteCode || (force == DontForceByteCode && jitCode);
}
};
/* Source to the RegExp, for lazy compilation. */
HeapPtr<JSAtom*> source;
RegExpFlag flags;
bool canStringMatch;
size_t parenCount;
RegExpCompilation compilationArray[4];
static int CompilationIndex(CompilationMode mode, bool latin1) {
switch (mode) {
case Normal: return latin1 ? 0 : 1;
case MatchOnly: return latin1 ? 2 : 3;
}
MOZ_CRASH();
}
// Tables referenced by JIT code.
using JitCodeTables = Vector<uint8_t*, 0, SystemAllocPolicy>;
JitCodeTables tables;
/* Internal functions. */
RegExpShared(JSAtom* source, RegExpFlag flags);
static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleLinearString input,
CompilationMode mode, ForceByteCodeEnum force);
static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleAtom pattern,
HandleLinearString input, CompilationMode mode, ForceByteCodeEnum force);
static bool compileIfNecessary(JSContext* cx, MutableHandleRegExpShared res,
HandleLinearString input, CompilationMode mode,
ForceByteCodeEnum force);
const RegExpCompilation& compilation(CompilationMode mode, bool latin1) const {
return compilationArray[CompilationIndex(mode, latin1)];
}
RegExpCompilation& compilation(CompilationMode mode, bool latin1) {
return compilationArray[CompilationIndex(mode, latin1)];
}
public:
~RegExpShared() = delete;
// Execute this RegExp on input starting from searchIndex, filling in
// matches if specified and otherwise only determining if there is a match.
static RegExpRunStatus execute(JSContext* cx, MutableHandleRegExpShared res,
HandleLinearString input, size_t searchIndex,
MatchPairs* matches, size_t* endIndex);
// Register a table with this RegExpShared, and take ownership.
bool addTable(uint8_t* table) {
return tables.append(table);
}
/* Accessors */
size_t getParenCount() const {
MOZ_ASSERT(isCompiled());
return parenCount;
}
/* Accounts for the "0" (whole match) pair. */
size_t pairCount() const { return getParenCount() + 1; }
JSAtom* getSource() const { return source; }
RegExpFlag getFlags() const { return flags; }
bool ignoreCase() const { return flags & IgnoreCaseFlag; }
bool global() const { return flags & GlobalFlag; }
bool multiline() const { return flags & MultilineFlag; }
bool sticky() const { return flags & StickyFlag; }
bool unicode() const { return flags & UnicodeFlag; }
bool isCompiled(CompilationMode mode, bool latin1,
ForceByteCodeEnum force = DontForceByteCode) const {
return compilation(mode, latin1).compiled(force);
}
bool isCompiled() const {
return isCompiled(Normal, true) || isCompiled(Normal, false)
|| isCompiled(MatchOnly, true) || isCompiled(MatchOnly, false);
}
void traceChildren(JSTracer* trc);
void discardJitCode();
void finalize(FreeOp* fop);
static size_t offsetOfSource() {
return offsetof(RegExpShared, source);
}
static size_t offsetOfFlags() {
return offsetof(RegExpShared, flags);
}
static size_t offsetOfParenCount() {
return offsetof(RegExpShared, parenCount);
}
static size_t offsetOfLatin1JitCode(CompilationMode mode) {
return offsetof(RegExpShared, compilationArray)
+ (CompilationIndex(mode, true) * sizeof(RegExpCompilation))
+ offsetof(RegExpCompilation, jitCode);
}
static size_t offsetOfTwoByteJitCode(CompilationMode mode) {
return offsetof(RegExpShared, compilationArray)
+ (CompilationIndex(mode, false) * sizeof(RegExpCompilation))
+ offsetof(RegExpCompilation, jitCode);
}
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
#ifdef DEBUG
static bool dumpBytecode(JSContext* cx, MutableHandleRegExpShared res, bool match_only,
HandleLinearString input);
#endif
};
class RegExpCompartment
{
struct Key {
JSAtom* atom;
uint16_t flag;
Key() {}
Key(JSAtom* atom, RegExpFlag flag)
: atom(atom), flag(flag)
{ }
MOZ_IMPLICIT Key(const ReadBarriered<RegExpShared*>& shared)
: atom(shared.unbarrieredGet()->getSource()),
flag(shared.unbarrieredGet()->getFlags())
{ }
typedef Key Lookup;
static HashNumber hash(const Lookup& l) {
return DefaultHasher<JSAtom*>::hash(l.atom) ^ (l.flag << 1);
}
static bool match(Key l, Key r) {
return l.atom == r.atom && l.flag == r.flag;
}
};
/*
* The set of all RegExpShareds in the compartment. On every GC, every
* RegExpShared that was not marked is deleted and removed from the set.
*/
using Set = GCHashSet<ReadBarriered<RegExpShared*>, Key, RuntimeAllocPolicy>;
JS::WeakCache<Set> set_;
/*
* This is the template object where the result of re.exec() is based on,
* if there is a result. This is used in CreateRegExpMatchResult to set
* the input/index properties faster.
*/
ReadBarriered<ArrayObject*> matchResultTemplateObject_;
/*
* The shape of RegExp.prototype object that satisfies following:
* * RegExp.prototype.flags getter is not modified
* * RegExp.prototype.global getter is not modified
* * RegExp.prototype.ignoreCase getter is not modified
* * RegExp.prototype.multiline getter is not modified
* * RegExp.prototype.sticky getter is not modified
* * RegExp.prototype.unicode getter is not modified
* * RegExp.prototype.exec is an own data property
* * RegExp.prototype[@@match] is an own data property
* * RegExp.prototype[@@search] is an own data property
*/
ReadBarriered<Shape*> optimizableRegExpPrototypeShape_;
/*
* The shape of RegExp instance that satisfies following:
* * lastProperty is lastIndex
* * prototype is RegExp.prototype
*/
ReadBarriered<Shape*> optimizableRegExpInstanceShape_;
ArrayObject* createMatchResultTemplateObject(JSContext* cx);
public:
explicit RegExpCompartment(Zone* zone);
~RegExpCompartment();
bool init(JSContext* cx);
void sweep(JSRuntime* rt);
bool empty() { return set_.empty(); }
bool get(JSContext* cx, HandleAtom source, RegExpFlag flags, MutableHandleRegExpShared shared);
/* Like 'get', but compile 'maybeOpt' (if non-null). */
bool get(JSContext* cx, HandleAtom source, JSString* maybeOpt,
MutableHandleRegExpShared shared);
/* Get or create template object used to base the result of .exec() on. */
ArrayObject* getOrCreateMatchResultTemplateObject(JSContext* cx) {
if (matchResultTemplateObject_)
return matchResultTemplateObject_;
return createMatchResultTemplateObject(cx);
}
Shape* getOptimizableRegExpPrototypeShape() {
return optimizableRegExpPrototypeShape_;
}
void setOptimizableRegExpPrototypeShape(Shape* shape) {
optimizableRegExpPrototypeShape_ = shape;
}
Shape* getOptimizableRegExpInstanceShape() {
return optimizableRegExpInstanceShape_;
}
void setOptimizableRegExpInstanceShape(Shape* shape) {
optimizableRegExpInstanceShape_ = shape;
}
static size_t offsetOfOptimizableRegExpPrototypeShape() {
return offsetof(RegExpCompartment, optimizableRegExpPrototypeShape_);
}
static size_t offsetOfOptimizableRegExpInstanceShape() {
return offsetof(RegExpCompartment, optimizableRegExpInstanceShape_);
}
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
};
class RegExpObject : public NativeObject
{
static const unsigned LAST_INDEX_SLOT = 0;
@ -520,29 +224,4 @@ StringHasRegExpMetaChars(JSLinearString* str);
} /* namespace js */
namespace JS {
namespace ubi {
template <>
class Concrete<js::RegExpShared> : TracerConcrete<js::RegExpShared>
{
protected:
explicit Concrete(js::RegExpShared* ptr) : TracerConcrete<js::RegExpShared>(ptr) { }
public:
static void construct(void* storage, js::RegExpShared* ptr) {
new (storage) Concrete(ptr);
}
CoarseType coarseType() const final { return CoarseType::Other; }
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
const char16_t* typeName() const override { return concreteTypeName; }
static const char16_t concreteTypeName[];
};
} // namespace ubi
} // namespace JS
#endif /* vm_RegExpObject_h */

363
js/src/vm/RegExpShared.h Normal file
Просмотреть файл

@ -0,0 +1,363 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* The compiled representation of a RegExp, potentially shared among RegExp instances created
* during separate evaluations of a single RegExp literal in source code.
*/
#ifndef vm_RegExpShared_h
#define vm_RegExpShared_h
#include "mozilla/Assertions.h"
#include "mozilla/MemoryReporting.h"
#include "jsalloc.h"
#include "jsatom.h"
#include "builtin/SelfHostingDefines.h"
#include "gc/Heap.h"
#include "gc/Marking.h"
#include "js/UbiNode.h"
#include "js/Vector.h"
struct JSContext;
namespace js {
class ArrayObject;
class MatchPairs;
class RegExpCompartment;
class RegExpShared;
class RegExpStatics;
using RootedRegExpShared = JS::Rooted<RegExpShared*>;
using HandleRegExpShared = JS::Handle<RegExpShared*>;
using MutableHandleRegExpShared = JS::MutableHandle<RegExpShared*>;
enum RegExpFlag : uint8_t
{
IgnoreCaseFlag = 0x01,
GlobalFlag = 0x02,
MultilineFlag = 0x04,
StickyFlag = 0x08,
UnicodeFlag = 0x10,
NoFlags = 0x00,
AllFlags = 0x1f
};
static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG &&
GlobalFlag == REGEXP_GLOBAL_FLAG &&
MultilineFlag == REGEXP_MULTILINE_FLAG &&
StickyFlag == REGEXP_STICKY_FLAG &&
UnicodeFlag == REGEXP_UNICODE_FLAG,
"Flag values should be in sync with self-hosted JS");
enum RegExpRunStatus
{
RegExpRunStatus_Error,
RegExpRunStatus_Success,
RegExpRunStatus_Success_NotFound
};
/*
* A RegExpShared is the compiled representation of a regexp. A RegExpShared is
* potentially pointed to by multiple RegExpObjects. Additionally, C++ code may
* have pointers to RegExpShareds on the stack. The RegExpShareds are kept in a
* table so that they can be reused when compiling the same regex string.
*
* To save memory, a RegExpShared is not created for a RegExpObject until it is
* needed for execution. When a RegExpShared needs to be created, it is looked
* up in a per-compartment table to allow reuse between objects.
*
* During a GC, RegExpShared instances are marked and swept like GC things.
* Usually, RegExpObjects clear their pointers to their RegExpShareds rather
* than explicitly tracing them, so that the RegExpShared and any jitcode can
* be reclaimed quicker. However, the RegExpShareds are traced through by
* objects when we are preserving jitcode in their zone, to avoid the same
* recompilation inefficiencies as normal Ion and baseline compilation.
*/
class RegExpShared : public gc::TenuredCell
{
public:
enum CompilationMode {
Normal,
MatchOnly
};
enum ForceByteCodeEnum {
DontForceByteCode,
ForceByteCode
};
private:
friend class RegExpCompartment;
friend class RegExpStatics;
struct RegExpCompilation
{
ReadBarriered<jit::JitCode*> jitCode;
uint8_t* byteCode;
RegExpCompilation() : byteCode(nullptr) {}
bool compiled(ForceByteCodeEnum force = DontForceByteCode) const {
return byteCode || (force == DontForceByteCode && jitCode);
}
};
/* Source to the RegExp, for lazy compilation. */
HeapPtr<JSAtom*> source;
RegExpFlag flags;
bool canStringMatch;
size_t parenCount;
RegExpCompilation compilationArray[4];
static int CompilationIndex(CompilationMode mode, bool latin1) {
switch (mode) {
case Normal: return latin1 ? 0 : 1;
case MatchOnly: return latin1 ? 2 : 3;
}
MOZ_CRASH();
}
// Tables referenced by JIT code.
using JitCodeTables = Vector<uint8_t*, 0, SystemAllocPolicy>;
JitCodeTables tables;
/* Internal functions. */
RegExpShared(JSAtom* source, RegExpFlag flags);
static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleLinearString input,
CompilationMode mode, ForceByteCodeEnum force);
static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleAtom pattern,
HandleLinearString input, CompilationMode mode, ForceByteCodeEnum force);
static bool compileIfNecessary(JSContext* cx, MutableHandleRegExpShared res,
HandleLinearString input, CompilationMode mode,
ForceByteCodeEnum force);
const RegExpCompilation& compilation(CompilationMode mode, bool latin1) const {
return compilationArray[CompilationIndex(mode, latin1)];
}
RegExpCompilation& compilation(CompilationMode mode, bool latin1) {
return compilationArray[CompilationIndex(mode, latin1)];
}
public:
~RegExpShared() = delete;
// Execute this RegExp on input starting from searchIndex, filling in
// matches if specified and otherwise only determining if there is a match.
static RegExpRunStatus execute(JSContext* cx, MutableHandleRegExpShared res,
HandleLinearString input, size_t searchIndex,
MatchPairs* matches, size_t* endIndex);
// Register a table with this RegExpShared, and take ownership.
bool addTable(uint8_t* table) {
return tables.append(table);
}
/* Accessors */
size_t getParenCount() const {
MOZ_ASSERT(isCompiled());
return parenCount;
}
/* Accounts for the "0" (whole match) pair. */
size_t pairCount() const { return getParenCount() + 1; }
JSAtom* getSource() const { return source; }
RegExpFlag getFlags() const { return flags; }
bool ignoreCase() const { return flags & IgnoreCaseFlag; }
bool global() const { return flags & GlobalFlag; }
bool multiline() const { return flags & MultilineFlag; }
bool sticky() const { return flags & StickyFlag; }
bool unicode() const { return flags & UnicodeFlag; }
bool isCompiled(CompilationMode mode, bool latin1,
ForceByteCodeEnum force = DontForceByteCode) const {
return compilation(mode, latin1).compiled(force);
}
bool isCompiled() const {
return isCompiled(Normal, true) || isCompiled(Normal, false)
|| isCompiled(MatchOnly, true) || isCompiled(MatchOnly, false);
}
void traceChildren(JSTracer* trc);
void discardJitCode();
void finalize(FreeOp* fop);
static size_t offsetOfSource() {
return offsetof(RegExpShared, source);
}
static size_t offsetOfFlags() {
return offsetof(RegExpShared, flags);
}
static size_t offsetOfParenCount() {
return offsetof(RegExpShared, parenCount);
}
static size_t offsetOfLatin1JitCode(CompilationMode mode) {
return offsetof(RegExpShared, compilationArray)
+ (CompilationIndex(mode, true) * sizeof(RegExpCompilation))
+ offsetof(RegExpCompilation, jitCode);
}
static size_t offsetOfTwoByteJitCode(CompilationMode mode) {
return offsetof(RegExpShared, compilationArray)
+ (CompilationIndex(mode, false) * sizeof(RegExpCompilation))
+ offsetof(RegExpCompilation, jitCode);
}
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
#ifdef DEBUG
static bool dumpBytecode(JSContext* cx, MutableHandleRegExpShared res, bool match_only,
HandleLinearString input);
#endif
};
class RegExpCompartment
{
struct Key {
JSAtom* atom;
uint16_t flag;
Key() {}
Key(JSAtom* atom, RegExpFlag flag)
: atom(atom), flag(flag)
{ }
MOZ_IMPLICIT Key(const ReadBarriered<RegExpShared*>& shared)
: atom(shared.unbarrieredGet()->getSource()),
flag(shared.unbarrieredGet()->getFlags())
{ }
typedef Key Lookup;
static HashNumber hash(const Lookup& l) {
return DefaultHasher<JSAtom*>::hash(l.atom) ^ (l.flag << 1);
}
static bool match(Key l, Key r) {
return l.atom == r.atom && l.flag == r.flag;
}
};
/*
* The set of all RegExpShareds in the compartment. On every GC, every
* RegExpShared that was not marked is deleted and removed from the set.
*/
using Set = JS::GCHashSet<ReadBarriered<RegExpShared*>, Key, RuntimeAllocPolicy>;
JS::WeakCache<Set> set_;
/*
* This is the template object where the result of re.exec() is based on,
* if there is a result. This is used in CreateRegExpMatchResult to set
* the input/index properties faster.
*/
ReadBarriered<ArrayObject*> matchResultTemplateObject_;
/*
* The shape of RegExp.prototype object that satisfies following:
* * RegExp.prototype.flags getter is not modified
* * RegExp.prototype.global getter is not modified
* * RegExp.prototype.ignoreCase getter is not modified
* * RegExp.prototype.multiline getter is not modified
* * RegExp.prototype.sticky getter is not modified
* * RegExp.prototype.unicode getter is not modified
* * RegExp.prototype.exec is an own data property
* * RegExp.prototype[@@match] is an own data property
* * RegExp.prototype[@@search] is an own data property
*/
ReadBarriered<Shape*> optimizableRegExpPrototypeShape_;
/*
* The shape of RegExp instance that satisfies following:
* * lastProperty is lastIndex
* * prototype is RegExp.prototype
*/
ReadBarriered<Shape*> optimizableRegExpInstanceShape_;
ArrayObject* createMatchResultTemplateObject(JSContext* cx);
public:
explicit RegExpCompartment(Zone* zone);
~RegExpCompartment();
bool init(JSContext* cx);
void sweep(JSRuntime* rt);
bool empty() { return set_.empty(); }
bool get(JSContext* cx, HandleAtom source, RegExpFlag flags, MutableHandleRegExpShared shared);
/* Like 'get', but compile 'maybeOpt' (if non-null). */
bool get(JSContext* cx, HandleAtom source, JSString* maybeOpt,
MutableHandleRegExpShared shared);
/* Get or create template object used to base the result of .exec() on. */
ArrayObject* getOrCreateMatchResultTemplateObject(JSContext* cx) {
if (matchResultTemplateObject_)
return matchResultTemplateObject_;
return createMatchResultTemplateObject(cx);
}
Shape* getOptimizableRegExpPrototypeShape() {
return optimizableRegExpPrototypeShape_;
}
void setOptimizableRegExpPrototypeShape(Shape* shape) {
optimizableRegExpPrototypeShape_ = shape;
}
Shape* getOptimizableRegExpInstanceShape() {
return optimizableRegExpInstanceShape_;
}
void setOptimizableRegExpInstanceShape(Shape* shape) {
optimizableRegExpInstanceShape_ = shape;
}
static size_t offsetOfOptimizableRegExpPrototypeShape() {
return offsetof(RegExpCompartment, optimizableRegExpPrototypeShape_);
}
static size_t offsetOfOptimizableRegExpInstanceShape() {
return offsetof(RegExpCompartment, optimizableRegExpInstanceShape_);
}
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
};
} /* namespace js */
namespace JS {
namespace ubi {
template <>
class Concrete<js::RegExpShared> : TracerConcrete<js::RegExpShared>
{
protected:
explicit Concrete(js::RegExpShared* ptr) : TracerConcrete<js::RegExpShared>(ptr) { }
public:
static void construct(void* storage, js::RegExpShared* ptr) {
new (storage) Concrete(ptr);
}
CoarseType coarseType() const final { return CoarseType::Other; }
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
const char16_t* typeName() const override { return concreteTypeName; }
static const char16_t concreteTypeName[];
};
} // namespace ubi
} // namespace JS
#endif /* vm_RegExpShared_h */

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

@ -7,9 +7,11 @@
#ifndef vm_RegExpStatics_h
#define vm_RegExpStatics_h
#include "jscntxt.h"
#include "gc/Marking.h"
#include "vm/MatchPairs.h"
#include "vm/RegExpObject.h"
#include "vm/RegExpShared.h"
#include "vm/Runtime.h"
namespace js {