mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
Bug 625600: Update Yarr import to WebKit rev 86639, r=cdleary,dvander
This commit is contained in:
parent
788ba5d7fa
commit
8cb0de51d8
@ -362,7 +362,6 @@ CPPSRCS += MethodJIT.cpp \
|
||||
Retcon.cpp \
|
||||
TrampolineCompiler.cpp \
|
||||
$(NULL)
|
||||
# PICStubCompiler.cpp \
|
||||
|
||||
ifeq (86, $(findstring 86,$(TARGET_CPU)))
|
||||
ifeq (x86_64, $(TARGET_CPU))
|
||||
@ -420,14 +419,17 @@ ifeq (,$(filter arm% sparc %86 x86_64,$(TARGET_CPU)))
|
||||
|
||||
VPATH += $(srcdir)/assembler \
|
||||
$(srcdir)/assembler/wtf \
|
||||
$(srcdir)/yarr/pcre \
|
||||
$(srcdir)/yarr\
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += pcre_compile.cpp \
|
||||
pcre_exec.cpp \
|
||||
pcre_tables.cpp \
|
||||
pcre_xclass.cpp \
|
||||
pcre_ucp_searchfuncs.cpp \
|
||||
CPPSRCS += \
|
||||
Assertions.cpp \
|
||||
OSAllocatorPosix.cpp \
|
||||
OSAllocatorWin.cpp \
|
||||
PageBlock.cpp \
|
||||
YarrInterpreter.cpp \
|
||||
YarrPattern.cpp \
|
||||
YarrSyntaxChecker.cpp \
|
||||
$(NULL)
|
||||
else
|
||||
|
||||
@ -440,9 +442,6 @@ VPATH += $(srcdir)/assembler \
|
||||
$(srcdir)/assembler/assembler \
|
||||
$(srcdir)/methodjit \
|
||||
$(srcdir)/yarr \
|
||||
$(srcdir)/yarr/yarr \
|
||||
$(srcdir)/yarr/pcre \
|
||||
$(srcdir)/yarr/wtf \
|
||||
$(NONE)
|
||||
|
||||
CPPSRCS += Assertions.cpp \
|
||||
@ -451,16 +450,16 @@ CPPSRCS += Assertions.cpp \
|
||||
ExecutableAllocatorOS2.cpp \
|
||||
ExecutableAllocator.cpp \
|
||||
ARMAssembler.cpp \
|
||||
Logging.cpp \
|
||||
Logging.cpp \
|
||||
MacroAssemblerARM.cpp \
|
||||
MacroAssemblerX86Common.cpp \
|
||||
RegexCompiler.cpp \
|
||||
RegexJIT.cpp \
|
||||
pcre_compile.cpp \
|
||||
pcre_exec.cpp \
|
||||
pcre_tables.cpp \
|
||||
pcre_xclass.cpp \
|
||||
pcre_ucp_searchfuncs.cpp \
|
||||
OSAllocatorPosix.cpp \
|
||||
OSAllocatorWin.cpp \
|
||||
PageBlock.cpp \
|
||||
YarrInterpreter.cpp \
|
||||
YarrJIT.cpp \
|
||||
YarrPattern.cpp \
|
||||
YarrSyntaxChecker.cpp \
|
||||
$(NONE)
|
||||
|
||||
ifeq (86, $(findstring 86,$(TARGET_CPU)))
|
||||
@ -653,7 +652,7 @@ check-malloc-function-usage: $(filter-out %jsalloc.h %jscntxt.h %jsutil.h, $(ALL
|
||||
|
||||
# We desire these numbers to go down, not up. See "User guide to memory
|
||||
# management within SpiderMonkey" in jsutil.h.
|
||||
$(srcdir)/config/check_source_count.py OffTheBooks:: 52 \
|
||||
$(srcdir)/config/check_source_count.py OffTheBooks:: 54 \
|
||||
"in Makefile.in" "{cx,rt}->{new_,new_array,malloc_,calloc_,realloc_}" $^
|
||||
# This should go to zero, if possible.
|
||||
$(srcdir)/config/check_source_count.py UnwantedForeground:: 34 \
|
||||
|
@ -847,7 +847,7 @@ namespace JSC {
|
||||
|
||||
JmpSrc blx(int rm, Condition cc = AL)
|
||||
{
|
||||
#if WTF_ARM_ARCH_AT_LEAST(5)
|
||||
#if WTF_CPU_ARM && WTF_ARM_ARCH_VERSION >= 5
|
||||
int s = m_buffer.uncheckedSize();
|
||||
js::JaegerSpew(
|
||||
js::JSpew_Insns,
|
||||
@ -980,7 +980,7 @@ namespace JSC {
|
||||
|
||||
static ARMWord* getLdrImmAddress(ARMWord* insn)
|
||||
{
|
||||
#if WTF_ARM_ARCH_AT_LEAST(5)
|
||||
#if WTF_CPU_ARM && WTF_ARM_ARCH_VERSION >= 5
|
||||
// Check for call
|
||||
if ((*insn & 0x0f7f0000) != 0x051f0000) {
|
||||
// Must be BLX
|
||||
|
@ -166,13 +166,13 @@ public:
|
||||
void* m_ptr;
|
||||
};
|
||||
|
||||
// ImmPtr:
|
||||
// TrustedImmPtr:
|
||||
//
|
||||
// A pointer sized immediate operand to an instruction - this is wrapped
|
||||
// in a class requiring explicit construction in order to differentiate
|
||||
// from pointers used as absolute addresses to memory operations
|
||||
struct ImmPtr {
|
||||
explicit ImmPtr(const void* value)
|
||||
struct TrustedImmPtr {
|
||||
explicit TrustedImmPtr(const void* value)
|
||||
: m_value(value)
|
||||
{
|
||||
}
|
||||
@ -185,14 +185,21 @@ public:
|
||||
const void* m_value;
|
||||
};
|
||||
|
||||
// Imm32:
|
||||
struct ImmPtr : public TrustedImmPtr {
|
||||
explicit ImmPtr(const void* value)
|
||||
: TrustedImmPtr(value)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// TrustedImm32:
|
||||
//
|
||||
// A 32bit immediate operand to an instruction - this is wrapped in a
|
||||
// class requiring explicit construction in order to prevent RegisterIDs
|
||||
// (which are implemented as an enum) from accidentally being passed as
|
||||
// immediate values.
|
||||
struct Imm32 {
|
||||
explicit Imm32(int32_t value)
|
||||
struct TrustedImm32 {
|
||||
explicit TrustedImm32(int32_t value)
|
||||
: m_value(value)
|
||||
#if WTF_CPU_ARM || WTF_CPU_MIPS
|
||||
, m_isPointer(false)
|
||||
@ -201,7 +208,7 @@ public:
|
||||
}
|
||||
|
||||
#if !WTF_CPU_X86_64
|
||||
explicit Imm32(ImmPtr ptr)
|
||||
explicit TrustedImm32(TrustedImmPtr ptr)
|
||||
: m_value(ptr.asIntptr())
|
||||
#if WTF_CPU_ARM || WTF_CPU_MIPS
|
||||
, m_isPointer(true)
|
||||
@ -223,6 +230,20 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct Imm32 : public TrustedImm32 {
|
||||
explicit Imm32(int32_t value)
|
||||
: TrustedImm32(value)
|
||||
{
|
||||
}
|
||||
#if !WTF_CPU_X86_64
|
||||
explicit Imm32(TrustedImmPtr ptr)
|
||||
: TrustedImm32(ptr)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ImmDouble {
|
||||
union {
|
||||
struct {
|
||||
@ -241,7 +262,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Section 2: MacroAssembler code buffer handles
|
||||
//
|
||||
// The following types are used to reference items in the code buffer
|
||||
@ -273,7 +293,7 @@ public:
|
||||
|
||||
bool isUsed() const { return m_label.isUsed(); }
|
||||
void used() { m_label.used(); }
|
||||
bool isValid() const { return m_label.isValid(); }
|
||||
bool isSet() const { return m_label.isValid(); }
|
||||
private:
|
||||
JmpDst m_label;
|
||||
};
|
||||
@ -296,6 +316,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
bool isSet() const { return m_label.isValid(); }
|
||||
|
||||
private:
|
||||
JmpDst m_label;
|
||||
};
|
||||
@ -411,6 +433,20 @@ public:
|
||||
public:
|
||||
typedef js::Vector<Jump, 16 ,js::SystemAllocPolicy > JumpVector;
|
||||
|
||||
JumpList() {}
|
||||
|
||||
JumpList(const JumpList &other)
|
||||
{
|
||||
m_jumps.append(other.m_jumps);
|
||||
}
|
||||
|
||||
JumpList &operator=(const JumpList &other)
|
||||
{
|
||||
m_jumps.clear();
|
||||
m_jumps.append(other.m_jumps);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void link(AbstractMacroAssembler<AssemblerType>* masm)
|
||||
{
|
||||
size_t size = m_jumps.length();
|
||||
@ -432,17 +468,22 @@ public:
|
||||
m_jumps.append(jump);
|
||||
}
|
||||
|
||||
void append(JumpList& other)
|
||||
void append(const JumpList& other)
|
||||
{
|
||||
m_jumps.append(other.m_jumps.begin(), other.m_jumps.length());
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_jumps.clear();
|
||||
}
|
||||
|
||||
bool empty()
|
||||
{
|
||||
return !m_jumps.length();
|
||||
}
|
||||
|
||||
const JumpVector& jumps() { return m_jumps; }
|
||||
const JumpVector& jumps() const { return m_jumps; }
|
||||
|
||||
private:
|
||||
JumpVector m_jumps;
|
||||
|
@ -95,12 +95,12 @@ public:
|
||||
storePtr(src, Address(stackPointerRegister, (index * sizeof(void*))));
|
||||
}
|
||||
|
||||
void poke(Imm32 value, int index = 0)
|
||||
void poke(TrustedImm32 value, int index = 0)
|
||||
{
|
||||
store32(value, Address(stackPointerRegister, (index * sizeof(void*))));
|
||||
}
|
||||
|
||||
void poke(ImmPtr imm, int index = 0)
|
||||
void poke(TrustedImmPtr imm, int index = 0)
|
||||
{
|
||||
storePtr(imm, Address(stackPointerRegister, (index * sizeof(void*))));
|
||||
}
|
||||
@ -117,7 +117,7 @@ public:
|
||||
branch32(cond, op1, op2).linkTo(target, this);
|
||||
}
|
||||
|
||||
void branch32(Condition cond, RegisterID op1, Imm32 imm, Label target)
|
||||
void branch32(Condition cond, RegisterID op1, TrustedImm32 imm, Label target)
|
||||
{
|
||||
branch32(cond, op1, imm).linkTo(target, this);
|
||||
}
|
||||
@ -177,21 +177,11 @@ public:
|
||||
and32(src, dest);
|
||||
}
|
||||
|
||||
void andPtr(Address address, RegisterID srcDest)
|
||||
{
|
||||
and32(address, srcDest);
|
||||
}
|
||||
|
||||
void andPtr(Imm32 imm, RegisterID srcDest)
|
||||
{
|
||||
and32(imm, srcDest);
|
||||
}
|
||||
|
||||
void andPtr(ImmPtr ptr, RegisterID srcDest)
|
||||
{
|
||||
and32(Imm32(ptr), srcDest);
|
||||
}
|
||||
|
||||
void notPtr(RegisterID srcDest)
|
||||
{
|
||||
not32(srcDest);
|
||||
@ -212,11 +202,6 @@ public:
|
||||
or32(imm, dest);
|
||||
}
|
||||
|
||||
void orPtr(Address address, RegisterID srcDest)
|
||||
{
|
||||
or32(address, srcDest);
|
||||
}
|
||||
|
||||
void subPtr(RegisterID src, RegisterID dest)
|
||||
{
|
||||
sub32(src, dest);
|
||||
@ -278,27 +263,22 @@ public:
|
||||
store32(src, address);
|
||||
}
|
||||
|
||||
void storePtr(RegisterID src, BaseIndex address)
|
||||
{
|
||||
store32(src, address);
|
||||
}
|
||||
|
||||
void storePtr(RegisterID src, void* address)
|
||||
{
|
||||
store32(src, address);
|
||||
}
|
||||
|
||||
void storePtr(ImmPtr imm, ImplicitAddress address)
|
||||
void storePtr(TrustedImmPtr imm, ImplicitAddress address)
|
||||
{
|
||||
store32(Imm32(imm), address);
|
||||
}
|
||||
|
||||
void storePtr(ImmPtr imm, BaseIndex address)
|
||||
void storePtr(TrustedImmPtr imm, BaseIndex address)
|
||||
{
|
||||
store32(Imm32(imm), address);
|
||||
}
|
||||
|
||||
void storePtr(ImmPtr imm, void* address)
|
||||
void storePtr(TrustedImmPtr imm, void* address)
|
||||
{
|
||||
store32(Imm32(imm), address);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#include "MacroAssemblerARM.h"
|
||||
|
||||
#if WTF_PLATFORM_LINUX || WTF_PLATFORM_ANDROID
|
||||
#if WTF_OS_LINUX || WTF_OS_ANDROID
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -91,14 +91,14 @@ public:
|
||||
m_assembler.adds_r(dest, dest, src);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, Address address)
|
||||
void add32(TrustedImm32 imm, Address address)
|
||||
{
|
||||
load32(address, ARMRegisters::S1);
|
||||
add32(imm, ARMRegisters::S1);
|
||||
store32(ARMRegisters::S1, address);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, RegisterID dest)
|
||||
void add32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.adds_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
|
||||
}
|
||||
@ -173,7 +173,7 @@ public:
|
||||
m_assembler.orrs_r(dest, dest, src);
|
||||
}
|
||||
|
||||
void or32(Imm32 imm, RegisterID dest)
|
||||
void or32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.orrs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
|
||||
}
|
||||
@ -211,12 +211,12 @@ public:
|
||||
m_assembler.subs_r(dest, dest, src);
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, RegisterID dest)
|
||||
void sub32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.subs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, Address address)
|
||||
void sub32(TrustedImm32 imm, Address address)
|
||||
{
|
||||
load32(address, ARMRegisters::S1);
|
||||
sub32(imm, ARMRegisters::S1);
|
||||
@ -240,7 +240,7 @@ public:
|
||||
m_assembler.eors_r(dest, dest, src);
|
||||
}
|
||||
|
||||
void xor32(Imm32 imm, RegisterID dest)
|
||||
void xor32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
|
||||
}
|
||||
@ -380,7 +380,7 @@ public:
|
||||
m_assembler.baseIndexTransfer32(false, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, BaseIndex address)
|
||||
void store32(TrustedImm32 imm, BaseIndex address)
|
||||
{
|
||||
if (imm.m_isPointer)
|
||||
m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value);
|
||||
@ -389,7 +389,7 @@ public:
|
||||
store32(ARMRegisters::S1, address);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, ImplicitAddress address)
|
||||
void store32(TrustedImm32 imm, ImplicitAddress address)
|
||||
{
|
||||
if (imm.m_isPointer)
|
||||
m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value);
|
||||
@ -404,7 +404,7 @@ public:
|
||||
m_assembler.dtr_u(false, src, ARMRegisters::S0, 0);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, void* address)
|
||||
void store32(TrustedImm32 imm, void* address)
|
||||
{
|
||||
m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
|
||||
if (imm.m_isPointer)
|
||||
@ -436,7 +436,7 @@ public:
|
||||
push(ARMRegisters::S0);
|
||||
}
|
||||
|
||||
void move(Imm32 imm, RegisterID dest)
|
||||
void move(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
if (imm.m_isPointer)
|
||||
m_assembler.ldr_un_imm(dest, imm.m_value);
|
||||
@ -449,7 +449,7 @@ public:
|
||||
m_assembler.mov_r(dest, src);
|
||||
}
|
||||
|
||||
void move(ImmPtr imm, RegisterID dest)
|
||||
void move(TrustedImmPtr imm, RegisterID dest)
|
||||
{
|
||||
move(Imm32(imm), dest);
|
||||
}
|
||||
@ -485,7 +485,7 @@ public:
|
||||
return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, RegisterID left, Imm32 right, int useConstantPool = 0)
|
||||
Jump branch32(Condition cond, RegisterID left, TrustedImm32 right, int useConstantPool = 0)
|
||||
{
|
||||
ASSERT(left != ARMRegisters::S0);
|
||||
if (right.m_isPointer) {
|
||||
@ -500,21 +500,21 @@ public:
|
||||
// number of instructions emitted is constant, regardless of the argument
|
||||
// values. For ARM, this is identical to branch32WithPatch, except that it
|
||||
// does not generate a DataLabel32.
|
||||
Jump branch32FixedLength(Condition cond, RegisterID left, Imm32 right)
|
||||
Jump branch32FixedLength(Condition cond, RegisterID left, TrustedImm32 right)
|
||||
{
|
||||
m_assembler.ldr_un_imm(ARMRegisters::S1, right.m_value);
|
||||
return branch32(cond, left, ARMRegisters::S1, true);
|
||||
}
|
||||
|
||||
// As branch32_force32, but allow the value ('right') to be patched.
|
||||
Jump branch32WithPatch(Condition cond, RegisterID left, Imm32 right, DataLabel32 &dataLabel)
|
||||
Jump branch32WithPatch(Condition cond, RegisterID left, TrustedImm32 right, DataLabel32 &dataLabel)
|
||||
{
|
||||
ASSERT(left != ARMRegisters::S1);
|
||||
dataLabel = moveWithPatch(right, ARMRegisters::S1);
|
||||
return branch32(cond, left, ARMRegisters::S1, true);
|
||||
}
|
||||
|
||||
Jump branch32WithPatch(Condition cond, Address left, Imm32 right, DataLabel32 &dataLabel)
|
||||
Jump branch32WithPatch(Condition cond, Address left, TrustedImm32 right, DataLabel32 &dataLabel)
|
||||
{
|
||||
ASSERT(left.base != ARMRegisters::S1);
|
||||
load32(left, ARMRegisters::S1);
|
||||
@ -534,19 +534,19 @@ public:
|
||||
return branch32(cond, ARMRegisters::S1, right);
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, Address left, Imm32 right)
|
||||
Jump branch32(Condition cond, Address left, TrustedImm32 right)
|
||||
{
|
||||
load32(left, ARMRegisters::S1);
|
||||
return branch32(cond, ARMRegisters::S1, right);
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, BaseIndex left, Imm32 right)
|
||||
Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
|
||||
{
|
||||
load32(left, ARMRegisters::S1);
|
||||
return branch32(cond, ARMRegisters::S1, right);
|
||||
}
|
||||
|
||||
Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
|
||||
Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
|
||||
{
|
||||
load32WithUnalignedHalfWords(left, ARMRegisters::S1);
|
||||
return branch32(cond, ARMRegisters::S1, right);
|
||||
@ -828,7 +828,7 @@ public:
|
||||
setTest32(cond, address, mask, dest);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, RegisterID src, RegisterID dest)
|
||||
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
|
||||
{
|
||||
m_assembler.add_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
|
||||
}
|
||||
@ -850,7 +850,7 @@ public:
|
||||
move(ARMRegisters::S1, dest);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, AbsoluteAddress address)
|
||||
void add32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
|
||||
m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
|
||||
@ -859,7 +859,7 @@ public:
|
||||
m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, AbsoluteAddress address)
|
||||
void sub32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
|
||||
m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
|
||||
@ -880,7 +880,7 @@ public:
|
||||
return branch32(cond, ARMRegisters::S1, right);
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
|
||||
Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right)
|
||||
{
|
||||
load32(left.m_ptr, ARMRegisters::S1);
|
||||
return branch32(cond, ARMRegisters::S1, right);
|
||||
@ -908,14 +908,14 @@ public:
|
||||
return Call::fromTailJump(oldJump);
|
||||
}
|
||||
|
||||
DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
|
||||
DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
|
||||
{
|
||||
DataLabelPtr dataLabel(this);
|
||||
m_assembler.ldr_un_imm(dest, reinterpret_cast<ARMWord>(initialValue.m_value));
|
||||
return dataLabel;
|
||||
}
|
||||
|
||||
DataLabel32 moveWithPatch(Imm32 initialValue, RegisterID dest)
|
||||
DataLabel32 moveWithPatch(TrustedImm32 initialValue, RegisterID dest)
|
||||
{
|
||||
DataLabel32 dataLabel(this);
|
||||
m_assembler.ldr_un_imm(dest, initialValue.m_value);
|
||||
@ -937,7 +937,7 @@ public:
|
||||
return jump;
|
||||
}
|
||||
|
||||
DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
|
||||
DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
|
||||
{
|
||||
DataLabelPtr dataLabel = moveWithPatch(initialValue, ARMRegisters::S1);
|
||||
store32(ARMRegisters::S1, address);
|
||||
|
@ -52,7 +52,7 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<ARMv7Assembler> {
|
||||
struct ArmAddress {
|
||||
enum AddressType {
|
||||
HasOffset,
|
||||
HasIndex,
|
||||
HasIndex
|
||||
} type;
|
||||
RegisterID base;
|
||||
union {
|
||||
@ -113,7 +113,7 @@ public:
|
||||
DoubleGreaterThanOrUnordered = ARMv7Assembler::ConditionHI,
|
||||
DoubleGreaterThanOrEqualOrUnordered = ARMv7Assembler::ConditionHS,
|
||||
DoubleLessThanOrUnordered = ARMv7Assembler::ConditionLT,
|
||||
DoubleLessThanOrEqualOrUnordered = ARMv7Assembler::ConditionLE,
|
||||
DoubleLessThanOrEqualOrUnordered = ARMv7Assembler::ConditionLE
|
||||
};
|
||||
|
||||
static const RegisterID stackPointerRegister = ARMRegisters::sp;
|
||||
@ -131,12 +131,12 @@ public:
|
||||
m_assembler.add(dest, dest, src);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, RegisterID dest)
|
||||
void add32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
add32(imm, dest, dest);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, RegisterID src, RegisterID dest)
|
||||
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
|
||||
{
|
||||
ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
|
||||
if (armImm.isValid())
|
||||
@ -147,7 +147,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, Address address)
|
||||
void add32(TrustedImm32 imm, Address address)
|
||||
{
|
||||
load32(address, dataTempRegister);
|
||||
|
||||
@ -170,7 +170,7 @@ public:
|
||||
add32(dataTempRegister, dest);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, AbsoluteAddress address)
|
||||
void add32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
load32(address.m_ptr, dataTempRegister);
|
||||
|
||||
@ -239,7 +239,7 @@ public:
|
||||
m_assembler.orr(dest, dest, src);
|
||||
}
|
||||
|
||||
void or32(Imm32 imm, RegisterID dest)
|
||||
void or32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
|
||||
if (armImm.isValid())
|
||||
@ -285,7 +285,7 @@ public:
|
||||
m_assembler.sub(dest, dest, src);
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, RegisterID dest)
|
||||
void sub32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
|
||||
if (armImm.isValid())
|
||||
@ -296,7 +296,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, Address address)
|
||||
void sub32(TrustedImm32 imm, Address address)
|
||||
{
|
||||
load32(address, dataTempRegister);
|
||||
|
||||
@ -319,7 +319,7 @@ public:
|
||||
sub32(dataTempRegister, dest);
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, AbsoluteAddress address)
|
||||
void sub32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
load32(address.m_ptr, dataTempRegister);
|
||||
|
||||
@ -341,7 +341,7 @@ public:
|
||||
m_assembler.eor(dest, dest, src);
|
||||
}
|
||||
|
||||
void xor32(Imm32 imm, RegisterID dest)
|
||||
void xor32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
|
||||
if (armImm.isValid())
|
||||
@ -486,7 +486,7 @@ public:
|
||||
store32(src, setupArmAddress(address));
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, ImplicitAddress address)
|
||||
void store32(TrustedImm32 imm, ImplicitAddress address)
|
||||
{
|
||||
move(imm, dataTempRegister);
|
||||
store32(dataTempRegister, setupArmAddress(address));
|
||||
@ -498,7 +498,7 @@ public:
|
||||
m_assembler.str(src, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, void* address)
|
||||
void store32(TrustedImm32 imm, void* address)
|
||||
{
|
||||
move(imm, dataTempRegister);
|
||||
store32(dataTempRegister, address);
|
||||
@ -667,7 +667,7 @@ public:
|
||||
//
|
||||
// Move values in registers.
|
||||
|
||||
void move(Imm32 imm, RegisterID dest)
|
||||
void move(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
uint32_t value = imm.m_value;
|
||||
|
||||
@ -693,7 +693,7 @@ public:
|
||||
m_assembler.mov(dest, src);
|
||||
}
|
||||
|
||||
void move(ImmPtr imm, RegisterID dest)
|
||||
void move(TrustedImmPtr imm, RegisterID dest)
|
||||
{
|
||||
move(Imm32(imm), dest);
|
||||
}
|
||||
@ -780,7 +780,7 @@ public:
|
||||
return Jump(makeBranch(cond));
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, RegisterID left, Imm32 right)
|
||||
Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
|
||||
{
|
||||
compare32(left, right);
|
||||
return Jump(makeBranch(cond));
|
||||
@ -798,21 +798,21 @@ public:
|
||||
return branch32(cond, dataTempRegister, right);
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, Address left, Imm32 right)
|
||||
Jump branch32(Condition cond, Address left, TrustedImm32 right)
|
||||
{
|
||||
// use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
|
||||
load32(left, addressTempRegister);
|
||||
return branch32(cond, addressTempRegister, right);
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, BaseIndex left, Imm32 right)
|
||||
Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
|
||||
{
|
||||
// use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
|
||||
load32(left, addressTempRegister);
|
||||
return branch32(cond, addressTempRegister, right);
|
||||
}
|
||||
|
||||
Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
|
||||
Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
|
||||
{
|
||||
// use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
|
||||
load32WithUnalignedHalfWords(left, addressTempRegister);
|
||||
@ -825,7 +825,7 @@ public:
|
||||
return branch32(cond, dataTempRegister, right);
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
|
||||
Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right)
|
||||
{
|
||||
// use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
|
||||
load32(left.m_ptr, addressTempRegister);
|
||||
@ -1065,13 +1065,13 @@ public:
|
||||
m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
|
||||
}
|
||||
|
||||
DataLabel32 moveWithPatch(Imm32 imm, RegisterID dst)
|
||||
DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dst)
|
||||
{
|
||||
moveFixedWidthEncoding(imm, dst);
|
||||
return DataLabel32(this);
|
||||
}
|
||||
|
||||
DataLabelPtr moveWithPatch(ImmPtr imm, RegisterID dst)
|
||||
DataLabelPtr moveWithPatch(TrustedImmPtr imm, RegisterID dst)
|
||||
{
|
||||
moveFixedWidthEncoding(Imm32(imm), dst);
|
||||
return DataLabelPtr(this);
|
||||
@ -1090,7 +1090,7 @@ public:
|
||||
return branch32(cond, addressTempRegister, dataTempRegister);
|
||||
}
|
||||
|
||||
DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
|
||||
DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
|
||||
{
|
||||
DataLabelPtr label = moveWithPatch(initialValue, dataTempRegister);
|
||||
store32(dataTempRegister, address);
|
||||
@ -1179,7 +1179,7 @@ protected:
|
||||
return addressTempRegister;
|
||||
}
|
||||
|
||||
void moveFixedWidthEncoding(Imm32 imm, RegisterID dst)
|
||||
void moveFixedWidthEncoding(TrustedImm32 imm, RegisterID dst)
|
||||
{
|
||||
uint32_t value = imm.m_value;
|
||||
m_assembler.movT3(dst, ARMThumbImmediate::makeUInt16(value & 0xffff));
|
||||
|
@ -180,7 +180,8 @@ private:
|
||||
class MacroAssemblerCodeRef {
|
||||
public:
|
||||
MacroAssemblerCodeRef()
|
||||
: m_size(0)
|
||||
: m_executablePool(NULL),
|
||||
m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -191,6 +192,20 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
// Release the code memory in this code ref.
|
||||
void release()
|
||||
{
|
||||
if (!m_executablePool)
|
||||
return;
|
||||
|
||||
#if defined DEBUG && (defined WTF_CPU_X86 || defined WTF_CPU_X86_64)
|
||||
void *addr = m_code.executableAddress();
|
||||
memset(addr, 0xcc, m_size);
|
||||
#endif
|
||||
m_executablePool->release();
|
||||
m_executablePool = NULL;
|
||||
}
|
||||
|
||||
MacroAssemblerCodePtr m_code;
|
||||
ExecutablePool* m_executablePool;
|
||||
size_t m_size;
|
||||
|
@ -97,14 +97,14 @@ namespace JSC {
|
||||
m_assembler.addcc_r(dest, src, dest);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, Address address)
|
||||
void add32(TrustedImm32 imm, Address address)
|
||||
{
|
||||
load32(address, SparcRegisters::g2);
|
||||
add32(imm, SparcRegisters::g2);
|
||||
store32(SparcRegisters::g2, address);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, RegisterID dest)
|
||||
void add32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
if (m_assembler.isimm13(imm.m_value))
|
||||
m_assembler.addcc_imm(dest, imm.m_value, dest);
|
||||
@ -126,7 +126,7 @@ namespace JSC {
|
||||
m_assembler.andcc_r(dest, SparcRegisters::g2, dest);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, RegisterID src, RegisterID dest)
|
||||
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
|
||||
{
|
||||
if (m_assembler.isimm13(imm.m_value))
|
||||
m_assembler.addcc_imm(src, imm.m_value, dest);
|
||||
@ -194,7 +194,7 @@ namespace JSC {
|
||||
m_assembler.orcc_r(dest, src, dest);
|
||||
}
|
||||
|
||||
void or32(Imm32 imm, RegisterID dest)
|
||||
void or32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
if (m_assembler.isimm13(imm.m_value))
|
||||
m_assembler.orcc_imm(dest, imm.m_value, dest);
|
||||
@ -240,7 +240,7 @@ namespace JSC {
|
||||
m_assembler.subcc_r(dest, src, dest);
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, RegisterID dest)
|
||||
void sub32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
if (m_assembler.isimm13(imm.m_value))
|
||||
m_assembler.subcc_imm(dest, imm.m_value, dest);
|
||||
@ -250,7 +250,7 @@ namespace JSC {
|
||||
}
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, Address address)
|
||||
void sub32(TrustedImm32 imm, Address address)
|
||||
{
|
||||
load32(address, SparcRegisters::g2);
|
||||
sub32(imm, SparcRegisters::g2);
|
||||
@ -268,7 +268,7 @@ namespace JSC {
|
||||
m_assembler.xorcc_r(src, dest, dest);
|
||||
}
|
||||
|
||||
void xor32(Imm32 imm, RegisterID dest)
|
||||
void xor32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
if (m_assembler.isimm13(imm.m_value))
|
||||
m_assembler.xorcc_imm(dest, imm.m_value, dest);
|
||||
@ -548,7 +548,7 @@ namespace JSC {
|
||||
m_assembler.stw_r(src, address.base, SparcRegisters::g2);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, BaseIndex address)
|
||||
void store32(TrustedImm32 imm, BaseIndex address)
|
||||
{
|
||||
m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
||||
add32(Imm32(address.offset), SparcRegisters::g2);
|
||||
@ -556,7 +556,7 @@ namespace JSC {
|
||||
m_assembler.stw_r(SparcRegisters::g3, SparcRegisters::g2, address.base);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, ImplicitAddress address)
|
||||
void store32(TrustedImm32 imm, ImplicitAddress address)
|
||||
{
|
||||
m_assembler.move_nocheck(imm.m_value, SparcRegisters::g2);
|
||||
store32(SparcRegisters::g2, address);
|
||||
@ -568,7 +568,7 @@ namespace JSC {
|
||||
m_assembler.stw_r(src, SparcRegisters::g0, SparcRegisters::g3);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, void* address)
|
||||
void store32(TrustedImm32 imm, void* address)
|
||||
{
|
||||
move(imm, SparcRegisters::g2);
|
||||
store32(SparcRegisters::g2, address);
|
||||
@ -598,7 +598,7 @@ namespace JSC {
|
||||
push(SparcRegisters::g2);
|
||||
}
|
||||
|
||||
void move(Imm32 imm, RegisterID dest)
|
||||
void move(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
if (m_assembler.isimm13(imm.m_value))
|
||||
m_assembler.or_imm(SparcRegisters::g0, imm.m_value, dest);
|
||||
@ -611,7 +611,7 @@ namespace JSC {
|
||||
m_assembler.or_r(src, SparcRegisters::g0, dest);
|
||||
}
|
||||
|
||||
void move(ImmPtr imm, RegisterID dest)
|
||||
void move(TrustedImmPtr imm, RegisterID dest)
|
||||
{
|
||||
move(Imm32(imm), dest);
|
||||
}
|
||||
@ -641,20 +641,20 @@ namespace JSC {
|
||||
return branch32(cond, SparcRegisters::g2, right);
|
||||
}
|
||||
|
||||
Jump branch32_force32(Condition cond, RegisterID left, Imm32 right)
|
||||
Jump branch32_force32(Condition cond, RegisterID left, TrustedImm32 right)
|
||||
{
|
||||
m_assembler.move_nocheck(right.m_value, SparcRegisters::g3);
|
||||
m_assembler.subcc_r(left, SparcRegisters::g3, SparcRegisters::g0);
|
||||
return Jump(m_assembler.branch(SparcCondition(cond)));
|
||||
}
|
||||
|
||||
Jump branch32FixedLength(Condition cond, RegisterID left, Imm32 right)
|
||||
Jump branch32FixedLength(Condition cond, RegisterID left, TrustedImm32 right)
|
||||
{
|
||||
m_assembler.move_nocheck(right.m_value, SparcRegisters::g2);
|
||||
return branch32(cond, left, SparcRegisters::g2);
|
||||
}
|
||||
|
||||
Jump branch32WithPatch(Condition cond, RegisterID left, Imm32 right, DataLabel32 &dataLabel)
|
||||
Jump branch32WithPatch(Condition cond, RegisterID left, TrustedImm32 right, DataLabel32 &dataLabel)
|
||||
{
|
||||
// Always use move_nocheck, since the value is to be patched.
|
||||
dataLabel = DataLabel32(this);
|
||||
@ -669,7 +669,7 @@ namespace JSC {
|
||||
return Jump(m_assembler.branch(SparcCondition(cond)));
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, RegisterID left, Imm32 right)
|
||||
Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
|
||||
{
|
||||
if (m_assembler.isimm13(right.m_value))
|
||||
m_assembler.subcc_imm(left, right.m_value, SparcRegisters::g0);
|
||||
@ -692,20 +692,20 @@ namespace JSC {
|
||||
return branch32(cond, SparcRegisters::g2, right);
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, Address left, Imm32 right)
|
||||
Jump branch32(Condition cond, Address left, TrustedImm32 right)
|
||||
{
|
||||
load32(left, SparcRegisters::g2);
|
||||
return branch32(cond, SparcRegisters::g2, right);
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, BaseIndex left, Imm32 right)
|
||||
Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
|
||||
{
|
||||
|
||||
load32(left, SparcRegisters::g2);
|
||||
return branch32(cond, SparcRegisters::g2, right);
|
||||
}
|
||||
|
||||
Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
|
||||
Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
|
||||
{
|
||||
load32WithUnalignedHalfWords(left, SparcRegisters::g4);
|
||||
return branch32(cond, SparcRegisters::g4, right);
|
||||
@ -1052,7 +1052,7 @@ namespace JSC {
|
||||
store32(SparcRegisters::g2, address.m_ptr);
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, AbsoluteAddress address)
|
||||
void sub32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
load32(address.m_ptr, SparcRegisters::g2);
|
||||
sub32(imm, SparcRegisters::g2);
|
||||
@ -1071,7 +1071,7 @@ namespace JSC {
|
||||
return branch32(cond, SparcRegisters::g2, right);
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
|
||||
Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right)
|
||||
{
|
||||
load32(left.m_ptr, SparcRegisters::g2);
|
||||
return branch32(cond, SparcRegisters::g2, right);
|
||||
@ -1099,7 +1099,7 @@ namespace JSC {
|
||||
return Call::fromTailJump(oldJump);
|
||||
}
|
||||
|
||||
DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
|
||||
DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
|
||||
{
|
||||
DataLabelPtr dataLabel(this);
|
||||
Imm32 imm = Imm32(initialValue);
|
||||
@ -1107,7 +1107,7 @@ namespace JSC {
|
||||
return dataLabel;
|
||||
}
|
||||
|
||||
DataLabel32 moveWithPatch(Imm32 initialValue, RegisterID dest)
|
||||
DataLabel32 moveWithPatch(TrustedImm32 initialValue, RegisterID dest)
|
||||
{
|
||||
DataLabel32 dataLabel(this);
|
||||
m_assembler.move_nocheck(initialValue.m_value, dest);
|
||||
@ -1129,7 +1129,7 @@ namespace JSC {
|
||||
return jump;
|
||||
}
|
||||
|
||||
DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
|
||||
DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
|
||||
{
|
||||
DataLabelPtr dataLabel = moveWithPatch(initialValue, SparcRegisters::g2);
|
||||
store32(SparcRegisters::g2, address);
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
using MacroAssemblerX86Common::storeDouble;
|
||||
using MacroAssemblerX86Common::convertInt32ToDouble;
|
||||
|
||||
void add32(Imm32 imm, RegisterID src, RegisterID dest)
|
||||
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
|
||||
{
|
||||
m_assembler.leal_mr(imm.m_value, src, dest);
|
||||
}
|
||||
@ -90,12 +90,12 @@ public:
|
||||
m_assembler.andl_im(imm.m_value, address.m_ptr);
|
||||
}
|
||||
|
||||
void or32(Imm32 imm, AbsoluteAddress address)
|
||||
void or32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
m_assembler.orl_im(imm.m_value, address.m_ptr);
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, AbsoluteAddress address)
|
||||
void sub32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
m_assembler.subl_im(imm.m_value, address.m_ptr);
|
||||
}
|
||||
@ -148,7 +148,7 @@ public:
|
||||
addDouble(Address(srcDest), dest);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, void* address)
|
||||
void store32(TrustedImm32 imm, void* address)
|
||||
{
|
||||
m_assembler.movl_i32m(imm.m_value, address);
|
||||
}
|
||||
@ -164,7 +164,7 @@ public:
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
|
||||
Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right)
|
||||
{
|
||||
m_assembler.cmpl_im(right.m_value, left.m_ptr);
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
@ -186,7 +186,7 @@ public:
|
||||
}
|
||||
|
||||
|
||||
DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
|
||||
DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
|
||||
{
|
||||
m_assembler.movl_i32r(initialValue.asIntptr(), dest);
|
||||
return DataLabelPtr(this);
|
||||
@ -206,7 +206,7 @@ public:
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
}
|
||||
|
||||
DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
|
||||
DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
|
||||
{
|
||||
m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base);
|
||||
return DataLabelPtr(this);
|
||||
|
@ -116,12 +116,12 @@ public:
|
||||
m_assembler.addl_rr(src, dest);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, Address address)
|
||||
void add32(TrustedImm32 imm, Address address)
|
||||
{
|
||||
m_assembler.addl_im(imm.m_value, address.offset, address.base);
|
||||
}
|
||||
|
||||
void add32(Imm32 imm, RegisterID dest)
|
||||
void add32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.addl_ir(imm.m_value, dest);
|
||||
}
|
||||
@ -234,7 +234,7 @@ public:
|
||||
m_assembler.orl_rr(src, dest);
|
||||
}
|
||||
|
||||
void or32(Imm32 imm, RegisterID dest)
|
||||
void or32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.orl_ir(imm.m_value, dest);
|
||||
}
|
||||
@ -249,7 +249,7 @@ public:
|
||||
m_assembler.orl_mr(src.offset, src.base, dest);
|
||||
}
|
||||
|
||||
void or32(Imm32 imm, Address address)
|
||||
void or32(TrustedImm32 imm, Address address)
|
||||
{
|
||||
m_assembler.orl_im(imm.m_value, address.offset, address.base);
|
||||
}
|
||||
@ -313,12 +313,12 @@ public:
|
||||
m_assembler.subl_rr(src, dest);
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, RegisterID dest)
|
||||
void sub32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.subl_ir(imm.m_value, dest);
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, Address address)
|
||||
void sub32(TrustedImm32 imm, Address address)
|
||||
{
|
||||
m_assembler.subl_im(imm.m_value, address.offset, address.base);
|
||||
}
|
||||
@ -339,12 +339,12 @@ public:
|
||||
m_assembler.xorl_rr(src, dest);
|
||||
}
|
||||
|
||||
void xor32(Imm32 imm, Address dest)
|
||||
void xor32(TrustedImm32 imm, Address dest)
|
||||
{
|
||||
m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
|
||||
}
|
||||
|
||||
void xor32(Imm32 imm, RegisterID dest)
|
||||
void xor32(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.xorl_ir(imm.m_value, dest);
|
||||
}
|
||||
@ -468,7 +468,7 @@ public:
|
||||
m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, BaseIndex address)
|
||||
void store32(TrustedImm32 imm, BaseIndex address)
|
||||
{
|
||||
m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
|
||||
}
|
||||
@ -483,7 +483,7 @@ public:
|
||||
m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, ImplicitAddress address)
|
||||
void store32(TrustedImm32 imm, ImplicitAddress address)
|
||||
{
|
||||
m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
|
||||
}
|
||||
@ -748,7 +748,7 @@ public:
|
||||
//
|
||||
// Move values in registers.
|
||||
|
||||
void move(Imm32 imm, RegisterID dest)
|
||||
void move(TrustedImm32 imm, RegisterID dest)
|
||||
{
|
||||
// Note: on 64-bit the Imm32 value is zero extended into the register, it
|
||||
// may be useful to have a separate version that sign extends the value?
|
||||
@ -767,7 +767,7 @@ public:
|
||||
m_assembler.movq_rr(src, dest);
|
||||
}
|
||||
|
||||
void move(ImmPtr imm, RegisterID dest)
|
||||
void move(TrustedImmPtr imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.movq_i64r(imm.asIntptr(), dest);
|
||||
}
|
||||
@ -798,7 +798,7 @@ public:
|
||||
m_assembler.movl_rr(src, dest);
|
||||
}
|
||||
|
||||
void move(ImmPtr imm, RegisterID dest)
|
||||
void move(TrustedImmPtr imm, RegisterID dest)
|
||||
{
|
||||
m_assembler.movl_i32r(imm.asIntptr(), dest);
|
||||
}
|
||||
@ -852,7 +852,7 @@ public:
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, RegisterID left, Imm32 right)
|
||||
Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
|
||||
{
|
||||
if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
|
||||
m_assembler.testl_rr(left, left);
|
||||
@ -864,14 +864,14 @@ public:
|
||||
// Branch based on a 32-bit comparison, forcing the size of the
|
||||
// immediate operand to 32 bits in the native code stream to ensure that
|
||||
// the length of code emitted by this instruction is consistent.
|
||||
Jump branch32FixedLength(Condition cond, RegisterID left, Imm32 right)
|
||||
Jump branch32FixedLength(Condition cond, RegisterID left, TrustedImm32 right)
|
||||
{
|
||||
m_assembler.cmpl_ir_force32(right.m_value, left);
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
}
|
||||
|
||||
// Branch and record a label after the comparison.
|
||||
Jump branch32WithPatch(Condition cond, RegisterID left, Imm32 right, DataLabel32 &dataLabel)
|
||||
Jump branch32WithPatch(Condition cond, RegisterID left, TrustedImm32 right, DataLabel32 &dataLabel)
|
||||
{
|
||||
// Always use cmpl, since the value is to be patched.
|
||||
m_assembler.cmpl_ir_force32(right.m_value, left);
|
||||
@ -879,7 +879,7 @@ public:
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
}
|
||||
|
||||
Jump branch32WithPatch(Condition cond, Address left, Imm32 right, DataLabel32 &dataLabel)
|
||||
Jump branch32WithPatch(Condition cond, Address left, TrustedImm32 right, DataLabel32 &dataLabel)
|
||||
{
|
||||
m_assembler.cmpl_im_force32(right.m_value, left.offset, left.base);
|
||||
dataLabel = DataLabel32(this);
|
||||
@ -898,19 +898,19 @@ public:
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, Address left, Imm32 right)
|
||||
Jump branch32(Condition cond, Address left, TrustedImm32 right)
|
||||
{
|
||||
m_assembler.cmpl_im(right.m_value, left.offset, left.base);
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
}
|
||||
|
||||
Jump branch32(Condition cond, BaseIndex left, Imm32 right)
|
||||
Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
|
||||
{
|
||||
m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
}
|
||||
|
||||
Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
|
||||
Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
|
||||
{
|
||||
return branch32(cond, left, right);
|
||||
}
|
||||
@ -1369,7 +1369,7 @@ private:
|
||||
}
|
||||
|
||||
#if WTF_CPU_X86
|
||||
#if WTF_PLATFORM_MAC
|
||||
#if WTF_OS_MAC_OS_X
|
||||
|
||||
// All X86 Macs are guaranteed to support at least SSE2
|
||||
static bool isSSEPresent()
|
||||
@ -1382,7 +1382,7 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
#else // PLATFORM(MAC)
|
||||
#else // OS(MAC_OS_X)
|
||||
|
||||
static bool isSSEPresent()
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
using MacroAssemblerX86Common::storeDouble;
|
||||
using MacroAssemblerX86Common::convertInt32ToDouble;
|
||||
|
||||
void add32(Imm32 imm, AbsoluteAddress address)
|
||||
void add32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
move(ImmPtr(address.m_ptr), scratchRegister);
|
||||
add32(imm, Address(scratchRegister));
|
||||
@ -72,13 +72,13 @@ public:
|
||||
and32(imm, Address(scratchRegister));
|
||||
}
|
||||
|
||||
void or32(Imm32 imm, AbsoluteAddress address)
|
||||
void or32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
move(ImmPtr(address.m_ptr), scratchRegister);
|
||||
or32(imm, Address(scratchRegister));
|
||||
}
|
||||
|
||||
void sub32(Imm32 imm, AbsoluteAddress address)
|
||||
void sub32(TrustedImm32 imm, AbsoluteAddress address)
|
||||
{
|
||||
move(ImmPtr(address.m_ptr), scratchRegister);
|
||||
sub32(imm, Address(scratchRegister));
|
||||
@ -114,7 +114,7 @@ public:
|
||||
m_assembler.cvtsq2sd_rr(srcDest, dest);
|
||||
}
|
||||
|
||||
void store32(Imm32 imm, void* address)
|
||||
void store32(TrustedImm32 imm, void* address)
|
||||
{
|
||||
move(X86Registers::eax, scratchRegister);
|
||||
move(imm, X86Registers::eax);
|
||||
@ -311,7 +311,7 @@ public:
|
||||
m_assembler.movq_rm(src, address.offset, address.base);
|
||||
}
|
||||
|
||||
void storePtr(ImmPtr imm, BaseIndex address)
|
||||
void storePtr(TrustedImmPtr imm, BaseIndex address)
|
||||
{
|
||||
intptr_t value = intptr_t(imm.m_value);
|
||||
|
||||
@ -341,7 +341,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void storePtr(ImmPtr imm, ImplicitAddress address)
|
||||
void storePtr(TrustedImmPtr imm, ImplicitAddress address)
|
||||
{
|
||||
intptr_t value = intptr_t(imm.m_value);
|
||||
|
||||
@ -487,7 +487,7 @@ public:
|
||||
return Jump(m_assembler.jCC(x86Condition(cond)));
|
||||
}
|
||||
|
||||
DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
|
||||
DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
|
||||
{
|
||||
m_assembler.movq_i64r(initialValue.asIntptr(), dest);
|
||||
return DataLabelPtr(this);
|
||||
@ -505,7 +505,7 @@ public:
|
||||
return branchPtr(cond, left, scratchRegister);
|
||||
}
|
||||
|
||||
DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
|
||||
DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
|
||||
{
|
||||
DataLabelPtr label = moveWithPatch(initialValue, scratchRegister);
|
||||
storePtr(scratchRegister, address);
|
||||
|
@ -52,16 +52,16 @@ extern "C" void sync_instruction_memory(caddr_t v, u_int len);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if WTF_PLATFORM_IPHONE
|
||||
#if WTF_OS_IOS
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#if WTF_PLATFORM_SYMBIAN
|
||||
#if WTF_OS_SYMBIAN
|
||||
#include <e32std.h>
|
||||
#endif
|
||||
|
||||
#if WTF_CPU_MIPS && WTF_PLATFORM_LINUX
|
||||
#if WTF_CPU_MIPS && WTF_OS_LINUX
|
||||
#include <sys/cachectl.h>
|
||||
#endif
|
||||
|
||||
@ -90,7 +90,7 @@ private:
|
||||
struct Allocation {
|
||||
char* pages;
|
||||
size_t size;
|
||||
#if WTF_PLATFORM_SYMBIAN
|
||||
#if WTF_OS_SYMBIAN
|
||||
RChunk* chunk;
|
||||
#endif
|
||||
};
|
||||
@ -269,6 +269,7 @@ private:
|
||||
return pool;
|
||||
}
|
||||
|
||||
public:
|
||||
ExecutablePool* poolForSize(size_t n)
|
||||
{
|
||||
#ifndef DEBUG_STRESS_JSC_ALLOCATOR
|
||||
@ -327,7 +328,6 @@ private:
|
||||
return pool;
|
||||
}
|
||||
|
||||
public:
|
||||
#if ENABLE_ASSEMBLER_WX_EXCLUSIVE
|
||||
static void makeWritable(void* start, size_t size)
|
||||
{
|
||||
@ -374,13 +374,13 @@ public:
|
||||
_flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
|
||||
#endif
|
||||
}
|
||||
#elif WTF_CPU_ARM_THUMB2 && WTF_PLATFORM_IPHONE
|
||||
#elif WTF_CPU_ARM_THUMB2 && WTF_OS_IOS
|
||||
static void cacheFlush(void* code, size_t size)
|
||||
{
|
||||
sys_dcache_flush(code, size);
|
||||
sys_icache_invalidate(code, size);
|
||||
}
|
||||
#elif WTF_CPU_ARM_THUMB2 && WTF_PLATFORM_LINUX
|
||||
#elif WTF_CPU_ARM_THUMB2 && WTF_IOS
|
||||
static void cacheFlush(void* code, size_t size)
|
||||
{
|
||||
asm volatile (
|
||||
@ -396,14 +396,14 @@ public:
|
||||
: "r" (code), "r" (reinterpret_cast<char*>(code) + size)
|
||||
: "r0", "r1", "r2");
|
||||
}
|
||||
#elif WTF_PLATFORM_SYMBIAN
|
||||
#elif WTF_OS_SYMBIAN
|
||||
static void cacheFlush(void* code, size_t size)
|
||||
{
|
||||
User::IMB_Range(code, static_cast<char*>(code) + size);
|
||||
}
|
||||
#elif WTF_CPU_ARM_TRADITIONAL && WTF_PLATFORM_LINUX && WTF_COMPILER_RVCT
|
||||
#elif WTF_CPU_ARM_TRADITIONAL && WTF_OS_LINUX && WTF_COMPILER_RVCT
|
||||
static __asm void cacheFlush(void* code, size_t size);
|
||||
#elif WTF_CPU_ARM_TRADITIONAL && (WTF_PLATFORM_LINUX || WTF_PLATFORM_ANDROID) && WTF_COMPILER_GCC
|
||||
#elif WTF_CPU_ARM_TRADITIONAL && (WTF_OS_LINUX || WTF_OS_ANDROID) && WTF_COMPILER_GCC
|
||||
static void cacheFlush(void* code, size_t size)
|
||||
{
|
||||
asm volatile (
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include "ExecutableAllocator.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_PLATFORM_OS2
|
||||
#if ENABLE_ASSEMBLER && WTF_OS_OS2
|
||||
|
||||
#define INCL_DOS
|
||||
#include <os2.h>
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
#include "ExecutableAllocator.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_PLATFORM_UNIX && !WTF_PLATFORM_SYMBIAN
|
||||
#if ENABLE_ASSEMBLER && WTF_OS_UNIX && !WTF_OS_SYMBIAN
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
@ -74,7 +74,7 @@ void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSe
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WTF_CPU_ARM_TRADITIONAL && WTF_PLATFORM_LINUX && WTF_COMPILER_RVCT
|
||||
#if WTF_CPU_ARM_TRADITIONAL && WTF_OS_LINUX && WTF_COMPILER_RVCT
|
||||
__asm void ExecutableAllocator::cacheFlush(void* code, size_t size)
|
||||
{
|
||||
ARM
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "ExecutableAllocator.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_PLATFORM_SYMBIAN
|
||||
#if ENABLE_ASSEMBLER && WTF_OS_SYMBIAN
|
||||
|
||||
#include <e32hal.h>
|
||||
#include <e32std.h>
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include "ExecutableAllocator.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_PLATFORM_WIN_OS
|
||||
#if ENABLE_ASSEMBLER && WTF_OS_WINDOWS
|
||||
|
||||
#include "jswin.h"
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,3 @@
|
||||
// |jit-test| error: InternalError: regular expression too complex
|
||||
|
||||
var sText = "s";
|
||||
|
||||
for (var i = 0; i < 250000; ++i)
|
||||
@ -12,6 +10,5 @@ var match = sText.match(/s(\s|.)*?e/gi);
|
||||
//var match = sText.match(/s([\s\S]*?)e/gi);
|
||||
//var match = sText.match(/s(?:[\s\S]*?)e/gi);
|
||||
var end = new Date();
|
||||
print(end - start);
|
||||
|
||||
assertEq(match.length, 1);
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "jstracer.h"
|
||||
#include "jswrapper.h"
|
||||
#include "assembler/wtf/Platform.h"
|
||||
#include "yarr/BumpPointerAllocator.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "methodjit/PolyIC.h"
|
||||
#include "methodjit/MonoIC.h"
|
||||
@ -73,6 +74,9 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
active(false),
|
||||
#ifdef JS_METHODJIT
|
||||
jaegerCompartment(NULL),
|
||||
#endif
|
||||
#if ENABLE_YARR_JIT
|
||||
regExpAllocator(NULL),
|
||||
#endif
|
||||
propertyTree(thisForCtor()),
|
||||
emptyArgumentsShape(NULL),
|
||||
@ -84,9 +88,6 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
initialRegExpShape(NULL),
|
||||
initialStringShape(NULL),
|
||||
debugMode(rt->debugMode),
|
||||
#if ENABLE_YARR_JIT
|
||||
regExpAllocator(NULL),
|
||||
#endif
|
||||
mathCache(NULL)
|
||||
{
|
||||
JS_INIT_CLIST(&scripts);
|
||||
@ -135,11 +136,9 @@ JSCompartment::init()
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
regExpAllocator = rt->new_<JSC::ExecutableAllocator>();
|
||||
regExpAllocator = rt->new_<WTF::BumpPointerAllocator>();
|
||||
if (!regExpAllocator)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (!backEdgeTable.init())
|
||||
return false;
|
||||
|
@ -54,11 +54,8 @@
|
||||
#pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */
|
||||
#endif
|
||||
|
||||
namespace JSC {
|
||||
|
||||
class ExecutableAllocator;
|
||||
|
||||
}
|
||||
namespace JSC { class ExecutableAllocator; }
|
||||
namespace WTF { class BumpPointerAllocator; }
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -420,6 +417,7 @@ struct JS_FRIEND_API(JSCompartment) {
|
||||
*/
|
||||
size_t getMjitCodeSize() const;
|
||||
#endif
|
||||
WTF::BumpPointerAllocator *regExpAllocator;
|
||||
|
||||
/*
|
||||
* Shared scope property tree, and arena-pool for allocating its nodes.
|
||||
@ -466,8 +464,6 @@ struct JS_FRIEND_API(JSCompartment) {
|
||||
bool debugMode; // true iff debug mode on
|
||||
JSCList scripts; // scripts in this compartment
|
||||
|
||||
JSC::ExecutableAllocator *regExpAllocator;
|
||||
|
||||
js::NativeIterCache nativeIterCache;
|
||||
|
||||
typedef js::Maybe<js::ToSourceCache> LazyToSourceCache;
|
||||
|
@ -59,8 +59,6 @@
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsregexpinlines.h"
|
||||
|
||||
#include "yarr/RegexParser.h"
|
||||
|
||||
#ifdef JS_TRACER
|
||||
#include "jstracer.h"
|
||||
using namespace nanojit;
|
||||
@ -193,11 +191,11 @@ js_ObjectIsRegExp(JSObject *obj)
|
||||
*/
|
||||
|
||||
void
|
||||
RegExp::handleYarrError(JSContext *cx, int error)
|
||||
RegExp::reportYarrError(JSContext *cx, JSC::Yarr::ErrorCode error)
|
||||
{
|
||||
switch (error) {
|
||||
case JSC::Yarr::NoError:
|
||||
JS_NOT_REACHED("Precondition violation: an error must have occurred.");
|
||||
JS_NOT_REACHED("Called reportYarrError with value for no error");
|
||||
return;
|
||||
#define COMPILE_EMSG(__code, __msg) \
|
||||
case JSC::Yarr::__code: \
|
||||
@ -210,49 +208,16 @@ RegExp::handleYarrError(JSContext *cx, int error)
|
||||
COMPILE_EMSG(ParenthesesUnmatched, JSMSG_UNMATCHED_RIGHT_PAREN);
|
||||
COMPILE_EMSG(ParenthesesTypeInvalid, JSMSG_BAD_QUANTIFIER); /* "(?" with bad next char */
|
||||
COMPILE_EMSG(CharacterClassUnmatched, JSMSG_BAD_CLASS_RANGE);
|
||||
COMPILE_EMSG(CharacterClassInvalidRange, JSMSG_BAD_CLASS_RANGE);
|
||||
COMPILE_EMSG(CharacterClassOutOfOrder, JSMSG_BAD_CLASS_RANGE);
|
||||
COMPILE_EMSG(CharacterClassRangeSingleChar, JSMSG_BAD_CLASS_RANGE);
|
||||
COMPILE_EMSG(EscapeUnterminated, JSMSG_TRAILING_SLASH);
|
||||
COMPILE_EMSG(QuantifierTooLarge, JSMSG_BAD_QUANTIFIER);
|
||||
COMPILE_EMSG(HitRecursionLimit, JSMSG_REGEXP_TOO_COMPLEX);
|
||||
COMPILE_EMSG(EscapeUnterminated, JSMSG_TRAILING_SLASH);
|
||||
#undef COMPILE_EMSG
|
||||
default:
|
||||
JS_NOT_REACHED("Precondition violation: unknown Yarr error code.");
|
||||
JS_NOT_REACHED("Unknown Yarr error code");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RegExp::handlePCREError(JSContext *cx, int error)
|
||||
{
|
||||
#define REPORT(msg_) \
|
||||
JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, msg_); \
|
||||
return
|
||||
switch (error) {
|
||||
case -2: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 0: JS_NOT_REACHED("Precondition violation: an error must have occurred.");
|
||||
case 1: REPORT(JSMSG_TRAILING_SLASH);
|
||||
case 2: REPORT(JSMSG_TRAILING_SLASH);
|
||||
case 3: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 4: REPORT(JSMSG_BAD_QUANTIFIER);
|
||||
case 5: REPORT(JSMSG_BAD_QUANTIFIER);
|
||||
case 6: REPORT(JSMSG_BAD_CLASS_RANGE);
|
||||
case 7: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 8: REPORT(JSMSG_BAD_CLASS_RANGE);
|
||||
case 9: REPORT(JSMSG_BAD_QUANTIFIER);
|
||||
case 10: REPORT(JSMSG_UNMATCHED_RIGHT_PAREN);
|
||||
case 11: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 12: REPORT(JSMSG_UNMATCHED_RIGHT_PAREN);
|
||||
case 13: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 14: REPORT(JSMSG_MISSING_PAREN);
|
||||
case 15: REPORT(JSMSG_BAD_BACKREF);
|
||||
case 16: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 17: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
default:
|
||||
JS_NOT_REACHED("Precondition violation: unknown PCRE error code.");
|
||||
}
|
||||
#undef REPORT
|
||||
}
|
||||
|
||||
bool
|
||||
RegExp::parseFlags(JSContext *cx, JSString *flagStr, uintN *flagsOut)
|
||||
{
|
||||
@ -929,3 +894,4 @@ js_InitRegExpClass(JSContext *cx, JSObject *global)
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
@ -48,12 +48,13 @@
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "assembler/wtf/Platform.h"
|
||||
#include "yarr/BumpPointerAllocator.h"
|
||||
|
||||
#include "yarr/Yarr.h"
|
||||
#if ENABLE_YARR_JIT
|
||||
#include "yarr/yarr/RegexJIT.h"
|
||||
#else
|
||||
#include "yarr/pcre/pcre.h"
|
||||
#include "yarr/YarrJIT.h"
|
||||
#endif
|
||||
|
||||
namespace js {
|
||||
@ -95,10 +96,10 @@ regexp_statics_construct(JSContext *cx, GlobalObject *parent)
|
||||
class RegExp
|
||||
{
|
||||
#if ENABLE_YARR_JIT
|
||||
JSC::Yarr::RegexCodeBlock compiled;
|
||||
#else
|
||||
JSRegExp *compiled;
|
||||
/* native code is valid only if codeBlock.isFallBack() == false */
|
||||
JSC::Yarr::YarrCodeBlock codeBlock;
|
||||
#endif
|
||||
JSC::Yarr::BytecodePattern *byteCode;
|
||||
JSLinearString *source;
|
||||
size_t refCount;
|
||||
unsigned parenCount; /* Must be |unsigned| to interface with YARR. */
|
||||
@ -111,7 +112,11 @@ class RegExp
|
||||
#endif
|
||||
|
||||
RegExp(JSLinearString *source, uint32 flags, JSCompartment *compartment)
|
||||
: compiled(), source(source), refCount(1), parenCount(0), flags(flags)
|
||||
:
|
||||
#if ENABLE_YARR_JIT
|
||||
codeBlock(),
|
||||
#endif
|
||||
byteCode(NULL), source(source), refCount(1), parenCount(0), flags(flags)
|
||||
#ifdef DEBUG
|
||||
, compartment(compartment)
|
||||
#endif
|
||||
@ -120,17 +125,18 @@ class RegExp
|
||||
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
|
||||
|
||||
~RegExp() {
|
||||
#if !ENABLE_YARR_JIT
|
||||
if (compiled)
|
||||
jsRegExpFree(compiled);
|
||||
#if ENABLE_YARR_JIT
|
||||
codeBlock.release();
|
||||
#endif
|
||||
// YYY
|
||||
if (byteCode)
|
||||
delete byteCode;
|
||||
}
|
||||
|
||||
bool compileHelper(JSContext *cx, JSLinearString &pattern);
|
||||
bool compile(JSContext *cx);
|
||||
static const uint32 allFlags = JSREG_FOLD | JSREG_GLOB | JSREG_MULTILINE | JSREG_STICKY;
|
||||
void handlePCREError(JSContext *cx, int error);
|
||||
void handleYarrError(JSContext *cx, int error);
|
||||
void reportYarrError(JSContext *cx, JSC::Yarr::ErrorCode error);
|
||||
static inline bool initArena(JSContext *cx);
|
||||
static inline void checkMatchPairs(JSString *input, int *buf, size_t matchItemCount);
|
||||
static JSObject *createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemCount);
|
||||
@ -318,9 +324,6 @@ inline bool
|
||||
RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *inputstr,
|
||||
size_t *lastIndex, bool test, Value *rval)
|
||||
{
|
||||
#if !ENABLE_YARR_JIT
|
||||
JS_ASSERT(compiled);
|
||||
#endif
|
||||
const size_t pairCount = parenCount + 1;
|
||||
const size_t bufCount = pairCount * 3; /* Should be x2, but PCRE has... needs. */
|
||||
const size_t matchItemCount = pairCount * 2;
|
||||
@ -360,27 +363,20 @@ RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *inputstr,
|
||||
inputOffset = *lastIndex;
|
||||
}
|
||||
|
||||
int result;
|
||||
#if ENABLE_YARR_JIT
|
||||
int result = JSC::Yarr::executeRegex(cx, compiled, chars, *lastIndex - inputOffset, len, buf,
|
||||
bufCount);
|
||||
if (!codeBlock.isFallBack())
|
||||
result = JSC::Yarr::execute(codeBlock, chars, *lastIndex - inputOffset, len, buf);
|
||||
else
|
||||
result = JSC::Yarr::interpret(byteCode, chars, *lastIndex - inputOffset, len, buf);
|
||||
#else
|
||||
int result = jsRegExpExecute(cx, compiled, chars, len, *lastIndex - inputOffset, buf,
|
||||
bufCount);
|
||||
result = JSC::Yarr::interpret(byteCode, chars, *lastIndex - inputOffset, len, buf);
|
||||
#endif
|
||||
if (result == -1) {
|
||||
*rval = NullValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
#if ENABLE_YARR_JIT
|
||||
handleYarrError(cx, result);
|
||||
#else
|
||||
handlePCREError(cx, result);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust buf for the inputOffset. Use of sticky is rare and the matchItemCount is small, so
|
||||
* just do another pass.
|
||||
@ -460,53 +456,43 @@ RegExp::createObjectNoStatics(JSContext *cx, const jschar *chars, size_t length,
|
||||
return obj;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
static bool
|
||||
YarrJITIsBroken(JSContext *cx)
|
||||
/*
|
||||
* This function should be deleted once we can. See bug 604774.
|
||||
*/
|
||||
static inline bool
|
||||
EnableYarrJIT(JSContext *cx)
|
||||
{
|
||||
#if defined(JS_TRACER) && defined(JS_METHODJIT)
|
||||
/* FIXME/bug 604774: dead code walking.
|
||||
*
|
||||
* If both JITs are disabled, assume they were disabled because
|
||||
* we're running on a blacklisted device.
|
||||
*/
|
||||
return !cx->traceJitEnabled && !cx->methodJitEnabled;
|
||||
#if defined ANDROID && defined(JS_TRACER) && defined(JS_METHODJIT)
|
||||
return cx->traceJitEnabled || cx->methodJitEnabled;
|
||||
#else
|
||||
return false;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif /* ANDROID */
|
||||
|
||||
inline bool
|
||||
RegExp::compileHelper(JSContext *cx, JSLinearString &pattern)
|
||||
{
|
||||
#if ENABLE_YARR_JIT
|
||||
bool fellBack = false;
|
||||
int error = 0;
|
||||
jitCompileRegex(*cx->compartment->regExpAllocator, compiled, pattern, parenCount, error, fellBack, ignoreCase(), multiline()
|
||||
#ifdef ANDROID
|
||||
/* Temporary gross hack to work around buggy kernels. */
|
||||
, YarrJITIsBroken(cx)
|
||||
#endif
|
||||
);
|
||||
if (!error)
|
||||
return true;
|
||||
if (fellBack)
|
||||
handlePCREError(cx, error);
|
||||
else
|
||||
handleYarrError(cx, error);
|
||||
return false;
|
||||
#else
|
||||
int error = 0;
|
||||
compiled = jsRegExpCompile(pattern.chars(), pattern.length(),
|
||||
ignoreCase() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase,
|
||||
multiline() ? JSRegExpMultiline : JSRegExpSingleLine,
|
||||
&parenCount, &error);
|
||||
if (!error)
|
||||
return true;
|
||||
handlePCREError(cx, error);
|
||||
return false;
|
||||
JSC::Yarr::ErrorCode yarrError;
|
||||
JSC::Yarr::YarrPattern yarrPattern(pattern, ignoreCase(), multiline(), &yarrError);
|
||||
if (yarrError) {
|
||||
reportYarrError(cx, yarrError);
|
||||
return false;
|
||||
}
|
||||
parenCount = yarrPattern.m_numSubpatterns;
|
||||
|
||||
#if ENABLE_YARR_JIT && defined(JS_METHODJIT)
|
||||
if (EnableYarrJIT(cx) && !yarrPattern.m_containsBackreferences) {
|
||||
JSC::Yarr::JSGlobalData globalData(cx->compartment->jaegerCompartment->execAlloc());
|
||||
JSC::Yarr::jitCompile(yarrPattern, &globalData, codeBlock);
|
||||
if (!codeBlock.isFallBack())
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
codeBlock.setFallBack(true);
|
||||
byteCode = JSC::Yarr::byteCompile(yarrPattern, cx->compartment->regExpAllocator).get();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -208,12 +208,30 @@ class Vector : private AllocPolicy
|
||||
|
||||
/* compute constants */
|
||||
|
||||
/*
|
||||
* Consider element size to be 1 for buffer sizing if there are
|
||||
* 0 inline elements. This allows us to compile when the definition
|
||||
* of the element type is not visible here.
|
||||
*
|
||||
* Explicit specialization is only allowed at namespace scope, so
|
||||
* in order to keep everything here, we use a dummy template
|
||||
* parameter with partial specialization.
|
||||
*/
|
||||
template <int M, int Dummy>
|
||||
struct ElemSize {
|
||||
static const size_t result = sizeof(T);
|
||||
};
|
||||
template <int Dummy>
|
||||
struct ElemSize<0, Dummy> {
|
||||
static const size_t result = 1;
|
||||
};
|
||||
|
||||
static const size_t sInlineCapacity =
|
||||
tl::Min<N, sMaxInlineBytes / sizeof(T)>::result;
|
||||
tl::Min<N, sMaxInlineBytes / ElemSize<N, 0>::result>::result;
|
||||
|
||||
/* Calculate inline buffer size; avoid 0-sized array. */
|
||||
static const size_t sInlineBytes =
|
||||
tl::Max<1, sInlineCapacity * sizeof(T)>::result;
|
||||
tl::Max<1, sInlineCapacity * ElemSize<N, 0>::result>::result;
|
||||
|
||||
/* member data */
|
||||
|
||||
|
@ -503,7 +503,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
analyze::Bytecode *opinfo = analysis->maybeCode(i);
|
||||
if (opinfo && opinfo->safePoint) {
|
||||
Label L = jumpMap[i];
|
||||
JS_ASSERT(L.isValid());
|
||||
JS_ASSERT(L.isSet());
|
||||
jitNmap[ix].bcOff = i;
|
||||
jitNmap[ix].ncode = (uint8 *)(result + masm.distanceOf(L));
|
||||
ix++;
|
||||
@ -625,7 +625,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
cursor += sizeof(ic::EqualityICInfo) * jit->nEqualityICs;
|
||||
for (size_t i = 0; i < jit->nEqualityICs; i++) {
|
||||
uint32 offs = uint32(equalityICs[i].jumpTarget - script->code);
|
||||
JS_ASSERT(jumpMap[offs].isValid());
|
||||
JS_ASSERT(jumpMap[offs].isSet());
|
||||
jitEqualityICs[i].target = fullCode.locationOf(jumpMap[offs]);
|
||||
jitEqualityICs[i].stubEntry = stubCode.locationOf(equalityICs[i].stubEntry);
|
||||
jitEqualityICs[i].stubCall = stubCode.locationOf(equalityICs[i].stubCall);
|
||||
@ -650,7 +650,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
continue;
|
||||
|
||||
uint32 offs = uint32(traceICs[i].jumpTarget - script->code);
|
||||
JS_ASSERT(jumpMap[offs].isValid());
|
||||
JS_ASSERT(jumpMap[offs].isSet());
|
||||
jitTraceICs[i].traceHint = fullCode.locationOf(traceICs[i].traceHint);
|
||||
jitTraceICs[i].jumpTarget = fullCode.locationOf(jumpMap[offs]);
|
||||
jitTraceICs[i].stubEntry = stubCode.locationOf(traceICs[i].stubEntry);
|
||||
@ -800,7 +800,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
|
||||
for (size_t i = 0; i < jumpTableOffsets.length(); i++) {
|
||||
uint32 offset = jumpTableOffsets[i];
|
||||
JS_ASSERT(jumpMap[offset].isValid());
|
||||
JS_ASSERT(jumpMap[offset].isSet());
|
||||
jumpVec[i] = (void *)(result + masm.distanceOf(jumpMap[offset]));
|
||||
}
|
||||
|
||||
@ -2089,7 +2089,7 @@ JSC::MacroAssembler::Label
|
||||
mjit::Compiler::labelOf(jsbytecode *pc)
|
||||
{
|
||||
uint32 offs = uint32(pc - script->code);
|
||||
JS_ASSERT(jumpMap[offs].isValid());
|
||||
JS_ASSERT(jumpMap[offs].isSet());
|
||||
return jumpMap[offs];
|
||||
}
|
||||
|
||||
|
@ -846,12 +846,7 @@ static inline void Destroy(T &t)
|
||||
|
||||
mjit::JITScript::~JITScript()
|
||||
{
|
||||
#if defined DEBUG && (defined JS_CPU_X86 || defined JS_CPU_X64)
|
||||
void *addr = code.m_code.executableAddress();
|
||||
memset(addr, 0xcc, code.m_size);
|
||||
#endif
|
||||
|
||||
code.m_executablePool->release();
|
||||
code.release();
|
||||
|
||||
#if defined JS_POLYIC
|
||||
ic::GetElementIC *getElems_ = getElems();
|
||||
|
@ -93,7 +93,7 @@ TrampolineCompiler::compileTrampoline(Trampolines::TrampolinePtr *where,
|
||||
|
||||
Label entry = masm.label();
|
||||
CHECK_RESULT(generator(masm));
|
||||
JS_ASSERT(entry.isValid());
|
||||
JS_ASSERT(entry.isSet());
|
||||
|
||||
bool ok;
|
||||
JSC::LinkBuffer buffer(&masm, execAlloc, poolp, &ok);
|
||||
|
@ -1,4 +1,7 @@
|
||||
/*
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -24,12 +27,13 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef WTF_ASCIICType_h
|
||||
#define WTF_ASCIICType_h
|
||||
|
||||
#include "yarr/jswtfbridge.h"
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
|
||||
// The behavior of many of the functions in the <ctype.h> header is dependent
|
||||
// on the current locale. But in the WebKit project, all uses of those functions
|
||||
@ -49,6 +53,7 @@ namespace WTF {
|
||||
inline bool isASCII(wchar_t c) { return !(c & ~0x7F); }
|
||||
#endif
|
||||
inline bool isASCII(int c) { return !(c & ~0x7F); }
|
||||
inline bool isASCII(unsigned c) { return !(c & ~0x7F); }
|
||||
|
||||
inline bool isASCIIAlpha(char c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
|
||||
inline bool isASCIIAlpha(unsigned short c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
|
||||
@ -56,6 +61,7 @@ namespace WTF {
|
||||
inline bool isASCIIAlpha(wchar_t c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
|
||||
#endif
|
||||
inline bool isASCIIAlpha(int c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
|
||||
inline bool isASCIIAlpha(unsigned c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
|
||||
|
||||
inline bool isASCIIAlphanumeric(char c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
|
||||
inline bool isASCIIAlphanumeric(unsigned short c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
|
||||
@ -63,6 +69,7 @@ namespace WTF {
|
||||
inline bool isASCIIAlphanumeric(wchar_t c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
|
||||
#endif
|
||||
inline bool isASCIIAlphanumeric(int c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
|
||||
inline bool isASCIIAlphanumeric(unsigned c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
|
||||
|
||||
inline bool isASCIIDigit(char c) { return (c >= '0') & (c <= '9'); }
|
||||
inline bool isASCIIDigit(unsigned short c) { return (c >= '0') & (c <= '9'); }
|
||||
@ -70,6 +77,7 @@ namespace WTF {
|
||||
inline bool isASCIIDigit(wchar_t c) { return (c >= '0') & (c <= '9'); }
|
||||
#endif
|
||||
inline bool isASCIIDigit(int c) { return (c >= '0') & (c <= '9'); }
|
||||
inline bool isASCIIDigit(unsigned c) { return (c >= '0') & (c <= '9'); }
|
||||
|
||||
inline bool isASCIIHexDigit(char c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
|
||||
inline bool isASCIIHexDigit(unsigned short c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
|
||||
@ -77,6 +85,7 @@ namespace WTF {
|
||||
inline bool isASCIIHexDigit(wchar_t c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
|
||||
#endif
|
||||
inline bool isASCIIHexDigit(int c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
|
||||
inline bool isASCIIHexDigit(unsigned c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
|
||||
|
||||
inline bool isASCIIOctalDigit(char c) { return (c >= '0') & (c <= '7'); }
|
||||
inline bool isASCIIOctalDigit(unsigned short c) { return (c >= '0') & (c <= '7'); }
|
||||
@ -84,6 +93,7 @@ namespace WTF {
|
||||
inline bool isASCIIOctalDigit(wchar_t c) { return (c >= '0') & (c <= '7'); }
|
||||
#endif
|
||||
inline bool isASCIIOctalDigit(int c) { return (c >= '0') & (c <= '7'); }
|
||||
inline bool isASCIIOctalDigit(unsigned c) { return (c >= '0') & (c <= '7'); }
|
||||
|
||||
inline bool isASCIILower(char c) { return c >= 'a' && c <= 'z'; }
|
||||
inline bool isASCIILower(unsigned short c) { return c >= 'a' && c <= 'z'; }
|
||||
@ -91,6 +101,7 @@ namespace WTF {
|
||||
inline bool isASCIILower(wchar_t c) { return c >= 'a' && c <= 'z'; }
|
||||
#endif
|
||||
inline bool isASCIILower(int c) { return c >= 'a' && c <= 'z'; }
|
||||
inline bool isASCIILower(unsigned c) { return c >= 'a' && c <= 'z'; }
|
||||
|
||||
inline bool isASCIIUpper(char c) { return c >= 'A' && c <= 'Z'; }
|
||||
inline bool isASCIIUpper(unsigned short c) { return c >= 'A' && c <= 'Z'; }
|
||||
@ -98,6 +109,7 @@ namespace WTF {
|
||||
inline bool isASCIIUpper(wchar_t c) { return c >= 'A' && c <= 'Z'; }
|
||||
#endif
|
||||
inline bool isASCIIUpper(int c) { return c >= 'A' && c <= 'Z'; }
|
||||
inline bool isASCIIUpper(unsigned c) { return c >= 'A' && c <= 'Z'; }
|
||||
|
||||
/*
|
||||
Statistics from a run of Apple's page load test for callers of isASCIISpace:
|
||||
@ -118,6 +130,7 @@ namespace WTF {
|
||||
inline bool isASCIISpace(wchar_t c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
|
||||
#endif
|
||||
inline bool isASCIISpace(int c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
|
||||
inline bool isASCIISpace(unsigned c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
|
||||
|
||||
inline char toASCIILower(char c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
|
||||
inline unsigned short toASCIILower(unsigned short c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
|
||||
@ -125,20 +138,24 @@ namespace WTF {
|
||||
inline wchar_t toASCIILower(wchar_t c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
|
||||
#endif
|
||||
inline int toASCIILower(int c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
|
||||
inline unsigned toASCIILower(unsigned c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
|
||||
|
||||
// FIXME: Why do these need static_cast?
|
||||
inline char toASCIIUpper(char c) { return static_cast<char>(c & ~((c >= 'a' && c <= 'z') << 5)); }
|
||||
inline unsigned short toASCIIUpper(unsigned short c) { return static_cast<unsigned short>(c & ~((c >= 'a' && c <= 'z') << 5)); }
|
||||
#if !WTF_COMPILER_MSVC || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
inline wchar_t toASCIIUpper(wchar_t c) { return static_cast<wchar_t>(c & ~((c >= 'a' && c <= 'z') << 5)); }
|
||||
#endif
|
||||
inline int toASCIIUpper(int c) { return static_cast<int>(c & ~((c >= 'a' && c <= 'z') << 5)); }
|
||||
inline unsigned toASCIIUpper(unsigned c) { return static_cast<unsigned>(c & ~((c >= 'a' && c <= 'z') << 5)); }
|
||||
|
||||
inline int toASCIIHexValue(char c) { JS_ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
|
||||
inline int toASCIIHexValue(unsigned short c) { JS_ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
|
||||
inline int toASCIIHexValue(char c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
|
||||
inline int toASCIIHexValue(unsigned short c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
|
||||
#if !WTF_COMPILER_MSVC || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
inline int toASCIIHexValue(wchar_t c) { JS_ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
|
||||
inline int toASCIIHexValue(wchar_t c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
|
||||
#endif
|
||||
inline int toASCIIHexValue(int c) { JS_ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
|
||||
inline int toASCIIHexValue(int c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
|
||||
inline int toASCIIHexValue(unsigned c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
|
||||
|
||||
inline bool isASCIIPrintable(char c) { return c >= ' ' && c <= '~'; }
|
||||
inline bool isASCIIPrintable(unsigned short c) { return c >= ' ' && c <= '~'; }
|
||||
@ -146,7 +163,7 @@ namespace WTF {
|
||||
inline bool isASCIIPrintable(wchar_t c) { return c >= ' ' && c <= '~'; }
|
||||
#endif
|
||||
inline bool isASCIIPrintable(int c) { return c >= ' ' && c <= '~'; }
|
||||
|
||||
inline bool isASCIIPrintable(unsigned c) { return c >= ' ' && c <= '~'; }
|
||||
}
|
||||
|
||||
using WTF::isASCII;
|
254
js/src/yarr/BumpPointerAllocator.h
Normal file
254
js/src/yarr/BumpPointerAllocator.h
Normal file
@ -0,0 +1,254 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef BumpPointerAllocator_h
|
||||
#define BumpPointerAllocator_h
|
||||
|
||||
#include "PageAllocation.h"
|
||||
|
||||
namespace WTF {
|
||||
|
||||
#define MINIMUM_BUMP_POOL_SIZE 0x1000
|
||||
|
||||
class BumpPointerPool {
|
||||
public:
|
||||
// ensureCapacity will check whether the current pool has capacity to
|
||||
// allocate 'size' bytes of memory If it does not, it will attempt to
|
||||
// allocate a new pool (which will be added to this one in a chain).
|
||||
//
|
||||
// If allocation fails (out of memory) this method will return null.
|
||||
// If the return value is non-null, then callers should update any
|
||||
// references they have to this current (possibly full) BumpPointerPool
|
||||
// to instead point to the newly returned BumpPointerPool.
|
||||
BumpPointerPool* ensureCapacity(size_t size)
|
||||
{
|
||||
void* allocationEnd = static_cast<char*>(m_current) + size;
|
||||
ASSERT(allocationEnd > m_current); // check for overflow
|
||||
if (allocationEnd <= static_cast<void*>(this))
|
||||
return this;
|
||||
return ensureCapacityCrossPool(this, size);
|
||||
}
|
||||
|
||||
// alloc should only be called after calling ensureCapacity; as such
|
||||
// alloc will never fail.
|
||||
void* alloc(size_t size)
|
||||
{
|
||||
void* current = m_current;
|
||||
void* allocationEnd = static_cast<char*>(current) + size;
|
||||
ASSERT(allocationEnd > current); // check for overflow
|
||||
ASSERT(allocationEnd <= static_cast<void*>(this));
|
||||
m_current = allocationEnd;
|
||||
return current;
|
||||
}
|
||||
|
||||
// The dealloc method releases memory allocated using alloc. Memory
|
||||
// must be released in a LIFO fashion, e.g. if the client calls alloc
|
||||
// four times, returning pointer A, B, C, D, then the only valid order
|
||||
// in which these may be deallocaed is D, C, B, A.
|
||||
//
|
||||
// The client may optionally skip some deallocations. In the example
|
||||
// above, it would be valid to only explicitly dealloc C, A (D being
|
||||
// dealloced along with C, B along with A).
|
||||
//
|
||||
// If pointer was not allocated from this pool (or pools) then dealloc
|
||||
// will CRASH(). Callers should update any references they have to
|
||||
// this current BumpPointerPool to instead point to the returned
|
||||
// BumpPointerPool.
|
||||
BumpPointerPool* dealloc(void* position)
|
||||
{
|
||||
if ((position >= m_start) && (position <= static_cast<void*>(this))) {
|
||||
ASSERT(position <= m_current);
|
||||
m_current = position;
|
||||
return this;
|
||||
}
|
||||
return deallocCrossPool(this, position);
|
||||
}
|
||||
|
||||
private:
|
||||
// Placement operator new, returns the last 'size' bytes of allocation for use as this.
|
||||
void* operator new(size_t size, const PageAllocation& allocation)
|
||||
{
|
||||
ASSERT(size < allocation.size());
|
||||
return reinterpret_cast<char*>(reinterpret_cast<intptr_t>(allocation.base()) + allocation.size()) - size;
|
||||
}
|
||||
|
||||
BumpPointerPool(const PageAllocation& allocation)
|
||||
: m_current(allocation.base())
|
||||
, m_start(allocation.base())
|
||||
, m_next(0)
|
||||
, m_previous(0)
|
||||
, m_allocation(allocation)
|
||||
{
|
||||
}
|
||||
|
||||
static BumpPointerPool* create(size_t minimumCapacity = 0)
|
||||
{
|
||||
// Add size of BumpPointerPool object, check for overflow.
|
||||
minimumCapacity += sizeof(BumpPointerPool);
|
||||
if (minimumCapacity < sizeof(BumpPointerPool))
|
||||
return 0;
|
||||
|
||||
size_t poolSize = MINIMUM_BUMP_POOL_SIZE;
|
||||
while (poolSize < minimumCapacity) {
|
||||
poolSize <<= 1;
|
||||
// The following if check relies on MINIMUM_BUMP_POOL_SIZE being a power of 2!
|
||||
ASSERT(!(MINIMUM_BUMP_POOL_SIZE & (MINIMUM_BUMP_POOL_SIZE - 1)));
|
||||
if (!poolSize)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PageAllocation allocation = PageAllocation::allocate(poolSize);
|
||||
if (!!allocation)
|
||||
return new(allocation) BumpPointerPool(allocation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shrink()
|
||||
{
|
||||
ASSERT(!m_previous);
|
||||
m_current = m_start;
|
||||
while (m_next) {
|
||||
BumpPointerPool* nextNext = m_next->m_next;
|
||||
m_next->destroy();
|
||||
m_next = nextNext;
|
||||
}
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
m_allocation.deallocate();
|
||||
}
|
||||
|
||||
static BumpPointerPool* ensureCapacityCrossPool(BumpPointerPool* previousPool, size_t size)
|
||||
{
|
||||
// The pool passed should not have capacity, so we'll start with the next one.
|
||||
ASSERT(previousPool);
|
||||
ASSERT((static_cast<char*>(previousPool->m_current) + size) > previousPool->m_current); // check for overflow
|
||||
ASSERT((static_cast<char*>(previousPool->m_current) + size) > static_cast<void*>(previousPool));
|
||||
BumpPointerPool* pool = previousPool->m_next;
|
||||
|
||||
while (true) {
|
||||
if (!pool) {
|
||||
// We've run to the end; allocate a new pool.
|
||||
pool = BumpPointerPool::create(size);
|
||||
previousPool->m_next = pool;
|
||||
pool->m_previous = previousPool;
|
||||
return pool;
|
||||
}
|
||||
|
||||
//
|
||||
void* current = pool->m_current;
|
||||
void* allocationEnd = static_cast<char*>(current) + size;
|
||||
ASSERT(allocationEnd > current); // check for overflow
|
||||
if (allocationEnd <= static_cast<void*>(pool))
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
|
||||
static BumpPointerPool* deallocCrossPool(BumpPointerPool* pool, void* position)
|
||||
{
|
||||
// Should only be called if position is not in the current pool.
|
||||
ASSERT((position < pool->m_start) || (position > static_cast<void*>(pool)));
|
||||
|
||||
while (true) {
|
||||
// Unwind the current pool to the start, move back in the chain to the previous pool.
|
||||
pool->m_current = pool->m_start;
|
||||
pool = pool->m_previous;
|
||||
|
||||
// position was nowhere in the chain!
|
||||
if (!pool)
|
||||
CRASH();
|
||||
|
||||
if ((position >= pool->m_start) && (position <= static_cast<void*>(pool))) {
|
||||
ASSERT(position <= pool->m_current);
|
||||
pool->m_current = position;
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void* m_current;
|
||||
void* m_start;
|
||||
BumpPointerPool* m_next;
|
||||
BumpPointerPool* m_previous;
|
||||
PageAllocation m_allocation;
|
||||
|
||||
friend class BumpPointerAllocator;
|
||||
};
|
||||
|
||||
// A BumpPointerAllocator manages a set of BumpPointerPool objects, which
|
||||
// can be used for LIFO (stack like) allocation.
|
||||
//
|
||||
// To begin allocating using this class call startAllocator(). The result
|
||||
// of this method will be null if the initial pool allocation fails, or a
|
||||
// pointer to a BumpPointerPool object that can be used to perform
|
||||
// allocations. Whilst running no memory will be released until
|
||||
// stopAllocator() is called. At this point all allocations made through
|
||||
// this allocator will be reaped, and underlying memory may be freed.
|
||||
//
|
||||
// (In practice we will still hold on to the initial pool to allow allocation
|
||||
// to be quickly restared, but aditional pools will be freed).
|
||||
//
|
||||
// This allocator is non-renetrant, it is encumbant on the clients to ensure
|
||||
// startAllocator() is not called again until stopAllocator() has been called.
|
||||
class BumpPointerAllocator {
|
||||
public:
|
||||
BumpPointerAllocator()
|
||||
: m_head(0)
|
||||
{
|
||||
}
|
||||
|
||||
~BumpPointerAllocator()
|
||||
{
|
||||
if (m_head)
|
||||
m_head->destroy();
|
||||
}
|
||||
|
||||
BumpPointerPool* startAllocator()
|
||||
{
|
||||
if (!m_head)
|
||||
m_head = BumpPointerPool::create();
|
||||
return m_head;
|
||||
}
|
||||
|
||||
void stopAllocator()
|
||||
{
|
||||
if (m_head)
|
||||
m_head->shrink();
|
||||
}
|
||||
|
||||
private:
|
||||
BumpPointerPool* m_head;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using WTF::BumpPointerAllocator;
|
||||
|
||||
#endif // BumpPointerAllocator_h
|
@ -1,5 +0,0 @@
|
||||
INCLUDES := -I. -Iyarr -Iwtf -I../assembler/assembler -I../assembler
|
||||
|
||||
all:
|
||||
$(CXX) -g3 -c $(INCLUDES) yarr/*.cpp
|
||||
$(CXX) -g3 $(INCLUDES) TestMain.cpp *.o
|
103
js/src/yarr/OSAllocator.h
Normal file
103
js/src/yarr/OSAllocator.h
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef OSAllocator_h
|
||||
#define OSAllocator_h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "wtfbridge.h"
|
||||
#include "assembler/wtf/VMTags.h"
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
|
||||
namespace WTF {
|
||||
|
||||
class OSAllocator {
|
||||
public:
|
||||
enum Usage {
|
||||
UnknownUsage = -1,
|
||||
FastMallocPages = VM_TAG_FOR_TCMALLOC_MEMORY,
|
||||
JSGCHeapPages = VM_TAG_FOR_COLLECTOR_MEMORY,
|
||||
JSVMStackPages = VM_TAG_FOR_REGISTERFILE_MEMORY,
|
||||
JSJITCodePages = VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY
|
||||
};
|
||||
|
||||
// These methods are symmetric; reserveUncommitted allocates VM in an uncommitted state,
|
||||
// releaseDecommitted should be called on a region of VM allocated by a single reservation,
|
||||
// the memory must all currently be in a decommitted state.
|
||||
static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
|
||||
static void releaseDecommitted(void*, size_t);
|
||||
|
||||
// These methods are symmetric; they commit or decommit a region of VM (uncommitted VM should
|
||||
// never be accessed, since the OS may not have attached physical memory for these regions).
|
||||
// Clients should only call commit on uncommitted regions and decommit on committed regions.
|
||||
static void commit(void*, size_t, bool writable, bool executable);
|
||||
static void decommit(void*, size_t);
|
||||
|
||||
// These methods are symmetric; reserveAndCommit allocates VM in an committed state,
|
||||
// decommitAndRelease should be called on a region of VM allocated by a single reservation,
|
||||
// the memory must all currently be in a committed state.
|
||||
static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
|
||||
static void decommitAndRelease(void* base, size_t size);
|
||||
|
||||
// These methods are akin to reserveAndCommit/decommitAndRelease, above - however rather than
|
||||
// committing/decommitting the entire region additional parameters allow a subregion to be
|
||||
// specified.
|
||||
static void* reserveAndCommit(size_t reserveSize, size_t commitSize, Usage = UnknownUsage, bool writable = true, bool executable = false);
|
||||
static void decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize);
|
||||
};
|
||||
|
||||
inline void* OSAllocator::reserveAndCommit(size_t reserveSize, size_t commitSize, Usage usage, bool writable, bool executable)
|
||||
{
|
||||
void* base = reserveUncommitted(reserveSize, usage, writable, executable);
|
||||
commit(base, commitSize, writable, executable);
|
||||
return base;
|
||||
}
|
||||
|
||||
inline void OSAllocator::decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize)
|
||||
{
|
||||
ASSERT(decommitBase >= releaseBase && (static_cast<char*>(decommitBase) + decommitSize) <= (static_cast<char*>(releaseBase) + releaseSize));
|
||||
#if WTF_OS_WINCE || WTF_OS_SYMBIAN
|
||||
// On most platforms we can actually skip this final decommit; releasing the VM will
|
||||
// implicitly decommit any physical memory in the region. This is not true on WINCE.
|
||||
// On Symbian, this makes implementation simpler and better aligned with the RChunk API
|
||||
decommit(decommitBase, decommitSize);
|
||||
#endif
|
||||
releaseDecommitted(releaseBase, releaseSize);
|
||||
}
|
||||
|
||||
inline void OSAllocator::decommitAndRelease(void* base, size_t size)
|
||||
{
|
||||
decommitAndRelease(base, size, base, size);
|
||||
}
|
||||
|
||||
} // namespace WTF
|
||||
|
||||
using WTF::OSAllocator;
|
||||
|
||||
#endif // OSAllocator_h
|
129
js/src/yarr/OSAllocatorPosix.cpp
Normal file
129
js/src/yarr/OSAllocatorPosix.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_OS_UNIX && !WTF_OS_SYMBIAN
|
||||
|
||||
#include "OSAllocator.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include "wtf/Assertions.h"
|
||||
|
||||
namespace WTF {
|
||||
|
||||
void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable)
|
||||
{
|
||||
void* result = reserveAndCommit(bytes, usage, writable, executable);
|
||||
#if HAVE_MADV_FREE_REUSE
|
||||
// To support the "reserve then commit" model, we have to initially decommit.
|
||||
while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable)
|
||||
{
|
||||
// All POSIX reservations start out logically committed.
|
||||
int protection = PROT_READ;
|
||||
if (writable)
|
||||
protection |= PROT_WRITE;
|
||||
if (executable)
|
||||
protection |= PROT_EXEC;
|
||||
|
||||
int flags = MAP_PRIVATE | MAP_ANON;
|
||||
|
||||
#if WTF_OS_DARWIN && !defined(BUILDING_ON_TIGER)
|
||||
int fd = usage;
|
||||
#else
|
||||
int fd = -1;
|
||||
#endif
|
||||
|
||||
void* result = 0;
|
||||
#if (WTF_OS_DARWIN && WTF_CPU_X86_64)
|
||||
if (executable) {
|
||||
// Cook up an address to allocate at, using the following recipe:
|
||||
// 17 bits of zero, stay in userspace kids.
|
||||
// 26 bits of randomness for ASLR.
|
||||
// 21 bits of zero, at least stay aligned within one level of the pagetables.
|
||||
//
|
||||
// But! - as a temporary workaround for some plugin problems (rdar://problem/6812854),
|
||||
// for now instead of 2^26 bits of ASLR lets stick with 25 bits of randomization plus
|
||||
// 2^24, which should put up somewhere in the middle of userspace (in the address range
|
||||
// 0x200000000000 .. 0x5fffffffffff).
|
||||
intptr_t randomLocation = 0;
|
||||
randomLocation = arc4random() & ((1 << 25) - 1);
|
||||
randomLocation += (1 << 24);
|
||||
randomLocation <<= 21;
|
||||
result = reinterpret_cast<void*>(randomLocation);
|
||||
}
|
||||
#endif
|
||||
|
||||
result = mmap(result, bytes, protection, flags, fd, 0);
|
||||
if (result == MAP_FAILED)
|
||||
CRASH();
|
||||
return result;
|
||||
}
|
||||
|
||||
void OSAllocator::commit(void* address, size_t bytes, bool, bool)
|
||||
{
|
||||
#if HAVE_MADV_FREE_REUSE
|
||||
while (madvise(address, bytes, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
|
||||
#else
|
||||
// Non-MADV_FREE_REUSE reservations automatically commit on demand.
|
||||
UNUSED_PARAM(address);
|
||||
UNUSED_PARAM(bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OSAllocator::decommit(void* address, size_t bytes)
|
||||
{
|
||||
#if HAVE_MADV_FREE_REUSE
|
||||
while (madvise(address, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
|
||||
#elif HAVE_MADV_FREE
|
||||
while (madvise(address, bytes, MADV_FREE) == -1 && errno == EAGAIN) { }
|
||||
#elif HAVE_MADV_DONTNEED
|
||||
while (madvise(address, bytes, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
|
||||
#else
|
||||
UNUSED_PARAM(address);
|
||||
UNUSED_PARAM(bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OSAllocator::releaseDecommitted(void* address, size_t bytes)
|
||||
{
|
||||
int result = munmap(address, bytes);
|
||||
if (result == -1)
|
||||
CRASH();
|
||||
}
|
||||
|
||||
} // namespace WTF
|
||||
|
||||
#endif
|
89
js/src/yarr/OSAllocatorWin.cpp
Normal file
89
js/src/yarr/OSAllocatorWin.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_ASSEMBLER && WTF_OS_WINDOWS
|
||||
|
||||
#include "windows.h"
|
||||
#include "wtf/Assertions.h"
|
||||
|
||||
#include "OSAllocator.h"
|
||||
|
||||
namespace WTF {
|
||||
|
||||
static inline DWORD protection(bool writable, bool executable)
|
||||
{
|
||||
return executable ?
|
||||
(writable ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ) :
|
||||
(writable ? PAGE_READWRITE : PAGE_READONLY);
|
||||
}
|
||||
|
||||
void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool writable, bool executable)
|
||||
{
|
||||
void* result = VirtualAlloc(0, bytes, MEM_RESERVE, protection(writable, executable));
|
||||
if (!result)
|
||||
CRASH();
|
||||
return result;
|
||||
}
|
||||
|
||||
void* OSAllocator::reserveAndCommit(size_t bytes, Usage, bool writable, bool executable)
|
||||
{
|
||||
void* result = VirtualAlloc(0, bytes, MEM_RESERVE | MEM_COMMIT, protection(writable, executable));
|
||||
if (!result)
|
||||
CRASH();
|
||||
return result;
|
||||
}
|
||||
|
||||
void OSAllocator::commit(void* address, size_t bytes, bool writable, bool executable)
|
||||
{
|
||||
void* result = VirtualAlloc(address, bytes, MEM_COMMIT, protection(writable, executable));
|
||||
if (!result)
|
||||
CRASH();
|
||||
}
|
||||
|
||||
void OSAllocator::decommit(void* address, size_t bytes)
|
||||
{
|
||||
bool result = VirtualFree(address, bytes, MEM_DECOMMIT);
|
||||
if (!result)
|
||||
CRASH();
|
||||
}
|
||||
|
||||
void OSAllocator::releaseDecommitted(void* address, size_t bytes)
|
||||
{
|
||||
// According to http://msdn.microsoft.com/en-us/library/aa366892(VS.85).aspx,
|
||||
// dwSize must be 0 if dwFreeType is MEM_RELEASE.
|
||||
bool result = VirtualFree(address, 0, MEM_RELEASE);
|
||||
if (!result)
|
||||
CRASH();
|
||||
}
|
||||
|
||||
} // namespace WTF
|
||||
|
||||
#endif
|
131
js/src/yarr/PageAllocation.h
Normal file
131
js/src/yarr/PageAllocation.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef PageAllocation_h
|
||||
#define PageAllocation_h
|
||||
|
||||
#include "wtfbridge.h"
|
||||
#include "OSAllocator.h"
|
||||
#include "PageBlock.h"
|
||||
#include "assembler/wtf/VMTags.h"
|
||||
|
||||
#if WTF_OS_DARWIN
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/vm_map.h>
|
||||
#endif
|
||||
|
||||
#if WTF_OS_HAIKU
|
||||
#include <OS.h>
|
||||
#endif
|
||||
|
||||
#if WTF_OS_WINDOWS
|
||||
#include <malloc.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if WTF_OS_SYMBIAN
|
||||
#include <e32hal.h>
|
||||
#include <e32std.h>
|
||||
#endif
|
||||
|
||||
#if WTF_HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if WTF_HAVE_MMAP
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace WTF {
|
||||
|
||||
/*
|
||||
PageAllocation
|
||||
|
||||
The PageAllocation class provides a cross-platform memory allocation interface
|
||||
with similar capabilities to posix mmap/munmap. Memory is allocated by calling
|
||||
PageAllocation::allocate, and deallocated by calling deallocate on the
|
||||
PageAllocation object. The PageAllocation holds the allocation's base pointer
|
||||
and size.
|
||||
|
||||
The allocate method is passed the size required (which must be a multiple of
|
||||
the system page size, which can be accessed using PageAllocation::pageSize).
|
||||
Callers may also optinally provide a flag indicating the usage (for use by
|
||||
system memory usage tracking tools, where implemented), and boolean values
|
||||
specifying the required protection (defaulting to writable, non-executable).
|
||||
*/
|
||||
|
||||
class PageAllocation : private PageBlock {
|
||||
public:
|
||||
PageAllocation()
|
||||
{
|
||||
}
|
||||
|
||||
using PageBlock::size;
|
||||
using PageBlock::base;
|
||||
|
||||
#ifndef __clang__
|
||||
using PageBlock::operator bool;
|
||||
#else
|
||||
// FIXME: This is a workaround for <rdar://problem/8876150>, wherein Clang incorrectly emits an access
|
||||
// control warning when a client tries to use operator bool exposed above via "using PageBlock::operator bool".
|
||||
operator bool() const { return PageBlock::operator bool(); }
|
||||
#endif
|
||||
|
||||
static PageAllocation allocate(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
|
||||
{
|
||||
ASSERT(isPageAligned(size));
|
||||
return PageAllocation(OSAllocator::reserveAndCommit(size, usage, writable, executable), size);
|
||||
}
|
||||
|
||||
void deallocate()
|
||||
{
|
||||
// Clear base & size before calling release; if this is *inside* allocation
|
||||
// then we won't be able to clear then after deallocating the memory.
|
||||
PageAllocation tmp;
|
||||
JSC::std::swap(tmp, *this);
|
||||
|
||||
ASSERT(tmp);
|
||||
ASSERT(!*this);
|
||||
|
||||
OSAllocator::decommitAndRelease(tmp.base(), tmp.size());
|
||||
}
|
||||
|
||||
private:
|
||||
PageAllocation(void* base, size_t size)
|
||||
: PageBlock(base, size)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace WTF
|
||||
|
||||
using WTF::PageAllocation;
|
||||
|
||||
#endif // PageAllocation_h
|
88
js/src/yarr/PageBlock.cpp
Normal file
88
js/src/yarr/PageBlock.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "PageBlock.h"
|
||||
#include "wtf/Assertions.h"
|
||||
|
||||
#if WTF_OS_UNIX && !WTF_OS_SYMBIAN
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if WTF_OS_WINDOWS
|
||||
#include <malloc.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if WTF_OS_SYMBIAN
|
||||
#include <e32hal.h>
|
||||
#include <e32std.h>
|
||||
#endif
|
||||
|
||||
namespace WTF {
|
||||
|
||||
static size_t s_pageSize;
|
||||
|
||||
#if WTF_OS_UNIX && !WTF_OS_SYMBIAN
|
||||
|
||||
inline size_t systemPageSize()
|
||||
{
|
||||
return getpagesize();
|
||||
}
|
||||
|
||||
#elif WTF_OS_WINDOWS
|
||||
|
||||
inline size_t systemPageSize()
|
||||
{
|
||||
static size_t size = 0;
|
||||
SYSTEM_INFO system_info;
|
||||
GetSystemInfo(&system_info);
|
||||
size = system_info.dwPageSize;
|
||||
return size;
|
||||
}
|
||||
|
||||
#elif WTF_OS_SYMBIAN
|
||||
|
||||
inline size_t systemPageSize()
|
||||
{
|
||||
static TInt page_size = 0;
|
||||
UserHal::PageSizeInBytes(page_size);
|
||||
return page_size;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
size_t pageSize()
|
||||
{
|
||||
if (!s_pageSize)
|
||||
s_pageSize = systemPageSize();
|
||||
ASSERT(isPowerOfTwo(s_pageSize));
|
||||
return s_pageSize;
|
||||
}
|
||||
|
||||
} // namespace WTF
|
91
js/src/yarr/PageBlock.h
Normal file
91
js/src/yarr/PageBlock.h
Normal file
@ -0,0 +1,91 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef PageBlock_h
|
||||
#define PageBlock_h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "jsstdint.h"
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
namespace WTF {
|
||||
|
||||
size_t pageSize();
|
||||
inline bool isPageAligned(void* address) { return !(reinterpret_cast<intptr_t>(address) & (pageSize() - 1)); }
|
||||
inline bool isPageAligned(size_t size) { return !(size & (pageSize() - 1)); }
|
||||
inline bool isPowerOfTwo(size_t size) { return !(size & (size - 1)); }
|
||||
|
||||
class PageBlock {
|
||||
public:
|
||||
PageBlock();
|
||||
PageBlock(const PageBlock&);
|
||||
PageBlock(void*, size_t);
|
||||
|
||||
void* base() const { return m_base; }
|
||||
size_t size() const { return m_size; }
|
||||
|
||||
operator bool() const { return !!m_base; }
|
||||
|
||||
bool contains(void* containedBase, size_t containedSize)
|
||||
{
|
||||
return containedBase >= m_base
|
||||
&& (static_cast<char*>(containedBase) + containedSize) <= (static_cast<char*>(m_base) + m_size);
|
||||
}
|
||||
|
||||
private:
|
||||
void* m_base;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
inline PageBlock::PageBlock()
|
||||
: m_base(0)
|
||||
, m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline PageBlock::PageBlock(const PageBlock& other)
|
||||
: m_base(other.m_base)
|
||||
, m_size(other.m_size)
|
||||
{
|
||||
}
|
||||
|
||||
inline PageBlock::PageBlock(void* base, size_t size)
|
||||
: m_base(base)
|
||||
, m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace WTF
|
||||
|
||||
using WTF::pageSize;
|
||||
using WTF::isPageAligned;
|
||||
using WTF::isPageAligned;
|
||||
using WTF::isPowerOfTwo;
|
||||
|
||||
#endif // PageBlock_h
|
90
js/src/yarr/VMTags.h
Normal file
90
js/src/yarr/VMTags.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VMTags_h
|
||||
#define VMTags_h
|
||||
|
||||
// On Mac OS X, the VM subsystem allows tagging memory requested from mmap and vm_map
|
||||
// in order to aid tools that inspect system memory use.
|
||||
#if WTF_OS_DARWIN
|
||||
|
||||
#include <mach/vm_statistics.h>
|
||||
|
||||
#if !defined(TARGETING_TIGER)
|
||||
|
||||
#if defined(VM_MEMORY_TCMALLOC)
|
||||
#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(VM_MEMORY_TCMALLOC)
|
||||
#else
|
||||
#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(53)
|
||||
#endif // defined(VM_MEMORY_TCMALLOC)
|
||||
|
||||
#if defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
|
||||
#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
|
||||
#else
|
||||
#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(64)
|
||||
#endif // defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
|
||||
|
||||
#if defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
|
||||
#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
|
||||
#else
|
||||
#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65)
|
||||
#endif // defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
|
||||
|
||||
#else // !defined(TARGETING_TIGER)
|
||||
|
||||
// mmap on Tiger fails with tags that work on Leopard, so fall
|
||||
// back to Tiger-compatible tags (that also work on Leopard)
|
||||
// when targeting Tiger.
|
||||
#define VM_TAG_FOR_TCMALLOC_MEMORY -1
|
||||
#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1
|
||||
#define VM_TAG_FOR_REGISTERFILE_MEMORY -1
|
||||
|
||||
#endif // !defined(TARGETING_TIGER)
|
||||
|
||||
// Tags for vm_map and vm_allocate work on both Tiger and Leopard.
|
||||
|
||||
#if defined(VM_MEMORY_JAVASCRIPT_CORE)
|
||||
#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE)
|
||||
#else
|
||||
#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63)
|
||||
#endif // defined(VM_MEMORY_JAVASCRIPT_CORE)
|
||||
|
||||
#if defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
|
||||
#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
|
||||
#else
|
||||
#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(69)
|
||||
#endif // defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
|
||||
|
||||
#else // OS(DARWIN)
|
||||
|
||||
#define VM_TAG_FOR_TCMALLOC_MEMORY -1
|
||||
#define VM_TAG_FOR_COLLECTOR_MEMORY -1
|
||||
#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1
|
||||
#define VM_TAG_FOR_REGISTERFILE_MEMORY -1
|
||||
#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY -1
|
||||
|
||||
#endif // OS(DARWIN)
|
||||
|
||||
#endif // VMTags_h
|
72
js/src/yarr/Yarr.h
Normal file
72
js/src/yarr/Yarr.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef Yarr_h
|
||||
#define Yarr_h
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "YarrInterpreter.h"
|
||||
#include "YarrPattern.h"
|
||||
|
||||
namespace JSC { namespace Yarr {
|
||||
|
||||
#define YarrStackSpaceForBackTrackInfoPatternCharacter 1 // Only for !fixed quantifiers.
|
||||
#define YarrStackSpaceForBackTrackInfoCharacterClass 1 // Only for !fixed quantifiers.
|
||||
#define YarrStackSpaceForBackTrackInfoBackReference 2
|
||||
#define YarrStackSpaceForBackTrackInfoAlternative 1 // One per alternative.
|
||||
#define YarrStackSpaceForBackTrackInfoParentheticalAssertion 1
|
||||
#define YarrStackSpaceForBackTrackInfoParenthesesOnce 1 // Only for !fixed quantifiers.
|
||||
#define YarrStackSpaceForBackTrackInfoParenthesesTerminal 1
|
||||
#define YarrStackSpaceForBackTrackInfoParentheses 2
|
||||
|
||||
static const unsigned quantifyInfinite = UINT_MAX;
|
||||
|
||||
// The below limit restricts the number of "recursive" match calls in order to
|
||||
// avoid spending exponential time on complex regular expressions.
|
||||
static const unsigned matchLimit = 1000000;
|
||||
|
||||
enum JSRegExpResult {
|
||||
JSRegExpMatch = 1,
|
||||
JSRegExpNoMatch = 0,
|
||||
JSRegExpErrorNoMatch = -1,
|
||||
JSRegExpErrorHitLimit = -2,
|
||||
JSRegExpErrorNoMemory = -3,
|
||||
JSRegExpErrorInternal = -4
|
||||
};
|
||||
|
||||
PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*);
|
||||
int interpret(BytecodePattern*, const UChar* input, unsigned start, unsigned length, int* output);
|
||||
|
||||
} } // namespace JSC::Yarr
|
||||
|
||||
#endif // Yarr_h
|
||||
|
1914
js/src/yarr/YarrInterpreter.cpp
Normal file
1914
js/src/yarr/YarrInterpreter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
380
js/src/yarr/YarrInterpreter.h
Normal file
380
js/src/yarr/YarrInterpreter.h
Normal file
@ -0,0 +1,380 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef YarrInterpreter_h
|
||||
#define YarrInterpreter_h
|
||||
|
||||
#include "YarrPattern.h"
|
||||
|
||||
namespace WTF {
|
||||
class BumpPointerAllocator;
|
||||
}
|
||||
using WTF::BumpPointerAllocator;
|
||||
|
||||
namespace JSC { namespace Yarr {
|
||||
|
||||
class ByteDisjunction;
|
||||
|
||||
struct ByteTerm {
|
||||
enum Type {
|
||||
TypeBodyAlternativeBegin,
|
||||
TypeBodyAlternativeDisjunction,
|
||||
TypeBodyAlternativeEnd,
|
||||
TypeAlternativeBegin,
|
||||
TypeAlternativeDisjunction,
|
||||
TypeAlternativeEnd,
|
||||
TypeSubpatternBegin,
|
||||
TypeSubpatternEnd,
|
||||
TypeAssertionBOL,
|
||||
TypeAssertionEOL,
|
||||
TypeAssertionWordBoundary,
|
||||
TypePatternCharacterOnce,
|
||||
TypePatternCharacterFixed,
|
||||
TypePatternCharacterGreedy,
|
||||
TypePatternCharacterNonGreedy,
|
||||
TypePatternCasedCharacterOnce,
|
||||
TypePatternCasedCharacterFixed,
|
||||
TypePatternCasedCharacterGreedy,
|
||||
TypePatternCasedCharacterNonGreedy,
|
||||
TypeCharacterClass,
|
||||
TypeBackReference,
|
||||
TypeParenthesesSubpattern,
|
||||
TypeParenthesesSubpatternOnceBegin,
|
||||
TypeParenthesesSubpatternOnceEnd,
|
||||
TypeParenthesesSubpatternTerminalBegin,
|
||||
TypeParenthesesSubpatternTerminalEnd,
|
||||
TypeParentheticalAssertionBegin,
|
||||
TypeParentheticalAssertionEnd,
|
||||
TypeCheckInput,
|
||||
TypeUncheckInput
|
||||
} type;
|
||||
union {
|
||||
struct {
|
||||
union {
|
||||
UChar patternCharacter;
|
||||
struct {
|
||||
UChar lo;
|
||||
UChar hi;
|
||||
} casedCharacter;
|
||||
CharacterClass* characterClass;
|
||||
unsigned subpatternId;
|
||||
};
|
||||
union {
|
||||
ByteDisjunction* parenthesesDisjunction;
|
||||
unsigned parenthesesWidth;
|
||||
};
|
||||
QuantifierType quantityType;
|
||||
unsigned quantityCount;
|
||||
} atom;
|
||||
struct {
|
||||
int next;
|
||||
int end;
|
||||
bool onceThrough;
|
||||
} alternative;
|
||||
unsigned checkInputCount;
|
||||
};
|
||||
unsigned frameLocation;
|
||||
bool m_capture : 1;
|
||||
bool m_invert : 1;
|
||||
int inputPosition;
|
||||
|
||||
// For js::Vector. Does not create a valid object.
|
||||
ByteTerm()
|
||||
{
|
||||
}
|
||||
|
||||
ByteTerm(UChar ch, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
|
||||
: frameLocation(frameLocation)
|
||||
, m_capture(false)
|
||||
, m_invert(false)
|
||||
{
|
||||
switch (quantityType) {
|
||||
case QuantifierFixedCount:
|
||||
type = (quantityCount == 1) ? ByteTerm::TypePatternCharacterOnce : ByteTerm::TypePatternCharacterFixed;
|
||||
break;
|
||||
case QuantifierGreedy:
|
||||
type = ByteTerm::TypePatternCharacterGreedy;
|
||||
break;
|
||||
case QuantifierNonGreedy:
|
||||
type = ByteTerm::TypePatternCharacterNonGreedy;
|
||||
break;
|
||||
}
|
||||
|
||||
atom.patternCharacter = ch;
|
||||
atom.quantityType = quantityType;
|
||||
atom.quantityCount = quantityCount;
|
||||
inputPosition = inputPos;
|
||||
}
|
||||
|
||||
ByteTerm(UChar lo, UChar hi, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
|
||||
: frameLocation(frameLocation)
|
||||
, m_capture(false)
|
||||
, m_invert(false)
|
||||
{
|
||||
switch (quantityType) {
|
||||
case QuantifierFixedCount:
|
||||
type = (quantityCount == 1) ? ByteTerm::TypePatternCasedCharacterOnce : ByteTerm::TypePatternCasedCharacterFixed;
|
||||
break;
|
||||
case QuantifierGreedy:
|
||||
type = ByteTerm::TypePatternCasedCharacterGreedy;
|
||||
break;
|
||||
case QuantifierNonGreedy:
|
||||
type = ByteTerm::TypePatternCasedCharacterNonGreedy;
|
||||
break;
|
||||
}
|
||||
|
||||
atom.casedCharacter.lo = lo;
|
||||
atom.casedCharacter.hi = hi;
|
||||
atom.quantityType = quantityType;
|
||||
atom.quantityCount = quantityCount;
|
||||
inputPosition = inputPos;
|
||||
}
|
||||
|
||||
ByteTerm(CharacterClass* characterClass, bool invert, int inputPos)
|
||||
: type(ByteTerm::TypeCharacterClass)
|
||||
, m_capture(false)
|
||||
, m_invert(invert)
|
||||
{
|
||||
atom.characterClass = characterClass;
|
||||
atom.quantityType = QuantifierFixedCount;
|
||||
atom.quantityCount = 1;
|
||||
inputPosition = inputPos;
|
||||
}
|
||||
|
||||
ByteTerm(Type type, unsigned subpatternId, ByteDisjunction* parenthesesInfo, bool capture, int inputPos)
|
||||
: type(type)
|
||||
, m_capture(capture)
|
||||
, m_invert(false)
|
||||
{
|
||||
atom.subpatternId = subpatternId;
|
||||
atom.parenthesesDisjunction = parenthesesInfo;
|
||||
atom.quantityType = QuantifierFixedCount;
|
||||
atom.quantityCount = 1;
|
||||
inputPosition = inputPos;
|
||||
}
|
||||
|
||||
ByteTerm(Type type, bool invert = false)
|
||||
: type(type)
|
||||
, m_capture(false)
|
||||
, m_invert(invert)
|
||||
{
|
||||
atom.quantityType = QuantifierFixedCount;
|
||||
atom.quantityCount = 1;
|
||||
}
|
||||
|
||||
ByteTerm(Type type, unsigned subpatternId, bool capture, bool invert, int inputPos)
|
||||
: type(type)
|
||||
, m_capture(capture)
|
||||
, m_invert(invert)
|
||||
{
|
||||
atom.subpatternId = subpatternId;
|
||||
atom.quantityType = QuantifierFixedCount;
|
||||
atom.quantityCount = 1;
|
||||
inputPosition = inputPos;
|
||||
}
|
||||
|
||||
static ByteTerm BOL(int inputPos)
|
||||
{
|
||||
ByteTerm term(TypeAssertionBOL);
|
||||
term.inputPosition = inputPos;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm CheckInput(unsigned count)
|
||||
{
|
||||
ByteTerm term(TypeCheckInput);
|
||||
term.checkInputCount = count;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm UncheckInput(unsigned count)
|
||||
{
|
||||
ByteTerm term(TypeUncheckInput);
|
||||
term.checkInputCount = count;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm EOL(int inputPos)
|
||||
{
|
||||
ByteTerm term(TypeAssertionEOL);
|
||||
term.inputPosition = inputPos;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm WordBoundary(bool invert, int inputPos)
|
||||
{
|
||||
ByteTerm term(TypeAssertionWordBoundary, invert);
|
||||
term.inputPosition = inputPos;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm BackReference(unsigned subpatternId, int inputPos)
|
||||
{
|
||||
return ByteTerm(TypeBackReference, subpatternId, false, false, inputPos);
|
||||
}
|
||||
|
||||
static ByteTerm BodyAlternativeBegin(bool onceThrough)
|
||||
{
|
||||
ByteTerm term(TypeBodyAlternativeBegin);
|
||||
term.alternative.next = 0;
|
||||
term.alternative.end = 0;
|
||||
term.alternative.onceThrough = onceThrough;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm BodyAlternativeDisjunction(bool onceThrough)
|
||||
{
|
||||
ByteTerm term(TypeBodyAlternativeDisjunction);
|
||||
term.alternative.next = 0;
|
||||
term.alternative.end = 0;
|
||||
term.alternative.onceThrough = onceThrough;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm BodyAlternativeEnd()
|
||||
{
|
||||
ByteTerm term(TypeBodyAlternativeEnd);
|
||||
term.alternative.next = 0;
|
||||
term.alternative.end = 0;
|
||||
term.alternative.onceThrough = false;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm AlternativeBegin()
|
||||
{
|
||||
ByteTerm term(TypeAlternativeBegin);
|
||||
term.alternative.next = 0;
|
||||
term.alternative.end = 0;
|
||||
term.alternative.onceThrough = false;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm AlternativeDisjunction()
|
||||
{
|
||||
ByteTerm term(TypeAlternativeDisjunction);
|
||||
term.alternative.next = 0;
|
||||
term.alternative.end = 0;
|
||||
term.alternative.onceThrough = false;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm AlternativeEnd()
|
||||
{
|
||||
ByteTerm term(TypeAlternativeEnd);
|
||||
term.alternative.next = 0;
|
||||
term.alternative.end = 0;
|
||||
term.alternative.onceThrough = false;
|
||||
return term;
|
||||
}
|
||||
|
||||
static ByteTerm SubpatternBegin()
|
||||
{
|
||||
return ByteTerm(TypeSubpatternBegin);
|
||||
}
|
||||
|
||||
static ByteTerm SubpatternEnd()
|
||||
{
|
||||
return ByteTerm(TypeSubpatternEnd);
|
||||
}
|
||||
|
||||
bool invert()
|
||||
{
|
||||
return m_invert;
|
||||
}
|
||||
|
||||
bool capture()
|
||||
{
|
||||
return m_capture;
|
||||
}
|
||||
};
|
||||
|
||||
class ByteDisjunction {
|
||||
WTF_MAKE_FAST_ALLOCATED
|
||||
public:
|
||||
ByteDisjunction(unsigned numSubpatterns, unsigned frameSize)
|
||||
: m_numSubpatterns(numSubpatterns)
|
||||
, m_frameSize(frameSize)
|
||||
{
|
||||
}
|
||||
|
||||
Vector<ByteTerm> terms;
|
||||
unsigned m_numSubpatterns;
|
||||
unsigned m_frameSize;
|
||||
};
|
||||
|
||||
struct BytecodePattern {
|
||||
WTF_MAKE_FAST_ALLOCATED
|
||||
public:
|
||||
BytecodePattern(PassOwnPtr<ByteDisjunction> body, Vector<ByteDisjunction*> allParenthesesInfo, YarrPattern& pattern, BumpPointerAllocator* allocator)
|
||||
: m_body(body)
|
||||
, m_ignoreCase(pattern.m_ignoreCase)
|
||||
, m_multiline(pattern.m_multiline)
|
||||
, m_containsBeginChars(pattern.m_containsBeginChars)
|
||||
, m_allocator(allocator)
|
||||
{
|
||||
newlineCharacterClass = pattern.newlineCharacterClass();
|
||||
wordcharCharacterClass = pattern.wordcharCharacterClass();
|
||||
|
||||
m_allParenthesesInfo.append(allParenthesesInfo);
|
||||
m_userCharacterClasses.append(pattern.m_userCharacterClasses);
|
||||
// 'Steal' the YarrPattern's CharacterClasses! We clear its
|
||||
// array, so that it won't delete them on destruction. We'll
|
||||
// take responsibility for that.
|
||||
pattern.m_userCharacterClasses.clear();
|
||||
|
||||
m_beginChars.append(pattern.m_beginChars);
|
||||
}
|
||||
|
||||
~BytecodePattern()
|
||||
{
|
||||
deleteAllValues(m_allParenthesesInfo);
|
||||
deleteAllValues(m_userCharacterClasses);
|
||||
}
|
||||
|
||||
OwnPtr<ByteDisjunction> m_body;
|
||||
bool m_ignoreCase;
|
||||
bool m_multiline;
|
||||
bool m_containsBeginChars;
|
||||
// Each BytecodePattern is associated with a RegExp, each RegExp is associated
|
||||
// with a JSGlobalData. Cache a pointer to out JSGlobalData's m_regExpAllocator.
|
||||
BumpPointerAllocator* m_allocator;
|
||||
|
||||
CharacterClass* newlineCharacterClass;
|
||||
CharacterClass* wordcharCharacterClass;
|
||||
|
||||
Vector<BeginChar> m_beginChars;
|
||||
|
||||
private:
|
||||
Vector<ByteDisjunction*> m_allParenthesesInfo;
|
||||
Vector<CharacterClass*> m_userCharacterClasses;
|
||||
};
|
||||
|
||||
} } // namespace JSC::Yarr
|
||||
|
||||
#endif // YarrInterpreter_h
|
2405
js/src/yarr/YarrJIT.cpp
Normal file
2405
js/src/yarr/YarrJIT.cpp
Normal file
File diff suppressed because it is too large
Load Diff
93
js/src/yarr/YarrJIT.h
Normal file
93
js/src/yarr/YarrJIT.h
Normal file
@ -0,0 +1,93 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef YarrJIT_h
|
||||
#define YarrJIT_h
|
||||
|
||||
#include "assembler/wtf/Platform.h"
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
|
||||
#include "assembler/assembler/MacroAssembler.h"
|
||||
#include "YarrPattern.h"
|
||||
|
||||
#if WTF_CPU_X86 && !WTF_COMPILER_MSVC
|
||||
#define YARR_CALL __attribute__ ((regparm (3)))
|
||||
#else
|
||||
#define YARR_CALL
|
||||
#endif
|
||||
|
||||
namespace JSC {
|
||||
|
||||
class JSGlobalData;
|
||||
class ExecutablePool;
|
||||
|
||||
namespace Yarr {
|
||||
|
||||
class YarrCodeBlock {
|
||||
typedef int (*YarrJITCode)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
|
||||
|
||||
public:
|
||||
YarrCodeBlock()
|
||||
: m_needFallBack(false)
|
||||
{
|
||||
}
|
||||
|
||||
~YarrCodeBlock()
|
||||
{
|
||||
}
|
||||
|
||||
void setFallBack(bool fallback) { m_needFallBack = fallback; }
|
||||
bool isFallBack() { return m_needFallBack; }
|
||||
void set(MacroAssembler::CodeRef ref) { m_ref = ref; }
|
||||
|
||||
int execute(const UChar* input, unsigned start, unsigned length, int* output)
|
||||
{
|
||||
return JS_EXTENSION((reinterpret_cast<YarrJITCode>(m_ref.m_code.executableAddress()))(input, start, length, output));
|
||||
}
|
||||
|
||||
#if ENABLE_REGEXP_TRACING
|
||||
void *getAddr() { return m_ref.m_code.executableAddress(); }
|
||||
#endif
|
||||
|
||||
void release() { m_ref.release(); }
|
||||
|
||||
private:
|
||||
MacroAssembler::CodeRef m_ref;
|
||||
bool m_needFallBack;
|
||||
};
|
||||
|
||||
void jitCompile(YarrPattern&, JSGlobalData*, YarrCodeBlock& jitObject);
|
||||
int execute(YarrCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output);
|
||||
|
||||
} } // namespace JSC::Yarr
|
||||
|
||||
#endif
|
||||
|
||||
#endif // YarrJIT_h
|
@ -1,4 +1,7 @@
|
||||
/*
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -21,18 +24,18 @@
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef RegexParser_h
|
||||
#define RegexParser_h
|
||||
#ifndef YarrParser_h
|
||||
#define YarrParser_h
|
||||
|
||||
#include <limits.h>
|
||||
#include <wtf/ASCIICType.h>
|
||||
#include "yarr/jswtfbridge.h"
|
||||
#include "yarr/yarr/RegexCommon.h"
|
||||
#include "Yarr.h"
|
||||
|
||||
namespace JSC { namespace Yarr {
|
||||
|
||||
#define REGEXP_ERROR_PREFIX "Invalid regular expression: "
|
||||
|
||||
enum BuiltInCharacterClassID {
|
||||
DigitClassID,
|
||||
SpaceClassID,
|
||||
@ -45,7 +48,7 @@ template<class Delegate>
|
||||
class Parser {
|
||||
private:
|
||||
template<class FriendDelegate>
|
||||
friend int parse(FriendDelegate& delegate, const UString& pattern, unsigned backReferenceLimit);
|
||||
friend ErrorCode parse(FriendDelegate& delegate, const UString& pattern, unsigned backReferenceLimit);
|
||||
|
||||
/*
|
||||
* CharacterClassParserDelegate:
|
||||
@ -61,10 +64,8 @@ private:
|
||||
CharacterClassParserDelegate(Delegate& delegate, ErrorCode& err)
|
||||
: m_delegate(delegate)
|
||||
, m_err(err)
|
||||
, m_state(empty)
|
||||
#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 5 /* quell GCC overwarning */
|
||||
, m_character(0xFFFF)
|
||||
#endif
|
||||
, m_state(Empty)
|
||||
, m_character(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -79,56 +80,62 @@ private:
|
||||
}
|
||||
|
||||
/*
|
||||
* atomPatternCharacterUnescaped():
|
||||
* atomPatternCharacter():
|
||||
*
|
||||
* This method is called directly from parseCharacterClass(), to report a new
|
||||
* pattern character token. This method differs from atomPatternCharacter(),
|
||||
* which will be called from parseEscape(), since a hypen provided via this
|
||||
* method may be indicating a character range, but a hyphen parsed by
|
||||
* parseEscape() cannot be interpreted as doing so.
|
||||
* This method is called either from parseCharacterClass() (for an unescaped
|
||||
* character in a character class), or from parseEscape(). In the former case
|
||||
* the value true will be passed for the argument 'hyphenIsRange', and in this
|
||||
* mode we will allow a hypen to be treated as indicating a range (i.e. /[a-z]/
|
||||
* is different to /[a\-z]/).
|
||||
*/
|
||||
void atomPatternCharacterUnescaped(UChar ch)
|
||||
void atomPatternCharacter(UChar ch, bool hyphenIsRange = false)
|
||||
{
|
||||
switch (m_state) {
|
||||
case empty:
|
||||
m_character = ch;
|
||||
m_state = cachedCharacter;
|
||||
break;
|
||||
case AfterCharacterClass:
|
||||
// Following a builtin character class we need look out for a hyphen.
|
||||
// We're looking for invalid ranges, such as /[\d-x]/ or /[\d-\d]/.
|
||||
// If we see a hyphen following a charater class then unlike usual
|
||||
// we'll report it to the delegate immediately, and put ourself into
|
||||
// a poisoned state. Any following calls to add another character or
|
||||
// character class will result in an error. (A hypen following a
|
||||
// character-class is itself valid, but only at the end of a regex).
|
||||
if (hyphenIsRange && ch == '-') {
|
||||
m_delegate.atomCharacterClassAtom('-');
|
||||
m_state = AfterCharacterClassHyphen;
|
||||
return;
|
||||
}
|
||||
// Otherwise just fall through - cached character so treat this as Empty.
|
||||
|
||||
case cachedCharacter:
|
||||
if (ch == '-')
|
||||
m_state = cachedCharacterHyphen;
|
||||
case Empty:
|
||||
m_character = ch;
|
||||
m_state = CachedCharacter;
|
||||
return;
|
||||
|
||||
case CachedCharacter:
|
||||
if (hyphenIsRange && ch == '-')
|
||||
m_state = CachedCharacterHyphen;
|
||||
else {
|
||||
m_delegate.atomCharacterClassAtom(m_character);
|
||||
m_character = ch;
|
||||
}
|
||||
break;
|
||||
return;
|
||||
|
||||
case cachedCharacterHyphen:
|
||||
if (ch >= m_character)
|
||||
m_delegate.atomCharacterClassRange(m_character, ch);
|
||||
else
|
||||
case CachedCharacterHyphen:
|
||||
if (ch < m_character) {
|
||||
m_err = CharacterClassOutOfOrder;
|
||||
m_state = empty;
|
||||
return;
|
||||
}
|
||||
m_delegate.atomCharacterClassRange(m_character, ch);
|
||||
m_state = Empty;
|
||||
return;
|
||||
|
||||
case AfterCharacterClassHyphen:
|
||||
m_delegate.atomCharacterClassAtom(ch);
|
||||
m_state = Empty;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* atomPatternCharacter():
|
||||
*
|
||||
* Adds a pattern character, called by parseEscape(), as such will not
|
||||
* interpret a hyphen as indicating a character range.
|
||||
*/
|
||||
void atomPatternCharacter(UChar ch)
|
||||
{
|
||||
// Flush if a character is already pending to prevent the
|
||||
// hyphen from begin interpreted as indicating a range.
|
||||
if((ch == '-') && (m_state == cachedCharacter))
|
||||
flush();
|
||||
|
||||
atomPatternCharacterUnescaped(ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* atomBuiltInCharacterClass():
|
||||
*
|
||||
@ -136,17 +143,28 @@ private:
|
||||
*/
|
||||
void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
|
||||
{
|
||||
if (m_state == cachedCharacterHyphen) {
|
||||
// If the RHS of a range does not contain exacly one character then a SyntaxError
|
||||
// must be thrown. SpiderMonkey only errors out in the [c-\s] case as an extension.
|
||||
// (This assumes none of the built in character classes contain a single
|
||||
// character.)
|
||||
m_err = CharacterClassRangeSingleChar;
|
||||
m_state = empty;
|
||||
switch (m_state) {
|
||||
case CachedCharacter:
|
||||
// Flush the currently cached character, then fall through.
|
||||
m_delegate.atomCharacterClassAtom(m_character);
|
||||
|
||||
case Empty:
|
||||
case AfterCharacterClass:
|
||||
m_state = AfterCharacterClass;
|
||||
m_delegate.atomCharacterClassBuiltIn(classID, invert);
|
||||
return;
|
||||
|
||||
case CachedCharacterHyphen:
|
||||
// Error! We have a range that looks like [x-\d]. We require
|
||||
// the end of the range to be a single character.
|
||||
m_err = CharacterClassInvalidRange;
|
||||
return;
|
||||
|
||||
case AfterCharacterClassHyphen:
|
||||
m_delegate.atomCharacterClassBuiltIn(classID, invert);
|
||||
m_state = Empty;
|
||||
return;
|
||||
}
|
||||
flush();
|
||||
m_delegate.atomCharacterClassBuiltIn(classID, invert);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -156,31 +174,29 @@ private:
|
||||
*/
|
||||
void end()
|
||||
{
|
||||
flush();
|
||||
if (m_state == CachedCharacter)
|
||||
m_delegate.atomCharacterClassAtom(m_character);
|
||||
else if (m_state == CachedCharacterHyphen) {
|
||||
m_delegate.atomCharacterClassAtom(m_character);
|
||||
m_delegate.atomCharacterClassAtom('-');
|
||||
}
|
||||
m_delegate.atomCharacterClassEnd();
|
||||
}
|
||||
|
||||
// parseEscape() should never call these delegate methods when
|
||||
// invoked with inCharacterClass set.
|
||||
void assertionWordBoundary(bool) { JS_NOT_REACHED("parseEscape() should never call this"); }
|
||||
void atomBackReference(unsigned) { JS_NOT_REACHED("parseEscape() should never call this"); }
|
||||
void assertionWordBoundary(bool) { ASSERT_NOT_REACHED(); }
|
||||
void atomBackReference(unsigned) { ASSERT_NOT_REACHED(); }
|
||||
|
||||
private:
|
||||
void flush()
|
||||
{
|
||||
if (m_state != empty) // either cachedCharacter or cachedCharacterHyphen
|
||||
m_delegate.atomCharacterClassAtom(m_character);
|
||||
if (m_state == cachedCharacterHyphen)
|
||||
m_delegate.atomCharacterClassAtom('-');
|
||||
m_state = empty;
|
||||
}
|
||||
|
||||
Delegate& m_delegate;
|
||||
ErrorCode& m_err;
|
||||
enum CharacterClassConstructionState {
|
||||
empty,
|
||||
cachedCharacter,
|
||||
cachedCharacterHyphen
|
||||
Empty,
|
||||
CachedCharacter,
|
||||
CachedCharacterHyphen,
|
||||
AfterCharacterClass,
|
||||
AfterCharacterClassHyphen
|
||||
} m_state;
|
||||
UChar m_character;
|
||||
};
|
||||
@ -189,7 +205,7 @@ private:
|
||||
: m_delegate(delegate)
|
||||
, m_backReferenceLimit(backReferenceLimit)
|
||||
, m_err(NoError)
|
||||
, m_data(const_cast<UString &>(pattern).chars())
|
||||
, m_data(pattern.chars())
|
||||
, m_size(pattern.length())
|
||||
, m_index(0)
|
||||
, m_parenthesesNestingDepth(0)
|
||||
@ -219,8 +235,8 @@ private:
|
||||
template<bool inCharacterClass, class EscapeDelegate>
|
||||
bool parseEscape(EscapeDelegate& delegate)
|
||||
{
|
||||
JS_ASSERT(!m_err);
|
||||
JS_ASSERT(peek() == '\\');
|
||||
ASSERT(!m_err);
|
||||
ASSERT(peek() == '\\');
|
||||
consume();
|
||||
|
||||
if (atEndOfPattern()) {
|
||||
@ -292,7 +308,7 @@ private:
|
||||
|
||||
unsigned backReference;
|
||||
if (!consumeNumber(backReference))
|
||||
return false;
|
||||
break;
|
||||
if (backReference <= m_backReferenceLimit) {
|
||||
delegate.atomBackReference(backReference);
|
||||
break;
|
||||
@ -402,14 +418,14 @@ private:
|
||||
/*
|
||||
* parseCharacterClass():
|
||||
*
|
||||
* Helper for parseTokens(); calls directly and indirectly (via parseCharacterClassEscape)
|
||||
* Helper for parseTokens(); calls dirctly and indirectly (via parseCharacterClassEscape)
|
||||
* to an instance of CharacterClassParserDelegate, to describe the character class to the
|
||||
* delegate.
|
||||
*/
|
||||
void parseCharacterClass()
|
||||
{
|
||||
JS_ASSERT(!m_err);
|
||||
JS_ASSERT(peek() == '[');
|
||||
ASSERT(!m_err);
|
||||
ASSERT(peek() == '[');
|
||||
consume();
|
||||
|
||||
CharacterClassParserDelegate characterClassConstructor(m_delegate, m_err);
|
||||
@ -428,7 +444,7 @@ private:
|
||||
break;
|
||||
|
||||
default:
|
||||
characterClassConstructor.atomPatternCharacterUnescaped(consume());
|
||||
characterClassConstructor.atomPatternCharacter(consume(), true);
|
||||
}
|
||||
|
||||
if (m_err)
|
||||
@ -445,8 +461,8 @@ private:
|
||||
*/
|
||||
void parseParenthesesBegin()
|
||||
{
|
||||
JS_ASSERT(!m_err);
|
||||
JS_ASSERT(peek() == '(');
|
||||
ASSERT(!m_err);
|
||||
ASSERT(peek() == '(');
|
||||
consume();
|
||||
|
||||
if (tryConsume('?')) {
|
||||
@ -484,8 +500,8 @@ private:
|
||||
*/
|
||||
void parseParenthesesEnd()
|
||||
{
|
||||
JS_ASSERT(!m_err);
|
||||
JS_ASSERT(peek() == ')');
|
||||
ASSERT(!m_err);
|
||||
ASSERT(peek() == ')');
|
||||
consume();
|
||||
|
||||
if (m_parenthesesNestingDepth > 0)
|
||||
@ -503,8 +519,8 @@ private:
|
||||
*/
|
||||
void parseQuantifier(bool lastTokenWasAnAtom, unsigned min, unsigned max)
|
||||
{
|
||||
JS_ASSERT(!m_err);
|
||||
JS_ASSERT(min <= max);
|
||||
ASSERT(!m_err);
|
||||
ASSERT(min <= max);
|
||||
|
||||
if (lastTokenWasAnAtom)
|
||||
m_delegate.quantifyAtom(min, max, !tryConsume('?'));
|
||||
@ -572,13 +588,13 @@ private:
|
||||
|
||||
case '*':
|
||||
consume();
|
||||
parseQuantifier(lastTokenWasAnAtom, 0, UINT_MAX);
|
||||
parseQuantifier(lastTokenWasAnAtom, 0, quantifyInfinite);
|
||||
lastTokenWasAnAtom = false;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
consume();
|
||||
parseQuantifier(lastTokenWasAnAtom, 1, UINT_MAX);
|
||||
parseQuantifier(lastTokenWasAnAtom, 1, quantifyInfinite);
|
||||
lastTokenWasAnAtom = false;
|
||||
break;
|
||||
|
||||
@ -603,7 +619,7 @@ private:
|
||||
if (!consumeNumber(max))
|
||||
break;
|
||||
} else {
|
||||
max = UINT_MAX;
|
||||
max = quantifyInfinite;
|
||||
}
|
||||
}
|
||||
|
||||
@ -636,26 +652,18 @@ private:
|
||||
/*
|
||||
* parse():
|
||||
*
|
||||
* This method calls regexBegin(), calls parseTokens() to parse over the input
|
||||
* patterns, calls regexEnd() or regexError() as appropriate, and converts any
|
||||
* This method calls parseTokens() to parse over the input and converts any
|
||||
* error code to a const char* for a result.
|
||||
*/
|
||||
int parse()
|
||||
ErrorCode parse()
|
||||
{
|
||||
m_delegate.regexBegin();
|
||||
|
||||
if (m_size > MAX_PATTERN_SIZE)
|
||||
m_err = PatternTooLarge;
|
||||
else
|
||||
parseTokens();
|
||||
JS_ASSERT(atEndOfPattern() || m_err);
|
||||
ASSERT(atEndOfPattern() || m_err);
|
||||
|
||||
if (m_err)
|
||||
m_delegate.regexError();
|
||||
else
|
||||
m_delegate.regexEnd();
|
||||
|
||||
return static_cast<int>(m_err);
|
||||
return m_err;
|
||||
}
|
||||
|
||||
|
||||
@ -675,13 +683,13 @@ private:
|
||||
|
||||
bool atEndOfPattern()
|
||||
{
|
||||
JS_ASSERT(m_index <= m_size);
|
||||
ASSERT(m_index <= m_size);
|
||||
return m_index == m_size;
|
||||
}
|
||||
|
||||
int peek()
|
||||
{
|
||||
JS_ASSERT(m_index < m_size);
|
||||
ASSERT(m_index < m_size);
|
||||
return m_data[m_index];
|
||||
}
|
||||
|
||||
@ -692,40 +700,40 @@ private:
|
||||
|
||||
unsigned peekDigit()
|
||||
{
|
||||
JS_ASSERT(peekIsDigit());
|
||||
ASSERT(peekIsDigit());
|
||||
return peek() - '0';
|
||||
}
|
||||
|
||||
int consume()
|
||||
{
|
||||
JS_ASSERT(m_index < m_size);
|
||||
ASSERT(m_index < m_size);
|
||||
return m_data[m_index++];
|
||||
}
|
||||
|
||||
unsigned consumeDigit()
|
||||
{
|
||||
JS_ASSERT(peekIsDigit());
|
||||
ASSERT(peekIsDigit());
|
||||
return consume() - '0';
|
||||
}
|
||||
|
||||
bool consumeNumber(unsigned &accum)
|
||||
{
|
||||
accum = consumeDigit();
|
||||
while (peekIsDigit()) {
|
||||
unsigned newValue = accum * 10 + peekDigit();
|
||||
if (newValue < accum) { /* Overflow check. */
|
||||
m_err = QuantifierTooLarge;
|
||||
return false;
|
||||
}
|
||||
accum = newValue;
|
||||
consume();
|
||||
}
|
||||
return true;
|
||||
bool consumeNumber(unsigned &accum)
|
||||
{
|
||||
accum = consumeDigit();
|
||||
while (peekIsDigit()) {
|
||||
unsigned newValue = accum * 10 + peekDigit();
|
||||
if (newValue < accum) { /* Overflow check. */
|
||||
m_err = QuantifierTooLarge;
|
||||
return false;
|
||||
}
|
||||
accum = newValue;
|
||||
consume();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned consumeOctal()
|
||||
{
|
||||
JS_ASSERT(WTF::isASCIIOctalDigit(peek()));
|
||||
ASSERT(WTF::isASCIIOctalDigit(peek()));
|
||||
|
||||
unsigned n = consumeDigit();
|
||||
while (n < 32 && !atEndOfPattern() && WTF::isASCIIOctalDigit(peek()))
|
||||
@ -798,14 +806,6 @@ private:
|
||||
*
|
||||
* void disjunction();
|
||||
*
|
||||
* void regexBegin();
|
||||
* void regexEnd();
|
||||
* void regexError();
|
||||
*
|
||||
* Before any call recording tokens are made, regexBegin() will be called on the
|
||||
* delegate once. Once parsing is complete either regexEnd() or regexError() will
|
||||
* be called, as appropriate.
|
||||
*
|
||||
* The regular expression is described by a sequence of assertion*() and atom*()
|
||||
* callbacks to the delegate, describing the terms in the regular expression.
|
||||
* Following an atom a quantifyAtom() call may occur to indicate that the previous
|
||||
@ -836,11 +836,11 @@ private:
|
||||
*/
|
||||
|
||||
template<class Delegate>
|
||||
int parse(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit = UINT_MAX)
|
||||
ErrorCode parse(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit = quantifyInfinite)
|
||||
{
|
||||
return Parser<Delegate>(delegate, pattern, backReferenceLimit).parse();
|
||||
}
|
||||
|
||||
} } // namespace JSC::Yarr
|
||||
|
||||
#endif // RegexParser_h
|
||||
#endif // YarrParser_h
|
@ -1,5 +1,9 @@
|
||||
/*
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -21,12 +25,13 @@
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "jsinttypes.h"
|
||||
#include "RegexCompiler.h"
|
||||
#include "YarrPattern.h"
|
||||
|
||||
#include "RegexPattern.h"
|
||||
#include "Yarr.h"
|
||||
#include "YarrParser.h"
|
||||
|
||||
using namespace WTF;
|
||||
|
||||
@ -34,12 +39,6 @@ namespace JSC { namespace Yarr {
|
||||
|
||||
#include "RegExpJitTables.h"
|
||||
|
||||
#if WTF_CPU_SPARC
|
||||
#define BASE_FRAME_SIZE 24
|
||||
#else
|
||||
#define BASE_FRAME_SIZE 0
|
||||
#endif
|
||||
|
||||
class CharacterClassConstructor {
|
||||
public:
|
||||
CharacterClassConstructor(bool isCaseInsensitive = false)
|
||||
@ -57,13 +56,13 @@ public:
|
||||
|
||||
void append(const CharacterClass* other)
|
||||
{
|
||||
for (size_t i = 0; i < other->m_matches.length(); ++i)
|
||||
for (size_t i = 0; i < other->m_matches.size(); ++i)
|
||||
addSorted(m_matches, other->m_matches[i]);
|
||||
for (size_t i = 0; i < other->m_ranges.length(); ++i)
|
||||
for (size_t i = 0; i < other->m_ranges.size(); ++i)
|
||||
addSortedRange(m_ranges, other->m_ranges[i].begin, other->m_ranges[i].end);
|
||||
for (size_t i = 0; i < other->m_matchesUnicode.length(); ++i)
|
||||
for (size_t i = 0; i < other->m_matchesUnicode.size(); ++i)
|
||||
addSorted(m_matchesUnicode, other->m_matchesUnicode[i]);
|
||||
for (size_t i = 0; i < other->m_rangesUnicode.length(); ++i)
|
||||
for (size_t i = 0; i < other->m_rangesUnicode.size(); ++i)
|
||||
addSortedRange(m_rangesUnicode, other->m_rangesUnicode[i].begin, other->m_rangesUnicode[i].end);
|
||||
}
|
||||
|
||||
@ -101,18 +100,18 @@ public:
|
||||
{
|
||||
if (lo <= 0x7f) {
|
||||
char asciiLo = lo;
|
||||
char asciiHi = JS_MIN(hi, (UChar)0x7f);
|
||||
char asciiHi = std::min(hi, (UChar)0x7f);
|
||||
addSortedRange(m_ranges, lo, asciiHi);
|
||||
|
||||
if (m_isCaseInsensitive) {
|
||||
if ((asciiLo <= 'Z') && (asciiHi >= 'A'))
|
||||
addSortedRange(m_ranges, JS_MAX(asciiLo, 'A')+('a'-'A'), JS_MIN(asciiHi, 'Z')+('a'-'A'));
|
||||
addSortedRange(m_ranges, std::max(asciiLo, 'A')+('a'-'A'), std::min(asciiHi, 'Z')+('a'-'A'));
|
||||
if ((asciiLo <= 'z') && (asciiHi >= 'a'))
|
||||
addSortedRange(m_ranges, JS_MAX(asciiLo, 'a')+('A'-'a'), JS_MIN(asciiHi, 'z')+('A'-'a'));
|
||||
addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a'));
|
||||
}
|
||||
}
|
||||
if (hi >= 0x80) {
|
||||
uint32 unicodeCurr = JS_MAX(lo, (UChar)0x80);
|
||||
uint32_t unicodeCurr = std::max(lo, (UChar)0x80);
|
||||
addSortedRange(m_rangesUnicode, unicodeCurr, hi);
|
||||
|
||||
if (m_isCaseInsensitive) {
|
||||
@ -122,7 +121,7 @@ public:
|
||||
// (if so we won't re-enter the loop, since the loop condition above
|
||||
// will definitely fail) - but this does mean we cannot use a UChar
|
||||
// to represent unicodeCurr, we must use a 32-bit value instead.
|
||||
JS_ASSERT(unicodeCurr <= 0xffff);
|
||||
ASSERT(unicodeCurr <= 0xffff);
|
||||
|
||||
if (isUnicodeUpper(unicodeCurr)) {
|
||||
UChar lowerCaseRangeBegin = Unicode::toLower(unicodeCurr);
|
||||
@ -145,8 +144,7 @@ public:
|
||||
|
||||
CharacterClass* charClass()
|
||||
{
|
||||
// FIXME: bug 574459 -- no NULL check
|
||||
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>((CharacterClassTable*)NULL);
|
||||
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(PassRefPtr<CharacterClassTable>(0));
|
||||
|
||||
characterClass->m_matches.append(m_matches);
|
||||
characterClass->m_ranges.append(m_ranges);
|
||||
@ -159,12 +157,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
typedef js::Vector<UChar, 0, js::SystemAllocPolicy> UChars;
|
||||
typedef js::Vector<CharacterRange, 0, js::SystemAllocPolicy> CharacterRanges;
|
||||
void addSorted(UChars& matches, UChar ch)
|
||||
void addSorted(Vector<UChar>& matches, UChar ch)
|
||||
{
|
||||
unsigned pos = 0;
|
||||
unsigned range = matches.length();
|
||||
unsigned range = matches.size();
|
||||
|
||||
// binary chop, find position to insert char.
|
||||
while (range) {
|
||||
@ -181,15 +177,15 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (pos == matches.length())
|
||||
if (pos == matches.size())
|
||||
matches.append(ch);
|
||||
else
|
||||
matches.insert(matches.begin() + pos, ch);
|
||||
matches.insert(pos, ch);
|
||||
}
|
||||
|
||||
void addSortedRange(CharacterRanges& ranges, UChar lo, UChar hi)
|
||||
void addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi)
|
||||
{
|
||||
unsigned end = ranges.length();
|
||||
unsigned end = ranges.size();
|
||||
|
||||
// Simple linear scan - I doubt there are that many ranges anyway...
|
||||
// feel free to fix this with something faster (eg binary chop).
|
||||
@ -201,7 +197,7 @@ private:
|
||||
ranges[i].begin = lo;
|
||||
return;
|
||||
}
|
||||
ranges.insert(ranges.begin() + i, CharacterRange(lo, hi));
|
||||
ranges.insert(i, CharacterRange(lo, hi));
|
||||
return;
|
||||
}
|
||||
// Okay, since we didn't hit the last case, the end of the new range is definitely at or after the begining
|
||||
@ -209,17 +205,17 @@ private:
|
||||
// end of the last range they concatenate, which is just as good.
|
||||
if (lo <= (ranges[i].end + 1)) {
|
||||
// found an intersect! we'll replace this entry in the array.
|
||||
ranges[i].begin = JS_MIN(ranges[i].begin, lo);
|
||||
ranges[i].end = JS_MAX(ranges[i].end, hi);
|
||||
ranges[i].begin = std::min(ranges[i].begin, lo);
|
||||
ranges[i].end = std::max(ranges[i].end, hi);
|
||||
|
||||
// now check if the new range can subsume any subsequent ranges.
|
||||
unsigned next = i+1;
|
||||
// each iteration of the loop we will either remove something from the list, or break the loop.
|
||||
while (next < ranges.length()) {
|
||||
while (next < ranges.size()) {
|
||||
if (ranges[next].begin <= (ranges[i].end + 1)) {
|
||||
// the next entry now overlaps / concatenates this one.
|
||||
ranges[i].end = JS_MAX(ranges[i].end, ranges[next].end);
|
||||
ranges.erase(ranges.begin() + next);
|
||||
ranges[i].end = std::max(ranges[i].end, ranges[next].end);
|
||||
ranges.remove(next);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
@ -234,21 +230,131 @@ private:
|
||||
|
||||
bool m_isCaseInsensitive;
|
||||
|
||||
UChars m_matches;
|
||||
CharacterRanges m_ranges;
|
||||
UChars m_matchesUnicode;
|
||||
CharacterRanges m_rangesUnicode;
|
||||
Vector<UChar> m_matches;
|
||||
Vector<CharacterRange> m_ranges;
|
||||
Vector<UChar> m_matchesUnicode;
|
||||
Vector<CharacterRange> m_rangesUnicode;
|
||||
};
|
||||
|
||||
class RegexPatternConstructor {
|
||||
public:
|
||||
RegexPatternConstructor(RegexPattern& pattern)
|
||||
: m_pattern(pattern)
|
||||
, m_characterClassConstructor(pattern.m_ignoreCase)
|
||||
struct BeginCharHelper {
|
||||
BeginCharHelper(Vector<BeginChar>* beginChars, bool isCaseInsensitive = false)
|
||||
: m_beginChars(beginChars)
|
||||
, m_isCaseInsensitive(isCaseInsensitive)
|
||||
{}
|
||||
|
||||
void addBeginChar(BeginChar beginChar, Vector<TermChain>* hotTerms, QuantifierType quantityType, unsigned quantityCount)
|
||||
{
|
||||
if (quantityType == QuantifierFixedCount && quantityCount > 1) {
|
||||
// We duplicate the first found character if the quantity of the term is more than one. eg.: /a{3}/
|
||||
beginChar.value |= beginChar.value << 16;
|
||||
beginChar.mask |= beginChar.mask << 16;
|
||||
addCharacter(beginChar);
|
||||
} else if (quantityType == QuantifierFixedCount && quantityCount == 1 && hotTerms->size())
|
||||
// In case of characters with fixed quantifier we should check the next character as well.
|
||||
linkHotTerms(beginChar, hotTerms);
|
||||
else
|
||||
// In case of greedy matching the next character checking is unnecessary therefore we just store
|
||||
// the first character.
|
||||
addCharacter(beginChar);
|
||||
}
|
||||
|
||||
~RegexPatternConstructor()
|
||||
// Merge two following BeginChars in the vector to reduce the number of character checks.
|
||||
void merge(unsigned size)
|
||||
{
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
BeginChar* curr = &m_beginChars->at(i);
|
||||
BeginChar* next = &m_beginChars->at(i + 1);
|
||||
|
||||
// If the current and the next size of value is different we should skip the merge process
|
||||
// because the 16bit and 32bit values are unmergable.
|
||||
if (curr->value <= 0xFFFF && next->value > 0xFFFF)
|
||||
continue;
|
||||
|
||||
unsigned diff = curr->value ^ next->value;
|
||||
|
||||
curr->mask |= diff;
|
||||
curr->value |= curr->mask;
|
||||
|
||||
m_beginChars->remove(i + 1);
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void addCharacter(BeginChar beginChar)
|
||||
{
|
||||
unsigned pos = 0;
|
||||
unsigned range = m_beginChars->size();
|
||||
|
||||
// binary chop, find position to insert char.
|
||||
while (range) {
|
||||
unsigned index = range >> 1;
|
||||
|
||||
int val = m_beginChars->at(pos+index).value - beginChar.value;
|
||||
if (!val)
|
||||
return;
|
||||
if (val < 0)
|
||||
range = index;
|
||||
else {
|
||||
pos += (index+1);
|
||||
range -= (index+1);
|
||||
}
|
||||
}
|
||||
|
||||
if (pos == m_beginChars->size())
|
||||
m_beginChars->append(beginChar);
|
||||
else
|
||||
m_beginChars->insert(pos, beginChar);
|
||||
}
|
||||
|
||||
// Create BeginChar objects by appending each terms from a hotTerms vector to an existing BeginChar object.
|
||||
void linkHotTerms(BeginChar beginChar, Vector<TermChain>* hotTerms)
|
||||
{
|
||||
for (unsigned i = 0; i < hotTerms->size(); i++) {
|
||||
PatternTerm hotTerm = hotTerms->at(i).term;
|
||||
ASSERT(hotTerm.type == PatternTerm::TypePatternCharacter);
|
||||
|
||||
UChar characterNext = hotTerm.patternCharacter;
|
||||
|
||||
// Append a character to an existing BeginChar object.
|
||||
if (characterNext <= 0x7f) {
|
||||
unsigned mask = 0;
|
||||
|
||||
if (m_isCaseInsensitive && isASCIIAlpha(characterNext)) {
|
||||
mask = 32;
|
||||
characterNext = toASCIILower(characterNext);
|
||||
}
|
||||
|
||||
addCharacter(BeginChar(beginChar.value | (characterNext << 16), beginChar.mask | (mask << 16)));
|
||||
} else {
|
||||
UChar upper, lower;
|
||||
if (m_isCaseInsensitive && ((upper = Unicode::toUpper(characterNext)) != (lower = Unicode::toLower(characterNext)))) {
|
||||
addCharacter(BeginChar(beginChar.value | (upper << 16), beginChar.mask));
|
||||
addCharacter(BeginChar(beginChar.value | (lower << 16), beginChar.mask));
|
||||
} else
|
||||
addCharacter(BeginChar(beginChar.value | (characterNext << 16), beginChar.mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector<BeginChar>* m_beginChars;
|
||||
bool m_isCaseInsensitive;
|
||||
};
|
||||
|
||||
class YarrPatternConstructor {
|
||||
public:
|
||||
YarrPatternConstructor(YarrPattern& pattern)
|
||||
: m_pattern(pattern)
|
||||
, m_characterClassConstructor(pattern.m_ignoreCase)
|
||||
, m_beginCharHelper(&pattern.m_beginChars, pattern.m_ignoreCase)
|
||||
, m_invertParentheticalAssertion(false)
|
||||
{
|
||||
m_pattern.m_body = js::OffTheBooks::new_<PatternDisjunction>();
|
||||
m_alternative = m_pattern.m_body->addNewAlternative();
|
||||
m_pattern.m_disjunctions.append(m_pattern.m_body);
|
||||
}
|
||||
|
||||
~YarrPatternConstructor()
|
||||
{
|
||||
}
|
||||
|
||||
@ -256,10 +362,19 @@ public:
|
||||
{
|
||||
m_pattern.reset();
|
||||
m_characterClassConstructor.reset();
|
||||
|
||||
m_pattern.m_body = js::OffTheBooks::new_<PatternDisjunction>();
|
||||
m_alternative = m_pattern.m_body->addNewAlternative();
|
||||
m_pattern.m_disjunctions.append(m_pattern.m_body);
|
||||
}
|
||||
|
||||
void assertionBOL()
|
||||
{
|
||||
if (!m_alternative->m_terms.size() & !m_invertParentheticalAssertion) {
|
||||
m_alternative->m_startsWithBOL = true;
|
||||
m_alternative->m_containsBOL = true;
|
||||
m_pattern.m_containsBOL = true;
|
||||
}
|
||||
m_alternative->m_terms.append(PatternTerm::BOL());
|
||||
}
|
||||
void assertionEOL()
|
||||
@ -318,7 +433,7 @@ public:
|
||||
|
||||
void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert)
|
||||
{
|
||||
JS_ASSERT(classID != NewlineClassID);
|
||||
ASSERT(classID != NewlineClassID);
|
||||
|
||||
switch (classID) {
|
||||
case DigitClassID:
|
||||
@ -334,7 +449,7 @@ public:
|
||||
break;
|
||||
|
||||
default:
|
||||
JS_NOT_REACHED("Invalid character class.");
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,36 +466,56 @@ public:
|
||||
if (capture)
|
||||
m_pattern.m_numSubpatterns++;
|
||||
|
||||
// FIXME: bug 574459 -- no NULL check
|
||||
PatternDisjunction* parenthesesDisjunction = js::OffTheBooks::new_<PatternDisjunction>(m_alternative);
|
||||
m_pattern.m_disjunctions.append(parenthesesDisjunction);
|
||||
m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture));
|
||||
m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture, false));
|
||||
m_alternative = parenthesesDisjunction->addNewAlternative();
|
||||
}
|
||||
|
||||
void atomParentheticalAssertionBegin(bool invert = false)
|
||||
{
|
||||
// FIXME: bug 574459 -- no NULL check
|
||||
PatternDisjunction* parenthesesDisjunction = js::OffTheBooks::new_<PatternDisjunction>(m_alternative);
|
||||
m_pattern.m_disjunctions.append(parenthesesDisjunction);
|
||||
m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, invert));
|
||||
m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, false, invert));
|
||||
m_alternative = parenthesesDisjunction->addNewAlternative();
|
||||
m_invertParentheticalAssertion = invert;
|
||||
}
|
||||
|
||||
void atomParenthesesEnd()
|
||||
{
|
||||
JS_ASSERT(m_alternative->m_parent);
|
||||
JS_ASSERT(m_alternative->m_parent->m_parent);
|
||||
ASSERT(m_alternative->m_parent);
|
||||
ASSERT(m_alternative->m_parent->m_parent);
|
||||
|
||||
PatternDisjunction* parenthesesDisjunction = m_alternative->m_parent;
|
||||
m_alternative = m_alternative->m_parent->m_parent;
|
||||
|
||||
m_alternative->lastTerm().parentheses.lastSubpatternId = m_pattern.m_numSubpatterns;
|
||||
|
||||
PatternTerm& lastTerm = m_alternative->lastTerm();
|
||||
|
||||
unsigned numParenAlternatives = parenthesesDisjunction->m_alternatives.size();
|
||||
unsigned numBOLAnchoredAlts = 0;
|
||||
|
||||
for (unsigned i = 0; i < numParenAlternatives; i++) {
|
||||
// Bubble up BOL flags
|
||||
if (parenthesesDisjunction->m_alternatives[i]->m_startsWithBOL)
|
||||
numBOLAnchoredAlts++;
|
||||
}
|
||||
|
||||
if (numBOLAnchoredAlts) {
|
||||
m_alternative->m_containsBOL = true;
|
||||
// If all the alternatives in parens start with BOL, then so does this one
|
||||
if (numBOLAnchoredAlts == numParenAlternatives)
|
||||
m_alternative->m_startsWithBOL = true;
|
||||
}
|
||||
|
||||
lastTerm.parentheses.lastSubpatternId = m_pattern.m_numSubpatterns;
|
||||
m_invertParentheticalAssertion = false;
|
||||
}
|
||||
|
||||
void atomBackReference(unsigned subpatternId)
|
||||
{
|
||||
JS_ASSERT(subpatternId);
|
||||
ASSERT(subpatternId);
|
||||
m_pattern.m_containsBackreferences = true;
|
||||
m_pattern.m_maxBackReference = JS_MAX(m_pattern.m_maxBackReference, subpatternId);
|
||||
m_pattern.m_maxBackReference = std::max(m_pattern.m_maxBackReference, subpatternId);
|
||||
|
||||
if (subpatternId > m_pattern.m_numSubpatterns) {
|
||||
m_alternative->m_terms.append(PatternTerm::ForwardReference());
|
||||
@ -388,14 +523,14 @@ public:
|
||||
}
|
||||
|
||||
PatternAlternative* currentAlternative = m_alternative;
|
||||
JS_ASSERT(currentAlternative);
|
||||
ASSERT(currentAlternative);
|
||||
|
||||
// Note to self: if we waited until the AST was baked, we could also remove forwards refs
|
||||
while ((currentAlternative = currentAlternative->m_parent->m_parent)) {
|
||||
PatternTerm& term = currentAlternative->lastTerm();
|
||||
JS_ASSERT((term.type == PatternTerm::TypeParenthesesSubpattern) || (term.type == PatternTerm::TypeParentheticalAssertion));
|
||||
ASSERT((term.type == PatternTerm::TypeParenthesesSubpattern) || (term.type == PatternTerm::TypeParentheticalAssertion));
|
||||
|
||||
if ((term.type == PatternTerm::TypeParenthesesSubpattern) && term.invertOrCapture && (subpatternId == term.subpatternId)) {
|
||||
if ((term.type == PatternTerm::TypeParenthesesSubpattern) && term.capture() && (subpatternId == term.parentheses.subpatternId)) {
|
||||
m_alternative->m_terms.append(PatternTerm::ForwardReference());
|
||||
return;
|
||||
}
|
||||
@ -404,37 +539,43 @@ public:
|
||||
m_alternative->m_terms.append(PatternTerm(subpatternId));
|
||||
}
|
||||
|
||||
PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction)
|
||||
// deep copy the argument disjunction. If filterStartsWithBOL is true,
|
||||
// skip alternatives with m_startsWithBOL set true.
|
||||
PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction, bool filterStartsWithBOL = false)
|
||||
{
|
||||
// FIXME: bug 574459 -- no NULL check
|
||||
PatternDisjunction* newDisjunction = js::OffTheBooks::new_<PatternDisjunction>();
|
||||
|
||||
newDisjunction->m_parent = disjunction->m_parent;
|
||||
for (unsigned alt = 0; alt < disjunction->m_alternatives.length(); ++alt) {
|
||||
PatternDisjunction* newDisjunction = 0;
|
||||
for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
|
||||
PatternAlternative* alternative = disjunction->m_alternatives[alt];
|
||||
PatternAlternative* newAlternative = newDisjunction->addNewAlternative();
|
||||
for (unsigned i = 0; i < alternative->m_terms.length(); ++i)
|
||||
newAlternative->m_terms.append(copyTerm(alternative->m_terms[i]));
|
||||
if (!filterStartsWithBOL || !alternative->m_startsWithBOL) {
|
||||
if (!newDisjunction) {
|
||||
newDisjunction = js::OffTheBooks::new_<PatternDisjunction>();
|
||||
newDisjunction->m_parent = disjunction->m_parent;
|
||||
}
|
||||
PatternAlternative* newAlternative = newDisjunction->addNewAlternative();
|
||||
for (unsigned i = 0; i < alternative->m_terms.size(); ++i)
|
||||
newAlternative->m_terms.append(copyTerm(alternative->m_terms[i], filterStartsWithBOL));
|
||||
}
|
||||
}
|
||||
|
||||
m_pattern.m_disjunctions.append(newDisjunction);
|
||||
|
||||
if (newDisjunction)
|
||||
m_pattern.m_disjunctions.append(newDisjunction);
|
||||
return newDisjunction;
|
||||
}
|
||||
|
||||
PatternTerm copyTerm(PatternTerm& term)
|
||||
|
||||
PatternTerm copyTerm(PatternTerm& term, bool filterStartsWithBOL = false)
|
||||
{
|
||||
if ((term.type != PatternTerm::TypeParenthesesSubpattern) && (term.type != PatternTerm::TypeParentheticalAssertion))
|
||||
return PatternTerm(term);
|
||||
|
||||
|
||||
PatternTerm termCopy = term;
|
||||
termCopy.parentheses.disjunction = copyDisjunction(termCopy.parentheses.disjunction);
|
||||
termCopy.parentheses.disjunction = copyDisjunction(termCopy.parentheses.disjunction, filterStartsWithBOL);
|
||||
return termCopy;
|
||||
}
|
||||
|
||||
|
||||
void quantifyAtom(unsigned min, unsigned max, bool greedy)
|
||||
{
|
||||
JS_ASSERT(min <= max);
|
||||
JS_ASSERT(m_alternative->m_terms.length());
|
||||
ASSERT(min <= max);
|
||||
ASSERT(m_alternative->m_terms.size());
|
||||
|
||||
if (!max) {
|
||||
m_alternative->removeLastTerm();
|
||||
@ -442,8 +583,8 @@ public:
|
||||
}
|
||||
|
||||
PatternTerm& term = m_alternative->lastTerm();
|
||||
JS_ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary);
|
||||
JS_ASSERT((term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount));
|
||||
ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary);
|
||||
ASSERT((term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount));
|
||||
|
||||
// For any assertion with a zero minimum, not matching is valid and has no effect,
|
||||
// remove it. Otherwise, we need to match as least once, but there is no point
|
||||
@ -464,7 +605,7 @@ public:
|
||||
term.quantify(min, QuantifierFixedCount);
|
||||
m_alternative->m_terms.append(copyTerm(term));
|
||||
// NOTE: this term is interesting from an analysis perspective, in that it can be ignored.....
|
||||
m_alternative->lastTerm().quantify((max == UINT_MAX) ? max : max - min, greedy ? QuantifierGreedy : QuantifierNonGreedy);
|
||||
m_alternative->lastTerm().quantify((max == quantifyInfinite) ? max : max - min, greedy ? QuantifierGreedy : QuantifierNonGreedy);
|
||||
if (m_alternative->lastTerm().type == PatternTerm::TypeParenthesesSubpattern)
|
||||
m_alternative->lastTerm().parentheses.isCopy = true;
|
||||
}
|
||||
@ -475,26 +616,12 @@ public:
|
||||
m_alternative = m_alternative->m_parent->addNewAlternative();
|
||||
}
|
||||
|
||||
void regexBegin()
|
||||
{
|
||||
// FIXME: bug 574459 -- no NULL check
|
||||
m_pattern.m_body = js::OffTheBooks::new_<PatternDisjunction>();
|
||||
m_alternative = m_pattern.m_body->addNewAlternative();
|
||||
m_pattern.m_disjunctions.append(m_pattern.m_body);
|
||||
}
|
||||
void regexEnd()
|
||||
{
|
||||
}
|
||||
void regexError()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition)
|
||||
{
|
||||
alternative->m_hasFixedSize = true;
|
||||
unsigned currentInputPosition = initialInputPosition;
|
||||
|
||||
for (unsigned i = 0; i < alternative->m_terms.length(); ++i) {
|
||||
for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
|
||||
PatternTerm& term = alternative->m_terms[i];
|
||||
|
||||
switch (term.type) {
|
||||
@ -507,7 +634,7 @@ public:
|
||||
case PatternTerm::TypeBackReference:
|
||||
term.inputPosition = currentInputPosition;
|
||||
term.frameLocation = currentCallFrameSize;
|
||||
currentCallFrameSize += RegexStackSpaceForBackTrackInfoBackReference;
|
||||
currentCallFrameSize += YarrStackSpaceForBackTrackInfoBackReference;
|
||||
alternative->m_hasFixedSize = false;
|
||||
break;
|
||||
|
||||
@ -518,7 +645,7 @@ public:
|
||||
term.inputPosition = currentInputPosition;
|
||||
if (term.quantityType != QuantifierFixedCount) {
|
||||
term.frameLocation = currentCallFrameSize;
|
||||
currentCallFrameSize += RegexStackSpaceForBackTrackInfoPatternCharacter;
|
||||
currentCallFrameSize += YarrStackSpaceForBackTrackInfoPatternCharacter;
|
||||
alternative->m_hasFixedSize = false;
|
||||
} else
|
||||
currentInputPosition += term.quantityCount;
|
||||
@ -528,7 +655,7 @@ public:
|
||||
term.inputPosition = currentInputPosition;
|
||||
if (term.quantityType != QuantifierFixedCount) {
|
||||
term.frameLocation = currentCallFrameSize;
|
||||
currentCallFrameSize += RegexStackSpaceForBackTrackInfoCharacterClass;
|
||||
currentCallFrameSize += YarrStackSpaceForBackTrackInfoCharacterClass;
|
||||
alternative->m_hasFixedSize = false;
|
||||
} else
|
||||
currentInputPosition += term.quantityCount;
|
||||
@ -539,20 +666,20 @@ public:
|
||||
term.frameLocation = currentCallFrameSize;
|
||||
if (term.quantityCount == 1 && !term.parentheses.isCopy) {
|
||||
if (term.quantityType != QuantifierFixedCount)
|
||||
currentCallFrameSize += RegexStackSpaceForBackTrackInfoParenthesesOnce;
|
||||
currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesOnce;
|
||||
currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
|
||||
// If quantity is fixed, then pre-check its minimum size.
|
||||
if (term.quantityType == QuantifierFixedCount)
|
||||
currentInputPosition += term.parentheses.disjunction->m_minimumSize;
|
||||
term.inputPosition = currentInputPosition;
|
||||
} else if (term.parentheses.isTerminal) {
|
||||
currentCallFrameSize += RegexStackSpaceForBackTrackInfoParenthesesTerminal;
|
||||
currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesTerminal;
|
||||
currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
|
||||
term.inputPosition = currentInputPosition;
|
||||
} else {
|
||||
term.inputPosition = currentInputPosition;
|
||||
setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition);
|
||||
currentCallFrameSize += RegexStackSpaceForBackTrackInfoParentheses;
|
||||
currentCallFrameSize += YarrStackSpaceForBackTrackInfoParentheses;
|
||||
}
|
||||
// Fixed count of 1 could be accepted, if they have a fixed size *AND* if all alternatives are of the same length.
|
||||
alternative->m_hasFixedSize = false;
|
||||
@ -561,7 +688,7 @@ public:
|
||||
case PatternTerm::TypeParentheticalAssertion:
|
||||
term.inputPosition = currentInputPosition;
|
||||
term.frameLocation = currentCallFrameSize;
|
||||
currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + RegexStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition);
|
||||
currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -572,23 +699,23 @@ public:
|
||||
|
||||
unsigned setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition)
|
||||
{
|
||||
if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.length() > 1))
|
||||
initialCallFrameSize += RegexStackSpaceForBackTrackInfoAlternative;
|
||||
if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))
|
||||
initialCallFrameSize += YarrStackSpaceForBackTrackInfoAlternative;
|
||||
|
||||
unsigned minimumInputSize = UINT_MAX;
|
||||
unsigned maximumCallFrameSize = 0;
|
||||
bool hasFixedSize = true;
|
||||
|
||||
for (unsigned alt = 0; alt < disjunction->m_alternatives.length(); ++alt) {
|
||||
for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
|
||||
PatternAlternative* alternative = disjunction->m_alternatives[alt];
|
||||
unsigned currentAlternativeCallFrameSize = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition);
|
||||
minimumInputSize = JS_MIN(minimumInputSize, alternative->m_minimumSize);
|
||||
maximumCallFrameSize = JS_MAX(maximumCallFrameSize, currentAlternativeCallFrameSize);
|
||||
minimumInputSize = std::min(minimumInputSize, alternative->m_minimumSize);
|
||||
maximumCallFrameSize = std::max(maximumCallFrameSize, currentAlternativeCallFrameSize);
|
||||
hasFixedSize &= alternative->m_hasFixedSize;
|
||||
}
|
||||
|
||||
JS_ASSERT(minimumInputSize != UINT_MAX);
|
||||
JS_ASSERT(maximumCallFrameSize >= initialCallFrameSize);
|
||||
ASSERT(minimumInputSize != UINT_MAX);
|
||||
ASSERT(maximumCallFrameSize >= initialCallFrameSize);
|
||||
|
||||
disjunction->m_hasFixedSize = hasFixedSize;
|
||||
disjunction->m_minimumSize = minimumInputSize;
|
||||
@ -598,13 +725,14 @@ public:
|
||||
|
||||
void setupOffsets()
|
||||
{
|
||||
setupDisjunctionOffsets(m_pattern.m_body, BASE_FRAME_SIZE, 0);
|
||||
setupDisjunctionOffsets(m_pattern.m_body, 0, 0);
|
||||
}
|
||||
|
||||
// This optimization identifies sets of parentheses that we will never need to backtrack.
|
||||
// In these cases we do not need to store state from prior iterations.
|
||||
// We can presently avoid backtracking for:
|
||||
// * a set of parens at the end of the regular expression (last term in any of the alternatives of the main body disjunction).
|
||||
// * where the parens are at the end of the regular expression (last term in any of the
|
||||
// alternatives of the main body disjunction).
|
||||
// * where the parens are non-capturing, and quantified unbounded greedy (*).
|
||||
// * where the parens do not contain any capturing subpatterns.
|
||||
void checkForTerminalParentheses()
|
||||
@ -614,57 +742,239 @@ public:
|
||||
if (m_pattern.m_numSubpatterns)
|
||||
return;
|
||||
|
||||
js::Vector<PatternAlternative*, 0, js::SystemAllocPolicy>& alternatives = m_pattern.m_body->m_alternatives;
|
||||
for (unsigned i =0; i < alternatives.length(); ++i) {
|
||||
js::Vector<PatternTerm, 0, js::SystemAllocPolicy>& terms = alternatives[i]->m_terms;
|
||||
if (terms.length()) {
|
||||
PatternTerm& term = terms.back();
|
||||
Vector<PatternAlternative*>& alternatives = m_pattern.m_body->m_alternatives;
|
||||
for (size_t i = 0; i < alternatives.size(); ++i) {
|
||||
Vector<PatternTerm>& terms = alternatives[i]->m_terms;
|
||||
if (terms.size()) {
|
||||
PatternTerm& term = terms.last();
|
||||
if (term.type == PatternTerm::TypeParenthesesSubpattern
|
||||
&& term.quantityType == QuantifierGreedy
|
||||
&& term.quantityCount == UINT_MAX
|
||||
&& term.quantityCount == quantifyInfinite
|
||||
&& !term.capture())
|
||||
term.parentheses.isTerminal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void optimizeBOL()
|
||||
{
|
||||
// Look for expressions containing beginning of line (^) anchoring and unroll them.
|
||||
// e.g. /^a|^b|c/ becomes /^a|^b|c/ which is executed once followed by /c/ which loops
|
||||
// This code relies on the parsing code tagging alternatives with m_containsBOL and
|
||||
// m_startsWithBOL and rolling those up to containing alternatives.
|
||||
// At this point, this is only valid for non-multiline expressions.
|
||||
PatternDisjunction* disjunction = m_pattern.m_body;
|
||||
|
||||
if (!m_pattern.m_containsBOL || m_pattern.m_multiline)
|
||||
return;
|
||||
|
||||
PatternDisjunction* loopDisjunction = copyDisjunction(disjunction, true);
|
||||
|
||||
// Set alternatives in disjunction to "onceThrough"
|
||||
for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt)
|
||||
disjunction->m_alternatives[alt]->setOnceThrough();
|
||||
|
||||
if (loopDisjunction) {
|
||||
// Move alternatives from loopDisjunction to disjunction
|
||||
for (unsigned alt = 0; alt < loopDisjunction->m_alternatives.size(); ++alt)
|
||||
disjunction->m_alternatives.append(loopDisjunction->m_alternatives[alt]);
|
||||
|
||||
loopDisjunction->m_alternatives.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// This function collects the terms which are potentially matching the first number of depth characters in the result.
|
||||
// If this function returns false then it found at least one term which makes the beginning character
|
||||
// look-up optimization inefficient.
|
||||
bool setupDisjunctionBeginTerms(PatternDisjunction* disjunction, Vector<TermChain>* beginTerms, unsigned depth)
|
||||
{
|
||||
for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
|
||||
PatternAlternative* alternative = disjunction->m_alternatives[alt];
|
||||
|
||||
if (!setupAlternativeBeginTerms(alternative, beginTerms, 0, depth))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setupAlternativeBeginTerms(PatternAlternative* alternative, Vector<TermChain>* beginTerms, unsigned termIndex, unsigned depth)
|
||||
{
|
||||
bool checkNext = true;
|
||||
unsigned numTerms = alternative->m_terms.size();
|
||||
|
||||
while (checkNext && termIndex < numTerms) {
|
||||
PatternTerm term = alternative->m_terms[termIndex];
|
||||
checkNext = false;
|
||||
|
||||
switch (term.type) {
|
||||
case PatternTerm::TypeAssertionBOL:
|
||||
case PatternTerm::TypeAssertionEOL:
|
||||
case PatternTerm::TypeAssertionWordBoundary:
|
||||
return false;
|
||||
|
||||
case PatternTerm::TypeBackReference:
|
||||
case PatternTerm::TypeForwardReference:
|
||||
return false;
|
||||
|
||||
case PatternTerm::TypePatternCharacter:
|
||||
if (termIndex != numTerms - 1) {
|
||||
beginTerms->append(TermChain(term));
|
||||
termIndex++;
|
||||
checkNext = true;
|
||||
} else if (term.quantityType == QuantifierFixedCount) {
|
||||
beginTerms->append(TermChain(term));
|
||||
if (depth < 2 && termIndex < numTerms - 1 && term.quantityCount == 1)
|
||||
if (!setupAlternativeBeginTerms(alternative, &beginTerms->last().hotTerms, termIndex + 1, depth + 1))
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PatternTerm::TypeCharacterClass:
|
||||
return false;
|
||||
|
||||
case PatternTerm::TypeParentheticalAssertion:
|
||||
if (term.invert())
|
||||
return false;
|
||||
|
||||
case PatternTerm::TypeParenthesesSubpattern:
|
||||
if (term.quantityType != QuantifierFixedCount) {
|
||||
if (termIndex == numTerms - 1)
|
||||
break;
|
||||
|
||||
termIndex++;
|
||||
checkNext = true;
|
||||
}
|
||||
|
||||
if (!setupDisjunctionBeginTerms(term.parentheses.disjunction, beginTerms, depth))
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void setupBeginChars()
|
||||
{
|
||||
Vector<TermChain> beginTerms;
|
||||
bool containsFixedCharacter = false;
|
||||
|
||||
if ((!m_pattern.m_body->m_hasFixedSize || m_pattern.m_body->m_alternatives.size() > 1)
|
||||
&& setupDisjunctionBeginTerms(m_pattern.m_body, &beginTerms, 0)) {
|
||||
unsigned size = beginTerms.size();
|
||||
|
||||
// If we haven't collected any terms we should abort the preparation of beginning character look-up optimization.
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
m_pattern.m_containsBeginChars = true;
|
||||
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
PatternTerm term = beginTerms[i].term;
|
||||
|
||||
// We have just collected PatternCharacter terms, other terms are not allowed.
|
||||
ASSERT(term.type == PatternTerm::TypePatternCharacter);
|
||||
|
||||
if (term.quantityType == QuantifierFixedCount)
|
||||
containsFixedCharacter = true;
|
||||
|
||||
UChar character = term.patternCharacter;
|
||||
unsigned mask = 0;
|
||||
|
||||
if (character <= 0x7f) {
|
||||
if (m_pattern.m_ignoreCase && isASCIIAlpha(character)) {
|
||||
mask = 32;
|
||||
character = toASCIILower(character);
|
||||
}
|
||||
|
||||
m_beginCharHelper.addBeginChar(BeginChar(character, mask), &beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
|
||||
} else {
|
||||
UChar upper, lower;
|
||||
if (m_pattern.m_ignoreCase && ((upper = Unicode::toUpper(character)) != (lower = Unicode::toLower(character)))) {
|
||||
m_beginCharHelper.addBeginChar(BeginChar(upper, mask), &beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
|
||||
m_beginCharHelper.addBeginChar(BeginChar(lower, mask), &beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
|
||||
} else
|
||||
m_beginCharHelper.addBeginChar(BeginChar(character, mask), &beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
|
||||
}
|
||||
}
|
||||
|
||||
// If the pattern doesn't contain terms with fixed quantifiers then the beginning character look-up optimization is inefficient.
|
||||
if (!containsFixedCharacter) {
|
||||
m_pattern.m_containsBeginChars = false;
|
||||
return;
|
||||
}
|
||||
|
||||
size = m_pattern.m_beginChars.size();
|
||||
|
||||
if (size > 2)
|
||||
m_beginCharHelper.merge(size - 1);
|
||||
else if (size <= 1)
|
||||
m_pattern.m_containsBeginChars = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RegexPattern& m_pattern;
|
||||
YarrPattern& m_pattern;
|
||||
PatternAlternative* m_alternative;
|
||||
CharacterClassConstructor m_characterClassConstructor;
|
||||
BeginCharHelper m_beginCharHelper;
|
||||
bool m_invertCharacterClass;
|
||||
bool m_invertParentheticalAssertion;
|
||||
};
|
||||
|
||||
|
||||
int compileRegex(const UString& patternString, RegexPattern& pattern)
|
||||
ErrorCode YarrPattern::compile(const UString& patternString)
|
||||
{
|
||||
RegexPatternConstructor constructor(pattern);
|
||||
YarrPatternConstructor constructor(*this);
|
||||
|
||||
if (int error = parse(constructor, patternString))
|
||||
if (ErrorCode error = parse(constructor, patternString))
|
||||
return error;
|
||||
|
||||
// If the pattern contains illegal backreferences reset & reparse.
|
||||
// Quoting Netscape's "What's new in JavaScript 1.2",
|
||||
// "Note: if the number of left parentheses is less than the number specified
|
||||
// in \#, the \# is taken as an octal escape as described in the next row."
|
||||
if (pattern.containsIllegalBackReference()) {
|
||||
unsigned numSubpatterns = pattern.m_numSubpatterns;
|
||||
if (containsIllegalBackReference()) {
|
||||
unsigned numSubpatterns = m_numSubpatterns;
|
||||
|
||||
constructor.reset();
|
||||
#ifdef DEBUG
|
||||
int error =
|
||||
#if !ASSERT_DISABLED
|
||||
ErrorCode error =
|
||||
#endif
|
||||
parse(constructor, patternString, numSubpatterns);
|
||||
|
||||
JS_ASSERT(!error);
|
||||
JS_ASSERT(numSubpatterns == pattern.m_numSubpatterns);
|
||||
ASSERT(!error);
|
||||
ASSERT(numSubpatterns == m_numSubpatterns);
|
||||
}
|
||||
|
||||
constructor.checkForTerminalParentheses();
|
||||
constructor.optimizeBOL();
|
||||
|
||||
constructor.setupOffsets();
|
||||
constructor.setupBeginChars();
|
||||
|
||||
return 0;
|
||||
return NoError;
|
||||
}
|
||||
|
||||
YarrPattern::YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, ErrorCode* error)
|
||||
: m_ignoreCase(ignoreCase)
|
||||
, m_multiline(multiline)
|
||||
, m_containsBackreferences(false)
|
||||
, m_containsBeginChars(false)
|
||||
, m_containsBOL(false)
|
||||
, m_numSubpatterns(0)
|
||||
, m_maxBackReference(0)
|
||||
, newlineCached(0)
|
||||
, digitsCached(0)
|
||||
, spacesCached(0)
|
||||
, wordcharCached(0)
|
||||
, nondigitsCached(0)
|
||||
, nonspacesCached(0)
|
||||
, nonwordcharCached(0)
|
||||
{
|
||||
*error = compile(pattern);
|
||||
}
|
||||
|
||||
} }
|
@ -1,5 +1,9 @@
|
||||
/*
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -21,26 +25,32 @@
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef RegexPattern_h
|
||||
#define RegexPattern_h
|
||||
|
||||
#include "jsvector.h"
|
||||
#include "yarr/jswtfbridge.h"
|
||||
#include "yarr/yarr/RegexCommon.h"
|
||||
#ifndef YarrPattern_h
|
||||
#define YarrPattern_h
|
||||
|
||||
#include "wtfbridge.h"
|
||||
#include "ASCIICType.h"
|
||||
|
||||
namespace JSC { namespace Yarr {
|
||||
|
||||
#define RegexStackSpaceForBackTrackInfoPatternCharacter 1 // Only for !fixed quantifiers.
|
||||
#define RegexStackSpaceForBackTrackInfoCharacterClass 1 // Only for !fixed quantifiers.
|
||||
#define RegexStackSpaceForBackTrackInfoBackReference 2
|
||||
#define RegexStackSpaceForBackTrackInfoAlternative 1 // One per alternative.
|
||||
#define RegexStackSpaceForBackTrackInfoParentheticalAssertion 1
|
||||
#define RegexStackSpaceForBackTrackInfoParenthesesOnce 1 // Only for !fixed quantifiers.
|
||||
#define RegexStackSpaceForBackTrackInfoParenthesesTerminal 1
|
||||
#define RegexStackSpaceForBackTrackInfoParentheses 4
|
||||
enum ErrorCode {
|
||||
NoError,
|
||||
PatternTooLarge,
|
||||
QuantifierOutOfOrder,
|
||||
QuantifierWithoutAtom,
|
||||
MissingParentheses,
|
||||
ParenthesesUnmatched,
|
||||
ParenthesesTypeInvalid,
|
||||
CharacterClassUnmatched,
|
||||
CharacterClassInvalidRange,
|
||||
CharacterClassOutOfOrder,
|
||||
EscapeUnterminated,
|
||||
QuantifierTooLarge,
|
||||
NumberOfErrorCodes
|
||||
};
|
||||
|
||||
struct PatternDisjunction;
|
||||
|
||||
@ -55,60 +65,42 @@ struct CharacterRange {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Wraps a table and indicates inversion. Can be efficiently borrowed
|
||||
* between character classes, so it's refcounted.
|
||||
*/
|
||||
struct CharacterClassTable {
|
||||
|
||||
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
|
||||
|
||||
struct CharacterClassTable : RefCounted<CharacterClassTable> {
|
||||
friend class js::OffTheBooks;
|
||||
const char* m_table;
|
||||
bool m_inverted;
|
||||
jsrefcount m_refcount;
|
||||
|
||||
/* Ownership transferred to caller. */
|
||||
static CharacterClassTable *create(const char* table, bool inverted)
|
||||
static PassRefPtr<CharacterClassTable> create(const char* table, bool inverted)
|
||||
{
|
||||
// FIXME: bug 574459 -- no NULL checks done by any of the callers, all
|
||||
// of which are in RegExpJitTables.h.
|
||||
return js::OffTheBooks::new_<CharacterClassTable>(table, inverted);
|
||||
return adoptRef(js::OffTheBooks::new_<CharacterClassTable>(table, inverted));
|
||||
}
|
||||
|
||||
void incref() { JS_ATOMIC_INCREMENT(&m_refcount); }
|
||||
void decref() { if (JS_ATOMIC_DECREMENT(&m_refcount) == 0) js::Foreground::delete_(this); }
|
||||
|
||||
private:
|
||||
CharacterClassTable(const char* table, bool inverted)
|
||||
: m_table(table)
|
||||
, m_inverted(inverted)
|
||||
, m_refcount(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct CharacterClass {
|
||||
WTF_MAKE_FAST_ALLOCATED
|
||||
public:
|
||||
// All CharacterClass instances have to have the full set of matches and ranges,
|
||||
// they may have an optional table for faster lookups (which must match the
|
||||
// specified matches and ranges)
|
||||
CharacterClass(CharacterClassTable *table)
|
||||
CharacterClass(PassRefPtr<CharacterClassTable> table)
|
||||
: m_table(table)
|
||||
{
|
||||
if (m_table)
|
||||
m_table->incref();
|
||||
}
|
||||
~CharacterClass()
|
||||
{
|
||||
if (m_table)
|
||||
m_table->decref();
|
||||
js::Foreground::delete_(m_table.get());
|
||||
}
|
||||
typedef js::Vector<UChar, 0, js::SystemAllocPolicy> UChars;
|
||||
typedef js::Vector<CharacterRange, 0, js::SystemAllocPolicy> CharacterRanges;
|
||||
UChars m_matches;
|
||||
CharacterRanges m_ranges;
|
||||
UChars m_matchesUnicode;
|
||||
CharacterRanges m_rangesUnicode;
|
||||
CharacterClassTable *m_table;
|
||||
Vector<UChar> m_matches;
|
||||
Vector<CharacterRange> m_ranges;
|
||||
Vector<UChar> m_matchesUnicode;
|
||||
Vector<CharacterRange> m_rangesUnicode;
|
||||
RefPtr<CharacterClassTable> m_table;
|
||||
};
|
||||
|
||||
enum QuantifierType {
|
||||
@ -129,11 +121,12 @@ struct PatternTerm {
|
||||
TypeParenthesesSubpattern,
|
||||
TypeParentheticalAssertion
|
||||
} type;
|
||||
bool invertOrCapture;
|
||||
bool m_capture :1;
|
||||
bool m_invert :1;
|
||||
union {
|
||||
UChar patternCharacter;
|
||||
CharacterClass* characterClass;
|
||||
unsigned subpatternId;
|
||||
unsigned backReferenceSubpatternId;
|
||||
struct {
|
||||
PatternDisjunction* disjunction;
|
||||
unsigned subpatternId;
|
||||
@ -147,8 +140,21 @@ struct PatternTerm {
|
||||
int inputPosition;
|
||||
unsigned frameLocation;
|
||||
|
||||
// No-argument constructor for js::Vector.
|
||||
PatternTerm()
|
||||
: type(PatternTerm::TypePatternCharacter)
|
||||
, m_capture(false)
|
||||
, m_invert(false)
|
||||
{
|
||||
patternCharacter = 0;
|
||||
quantityType = QuantifierFixedCount;
|
||||
quantityCount = 1;
|
||||
}
|
||||
|
||||
PatternTerm(UChar ch)
|
||||
: type(PatternTerm::TypePatternCharacter)
|
||||
, m_capture(false)
|
||||
, m_invert(false)
|
||||
{
|
||||
patternCharacter = ch;
|
||||
quantityType = QuantifierFixedCount;
|
||||
@ -157,16 +163,18 @@ struct PatternTerm {
|
||||
|
||||
PatternTerm(CharacterClass* charClass, bool invert)
|
||||
: type(PatternTerm::TypeCharacterClass)
|
||||
, invertOrCapture(invert)
|
||||
, m_capture(false)
|
||||
, m_invert(invert)
|
||||
{
|
||||
characterClass = charClass;
|
||||
quantityType = QuantifierFixedCount;
|
||||
quantityCount = 1;
|
||||
}
|
||||
|
||||
PatternTerm(Type type, unsigned subpatternId, PatternDisjunction* disjunction, bool invertOrCapture)
|
||||
PatternTerm(Type type, unsigned subpatternId, PatternDisjunction* disjunction, bool capture = false, bool invert = false)
|
||||
: type(type)
|
||||
, invertOrCapture(invertOrCapture)
|
||||
, m_capture(capture)
|
||||
, m_invert(invert)
|
||||
{
|
||||
parentheses.disjunction = disjunction;
|
||||
parentheses.subpatternId = subpatternId;
|
||||
@ -178,7 +186,8 @@ struct PatternTerm {
|
||||
|
||||
PatternTerm(Type type, bool invert = false)
|
||||
: type(type)
|
||||
, invertOrCapture(invert)
|
||||
, m_capture(false)
|
||||
, m_invert(invert)
|
||||
{
|
||||
quantityType = QuantifierFixedCount;
|
||||
quantityCount = 1;
|
||||
@ -186,9 +195,10 @@ struct PatternTerm {
|
||||
|
||||
PatternTerm(unsigned spatternId)
|
||||
: type(TypeBackReference)
|
||||
, invertOrCapture(false)
|
||||
, m_capture(false)
|
||||
, m_invert(false)
|
||||
{
|
||||
subpatternId = spatternId;
|
||||
backReferenceSubpatternId = spatternId;
|
||||
quantityType = QuantifierFixedCount;
|
||||
quantityCount = 1;
|
||||
}
|
||||
@ -215,12 +225,12 @@ struct PatternTerm {
|
||||
|
||||
bool invert()
|
||||
{
|
||||
return invertOrCapture;
|
||||
return m_invert;
|
||||
}
|
||||
|
||||
bool capture()
|
||||
{
|
||||
return invertOrCapture;
|
||||
return m_capture;
|
||||
}
|
||||
|
||||
void quantify(unsigned count, QuantifierType type)
|
||||
@ -231,9 +241,8 @@ struct PatternTerm {
|
||||
};
|
||||
|
||||
struct PatternAlternative {
|
||||
|
||||
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
|
||||
|
||||
WTF_MAKE_FAST_ALLOCATED
|
||||
public:
|
||||
PatternAlternative(PatternDisjunction* disjunction)
|
||||
: m_parent(disjunction)
|
||||
, m_onceThrough(false)
|
||||
@ -245,14 +254,14 @@ struct PatternAlternative {
|
||||
|
||||
PatternTerm& lastTerm()
|
||||
{
|
||||
JS_ASSERT(m_terms.length());
|
||||
return m_terms[m_terms.length() - 1];
|
||||
ASSERT(m_terms.size());
|
||||
return m_terms[m_terms.size() - 1];
|
||||
}
|
||||
|
||||
void removeLastTerm()
|
||||
{
|
||||
JS_ASSERT(m_terms.length());
|
||||
m_terms.popBack();
|
||||
ASSERT(m_terms.size());
|
||||
m_terms.shrink(m_terms.size() - 1);
|
||||
}
|
||||
|
||||
void setOnceThrough()
|
||||
@ -265,7 +274,7 @@ struct PatternAlternative {
|
||||
return m_onceThrough;
|
||||
}
|
||||
|
||||
js::Vector<PatternTerm, 0, js::SystemAllocPolicy> m_terms;
|
||||
Vector<PatternTerm> m_terms;
|
||||
PatternDisjunction* m_parent;
|
||||
unsigned m_minimumSize;
|
||||
bool m_onceThrough : 1;
|
||||
@ -274,18 +283,9 @@ struct PatternAlternative {
|
||||
bool m_containsBOL : 1;
|
||||
};
|
||||
|
||||
template<typename T, size_t N, class AP>
|
||||
static inline void
|
||||
deleteAllValues(js::Vector<T*,N,AP> &vector)
|
||||
{
|
||||
for (T** t = vector.begin(); t < vector.end(); ++t)
|
||||
js::Foreground::delete_(*t);
|
||||
}
|
||||
|
||||
struct PatternDisjunction {
|
||||
|
||||
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
|
||||
|
||||
WTF_MAKE_FAST_ALLOCATED
|
||||
public:
|
||||
PatternDisjunction(PatternAlternative* parent = 0)
|
||||
: m_parent(parent)
|
||||
, m_hasFixedSize(false)
|
||||
@ -299,13 +299,12 @@ struct PatternDisjunction {
|
||||
|
||||
PatternAlternative* addNewAlternative()
|
||||
{
|
||||
// FIXME: bug 574459 -- no NULL check
|
||||
PatternAlternative* alternative = js::OffTheBooks::new_<PatternAlternative>(this);
|
||||
m_alternatives.append(alternative);
|
||||
return alternative;
|
||||
}
|
||||
|
||||
js::Vector<PatternAlternative*, 0, js::SystemAllocPolicy> m_alternatives;
|
||||
Vector<PatternAlternative*> m_alternatives;
|
||||
PatternAlternative* m_parent;
|
||||
unsigned m_minimumSize;
|
||||
unsigned m_callFrameSize;
|
||||
@ -314,7 +313,7 @@ struct PatternDisjunction {
|
||||
|
||||
// You probably don't want to be calling these functions directly
|
||||
// (please to be calling newlineCharacterClass() et al on your
|
||||
// friendly neighborhood RegexPattern instance to get nicely
|
||||
// friendly neighborhood YarrPattern instance to get nicely
|
||||
// cached copies).
|
||||
CharacterClass* newlineCreate();
|
||||
CharacterClass* digitsCreate();
|
||||
@ -324,25 +323,34 @@ CharacterClass* nondigitsCreate();
|
||||
CharacterClass* nonspacesCreate();
|
||||
CharacterClass* nonwordcharCreate();
|
||||
|
||||
struct RegexPattern {
|
||||
RegexPattern(bool ignoreCase, bool multiline)
|
||||
: m_ignoreCase(ignoreCase)
|
||||
, m_multiline(multiline)
|
||||
, m_containsBackreferences(false)
|
||||
, m_containsBOL(false)
|
||||
, m_numSubpatterns(0)
|
||||
, m_maxBackReference(0)
|
||||
, newlineCached(0)
|
||||
, digitsCached(0)
|
||||
, spacesCached(0)
|
||||
, wordcharCached(0)
|
||||
, nondigitsCached(0)
|
||||
, nonspacesCached(0)
|
||||
, nonwordcharCached(0)
|
||||
{
|
||||
}
|
||||
struct TermChain {
|
||||
TermChain(PatternTerm term)
|
||||
: term(term)
|
||||
{}
|
||||
|
||||
~RegexPattern()
|
||||
PatternTerm term;
|
||||
Vector<TermChain> hotTerms;
|
||||
};
|
||||
|
||||
struct BeginChar {
|
||||
BeginChar()
|
||||
: value(0)
|
||||
, mask(0)
|
||||
{}
|
||||
|
||||
BeginChar(unsigned value, unsigned mask)
|
||||
: value(value)
|
||||
, mask(mask)
|
||||
{}
|
||||
|
||||
unsigned value;
|
||||
unsigned mask;
|
||||
};
|
||||
|
||||
struct YarrPattern {
|
||||
YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, ErrorCode* error);
|
||||
|
||||
~YarrPattern()
|
||||
{
|
||||
deleteAllValues(m_disjunctions);
|
||||
deleteAllValues(m_userCharacterClasses);
|
||||
@ -354,6 +362,7 @@ struct RegexPattern {
|
||||
m_maxBackReference = 0;
|
||||
|
||||
m_containsBackreferences = false;
|
||||
m_containsBeginChars = false;
|
||||
m_containsBOL = false;
|
||||
|
||||
newlineCached = 0;
|
||||
@ -368,6 +377,7 @@ struct RegexPattern {
|
||||
m_disjunctions.clear();
|
||||
deleteAllValues(m_userCharacterClasses);
|
||||
m_userCharacterClasses.clear();
|
||||
m_beginChars.clear();
|
||||
}
|
||||
|
||||
bool containsIllegalBackReference()
|
||||
@ -418,19 +428,21 @@ struct RegexPattern {
|
||||
return nonwordcharCached;
|
||||
}
|
||||
|
||||
typedef js::Vector<PatternDisjunction*, 4, js::SystemAllocPolicy> PatternDisjunctions;
|
||||
typedef js::Vector<CharacterClass*, 0, js::SystemAllocPolicy> CharacterClasses;
|
||||
bool m_ignoreCase : 1;
|
||||
bool m_multiline : 1;
|
||||
bool m_containsBackreferences : 1;
|
||||
bool m_containsBeginChars : 1;
|
||||
bool m_containsBOL : 1;
|
||||
unsigned m_numSubpatterns;
|
||||
unsigned m_maxBackReference;
|
||||
PatternDisjunction *m_body;
|
||||
PatternDisjunctions m_disjunctions;
|
||||
CharacterClasses m_userCharacterClasses;
|
||||
PatternDisjunction* m_body;
|
||||
Vector<PatternDisjunction*, 4> m_disjunctions;
|
||||
Vector<CharacterClass*> m_userCharacterClasses;
|
||||
Vector<BeginChar> m_beginChars;
|
||||
|
||||
private:
|
||||
ErrorCode compile(const UString& patternString);
|
||||
|
||||
CharacterClass* newlineCached;
|
||||
CharacterClass* digitsCached;
|
||||
CharacterClass* spacesCached;
|
||||
@ -442,4 +454,4 @@ private:
|
||||
|
||||
} } // namespace JSC::Yarr
|
||||
|
||||
#endif // RegexPattern_h
|
||||
#endif // YarrPattern_h
|
@ -1,5 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -21,30 +24,39 @@
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef RegexCommon_h
|
||||
#define RegexCommon_h
|
||||
#include "YarrSyntaxChecker.h"
|
||||
|
||||
#include "YarrParser.h"
|
||||
|
||||
namespace JSC { namespace Yarr {
|
||||
|
||||
enum ErrorCode {
|
||||
HitRecursionLimit = -2,
|
||||
NoError = 0,
|
||||
PatternTooLarge,
|
||||
QuantifierOutOfOrder,
|
||||
QuantifierWithoutAtom,
|
||||
MissingParentheses,
|
||||
ParenthesesUnmatched,
|
||||
ParenthesesTypeInvalid,
|
||||
CharacterClassUnmatched,
|
||||
CharacterClassOutOfOrder,
|
||||
CharacterClassRangeSingleChar,
|
||||
EscapeUnterminated,
|
||||
QuantifierTooLarge,
|
||||
NumberOfErrorCodes
|
||||
class SyntaxChecker {
|
||||
public:
|
||||
void assertionBOL() {}
|
||||
void assertionEOL() {}
|
||||
void assertionWordBoundary(bool) {}
|
||||
void atomPatternCharacter(UChar) {}
|
||||
void atomBuiltInCharacterClass(BuiltInCharacterClassID, bool) {}
|
||||
void atomCharacterClassBegin(bool = false) {}
|
||||
void atomCharacterClassAtom(UChar) {}
|
||||
void atomCharacterClassRange(UChar, UChar) {}
|
||||
void atomCharacterClassBuiltIn(BuiltInCharacterClassID, bool) {}
|
||||
void atomCharacterClassEnd() {}
|
||||
void atomParenthesesSubpatternBegin(bool = true) {}
|
||||
void atomParentheticalAssertionBegin(bool = false) {}
|
||||
void atomParenthesesEnd() {}
|
||||
void atomBackReference(unsigned) {}
|
||||
void quantifyAtom(unsigned, unsigned, bool) {}
|
||||
void disjunction() {}
|
||||
};
|
||||
|
||||
}}
|
||||
ErrorCode checkSyntax(const UString& pattern)
|
||||
{
|
||||
SyntaxChecker syntaxChecker;
|
||||
return parse(syntaxChecker, pattern);
|
||||
}
|
||||
|
||||
#endif
|
||||
}} // JSC::YARR
|
@ -1,5 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -21,18 +24,20 @@
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef RegexCompiler_h
|
||||
#define RegexCompiler_h
|
||||
#ifndef YarrSyntaxChecker_h
|
||||
#define YarrSyntaxChecker_h
|
||||
|
||||
#include "RegexParser.h"
|
||||
#include "RegexPattern.h"
|
||||
#include "wtfbridge.h"
|
||||
#include "YarrParser.h"
|
||||
|
||||
namespace JSC { namespace Yarr {
|
||||
|
||||
int compileRegex(const UString& patternString, RegexPattern& pattern);
|
||||
ErrorCode checkSyntax(const UString& pattern);
|
||||
|
||||
} } // namespace JSC::Yarr
|
||||
}} // JSC::YARR
|
||||
|
||||
#endif // YarrSyntaxChecker_h
|
||||
|
||||
#endif // RegexCompiler_h
|
@ -1,61 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* June 12, 2009.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Corporation.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Leary <cdleary@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef jswtfbridge_h__
|
||||
#define jswtfbridge_h__
|
||||
|
||||
/*
|
||||
* The JS/WTF Bridge to Bona-fide Quality.
|
||||
*/
|
||||
|
||||
#include "assembler/wtf/Platform.h"
|
||||
#include "jsstr.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jstl.h"
|
||||
|
||||
typedef jschar UChar;
|
||||
typedef JSLinearString UString;
|
||||
|
||||
class Unicode {
|
||||
public:
|
||||
static UChar toUpper(UChar c) { return JS_TOUPPER(c); }
|
||||
static UChar toLower(UChar c) { return JS_TOLOWER(c); }
|
||||
};
|
||||
|
||||
#endif
|
@ -1,12 +0,0 @@
|
||||
Originally written by: Philip Hazel
|
||||
Email local part: ph10
|
||||
Email domain: cam.ac.uk
|
||||
|
||||
University of Cambridge Computing Service,
|
||||
Cambridge, England. Phone: +44 1223 334714.
|
||||
|
||||
Copyright (c) 1997-2005 University of Cambridge. All rights reserved.
|
||||
|
||||
Adapted for JavaScriptCore and WebKit by Apple Inc.
|
||||
|
||||
Copyright (c) 2005, 2006, 2007 Apple Inc. All rights reserved.
|
@ -1,35 +0,0 @@
|
||||
PCRE is a library of functions to support regular expressions whose syntax
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
This is JavaScriptCore's variant of the PCRE library. While this library
|
||||
started out as a copy of PCRE, many of the features of PCRE have been
|
||||
removed.
|
||||
|
||||
Copyright (c) 1997-2005 University of Cambridge. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the name of Apple
|
||||
Inc. nor the names of their contributors may be used to endorse or
|
||||
promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
@ -1,96 +0,0 @@
|
||||
/*************************************************
|
||||
* Perl-Compatible Regular Expressions *
|
||||
*************************************************/
|
||||
|
||||
/* This file is automatically written by the dftables auxiliary
|
||||
program. If you edit it by hand, you might like to edit the Makefile to
|
||||
prevent its ever being regenerated.
|
||||
|
||||
This file contains the default tables for characters with codes less than
|
||||
128 (ASCII characters). These tables are used when no external tables are
|
||||
passed to PCRE. */
|
||||
|
||||
const unsigned char jsc_pcre_default_tables[480] = {
|
||||
|
||||
/* This table is a lower casing table. */
|
||||
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
|
||||
/* This table is a case flipping table. */
|
||||
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
|
||||
/* This table contains bit maps for various character classes.
|
||||
Each map is 32 bytes long and the bits run from the least
|
||||
significant end of each byte. The classes are: space, digit, word. */
|
||||
|
||||
0x00, 0x3E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03,
|
||||
0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x07,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
/* This table identifies various classes of character by individual bits:
|
||||
0x01 white space character
|
||||
0x08 hexadecimal digit
|
||||
0x10 alphanumeric or '_'
|
||||
*/
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0- 7 */
|
||||
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 8- 15 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16- 23 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 24- 31 */
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* - ' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ( - / */
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, /* 0 - 7 */
|
||||
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 - ? */
|
||||
0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, /* @ - G */
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, /* H - O */
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, /* P - W */
|
||||
0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, /* X - _ */
|
||||
0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, /* ` - g */
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, /* h - o */
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, /* p - w */
|
||||
0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}; /* x -127 */
|
||||
|
||||
|
||||
/* End of chartables.c */
|
@ -1,273 +0,0 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# This is JavaScriptCore's variant of the PCRE library. While this library
|
||||
# started out as a copy of PCRE, many of the features of PCRE have been
|
||||
# removed. This library now supports only the regular expression features
|
||||
# required by the JavaScript language specification, and has only the functions
|
||||
# needed by JavaScriptCore and the rest of WebKit.
|
||||
#
|
||||
# Originally written by Philip Hazel
|
||||
# Copyright (c) 1997-2006 University of Cambridge
|
||||
# Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
|
||||
#
|
||||
# -----------------------------------------------------------------------------
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# * Neither the name of the University of Cambridge nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# This is a freestanding support program to generate a file containing
|
||||
# character tables. The tables are built according to the default C
|
||||
# locale.
|
||||
|
||||
use strict;
|
||||
|
||||
use File::Basename;
|
||||
use File::Spec;
|
||||
use File::Temp qw(tempfile);
|
||||
use Getopt::Long;
|
||||
|
||||
sub readHeaderValues();
|
||||
|
||||
my %pcre_internal;
|
||||
|
||||
if (scalar(@ARGV) < 1) {
|
||||
print STDERR "Usage: ", basename($0), " [--preprocessor=program] output-file\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $outputFile;
|
||||
my $preprocessor;
|
||||
GetOptions('preprocessor=s' => \$preprocessor);
|
||||
if (not $preprocessor) {
|
||||
$preprocessor = "cpp";
|
||||
}
|
||||
|
||||
$outputFile = $ARGV[0];
|
||||
die('Must specify output file.') unless defined($outputFile);
|
||||
|
||||
readHeaderValues();
|
||||
|
||||
open(OUT, ">", $outputFile) or die "$!";
|
||||
binmode(OUT);
|
||||
|
||||
printf(OUT
|
||||
"/*************************************************\n" .
|
||||
"* Perl-Compatible Regular Expressions *\n" .
|
||||
"*************************************************/\n\n" .
|
||||
"/* This file is automatically written by the dftables auxiliary \n" .
|
||||
"program. If you edit it by hand, you might like to edit the Makefile to \n" .
|
||||
"prevent its ever being regenerated.\n\n");
|
||||
printf(OUT
|
||||
"This file contains the default tables for characters with codes less than\n" .
|
||||
"128 (ASCII characters). These tables are used when no external tables are\n" .
|
||||
"passed to PCRE. */\n\n" .
|
||||
"const unsigned char jsc_pcre_default_tables[%d] = {\n\n" .
|
||||
"/* This table is a lower casing table. */\n\n", $pcre_internal{tables_length});
|
||||
|
||||
if ($pcre_internal{lcc_offset} != 0) {
|
||||
die "lcc_offset != 0";
|
||||
}
|
||||
|
||||
printf(OUT " ");
|
||||
for (my $i = 0; $i < 128; $i++) {
|
||||
if (($i & 7) == 0 && $i != 0) {
|
||||
printf(OUT "\n ");
|
||||
}
|
||||
printf(OUT "0x%02X", ord(lc(chr($i))));
|
||||
if ($i != 127) {
|
||||
printf(OUT ", ");
|
||||
}
|
||||
}
|
||||
printf(OUT ",\n\n");
|
||||
|
||||
printf(OUT "/* This table is a case flipping table. */\n\n");
|
||||
|
||||
if ($pcre_internal{fcc_offset} != 128) {
|
||||
die "fcc_offset != 128";
|
||||
}
|
||||
|
||||
printf(OUT " ");
|
||||
for (my $i = 0; $i < 128; $i++) {
|
||||
if (($i & 7) == 0 && $i != 0) {
|
||||
printf(OUT "\n ");
|
||||
}
|
||||
my $c = chr($i);
|
||||
printf(OUT "0x%02X", $c =~ /[[:lower:]]/ ? ord(uc($c)) : ord(lc($c)));
|
||||
if ($i != 127) {
|
||||
printf(OUT ", ");
|
||||
}
|
||||
}
|
||||
printf(OUT ",\n\n");
|
||||
|
||||
printf(OUT
|
||||
"/* This table contains bit maps for various character classes.\n" .
|
||||
"Each map is 32 bytes long and the bits run from the least\n" .
|
||||
"significant end of each byte. The classes are: space, digit, word. */\n\n");
|
||||
|
||||
if ($pcre_internal{cbits_offset} != $pcre_internal{fcc_offset} + 128) {
|
||||
die "cbits_offset != fcc_offset + 128";
|
||||
}
|
||||
|
||||
my @cbit_table = (0) x $pcre_internal{cbit_length};
|
||||
for (my $i = ord('0'); $i <= ord('9'); $i++) {
|
||||
$cbit_table[$pcre_internal{cbit_digit} + $i / 8] |= 1 << ($i & 7);
|
||||
}
|
||||
$cbit_table[$pcre_internal{cbit_word} + ord('_') / 8] |= 1 << (ord('_') & 7);
|
||||
for (my $i = 0; $i < 128; $i++) {
|
||||
my $c = chr($i);
|
||||
if ($c =~ /[[:alnum:]]/) {
|
||||
$cbit_table[$pcre_internal{cbit_word} + $i / 8] |= 1 << ($i & 7);
|
||||
}
|
||||
if ($c =~ /[[:space:]]/) {
|
||||
$cbit_table[$pcre_internal{cbit_space} + $i / 8] |= 1 << ($i & 7);
|
||||
}
|
||||
}
|
||||
|
||||
printf(OUT " ");
|
||||
for (my $i = 0; $i < $pcre_internal{cbit_length}; $i++) {
|
||||
if (($i & 7) == 0 && $i != 0) {
|
||||
if (($i & 31) == 0) {
|
||||
printf(OUT "\n");
|
||||
}
|
||||
printf(OUT "\n ");
|
||||
}
|
||||
printf(OUT "0x%02X", $cbit_table[$i]);
|
||||
if ($i != $pcre_internal{cbit_length} - 1) {
|
||||
printf(OUT ", ");
|
||||
}
|
||||
}
|
||||
printf(OUT ",\n\n");
|
||||
|
||||
printf(OUT
|
||||
"/* This table identifies various classes of character by individual bits:\n" .
|
||||
" 0x%02x white space character\n" .
|
||||
" 0x%02x hexadecimal digit\n" .
|
||||
" 0x%02x alphanumeric or '_'\n*/\n\n",
|
||||
$pcre_internal{ctype_space}, $pcre_internal{ctype_xdigit}, $pcre_internal{ctype_word});
|
||||
|
||||
if ($pcre_internal{ctypes_offset} != $pcre_internal{cbits_offset} + $pcre_internal{cbit_length}) {
|
||||
die "ctypes_offset != cbits_offset + cbit_length";
|
||||
}
|
||||
|
||||
printf(OUT " ");
|
||||
for (my $i = 0; $i < 128; $i++) {
|
||||
my $x = 0;
|
||||
my $c = chr($i);
|
||||
if ($c =~ /[[:space:]]/) {
|
||||
$x += $pcre_internal{ctype_space};
|
||||
}
|
||||
if ($c =~ /[[:xdigit:]]/) {
|
||||
$x += $pcre_internal{ctype_xdigit};
|
||||
}
|
||||
if ($c =~ /[[:alnum:]_]/) {
|
||||
$x += $pcre_internal{ctype_word};
|
||||
}
|
||||
printf(OUT "0x%02X", $x);
|
||||
if ($i != 127) {
|
||||
printf(OUT ", ");
|
||||
} else {
|
||||
printf(OUT "};");
|
||||
}
|
||||
if (($i & 7) == 7) {
|
||||
printf(OUT " /* ");
|
||||
my $d = chr($i - 7);
|
||||
if ($d =~ /[[:print:]]/) {
|
||||
printf(OUT " %c -", $i - 7);
|
||||
} else {
|
||||
printf(OUT "%3d-", $i - 7);
|
||||
}
|
||||
if ($c =~ m/[[:print:]]/) {
|
||||
printf(OUT " %c ", $i);
|
||||
} else {
|
||||
printf(OUT "%3d", $i);
|
||||
}
|
||||
printf(OUT " */\n");
|
||||
if ($i != 127) {
|
||||
printf(OUT " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($pcre_internal{tables_length} != $pcre_internal{ctypes_offset} + 128) {
|
||||
die "tables_length != ctypes_offset + 128";
|
||||
}
|
||||
|
||||
printf(OUT "\n\n/* End of chartables.c */\n");
|
||||
|
||||
close(OUT);
|
||||
|
||||
exit 0;
|
||||
|
||||
sub readHeaderValues()
|
||||
{
|
||||
my @variables = qw(
|
||||
cbit_digit
|
||||
cbit_length
|
||||
cbit_space
|
||||
cbit_word
|
||||
cbits_offset
|
||||
ctype_space
|
||||
ctype_word
|
||||
ctype_xdigit
|
||||
ctypes_offset
|
||||
fcc_offset
|
||||
lcc_offset
|
||||
tables_length
|
||||
);
|
||||
|
||||
local $/ = undef;
|
||||
|
||||
my $headerPath = File::Spec->catfile(dirname($0), "pcre_internal.h");
|
||||
|
||||
my ($fh, $tempFile) = tempfile(
|
||||
basename($0) . "-XXXXXXXX",
|
||||
DIR => File::Spec->tmpdir(),
|
||||
SUFFIX => ".in",
|
||||
UNLINK => 0,
|
||||
);
|
||||
|
||||
print $fh "#define DFTABLES\n\n";
|
||||
|
||||
open(HEADER, "<", $headerPath) or die "$!";
|
||||
print $fh <HEADER>;
|
||||
close(HEADER);
|
||||
|
||||
print $fh "\n\n";
|
||||
|
||||
for my $v (@variables) {
|
||||
print $fh "\$pcre_internal{\"$v\"} = $v;\n";
|
||||
}
|
||||
|
||||
close($fh);
|
||||
|
||||
open(CPP, "$preprocessor \"$tempFile\" |") or die "$!";
|
||||
my $content = <CPP>;
|
||||
close(CPP);
|
||||
|
||||
eval $content;
|
||||
die "$@" if $@;
|
||||
unlink $tempFile;
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/* This is the public header file for JavaScriptCore's variant of the PCRE
|
||||
library. While this library started out as a copy of PCRE, many of the
|
||||
features of PCRE have been removed. This library now supports only the
|
||||
regular expression features required by the JavaScript language
|
||||
specification, and has only the functions needed by JavaScriptCore and the
|
||||
rest of WebKit.
|
||||
|
||||
Copyright (c) 1997-2005 University of Cambridge
|
||||
Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// FIXME: This file needs to be renamed to JSRegExp.h; it's no longer PCRE.
|
||||
|
||||
#ifndef JSRegExp_h
|
||||
#define JSRegExp_h
|
||||
|
||||
#include "yarr/jswtfbridge.h"
|
||||
|
||||
struct JSRegExp;
|
||||
struct JSContext;
|
||||
|
||||
enum JSRegExpIgnoreCaseOption { JSRegExpDoNotIgnoreCase, JSRegExpIgnoreCase };
|
||||
enum JSRegExpMultilineOption { JSRegExpSingleLine, JSRegExpMultiline };
|
||||
|
||||
/* jsRegExpExecute error codes */
|
||||
const int JSRegExpErrorNoMatch = -1;
|
||||
const int JSRegExpErrorHitLimit = -2;
|
||||
const int JSRegExpErrorInternal = -4;
|
||||
|
||||
JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
|
||||
JSRegExpIgnoreCaseOption, JSRegExpMultilineOption,
|
||||
unsigned* numSubpatterns, int *error);
|
||||
|
||||
int jsRegExpExecute(JSContext *, const JSRegExp*,
|
||||
const UChar* subject, int subjectLength, int startOffset,
|
||||
int* offsetsVector, int offsetsVectorLength);
|
||||
|
||||
void jsRegExpFree(JSRegExp*);
|
||||
|
||||
#endif
|
@ -1,12 +0,0 @@
|
||||
# Perl Compatible Regular Expressions - Qt4 build info
|
||||
VPATH += $$PWD
|
||||
INCLUDEPATH += $$PWD $$OUTPUT_DIR/JavaScriptCore/tmp
|
||||
DEPENDPATH += $$PWD
|
||||
|
||||
SOURCES += \
|
||||
pcre_compile.cpp \
|
||||
pcre_exec.cpp \
|
||||
pcre_tables.cpp \
|
||||
pcre_ucp_searchfuncs.cpp \
|
||||
pcre_xclass.cpp
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,434 +0,0 @@
|
||||
/* This is JavaScriptCore's variant of the PCRE library. While this library
|
||||
started out as a copy of PCRE, many of the features of PCRE have been
|
||||
removed. This library now supports only the regular expression features
|
||||
required by the JavaScript language specification, and has only the functions
|
||||
needed by JavaScriptCore and the rest of WebKit.
|
||||
|
||||
Originally written by Philip Hazel
|
||||
Copyright (c) 1997-2006 University of Cambridge
|
||||
Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* This header contains definitions that are shared between the different
|
||||
modules, but which are not relevant to the exported API. This includes some
|
||||
functions whose names all begin with "_pcre_". */
|
||||
|
||||
#ifndef PCRE_INTERNAL_H
|
||||
#define PCRE_INTERNAL_H
|
||||
|
||||
/* Bit definitions for entries in the pcre_ctypes table. */
|
||||
|
||||
#define ctype_space 0x01
|
||||
#define ctype_xdigit 0x08
|
||||
#define ctype_word 0x10 /* alphameric or '_' */
|
||||
|
||||
/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
|
||||
of bits for a class map. Some classes are built by combining these tables. */
|
||||
|
||||
#define cbit_space 0 /* \s */
|
||||
#define cbit_digit 32 /* \d */
|
||||
#define cbit_word 64 /* \w */
|
||||
#define cbit_length 96 /* Length of the cbits table */
|
||||
|
||||
/* Offsets of the various tables from the base tables pointer, and
|
||||
total length. */
|
||||
|
||||
#define lcc_offset 0
|
||||
#define fcc_offset 128
|
||||
#define cbits_offset 256
|
||||
#define ctypes_offset (cbits_offset + cbit_length)
|
||||
#define tables_length (ctypes_offset + 128)
|
||||
|
||||
#ifndef DFTABLES
|
||||
|
||||
#include "pcre.h"
|
||||
|
||||
/* The value of LINK_SIZE determines the number of bytes used to store links as
|
||||
offsets within the compiled regex. The default is 2, which allows for compiled
|
||||
patterns up to 64K long. */
|
||||
|
||||
#define LINK_SIZE 3
|
||||
|
||||
/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
|
||||
inline, and there are *still* stupid compilers about that don't like indented
|
||||
pre-processor statements, or at least there were when I first wrote this. After
|
||||
all, it had only been about 10 years then... */
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DPRINTF(p) /*printf p; fflush(stdout);*/
|
||||
#else
|
||||
#define DPRINTF(p) /*nothing*/
|
||||
#endif
|
||||
|
||||
/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored
|
||||
in big-endian order) by default. These are used, for example, to link from the
|
||||
start of a subpattern to its alternatives and its end. The use of 2 bytes per
|
||||
offset limits the size of the compiled regex to around 64K, which is big enough
|
||||
for almost everybody. However, I received a request for an even bigger limit.
|
||||
For this reason, and also to make the code easier to maintain, the storing and
|
||||
loading of offsets from the byte string is now handled by the functions that are
|
||||
defined here. */
|
||||
|
||||
/* PCRE uses some other 2-byte quantities that do not change when the size of
|
||||
offsets changes. There are used for repeat counts and for other things such as
|
||||
capturing parenthesis numbers in back references. */
|
||||
|
||||
static inline void put2ByteValue(unsigned char* opcodePtr, int value)
|
||||
{
|
||||
JS_ASSERT(value >= 0 && value <= 0xFFFF);
|
||||
opcodePtr[0] = value >> 8;
|
||||
opcodePtr[1] = value;
|
||||
}
|
||||
|
||||
static inline void put3ByteValue(unsigned char* opcodePtr, int value)
|
||||
{
|
||||
JS_ASSERT(value >= 0 && value <= 0xFFFFFF);
|
||||
opcodePtr[0] = value >> 16;
|
||||
opcodePtr[1] = value >> 8;
|
||||
opcodePtr[2] = value;
|
||||
}
|
||||
|
||||
static inline int get2ByteValue(const unsigned char* opcodePtr)
|
||||
{
|
||||
return (opcodePtr[0] << 8) | opcodePtr[1];
|
||||
}
|
||||
|
||||
static inline int get3ByteValue(const unsigned char* opcodePtr)
|
||||
{
|
||||
return (opcodePtr[0] << 16) | (opcodePtr[1] << 8) | opcodePtr[2];
|
||||
}
|
||||
|
||||
static inline void put2ByteValueAndAdvance(unsigned char*& opcodePtr, int value)
|
||||
{
|
||||
put2ByteValue(opcodePtr, value);
|
||||
opcodePtr += 2;
|
||||
}
|
||||
|
||||
static inline void put3ByteValueAndAdvance(unsigned char*& opcodePtr, int value)
|
||||
{
|
||||
put3ByteValue(opcodePtr, value);
|
||||
opcodePtr += 3;
|
||||
}
|
||||
|
||||
static inline void putLinkValueAllowZero(unsigned char* opcodePtr, int value)
|
||||
{
|
||||
#if LINK_SIZE == 3
|
||||
put3ByteValue(opcodePtr, value);
|
||||
#elif LINK_SIZE == 2
|
||||
put2ByteValue(opcodePtr, value);
|
||||
#else
|
||||
# error LINK_SIZE not supported.
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int getLinkValueAllowZero(const unsigned char* opcodePtr)
|
||||
{
|
||||
#if LINK_SIZE == 3
|
||||
return get3ByteValue(opcodePtr);
|
||||
#elif LINK_SIZE == 2
|
||||
return get2ByteValue(opcodePtr);
|
||||
#else
|
||||
# error LINK_SIZE not supported.
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MAX_PATTERN_SIZE 1024 * 1024 // Derived by empirical testing of compile time in PCRE and WREC.
|
||||
JS_STATIC_ASSERT(MAX_PATTERN_SIZE < (1 << (8 * LINK_SIZE)));
|
||||
|
||||
static inline void putLinkValue(unsigned char* opcodePtr, int value)
|
||||
{
|
||||
JS_ASSERT(value);
|
||||
putLinkValueAllowZero(opcodePtr, value);
|
||||
}
|
||||
|
||||
static inline int getLinkValue(const unsigned char* opcodePtr)
|
||||
{
|
||||
int value = getLinkValueAllowZero(opcodePtr);
|
||||
JS_ASSERT(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline void putLinkValueAndAdvance(unsigned char*& opcodePtr, int value)
|
||||
{
|
||||
putLinkValue(opcodePtr, value);
|
||||
opcodePtr += LINK_SIZE;
|
||||
}
|
||||
|
||||
static inline void putLinkValueAllowZeroAndAdvance(unsigned char*& opcodePtr, int value)
|
||||
{
|
||||
putLinkValueAllowZero(opcodePtr, value);
|
||||
opcodePtr += LINK_SIZE;
|
||||
}
|
||||
|
||||
// FIXME: These are really more of a "compiled regexp state" than "regexp options"
|
||||
enum RegExpOptions {
|
||||
UseFirstByteOptimizationOption = 0x40000000, /* firstByte is set */
|
||||
UseRequiredByteOptimizationOption = 0x20000000, /* reqByte is set */
|
||||
UseMultiLineFirstByteOptimizationOption = 0x10000000, /* start after \n for multiline */
|
||||
IsAnchoredOption = 0x02000000, /* can't use partial with this regex */
|
||||
IgnoreCaseOption = 0x00000001,
|
||||
MatchAcrossMultipleLinesOption = 0x00000002
|
||||
};
|
||||
|
||||
/* Flags added to firstByte or reqByte; a "non-literal" item is either a
|
||||
variable-length repeat, or a anything other than literal characters. */
|
||||
|
||||
#define REQ_IGNORE_CASE 0x0100 /* indicates should ignore case */
|
||||
#define REQ_VARY 0x0200 /* reqByte followed non-literal item */
|
||||
|
||||
/* Miscellaneous definitions */
|
||||
|
||||
/* Flag bits and data types for the extended class (OP_XCLASS) for classes that
|
||||
contain UTF-8 characters with values greater than 255. */
|
||||
|
||||
#define XCL_NOT 0x01 /* Flag: this is a negative class */
|
||||
#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
|
||||
|
||||
#define XCL_END 0 /* Marks end of individual items */
|
||||
#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */
|
||||
#define XCL_RANGE 2 /* A range (two multibyte chars) follows */
|
||||
|
||||
/* These are escaped items that aren't just an encoding of a particular data
|
||||
value such as \n. They must have non-zero values, as check_escape() returns
|
||||
their negation. Also, they must appear in the same order as in the opcode
|
||||
definitions below, up to ESC_w. The final one must be
|
||||
ESC_REF as subsequent values are used for \1, \2, \3, etc. There is are two
|
||||
tests in the code for an escape > ESC_b and <= ESC_w to
|
||||
detect the types that may be repeated. These are the types that consume
|
||||
characters. If any new escapes are put in between that don't consume a
|
||||
character, that code will have to change. */
|
||||
|
||||
enum { ESC_B = 1, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w, ESC_REF };
|
||||
|
||||
/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
|
||||
that extract substrings. Starting from 1 (i.e. after OP_END), the values up to
|
||||
OP_EOD must correspond in order to the list of escapes immediately above.
|
||||
Note that whenever this list is updated, the two macro definitions that follow
|
||||
must also be updated to match. */
|
||||
|
||||
#define FOR_EACH_OPCODE(macro) \
|
||||
macro(END) \
|
||||
\
|
||||
, macro(NOT_WORD_BOUNDARY) \
|
||||
, macro(WORD_BOUNDARY) \
|
||||
, macro(NOT_DIGIT) \
|
||||
, macro(DIGIT) \
|
||||
, macro(NOT_WHITESPACE) \
|
||||
, macro(WHITESPACE) \
|
||||
, macro(NOT_WORDCHAR) \
|
||||
, macro(WORDCHAR) \
|
||||
\
|
||||
, macro(NOT_NEWLINE) \
|
||||
\
|
||||
, macro(CIRC) \
|
||||
, macro(DOLL) \
|
||||
, macro(BOL) \
|
||||
, macro(EOL) \
|
||||
, macro(CHAR) \
|
||||
, macro(CHAR_IGNORING_CASE) \
|
||||
, macro(ASCII_CHAR) \
|
||||
, macro(ASCII_LETTER_IGNORING_CASE) \
|
||||
, macro(NOT) \
|
||||
\
|
||||
, macro(STAR) \
|
||||
, macro(MINSTAR) \
|
||||
, macro(PLUS) \
|
||||
, macro(MINPLUS) \
|
||||
, macro(QUERY) \
|
||||
, macro(MINQUERY) \
|
||||
, macro(UPTO) \
|
||||
, macro(MINUPTO) \
|
||||
, macro(EXACT) \
|
||||
\
|
||||
, macro(NOTSTAR) \
|
||||
, macro(NOTMINSTAR) \
|
||||
, macro(NOTPLUS) \
|
||||
, macro(NOTMINPLUS) \
|
||||
, macro(NOTQUERY) \
|
||||
, macro(NOTMINQUERY) \
|
||||
, macro(NOTUPTO) \
|
||||
, macro(NOTMINUPTO) \
|
||||
, macro(NOTEXACT) \
|
||||
\
|
||||
, macro(TYPESTAR) \
|
||||
, macro(TYPEMINSTAR) \
|
||||
, macro(TYPEPLUS) \
|
||||
, macro(TYPEMINPLUS) \
|
||||
, macro(TYPEQUERY) \
|
||||
, macro(TYPEMINQUERY) \
|
||||
, macro(TYPEUPTO) \
|
||||
, macro(TYPEMINUPTO) \
|
||||
, macro(TYPEEXACT) \
|
||||
\
|
||||
, macro(CRSTAR) \
|
||||
, macro(CRMINSTAR) \
|
||||
, macro(CRPLUS) \
|
||||
, macro(CRMINPLUS) \
|
||||
, macro(CRQUERY) \
|
||||
, macro(CRMINQUERY) \
|
||||
, macro(CRRANGE) \
|
||||
, macro(CRMINRANGE) \
|
||||
\
|
||||
, macro(CLASS) \
|
||||
, macro(NCLASS) \
|
||||
, macro(XCLASS) \
|
||||
\
|
||||
, macro(REF) \
|
||||
\
|
||||
, macro(ALT) \
|
||||
, macro(KET) \
|
||||
, macro(KETRMAX) \
|
||||
, macro(KETRMIN) \
|
||||
\
|
||||
, macro(ASSERT) \
|
||||
, macro(ASSERT_NOT) \
|
||||
\
|
||||
, macro(BRAZERO) \
|
||||
, macro(BRAMINZERO) \
|
||||
, macro(BRANUMBER) \
|
||||
, macro(BRA)
|
||||
|
||||
#define OPCODE_ENUM_VALUE(opcode) OP_##opcode
|
||||
enum { FOR_EACH_OPCODE(OPCODE_ENUM_VALUE) };
|
||||
|
||||
/* WARNING WARNING WARNING: There is an implicit assumption in pcre.c and
|
||||
study.c that all opcodes are less than 128 in value. This makes handling UTF-8
|
||||
character sequences easier. */
|
||||
|
||||
/* The highest extraction number before we have to start using additional
|
||||
bytes. (Originally PCRE didn't have support for extraction counts higher than
|
||||
this number.) The value is limited by the number of opcodes left after OP_BRA,
|
||||
i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional
|
||||
opcodes. */
|
||||
|
||||
/* FIXME: Note that OP_BRA + 100 is > 128, so the two comments above
|
||||
are in conflict! */
|
||||
|
||||
#define EXTRACT_BASIC_MAX 100
|
||||
|
||||
/* The code vector runs on as long as necessary after the end. */
|
||||
|
||||
struct JSRegExp {
|
||||
unsigned options;
|
||||
|
||||
unsigned short topBracket;
|
||||
unsigned short topBackref;
|
||||
|
||||
unsigned short firstByte;
|
||||
unsigned short reqByte;
|
||||
};
|
||||
|
||||
/* Internal shared data tables. These are tables that are used by more than one
|
||||
of the exported public functions. They have to be "external" in the C sense,
|
||||
but are not part of the PCRE public API. The data for these tables is in the
|
||||
pcre_tables.c module. */
|
||||
|
||||
#define jsc_pcre_utf8_table1_size 6
|
||||
|
||||
extern const int jsc_pcre_utf8_table1[6];
|
||||
extern const int jsc_pcre_utf8_table2[6];
|
||||
extern const int jsc_pcre_utf8_table3[6];
|
||||
extern const unsigned char jsc_pcre_utf8_table4[0x40];
|
||||
|
||||
extern const unsigned char jsc_pcre_default_tables[tables_length];
|
||||
|
||||
static inline unsigned char toLowerCase(unsigned char c)
|
||||
{
|
||||
static const unsigned char* lowerCaseChars = jsc_pcre_default_tables + lcc_offset;
|
||||
return lowerCaseChars[c];
|
||||
}
|
||||
|
||||
static inline unsigned char flipCase(unsigned char c)
|
||||
{
|
||||
static const unsigned char* flippedCaseChars = jsc_pcre_default_tables + fcc_offset;
|
||||
return flippedCaseChars[c];
|
||||
}
|
||||
|
||||
static inline unsigned char classBitmapForChar(unsigned char c)
|
||||
{
|
||||
static const unsigned char* charClassBitmaps = jsc_pcre_default_tables + cbits_offset;
|
||||
return charClassBitmaps[c];
|
||||
}
|
||||
|
||||
static inline unsigned char charTypeForChar(unsigned char c)
|
||||
{
|
||||
const unsigned char* charTypeMap = jsc_pcre_default_tables + ctypes_offset;
|
||||
return charTypeMap[c];
|
||||
}
|
||||
|
||||
static inline bool isWordChar(UChar c)
|
||||
{
|
||||
return c < 128 && (charTypeForChar(c) & ctype_word);
|
||||
}
|
||||
|
||||
static inline bool isSpaceChar(UChar c)
|
||||
{
|
||||
return (c < 128 && (charTypeForChar(c) & ctype_space)) || c == 0x00A0;
|
||||
}
|
||||
|
||||
static inline bool isNewline(UChar nl)
|
||||
{
|
||||
return (nl == 0xA || nl == 0xD || nl == 0x2028 || nl == 0x2029);
|
||||
}
|
||||
|
||||
static inline bool isBracketStartOpcode(unsigned char opcode)
|
||||
{
|
||||
if (opcode >= OP_BRA)
|
||||
return true;
|
||||
switch (opcode) {
|
||||
case OP_ASSERT:
|
||||
case OP_ASSERT_NOT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void advanceToEndOfBracket(const unsigned char*& opcodePtr)
|
||||
{
|
||||
JS_ASSERT(isBracketStartOpcode(*opcodePtr) || *opcodePtr == OP_ALT);
|
||||
do
|
||||
opcodePtr += getLinkValue(opcodePtr + 1);
|
||||
while (*opcodePtr == OP_ALT);
|
||||
}
|
||||
|
||||
/* Internal shared functions. These are functions that are used in more
|
||||
that one of the source files. They have to have external linkage, but
|
||||
but are not part of the public API and so not exported from the library. */
|
||||
|
||||
extern int jsc_pcre_ucp_othercase(unsigned);
|
||||
extern bool jsc_pcre_xclass(int, const unsigned char*);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* End of pcre_internal.h */
|
@ -1,71 +0,0 @@
|
||||
/* This is JavaScriptCore's variant of the PCRE library. While this library
|
||||
started out as a copy of PCRE, many of the features of PCRE have been
|
||||
removed. This library now supports only the regular expression features
|
||||
required by the JavaScript language specification, and has only the functions
|
||||
needed by JavaScriptCore and the rest of WebKit.
|
||||
|
||||
Originally written by Philip Hazel
|
||||
Copyright (c) 1997-2006 University of Cambridge
|
||||
Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* This module contains some fixed tables that are used by more than one of the
|
||||
PCRE code modules. */
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
/*************************************************
|
||||
* Tables for UTF-8 support *
|
||||
*************************************************/
|
||||
|
||||
/* These are the breakpoints for different numbers of bytes in a UTF-8
|
||||
character. */
|
||||
|
||||
const int jsc_pcre_utf8_table1[6] =
|
||||
{ 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
|
||||
|
||||
/* These are the indicator bits and the mask for the data bits to set in the
|
||||
first byte of a character, indexed by the number of additional bytes. */
|
||||
|
||||
const int jsc_pcre_utf8_table2[6] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
|
||||
const int jsc_pcre_utf8_table3[6] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
|
||||
|
||||
/* Table of the number of extra characters, indexed by the first character
|
||||
masked with 0x3f. The highest number for a valid UTF-8 character is in fact
|
||||
0x3d. */
|
||||
|
||||
const unsigned char jsc_pcre_utf8_table4[0x40] = {
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
|
||||
|
||||
#include "chartables.c"
|
@ -1,98 +0,0 @@
|
||||
/* This is JavaScriptCore's variant of the PCRE library. While this library
|
||||
started out as a copy of PCRE, many of the features of PCRE have been
|
||||
removed. This library now supports only the regular expression features
|
||||
required by the JavaScript language specification, and has only the functions
|
||||
needed by JavaScriptCore and the rest of WebKit.
|
||||
|
||||
Originally written by Philip Hazel
|
||||
Copyright (c) 1997-2006 University of Cambridge
|
||||
Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/* This module contains code for searching the table of Unicode character
|
||||
properties. */
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
#include "ucpinternal.h" /* Internal table details */
|
||||
#include "ucptable.cpp" /* The table itself */
|
||||
|
||||
/*************************************************
|
||||
* Search table and return other case *
|
||||
*************************************************/
|
||||
|
||||
/* If the given character is a letter, and there is another case for the
|
||||
letter, return the other case. Otherwise, return -1.
|
||||
|
||||
Arguments:
|
||||
c the character value
|
||||
|
||||
Returns: the other case or -1 if none
|
||||
*/
|
||||
|
||||
int jsc_pcre_ucp_othercase(unsigned c)
|
||||
{
|
||||
int bot = 0;
|
||||
int top = sizeof(ucp_table) / sizeof(cnode);
|
||||
int mid;
|
||||
|
||||
/* The table is searched using a binary chop. You might think that using
|
||||
intermediate variables to hold some of the common expressions would speed
|
||||
things up, but tests with gcc 3.4.4 on Linux showed that, on the contrary, it
|
||||
makes things a lot slower. */
|
||||
|
||||
for (;;) {
|
||||
if (top <= bot)
|
||||
return -1;
|
||||
mid = (bot + top) >> 1;
|
||||
if (c == (ucp_table[mid].f0 & f0_charmask))
|
||||
break;
|
||||
if (c < (ucp_table[mid].f0 & f0_charmask))
|
||||
top = mid;
|
||||
else {
|
||||
if ((ucp_table[mid].f0 & f0_rangeflag) && (c <= (ucp_table[mid].f0 & f0_charmask) + (ucp_table[mid].f1 & f1_rangemask)))
|
||||
break;
|
||||
bot = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Found an entry in the table. Return -1 for a range entry. Otherwise return
|
||||
the other case if there is one, else -1. */
|
||||
|
||||
if (ucp_table[mid].f0 & f0_rangeflag)
|
||||
return -1;
|
||||
|
||||
int offset = ucp_table[mid].f1 & f1_casemask;
|
||||
if (offset & f1_caseneg)
|
||||
offset |= f1_caseneg;
|
||||
return !offset ? -1 : c + offset;
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
/* This is JavaScriptCore's variant of the PCRE library. While this library
|
||||
started out as a copy of PCRE, many of the features of PCRE have been
|
||||
removed. This library now supports only the regular expression features
|
||||
required by the JavaScript language specification, and has only the functions
|
||||
needed by JavaScriptCore and the rest of WebKit.
|
||||
|
||||
Originally written by Philip Hazel
|
||||
Copyright (c) 1997-2006 University of Cambridge
|
||||
Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* This module contains an internal function that is used to match an extended
|
||||
class (one that contains characters whose values are > 255). */
|
||||
|
||||
#include "pcre_internal.h"
|
||||
|
||||
/*************************************************
|
||||
* Match character against an XCLASS *
|
||||
*************************************************/
|
||||
|
||||
/* This function is called to match a character against an extended class that
|
||||
might contain values > 255.
|
||||
|
||||
Arguments:
|
||||
c the character
|
||||
data points to the flag byte of the XCLASS data
|
||||
|
||||
Returns: true if character matches, else false
|
||||
*/
|
||||
|
||||
/* Get the next UTF-8 character, advancing the pointer. This is called when we
|
||||
know we are in UTF-8 mode. */
|
||||
|
||||
static inline void getUTF8CharAndAdvancePointer(int& c, const unsigned char*& subjectPtr)
|
||||
{
|
||||
c = *subjectPtr++;
|
||||
if ((c & 0xc0) == 0xc0) {
|
||||
int gcaa = jsc_pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */
|
||||
int gcss = 6 * gcaa;
|
||||
c = (c & jsc_pcre_utf8_table3[gcaa]) << gcss;
|
||||
while (gcaa-- > 0) {
|
||||
gcss -= 6;
|
||||
c |= (*subjectPtr++ & 0x3f) << gcss;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool jsc_pcre_xclass(int c, const unsigned char* data)
|
||||
{
|
||||
bool negated = (*data & XCL_NOT);
|
||||
|
||||
/* Character values < 256 are matched against a bitmap, if one is present. If
|
||||
not, we still carry on, because there may be ranges that start below 256 in the
|
||||
additional data. */
|
||||
|
||||
if (c < 256) {
|
||||
if ((*data & XCL_MAP) != 0 && (data[1 + c/8] & (1 << (c&7))) != 0)
|
||||
return !negated; /* char found */
|
||||
}
|
||||
|
||||
/* First skip the bit map if present. Then match against the list of Unicode
|
||||
properties or large chars or ranges that end with a large char. We won't ever
|
||||
encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */
|
||||
|
||||
if ((*data++ & XCL_MAP) != 0)
|
||||
data += 32;
|
||||
|
||||
int t;
|
||||
while ((t = *data++) != XCL_END) {
|
||||
if (t == XCL_SINGLE) {
|
||||
int x;
|
||||
getUTF8CharAndAdvancePointer(x, data);
|
||||
if (c == x)
|
||||
return !negated;
|
||||
}
|
||||
else if (t == XCL_RANGE) {
|
||||
int x, y;
|
||||
getUTF8CharAndAdvancePointer(x, data);
|
||||
getUTF8CharAndAdvancePointer(y, data);
|
||||
if (c >= x && c <= y)
|
||||
return !negated;
|
||||
}
|
||||
}
|
||||
|
||||
return negated; /* char did not match */
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
/* This is JavaScriptCore's variant of the PCRE library. While this library
|
||||
started out as a copy of PCRE, many of the features of PCRE have been
|
||||
removed. This library now supports only the regular expression features
|
||||
required by the JavaScript language specification, and has only the functions
|
||||
needed by JavaScriptCore and the rest of WebKit.
|
||||
|
||||
Originally written by Philip Hazel
|
||||
Copyright (c) 1997-2006 University of Cambridge
|
||||
Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
* Unicode Property Table handler *
|
||||
*************************************************/
|
||||
|
||||
/* Internal header file defining the layout of the bits in each pair of 32-bit
|
||||
words that form a data item in the table. */
|
||||
|
||||
typedef struct cnode {
|
||||
unsigned f0;
|
||||
unsigned f1;
|
||||
} cnode;
|
||||
|
||||
/* Things for the f0 field */
|
||||
|
||||
#define f0_scriptmask 0xff000000 /* Mask for script field */
|
||||
#define f0_scriptshift 24 /* Shift for script value */
|
||||
#define f0_rangeflag 0x00f00000 /* Flag for a range item */
|
||||
#define f0_charmask 0x001fffff /* Mask for code point value */
|
||||
|
||||
/* Things for the f1 field */
|
||||
|
||||
#define f1_typemask 0xfc000000 /* Mask for char type field */
|
||||
#define f1_typeshift 26 /* Shift for the type field */
|
||||
#define f1_rangemask 0x0000ffff /* Mask for a range offset */
|
||||
#define f1_casemask 0x0000ffff /* Mask for a case offset */
|
||||
#define f1_caseneg 0xffff8000 /* Bits for negation */
|
||||
|
||||
/* The data consists of a vector of structures of type cnode. The two unsigned
|
||||
32-bit integers are used as follows:
|
||||
|
||||
(f0) (1) The most significant byte holds the script number. The numbers are
|
||||
defined by the enum in ucp.h.
|
||||
|
||||
(2) The 0x00800000 bit is set if this entry defines a range of characters.
|
||||
It is not set if this entry defines a single character
|
||||
|
||||
(3) The 0x00600000 bits are spare.
|
||||
|
||||
(4) The 0x001fffff bits contain the code point. No Unicode code point will
|
||||
ever be greater than 0x0010ffff, so this should be OK for ever.
|
||||
|
||||
(f1) (1) The 0xfc000000 bits contain the character type number. The numbers are
|
||||
defined by an enum in ucp.h.
|
||||
|
||||
(2) The 0x03ff0000 bits are spare.
|
||||
|
||||
(3) The 0x0000ffff bits contain EITHER the unsigned offset to the top of
|
||||
range if this entry defines a range, OR the *signed* offset to the
|
||||
character's "other case" partner if this entry defines a single
|
||||
character. There is no partner if the value is zero.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
| script (8) |.|.|.| codepoint (21) || type (6) |.|.| spare (8) | offset (16) |
|
||||
-------------------------------------------------------------------------------
|
||||
| | | | |
|
||||
| | |-> spare | |-> spare
|
||||
| | |
|
||||
| |-> spare |-> spare
|
||||
|
|
||||
|-> range flag
|
||||
|
||||
The upper/lower casing information is set only for characters that come in
|
||||
pairs. The non-one-to-one mappings in the Unicode data are ignored.
|
||||
|
||||
When searching the data, proceed as follows:
|
||||
|
||||
(1) Set up for a binary chop search.
|
||||
|
||||
(2) If the top is not greater than the bottom, the character is not in the
|
||||
table. Its type must therefore be "Cn" ("Undefined").
|
||||
|
||||
(3) Find the middle vector element.
|
||||
|
||||
(4) Extract the code point and compare. If equal, we are done.
|
||||
|
||||
(5) If the test character is smaller, set the top to the current point, and
|
||||
goto (2).
|
||||
|
||||
(6) If the current entry defines a range, compute the last character by adding
|
||||
the offset, and see if the test character is within the range. If it is,
|
||||
we are done.
|
||||
|
||||
(7) Otherwise, set the bottom to one element past the current point and goto
|
||||
(2).
|
||||
*/
|
||||
|
||||
/* End of ucpinternal.h */
|
File diff suppressed because it is too large
Load Diff
329
js/src/yarr/wtfbridge.h
Normal file
329
js/src/yarr/wtfbridge.h
Normal file
@ -0,0 +1,329 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* June 12, 2009.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Corporation.
|
||||
*
|
||||
* Contributor(s):
|
||||
* David Mandelin <dmandelin@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef jswtfbridge_h__
|
||||
#define jswtfbridge_h__
|
||||
|
||||
/*
|
||||
* WTF compatibility layer. This file provides various type and data
|
||||
* definitions for use by Yarr.
|
||||
*/
|
||||
|
||||
#include "jsstr.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jstl.h"
|
||||
#include "assembler/wtf/Platform.h"
|
||||
#include "assembler/jit/ExecutableAllocator.h"
|
||||
|
||||
namespace JSC { namespace Yarr {
|
||||
|
||||
/*
|
||||
* Basic type definitions.
|
||||
*/
|
||||
|
||||
typedef jschar UChar;
|
||||
typedef JSLinearString UString;
|
||||
|
||||
class Unicode {
|
||||
public:
|
||||
static UChar toUpper(UChar c) { return JS_TOUPPER(c); }
|
||||
static UChar toLower(UChar c) { return JS_TOLOWER(c); }
|
||||
};
|
||||
|
||||
/*
|
||||
* Do-nothing smart pointer classes. These have a compatible interface
|
||||
* with the smart pointers used by Yarr, but they don't actually do
|
||||
* reference counting.
|
||||
*/
|
||||
template<typename T>
|
||||
class RefCounted {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class RefPtr {
|
||||
T *ptr;
|
||||
public:
|
||||
RefPtr(T *p) { ptr = p; }
|
||||
operator bool() const { return ptr != NULL; }
|
||||
const T *operator ->() const { return ptr; }
|
||||
T *get() { return ptr; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class PassRefPtr {
|
||||
T *ptr;
|
||||
public:
|
||||
PassRefPtr(T *p) { ptr = p; }
|
||||
operator T*() { return ptr; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class PassOwnPtr {
|
||||
T *ptr;
|
||||
public:
|
||||
PassOwnPtr(T *p) { ptr = p; }
|
||||
|
||||
T *get() { return ptr; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class OwnPtr {
|
||||
T *ptr;
|
||||
public:
|
||||
OwnPtr() : ptr(NULL) { }
|
||||
OwnPtr(PassOwnPtr<T> p) : ptr(p.get()) { }
|
||||
|
||||
~OwnPtr() {
|
||||
if (ptr)
|
||||
js::Foreground::delete_(ptr);
|
||||
}
|
||||
|
||||
OwnPtr<T> &operator=(PassOwnPtr<T> p) {
|
||||
ptr = p.get();
|
||||
return *this;
|
||||
}
|
||||
|
||||
T *operator ->() { return ptr; }
|
||||
|
||||
T *get() { return ptr; }
|
||||
|
||||
T *release() {
|
||||
T *result = ptr;
|
||||
ptr = NULL;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
PassRefPtr<T> adoptRef(T *p) { return PassRefPtr<T>(p); }
|
||||
|
||||
template<typename T>
|
||||
PassOwnPtr<T> adoptPtr(T *p) { return PassOwnPtr<T>(p); }
|
||||
|
||||
#define WTF_MAKE_FAST_ALLOCATED
|
||||
|
||||
template<typename T>
|
||||
class Ref {
|
||||
T &val;
|
||||
public:
|
||||
Ref(T &val) : val(val) { }
|
||||
operator T&() const { return val; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Vector class for Yarr. This wraps js::Vector and provides all
|
||||
* the API method signatures used by Yarr.
|
||||
*/
|
||||
template<typename T, size_t N = 0>
|
||||
class Vector {
|
||||
public:
|
||||
js::Vector<T, N, js::SystemAllocPolicy> impl;
|
||||
public:
|
||||
Vector() {}
|
||||
|
||||
Vector(const Vector &v) {
|
||||
// XXX yarr-oom
|
||||
(void) append(v);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return impl.length();
|
||||
}
|
||||
|
||||
T &operator[](size_t i) {
|
||||
return impl[i];
|
||||
}
|
||||
|
||||
const T &operator[](size_t i) const {
|
||||
return impl[i];
|
||||
}
|
||||
|
||||
T &at(size_t i) {
|
||||
return impl[i];
|
||||
}
|
||||
|
||||
const T *begin() const {
|
||||
return impl.begin();
|
||||
}
|
||||
|
||||
T &last() {
|
||||
return impl.back();
|
||||
}
|
||||
|
||||
bool isEmpty() const {
|
||||
return impl.empty();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void append(const U &u) {
|
||||
// XXX yarr-oom
|
||||
(void) impl.append(static_cast<T>(u));
|
||||
}
|
||||
|
||||
template <size_t M>
|
||||
void append(const Vector<T,M> &v) {
|
||||
// XXX yarr-oom
|
||||
(void) impl.append(v.impl);
|
||||
}
|
||||
|
||||
void insert(size_t i, const T& t) {
|
||||
// XXX yarr-oom
|
||||
(void) impl.insert(&impl[i], t);
|
||||
}
|
||||
|
||||
void remove(size_t i) {
|
||||
impl.erase(&impl[i]);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
return impl.clear();
|
||||
}
|
||||
|
||||
void shrink(size_t newLength) {
|
||||
// XXX yarr-oom
|
||||
JS_ASSERT(newLength <= impl.length());
|
||||
(void) impl.resize(newLength);
|
||||
}
|
||||
|
||||
void deleteAllValues() {
|
||||
for (T *p = impl.begin(); p != impl.end(); ++p)
|
||||
js::Foreground::delete_(*p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class Vector<OwnPtr<T> > {
|
||||
public:
|
||||
js::Vector<T *, 0, js::SystemAllocPolicy> impl;
|
||||
public:
|
||||
Vector() {}
|
||||
|
||||
size_t size() const {
|
||||
return impl.length();
|
||||
}
|
||||
|
||||
void append(T *t) {
|
||||
// XXX yarr-oom
|
||||
(void) impl.append(t);
|
||||
}
|
||||
|
||||
PassOwnPtr<T> operator[](size_t i) {
|
||||
return PassOwnPtr<T>(impl[i]);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (T **p = impl.begin(); p != impl.end(); ++p)
|
||||
js::Foreground::delete_(*p);
|
||||
return impl.clear();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, size_t N>
|
||||
inline void
|
||||
deleteAllValues(Vector<T, N> &v) {
|
||||
v.deleteAllValues();
|
||||
}
|
||||
|
||||
/*
|
||||
* Minimal JSGlobalData. This used by Yarr to get the allocator.
|
||||
*/
|
||||
class JSGlobalData {
|
||||
public:
|
||||
ExecutableAllocator *regexAllocator;
|
||||
|
||||
JSGlobalData(ExecutableAllocator *regexAllocator)
|
||||
: regexAllocator(regexAllocator) { }
|
||||
};
|
||||
|
||||
/*
|
||||
* Sentinel value used in Yarr.
|
||||
*/
|
||||
const size_t notFound = size_t(-1);
|
||||
|
||||
/*
|
||||
* Do-nothing version of a macro used by WTF to avoid unused
|
||||
* parameter warnings.
|
||||
*/
|
||||
#define UNUSED_PARAM(e)
|
||||
|
||||
} /* namespace Yarr */
|
||||
|
||||
/*
|
||||
* Replacements for std:: functions used in Yarr. We put them in
|
||||
* namespace JSC::std so that they can still be called as std::X
|
||||
* in Yarr.
|
||||
*/
|
||||
namespace std {
|
||||
|
||||
/*
|
||||
* windows.h defines a 'min' macro that would mangle the function
|
||||
* name.
|
||||
*/
|
||||
#if WTF_COMPILER_MSVC
|
||||
# undef min
|
||||
# undef max
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
inline T
|
||||
min(T t1, T t2)
|
||||
{
|
||||
return JS_MIN(t1, t2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T
|
||||
max(T t1, T t2)
|
||||
{
|
||||
return JS_MAX(t1, t2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
swap(T &t1, T &t2)
|
||||
{
|
||||
T tmp = t1;
|
||||
t1 = t2;
|
||||
t2 = tmp;
|
||||
}
|
||||
} /* namespace std */
|
||||
|
||||
} /* namespace JSC */
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RegexJIT_h
|
||||
#define RegexJIT_h
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
|
||||
#include "assembler/assembler/MacroAssembler.h"
|
||||
#include "assembler/assembler/MacroAssemblerCodeRef.h"
|
||||
#include "assembler/jit/ExecutableAllocator.h"
|
||||
#include "RegexPattern.h"
|
||||
#include "yarr/jswtfbridge.h"
|
||||
|
||||
#include "yarr/pcre/pcre.h"
|
||||
struct JSRegExp; // temporary, remove when fallback is removed.
|
||||
|
||||
#if WTF_CPU_X86 && !WTF_COMPILER_MSVC && !WTF_COMPILER_SUNPRO
|
||||
#define YARR_CALL __attribute__ ((regparm (3)))
|
||||
#else
|
||||
#define YARR_CALL
|
||||
#endif
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace JSC {
|
||||
|
||||
namespace Yarr {
|
||||
|
||||
class RegexCodeBlock {
|
||||
typedef int (*RegexJITCode)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
|
||||
|
||||
public:
|
||||
RegexCodeBlock()
|
||||
: m_fallback(0)
|
||||
{
|
||||
}
|
||||
|
||||
~RegexCodeBlock()
|
||||
{
|
||||
if (m_fallback)
|
||||
jsRegExpFree(m_fallback);
|
||||
if (m_ref.m_size)
|
||||
m_ref.m_executablePool->release();
|
||||
}
|
||||
|
||||
JSRegExp* getFallback() { return m_fallback; }
|
||||
void setFallback(JSRegExp* fallback) { m_fallback = fallback; }
|
||||
|
||||
bool operator!() { return (!m_ref.m_code.executableAddress() && !m_fallback); }
|
||||
void set(MacroAssembler::CodeRef ref) { m_ref = ref; }
|
||||
|
||||
int execute(const UChar* input, unsigned start, unsigned length, int* output)
|
||||
{
|
||||
void *code = m_ref.m_code.executableAddress();
|
||||
return JS_EXTENSION((reinterpret_cast<RegexJITCode>(code))(input, start, length, output));
|
||||
}
|
||||
|
||||
private:
|
||||
MacroAssembler::CodeRef m_ref;
|
||||
JSRegExp* m_fallback;
|
||||
};
|
||||
|
||||
void jitCompileRegex(ExecutableAllocator &allocator, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, int& error, bool &fellBack, bool ignoreCase = false, bool multiline = false
|
||||
#ifdef ANDROID
|
||||
, bool forceFallback = false
|
||||
#endif
|
||||
);
|
||||
|
||||
inline int executeRegex(JSContext *cx, RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize)
|
||||
{
|
||||
if (JSRegExp* fallback = jitObject.getFallback()) {
|
||||
int result = jsRegExpExecute(cx, fallback, input, length, start, output, outputArraySize);
|
||||
|
||||
if (result == JSRegExpErrorHitLimit)
|
||||
return HitRecursionLimit;
|
||||
|
||||
// -1 represents no-match for both PCRE and YARR.
|
||||
JS_ASSERT(result >= -1);
|
||||
return result;
|
||||
}
|
||||
|
||||
return jitObject.execute(input, start, length, output);
|
||||
}
|
||||
|
||||
} } // namespace JSC::Yarr
|
||||
|
||||
#endif /* ENABLE_ASSEMBLER */
|
||||
|
||||
#endif // RegexJIT_h
|
@ -2032,7 +2032,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
<h1><a name="apple"></a>Apple License</h1>
|
||||
|
||||
<p class="correctme">This license applies to certain files in the directories <span class="path">js/src/assembler/assembler/</span>, <span class="path">js/src/assembler/wtf/</span>, <span class="path">js/src/yarr/wtf</span>, <span class="path">js/src/yarr/yarr</span>, and <span class="path">widget/src/cocoa</span>.</p>
|
||||
<p class="correctme">This license applies to certain files in the directories <span class="path">js/src/assembler/assembler/</span>, <span class="path">js/src/assembler/wtf/</span>, <span class="path">js/src/yarr</span>, and <span class="path">widget/src/cocoa</span>.</p>
|
||||
|
||||
<pre>
|
||||
Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
|
||||
|
Loading…
Reference in New Issue
Block a user