Bug 625600: Update Yarr import to WebKit rev 86639, r=cdleary,dvander

This commit is contained in:
David Mandelin 2011-05-12 18:39:47 -07:00
parent 788ba5d7fa
commit 8cb0de51d8
67 changed files with 7872 additions and 12046 deletions

View File

@ -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 \

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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>

View File

@ -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);

View File

@ -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));

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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()
{

View File

@ -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);

View File

@ -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 (

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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];
}

View File

@ -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();

View File

@ -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);

View File

@ -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;

View 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

View File

@ -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
View 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

View 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

View 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

View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

93
js/src/yarr/YarrJIT.h Normal file
View 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

View File

@ -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

View File

@ -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);
}
} }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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"

View File

@ -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;
}

View File

@ -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 */
}

View File

@ -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
View 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

View File

@ -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

View File

@ -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.