ARM native regexps.
Review URL: http://codereview.chromium.org/173567 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2785 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
fcf8293df2
commit
9230ad29eb
@ -99,12 +99,7 @@ LIBRARY_FLAGS = {
|
|||||||
'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING'],
|
'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING'],
|
||||||
'CPPPATH': [join(root_dir, 'src')],
|
'CPPPATH': [join(root_dir, 'src')],
|
||||||
'regexp:native': {
|
'regexp:native': {
|
||||||
'arch:ia32' : {
|
|
||||||
'CPPDEFINES': ['V8_NATIVE_REGEXP']
|
'CPPDEFINES': ['V8_NATIVE_REGEXP']
|
||||||
},
|
|
||||||
'arch:x64' : {
|
|
||||||
'CPPDEFINES': ['V8_NATIVE_REGEXP']
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
'mode:debug': {
|
'mode:debug': {
|
||||||
'CPPDEFINES': ['V8_ENABLE_CHECKS']
|
'CPPDEFINES': ['V8_ENABLE_CHECKS']
|
||||||
|
@ -63,32 +63,22 @@ SOURCES = {
|
|||||||
'arm/register-allocator-arm.cc', 'arm/stub-cache-arm.cc',
|
'arm/register-allocator-arm.cc', 'arm/stub-cache-arm.cc',
|
||||||
'arm/virtual-frame-arm.cc'
|
'arm/virtual-frame-arm.cc'
|
||||||
],
|
],
|
||||||
'arch:ia32': {
|
'arch:ia32': [
|
||||||
'all': [
|
'ia32/assembler-ia32.cc', 'ia32/builtins-ia32.cc', 'ia32/cfg-ia32.cc',
|
||||||
'ia32/assembler-ia32.cc', 'ia32/builtins-ia32.cc', 'ia32/cfg-ia32.cc',
|
'ia32/codegen-ia32.cc', 'ia32/cpu-ia32.cc', 'ia32/disasm-ia32.cc',
|
||||||
'ia32/codegen-ia32.cc', 'ia32/cpu-ia32.cc', 'ia32/disasm-ia32.cc',
|
'ia32/debug-ia32.cc', 'ia32/frames-ia32.cc', 'ia32/ic-ia32.cc',
|
||||||
'ia32/debug-ia32.cc', 'ia32/frames-ia32.cc', 'ia32/ic-ia32.cc',
|
'ia32/jump-target-ia32.cc', 'ia32/macro-assembler-ia32.cc',
|
||||||
'ia32/jump-target-ia32.cc', 'ia32/macro-assembler-ia32.cc',
|
'ia32/regexp-macro-assembler-ia32.cc', 'ia32/register-allocator-ia32.cc',
|
||||||
'ia32/register-allocator-ia32.cc', 'ia32/stub-cache-ia32.cc',
|
'ia32/stub-cache-ia32.cc', 'ia32/virtual-frame-ia32.cc'
|
||||||
'ia32/virtual-frame-ia32.cc'
|
],
|
||||||
],
|
'arch:x64': [
|
||||||
'regexp:native': [
|
'x64/assembler-x64.cc', 'x64/builtins-x64.cc', 'x64/cfg-x64.cc',
|
||||||
'ia32/regexp-macro-assembler-ia32.cc',
|
'x64/codegen-x64.cc', 'x64/cpu-x64.cc', 'x64/disasm-x64.cc',
|
||||||
]
|
'x64/debug-x64.cc', 'x64/frames-x64.cc', 'x64/ic-x64.cc',
|
||||||
},
|
'x64/jump-target-x64.cc', 'x64/macro-assembler-x64.cc',
|
||||||
'arch:x64': {
|
'x64/regexp-macro-assembler-x64.cc', 'x64/register-allocator-x64.cc',
|
||||||
'all': [
|
'x64/stub-cache-x64.cc', 'x64/virtual-frame-x64.cc'
|
||||||
'x64/assembler-x64.cc', 'x64/builtins-x64.cc', 'x64/cfg-x64.cc',
|
],
|
||||||
'x64/codegen-x64.cc', 'x64/cpu-x64.cc', 'x64/disasm-x64.cc',
|
|
||||||
'x64/debug-x64.cc', 'x64/frames-x64.cc', 'x64/ic-x64.cc',
|
|
||||||
'x64/jump-target-x64.cc', 'x64/macro-assembler-x64.cc',
|
|
||||||
'x64/register-allocator-x64.cc',
|
|
||||||
'x64/stub-cache-x64.cc', 'x64/virtual-frame-x64.cc'
|
|
||||||
],
|
|
||||||
'regexp:native': [
|
|
||||||
'x64/regexp-macro-assembler-x64.cc'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'simulator:arm': ['arm/simulator-arm.cc'],
|
'simulator:arm': ['arm/simulator-arm.cc'],
|
||||||
'os:freebsd': ['platform-freebsd.cc', 'platform-posix.cc'],
|
'os:freebsd': ['platform-freebsd.cc', 'platform-posix.cc'],
|
||||||
'os:linux': ['platform-linux.cc', 'platform-posix.cc'],
|
'os:linux': ['platform-linux.cc', 'platform-posix.cc'],
|
||||||
|
@ -204,7 +204,7 @@ void Assembler::CheckBuffer() {
|
|||||||
if (buffer_space() <= kGap) {
|
if (buffer_space() <= kGap) {
|
||||||
GrowBuffer();
|
GrowBuffer();
|
||||||
}
|
}
|
||||||
if (pc_offset() > next_buffer_check_) {
|
if (pc_offset() >= next_buffer_check_) {
|
||||||
CheckConstPool(false, true);
|
CheckConstPool(false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,19 +329,30 @@ const int kEndOfChain = -4;
|
|||||||
|
|
||||||
int Assembler::target_at(int pos) {
|
int Assembler::target_at(int pos) {
|
||||||
Instr instr = instr_at(pos);
|
Instr instr = instr_at(pos);
|
||||||
|
if ((instr & ~Imm24Mask) == 0) {
|
||||||
|
// Emitted label constant, not part of a branch.
|
||||||
|
return instr - (Code::kHeaderSize - kHeapObjectTag);
|
||||||
|
}
|
||||||
ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
|
ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
|
||||||
int imm26 = ((instr & Imm24Mask) << 8) >> 6;
|
int imm26 = ((instr & Imm24Mask) << 8) >> 6;
|
||||||
if ((instr & CondMask) == nv && (instr & B24) != 0)
|
if ((instr & CondMask) == nv && (instr & B24) != 0)
|
||||||
// blx uses bit 24 to encode bit 2 of imm26
|
// blx uses bit 24 to encode bit 2 of imm26
|
||||||
imm26 += 2;
|
imm26 += 2;
|
||||||
|
|
||||||
return pos + 8 + imm26;
|
return pos + kPcLoadDelta + imm26;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Assembler::target_at_put(int pos, int target_pos) {
|
void Assembler::target_at_put(int pos, int target_pos) {
|
||||||
int imm26 = target_pos - pos - 8;
|
|
||||||
Instr instr = instr_at(pos);
|
Instr instr = instr_at(pos);
|
||||||
|
if ((instr & ~Imm24Mask) == 0) {
|
||||||
|
ASSERT(target_pos == kEndOfChain || target_pos >= 0);
|
||||||
|
// Emitted label constant, not part of a branch.
|
||||||
|
// Make label relative to Code* of generated Code object.
|
||||||
|
instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int imm26 = target_pos - (pos + kPcLoadDelta);
|
||||||
ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
|
ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
|
||||||
if ((instr & CondMask) == nv) {
|
if ((instr & CondMask) == nv) {
|
||||||
// blx uses bit 24 to encode bit 2 of imm26
|
// blx uses bit 24 to encode bit 2 of imm26
|
||||||
@ -368,41 +379,45 @@ void Assembler::print(Label* L) {
|
|||||||
while (l.is_linked()) {
|
while (l.is_linked()) {
|
||||||
PrintF("@ %d ", l.pos());
|
PrintF("@ %d ", l.pos());
|
||||||
Instr instr = instr_at(l.pos());
|
Instr instr = instr_at(l.pos());
|
||||||
ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx
|
if ((instr & ~Imm24Mask) == 0) {
|
||||||
int cond = instr & CondMask;
|
PrintF("value\n");
|
||||||
const char* b;
|
|
||||||
const char* c;
|
|
||||||
if (cond == nv) {
|
|
||||||
b = "blx";
|
|
||||||
c = "";
|
|
||||||
} else {
|
} else {
|
||||||
if ((instr & B24) != 0)
|
ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx
|
||||||
b = "bl";
|
int cond = instr & CondMask;
|
||||||
else
|
const char* b;
|
||||||
b = "b";
|
const char* c;
|
||||||
|
if (cond == nv) {
|
||||||
|
b = "blx";
|
||||||
|
c = "";
|
||||||
|
} else {
|
||||||
|
if ((instr & B24) != 0)
|
||||||
|
b = "bl";
|
||||||
|
else
|
||||||
|
b = "b";
|
||||||
|
|
||||||
switch (cond) {
|
switch (cond) {
|
||||||
case eq: c = "eq"; break;
|
case eq: c = "eq"; break;
|
||||||
case ne: c = "ne"; break;
|
case ne: c = "ne"; break;
|
||||||
case hs: c = "hs"; break;
|
case hs: c = "hs"; break;
|
||||||
case lo: c = "lo"; break;
|
case lo: c = "lo"; break;
|
||||||
case mi: c = "mi"; break;
|
case mi: c = "mi"; break;
|
||||||
case pl: c = "pl"; break;
|
case pl: c = "pl"; break;
|
||||||
case vs: c = "vs"; break;
|
case vs: c = "vs"; break;
|
||||||
case vc: c = "vc"; break;
|
case vc: c = "vc"; break;
|
||||||
case hi: c = "hi"; break;
|
case hi: c = "hi"; break;
|
||||||
case ls: c = "ls"; break;
|
case ls: c = "ls"; break;
|
||||||
case ge: c = "ge"; break;
|
case ge: c = "ge"; break;
|
||||||
case lt: c = "lt"; break;
|
case lt: c = "lt"; break;
|
||||||
case gt: c = "gt"; break;
|
case gt: c = "gt"; break;
|
||||||
case le: c = "le"; break;
|
case le: c = "le"; break;
|
||||||
case al: c = ""; break;
|
case al: c = ""; break;
|
||||||
default:
|
default:
|
||||||
c = "";
|
c = "";
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
PrintF("%s%s\n", b, c);
|
||||||
}
|
}
|
||||||
PrintF("%s%s\n", b, c);
|
|
||||||
next(&l);
|
next(&l);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -670,8 +685,23 @@ int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
|
|||||||
// Block the emission of the constant pool, since the branch instruction must
|
// Block the emission of the constant pool, since the branch instruction must
|
||||||
// be emitted at the pc offset recorded by the label
|
// be emitted at the pc offset recorded by the label
|
||||||
BlockConstPoolBefore(pc_offset() + kInstrSize);
|
BlockConstPoolBefore(pc_offset() + kInstrSize);
|
||||||
|
return target_pos - (pc_offset() + kPcLoadDelta);
|
||||||
|
}
|
||||||
|
|
||||||
return target_pos - pc_offset() - 8;
|
|
||||||
|
void Assembler::label_at_put(Label* L, int at_offset) {
|
||||||
|
int target_pos;
|
||||||
|
if (L->is_bound()) {
|
||||||
|
target_pos = L->pos();
|
||||||
|
} else {
|
||||||
|
if (L->is_linked()) {
|
||||||
|
target_pos = L->pos(); // L's link
|
||||||
|
} else {
|
||||||
|
target_pos = kEndOfChain;
|
||||||
|
}
|
||||||
|
L->link_to(at_offset);
|
||||||
|
instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
#ifndef V8_ARM_ASSEMBLER_ARM_H_
|
#ifndef V8_ARM_ASSEMBLER_ARM_H_
|
||||||
#define V8_ARM_ASSEMBLER_ARM_H_
|
#define V8_ARM_ASSEMBLER_ARM_H_
|
||||||
|
#include <stdio.h>
|
||||||
#include "assembler.h"
|
#include "assembler.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -165,9 +165,10 @@ enum Coprocessor {
|
|||||||
enum Condition {
|
enum Condition {
|
||||||
eq = 0 << 28, // Z set equal.
|
eq = 0 << 28, // Z set equal.
|
||||||
ne = 1 << 28, // Z clear not equal.
|
ne = 1 << 28, // Z clear not equal.
|
||||||
cs = 2 << 28, // C set unsigned higher or same.
|
nz = 1 << 28, // Z clear not zero.
|
||||||
|
cs = 2 << 28, // C set carry set.
|
||||||
hs = 2 << 28, // C set unsigned higher or same.
|
hs = 2 << 28, // C set unsigned higher or same.
|
||||||
cc = 3 << 28, // C clear unsigned lower.
|
cc = 3 << 28, // C clear carry clear.
|
||||||
lo = 3 << 28, // C clear unsigned lower.
|
lo = 3 << 28, // C clear unsigned lower.
|
||||||
mi = 4 << 28, // N set negative.
|
mi = 4 << 28, // N set negative.
|
||||||
pl = 5 << 28, // N clear positive or zero.
|
pl = 5 << 28, // N clear positive or zero.
|
||||||
@ -420,6 +421,10 @@ class Assembler : public Malloced {
|
|||||||
// Manages the jump elimination optimization if the second parameter is true.
|
// Manages the jump elimination optimization if the second parameter is true.
|
||||||
int branch_offset(Label* L, bool jump_elimination_allowed);
|
int branch_offset(Label* L, bool jump_elimination_allowed);
|
||||||
|
|
||||||
|
// Puts a labels target address at the given position.
|
||||||
|
// The high 8 bits are set to zero.
|
||||||
|
void label_at_put(Label* L, int at_offset);
|
||||||
|
|
||||||
// Return the address in the constant pool of the code target address used by
|
// Return the address in the constant pool of the code target address used by
|
||||||
// the branch/call instruction at pc.
|
// the branch/call instruction at pc.
|
||||||
INLINE(static Address target_address_address_at(Address pc));
|
INLINE(static Address target_address_address_at(Address pc));
|
||||||
@ -435,6 +440,10 @@ class Assembler : public Malloced {
|
|||||||
// to jump to.
|
// to jump to.
|
||||||
static const int kPatchReturnSequenceAddressOffset = 1;
|
static const int kPatchReturnSequenceAddressOffset = 1;
|
||||||
|
|
||||||
|
// Difference between address of current opcode and value read from pc
|
||||||
|
// register.
|
||||||
|
static const int kPcLoadDelta = 8;
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Code generation
|
// Code generation
|
||||||
@ -784,6 +793,8 @@ class Assembler : public Malloced {
|
|||||||
|
|
||||||
// Record reloc info for current pc_
|
// Record reloc info for current pc_
|
||||||
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
|
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
|
||||||
|
|
||||||
|
friend class RegExpMacroAssemblerARM;
|
||||||
};
|
};
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
@ -5682,9 +5682,9 @@ void UnarySubStub::Generate(MacroAssembler* masm) {
|
|||||||
__ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
|
__ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
|
||||||
} else {
|
} else {
|
||||||
AllocateHeapNumber(masm, &slow, r1, r2, r3);
|
AllocateHeapNumber(masm, &slow, r1, r2, r3);
|
||||||
__ ldr(r2, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
|
__ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
|
||||||
__ str(r2, FieldMemOperand(r1, HeapNumber::kMantissaOffset));
|
|
||||||
__ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
|
__ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
|
||||||
|
__ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset));
|
||||||
__ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign.
|
__ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign.
|
||||||
__ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset));
|
__ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset));
|
||||||
__ mov(r0, Operand(r1));
|
__ mov(r0, Operand(r1));
|
||||||
|
@ -119,6 +119,7 @@ class Decoder {
|
|||||||
void DecodeType5(Instr* instr);
|
void DecodeType5(Instr* instr);
|
||||||
void DecodeType6(Instr* instr);
|
void DecodeType6(Instr* instr);
|
||||||
void DecodeType7(Instr* instr);
|
void DecodeType7(Instr* instr);
|
||||||
|
void DecodeUnconditional(Instr* instr);
|
||||||
|
|
||||||
const disasm::NameConverter& converter_;
|
const disasm::NameConverter& converter_;
|
||||||
v8::internal::Vector<char> out_buffer_;
|
v8::internal::Vector<char> out_buffer_;
|
||||||
@ -774,6 +775,67 @@ void Decoder::DecodeType7(Instr* instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Decoder::DecodeUnconditional(Instr* instr) {
|
||||||
|
if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 && instr->HasL()) {
|
||||||
|
Format(instr, "'memop'h'pu 'rd, ");
|
||||||
|
bool immediate = instr->HasB();
|
||||||
|
switch (instr->PUField()) {
|
||||||
|
case 0: {
|
||||||
|
// Post index, negative.
|
||||||
|
if (instr->HasW()) {
|
||||||
|
Unknown(instr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (immediate) {
|
||||||
|
Format(instr, "['rn], #-'imm12");
|
||||||
|
} else {
|
||||||
|
Format(instr, "['rn], -'rm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
// Post index, positive.
|
||||||
|
if (instr->HasW()) {
|
||||||
|
Unknown(instr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (immediate) {
|
||||||
|
Format(instr, "['rn], #+'imm12");
|
||||||
|
} else {
|
||||||
|
Format(instr, "['rn], +'rm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
// Pre index or offset, negative.
|
||||||
|
if (immediate) {
|
||||||
|
Format(instr, "['rn, #-'imm12]'w");
|
||||||
|
} else {
|
||||||
|
Format(instr, "['rn, -'rm]'w");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
// Pre index or offset, positive.
|
||||||
|
if (immediate) {
|
||||||
|
Format(instr, "['rn, #+'imm12]'w");
|
||||||
|
} else {
|
||||||
|
Format(instr, "['rn, +'rm]'w");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// The PU field is a 2-bit field.
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Format(instr, "break 'msg");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Disassemble the instruction at *instr_ptr into the output buffer.
|
// Disassemble the instruction at *instr_ptr into the output buffer.
|
||||||
int Decoder::InstructionDecode(byte* instr_ptr) {
|
int Decoder::InstructionDecode(byte* instr_ptr) {
|
||||||
Instr* instr = Instr::At(instr_ptr);
|
Instr* instr = Instr::At(instr_ptr);
|
||||||
@ -782,7 +844,7 @@ int Decoder::InstructionDecode(byte* instr_ptr) {
|
|||||||
"%08x ",
|
"%08x ",
|
||||||
instr->InstructionBits());
|
instr->InstructionBits());
|
||||||
if (instr->ConditionField() == special_condition) {
|
if (instr->ConditionField() == special_condition) {
|
||||||
Format(instr, "break 'msg");
|
DecodeUnconditional(instr);
|
||||||
return Instr::kInstrSize;
|
return Instr::kInstrSize;
|
||||||
}
|
}
|
||||||
switch (instr->TypeField()) {
|
switch (instr->TypeField()) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -31,12 +31,239 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef V8_NATIVE_REGEXP
|
||||||
class RegExpMacroAssemblerARM: public RegExpMacroAssembler {
|
class RegExpMacroAssemblerARM: public RegExpMacroAssembler {
|
||||||
public:
|
public:
|
||||||
RegExpMacroAssemblerARM();
|
RegExpMacroAssemblerARM();
|
||||||
virtual ~RegExpMacroAssemblerARM();
|
virtual ~RegExpMacroAssemblerARM();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
|
||||||
|
public:
|
||||||
|
RegExpMacroAssemblerARM(Mode mode, int registers_to_save);
|
||||||
|
virtual ~RegExpMacroAssemblerARM();
|
||||||
|
virtual int stack_limit_slack();
|
||||||
|
virtual bool CanReadUnaligned();
|
||||||
|
virtual void AdvanceCurrentPosition(int by);
|
||||||
|
virtual void AdvanceRegister(int reg, int by);
|
||||||
|
virtual void Backtrack();
|
||||||
|
virtual void Bind(Label* label);
|
||||||
|
virtual void CheckAtStart(Label* on_at_start);
|
||||||
|
virtual void CheckCharacter(uint32_t c, Label* on_equal);
|
||||||
|
virtual void CheckCharacterAfterAnd(uint32_t c,
|
||||||
|
uint32_t mask,
|
||||||
|
Label* on_equal);
|
||||||
|
virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
|
||||||
|
virtual void CheckCharacterLT(uc16 limit, Label* on_less);
|
||||||
|
virtual void CheckCharacters(Vector<const uc16> str,
|
||||||
|
int cp_offset,
|
||||||
|
Label* on_failure,
|
||||||
|
bool check_end_of_string);
|
||||||
|
// A "greedy loop" is a loop that is both greedy and with a simple
|
||||||
|
// body. It has a particularly simple implementation.
|
||||||
|
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
||||||
|
virtual void CheckNotAtStart(Label* on_not_at_start);
|
||||||
|
virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
|
||||||
|
virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
|
||||||
|
Label* on_no_match);
|
||||||
|
virtual void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
|
||||||
|
virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal);
|
||||||
|
virtual void CheckNotCharacterAfterAnd(uint32_t c,
|
||||||
|
uint32_t mask,
|
||||||
|
Label* on_not_equal);
|
||||||
|
virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
|
||||||
|
uc16 minus,
|
||||||
|
uc16 mask,
|
||||||
|
Label* on_not_equal);
|
||||||
|
// Checks whether the given offset from the current position is before
|
||||||
|
// the end of the string.
|
||||||
|
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
||||||
|
virtual bool CheckSpecialCharacterClass(uc16 type,
|
||||||
|
int cp_offset,
|
||||||
|
bool check_offset,
|
||||||
|
Label* on_no_match);
|
||||||
|
virtual void Fail();
|
||||||
|
virtual Handle<Object> GetCode(Handle<String> source);
|
||||||
|
virtual void GoTo(Label* label);
|
||||||
|
virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
|
||||||
|
virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
|
||||||
|
virtual void IfRegisterEqPos(int reg, Label* if_eq);
|
||||||
|
virtual IrregexpImplementation Implementation();
|
||||||
|
virtual void LoadCurrentCharacter(int cp_offset,
|
||||||
|
Label* on_end_of_input,
|
||||||
|
bool check_bounds = true,
|
||||||
|
int characters = 1);
|
||||||
|
virtual void PopCurrentPosition();
|
||||||
|
virtual void PopRegister(int register_index);
|
||||||
|
virtual void PushBacktrack(Label* label);
|
||||||
|
virtual void PushCurrentPosition();
|
||||||
|
virtual void PushRegister(int register_index,
|
||||||
|
StackCheckFlag check_stack_limit);
|
||||||
|
virtual void ReadCurrentPositionFromRegister(int reg);
|
||||||
|
virtual void ReadStackPointerFromRegister(int reg);
|
||||||
|
virtual void SetRegister(int register_index, int to);
|
||||||
|
virtual void Succeed();
|
||||||
|
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
|
||||||
|
virtual void ClearRegisters(int reg_from, int reg_to);
|
||||||
|
virtual void WriteStackPointerToRegister(int reg);
|
||||||
|
|
||||||
|
// Called from RegExp if the stack-guard is triggered.
|
||||||
|
// If the code object is relocated, the return address is fixed before
|
||||||
|
// returning.
|
||||||
|
static int CheckStackGuardState(Address* return_address,
|
||||||
|
Code* re_code,
|
||||||
|
Address re_frame);
|
||||||
|
private:
|
||||||
|
// Offsets from frame_pointer() of function parameters and stored registers.
|
||||||
|
static const int kFramePointer = 0;
|
||||||
|
|
||||||
|
// Above the frame pointer - Stored registers and stack passed parameters.
|
||||||
|
// Register 4..11.
|
||||||
|
static const int kStoredRegisters = kFramePointer;
|
||||||
|
// Return address (stored from link register, read into pc on return).
|
||||||
|
static const int kReturnAddress = kStoredRegisters + 8 * kPointerSize;
|
||||||
|
// Stack parameters placed by caller.
|
||||||
|
static const int kRegisterOutput = kReturnAddress + kPointerSize;
|
||||||
|
static const int kAtStart = kRegisterOutput + kPointerSize;
|
||||||
|
static const int kStackHighEnd = kAtStart + kPointerSize;
|
||||||
|
|
||||||
|
// Below the frame pointer.
|
||||||
|
// Register parameters stored by setup code.
|
||||||
|
static const int kInputEnd = kFramePointer - kPointerSize;
|
||||||
|
static const int kInputStart = kInputEnd - kPointerSize;
|
||||||
|
static const int kStartIndex = kInputStart - kPointerSize;
|
||||||
|
static const int kInputString = kStartIndex - kPointerSize;
|
||||||
|
// When adding local variables remember to push space for them in
|
||||||
|
// the frame in GetCode.
|
||||||
|
static const int kInputStartMinusOne = kInputString - kPointerSize;
|
||||||
|
// First register address. Following registers are below it on the stack.
|
||||||
|
static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
|
||||||
|
|
||||||
|
// Initial size of code buffer.
|
||||||
|
static const size_t kRegExpCodeSize = 1024;
|
||||||
|
|
||||||
|
static const int kBacktrackConstantPoolSize = 4;
|
||||||
|
|
||||||
|
// Load a number of characters at the given offset from the
|
||||||
|
// current position, into the current-character register.
|
||||||
|
void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
|
||||||
|
|
||||||
|
// Check whether preemption has been requested.
|
||||||
|
void CheckPreemption();
|
||||||
|
|
||||||
|
// Check whether we are exceeding the stack limit on the backtrack stack.
|
||||||
|
void CheckStackLimit();
|
||||||
|
|
||||||
|
void EmitBacktrackConstantPool();
|
||||||
|
int GetBacktrackConstantPoolEntry();
|
||||||
|
|
||||||
|
|
||||||
|
// Generate a call to CheckStackGuardState.
|
||||||
|
void CallCheckStackGuardState(Register scratch);
|
||||||
|
|
||||||
|
// The ebp-relative location of a regexp register.
|
||||||
|
MemOperand register_location(int register_index);
|
||||||
|
|
||||||
|
// Register holding the current input position as negative offset from
|
||||||
|
// the end of the string.
|
||||||
|
inline Register current_input_offset() { return r6; }
|
||||||
|
|
||||||
|
// The register containing the current character after LoadCurrentCharacter.
|
||||||
|
inline Register current_character() { return r7; }
|
||||||
|
|
||||||
|
// Register holding address of the end of the input string.
|
||||||
|
inline Register end_of_input_address() { return r10; }
|
||||||
|
|
||||||
|
// Register holding the frame address. Local variables, parameters and
|
||||||
|
// regexp registers are addressed relative to this.
|
||||||
|
inline Register frame_pointer() { return fp; }
|
||||||
|
|
||||||
|
// The register containing the backtrack stack top. Provides a meaningful
|
||||||
|
// name to the register.
|
||||||
|
inline Register backtrack_stackpointer() { return r8; }
|
||||||
|
|
||||||
|
// Register holding pointer to the current code object.
|
||||||
|
inline Register code_pointer() { return r5; }
|
||||||
|
|
||||||
|
// Byte size of chars in the string to match (decided by the Mode argument)
|
||||||
|
inline int char_size() { return static_cast<int>(mode_); }
|
||||||
|
|
||||||
|
// Equivalent to a conditional branch to the label, unless the label
|
||||||
|
// is NULL, in which case it is a conditional Backtrack.
|
||||||
|
void BranchOrBacktrack(Condition condition, Label* to);
|
||||||
|
|
||||||
|
// Call and return internally in the generated code in a way that
|
||||||
|
// is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
|
||||||
|
inline void SafeCall(Label* to, Condition cond = al);
|
||||||
|
inline void SafeReturn();
|
||||||
|
inline void SafeCallTarget(Label* name);
|
||||||
|
|
||||||
|
// Pushes the value of a register on the backtrack stack. Decrements the
|
||||||
|
// stack pointer by a word size and stores the register's value there.
|
||||||
|
inline void Push(Register source);
|
||||||
|
|
||||||
|
// Pops a value from the backtrack stack. Reads the word at the stack pointer
|
||||||
|
// and increments it by a word size.
|
||||||
|
inline void Pop(Register target);
|
||||||
|
|
||||||
|
// Before calling a C-function from generated code, align arguments on stack.
|
||||||
|
// After aligning the frame, non-register arguments must be stored in
|
||||||
|
// sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
|
||||||
|
// are word sized.
|
||||||
|
// Some compilers/platforms require the stack to be aligned when calling
|
||||||
|
// C++ code.
|
||||||
|
// Needs a scratch register to do some arithmetic. This register will be
|
||||||
|
// trashed.
|
||||||
|
inline void FrameAlign(int num_arguments, Register scratch);
|
||||||
|
|
||||||
|
// Calls a C function and cleans up the space for arguments allocated
|
||||||
|
// by FrameAlign. The called function is not allowed to trigger a garbage
|
||||||
|
// collection.
|
||||||
|
inline void CallCFunction(ExternalReference function,
|
||||||
|
int num_arguments);
|
||||||
|
|
||||||
|
// Calls a C function and cleans up the frame alignment done by
|
||||||
|
// by FrameAlign. The called function *is* allowed to trigger a garbage
|
||||||
|
// collection, but may not take more than four arguments (no arguments
|
||||||
|
// passed on the stack), and the first argument will be a pointer to the
|
||||||
|
// return address.
|
||||||
|
inline void CallCFunctionUsingStub(ExternalReference function,
|
||||||
|
int num_arguments);
|
||||||
|
|
||||||
|
|
||||||
|
MacroAssembler* masm_;
|
||||||
|
|
||||||
|
// Which mode to generate code for (ASCII or UC16).
|
||||||
|
Mode mode_;
|
||||||
|
|
||||||
|
// One greater than maximal register index actually used.
|
||||||
|
int num_registers_;
|
||||||
|
|
||||||
|
// Number of registers to output at the end (the saved registers
|
||||||
|
// are always 0..num_saved_registers_-1)
|
||||||
|
int num_saved_registers_;
|
||||||
|
|
||||||
|
// Manage a small pre-allocated pool for writing label targets
|
||||||
|
// to for pushing backtrack addresses.
|
||||||
|
int backtrack_constant_pool_offset_;
|
||||||
|
int backtrack_constant_pool_capacity_;
|
||||||
|
|
||||||
|
// Labels used internally.
|
||||||
|
Label entry_label_;
|
||||||
|
Label start_label_;
|
||||||
|
Label success_label_;
|
||||||
|
Label backtrack_label_;
|
||||||
|
Label exit_label_;
|
||||||
|
Label check_preempt_label_;
|
||||||
|
Label stack_overflow_label_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // V8_NATIVE_REGEXP
|
||||||
|
|
||||||
|
|
||||||
}} // namespace v8::internal
|
}} // namespace v8::internal
|
||||||
|
|
||||||
#endif // V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
#endif // V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <cstdarg>
|
||||||
#include "v8.h"
|
#include "v8.h"
|
||||||
|
|
||||||
#include "disasm.h"
|
#include "disasm.h"
|
||||||
@ -598,7 +598,7 @@ uint16_t Simulator::ReadHU(int32_t addr, Instr* instr) {
|
|||||||
uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
|
uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
|
||||||
return *ptr;
|
return *ptr;
|
||||||
}
|
}
|
||||||
PrintF("Unaligned read at %x, pc=%p\n", addr, instr);
|
PrintF("Unaligned unsigned halfword read at %x, pc=%p\n", addr, instr);
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -609,7 +609,7 @@ int16_t Simulator::ReadH(int32_t addr, Instr* instr) {
|
|||||||
int16_t* ptr = reinterpret_cast<int16_t*>(addr);
|
int16_t* ptr = reinterpret_cast<int16_t*>(addr);
|
||||||
return *ptr;
|
return *ptr;
|
||||||
}
|
}
|
||||||
PrintF("Unaligned read at %x\n", addr);
|
PrintF("Unaligned signed halfword read at %x\n", addr);
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -621,7 +621,7 @@ void Simulator::WriteH(int32_t addr, uint16_t value, Instr* instr) {
|
|||||||
*ptr = value;
|
*ptr = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PrintF("Unaligned write at %x, pc=%p\n", addr, instr);
|
PrintF("Unaligned unsigned halfword write at %x, pc=%p\n", addr, instr);
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,7 +632,7 @@ void Simulator::WriteH(int32_t addr, int16_t value, Instr* instr) {
|
|||||||
*ptr = value;
|
*ptr = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PrintF("Unaligned write at %x, pc=%p\n", addr, instr);
|
PrintF("Unaligned halfword write at %x, pc=%p\n", addr, instr);
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1416,8 +1416,12 @@ void Simulator::DecodeType01(Instr* instr) {
|
|||||||
|
|
||||||
case CMN: {
|
case CMN: {
|
||||||
if (instr->HasS()) {
|
if (instr->HasS()) {
|
||||||
Format(instr, "cmn'cond 'rn, 'shift_rm");
|
// Format(instr, "cmn'cond 'rn, 'shift_rm");
|
||||||
Format(instr, "cmn'cond 'rn, 'imm");
|
// Format(instr, "cmn'cond 'rn, 'imm");
|
||||||
|
alu_out = rn_val + shifter_operand;
|
||||||
|
SetNZFlags(alu_out);
|
||||||
|
SetCFlag(!CarryFrom(rn_val, shifter_operand));
|
||||||
|
SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
|
||||||
} else {
|
} else {
|
||||||
ASSERT(type == 0);
|
ASSERT(type == 0);
|
||||||
int rm = instr->RmField();
|
int rm = instr->RmField();
|
||||||
@ -1566,6 +1570,7 @@ void Simulator::DecodeType2(Instr* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void Simulator::DecodeType3(Instr* instr) {
|
void Simulator::DecodeType3(Instr* instr) {
|
||||||
|
ASSERT(instr->Bit(4) == 0);
|
||||||
int rd = instr->RdField();
|
int rd = instr->RdField();
|
||||||
int rn = instr->RnField();
|
int rn = instr->RnField();
|
||||||
int32_t rn_val = get_register(rn);
|
int32_t rn_val = get_register(rn);
|
||||||
@ -1605,7 +1610,12 @@ void Simulator::DecodeType3(Instr* instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (instr->HasB()) {
|
if (instr->HasB()) {
|
||||||
UNIMPLEMENTED();
|
if (instr->HasL()) {
|
||||||
|
uint8_t byte = ReadB(addr);
|
||||||
|
set_register(rd, byte);
|
||||||
|
} else {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (instr->HasL()) {
|
if (instr->HasL()) {
|
||||||
set_register(rd, ReadW(addr, instr));
|
set_register(rd, ReadW(addr, instr));
|
||||||
@ -1630,12 +1640,13 @@ void Simulator::DecodeType4(Instr* instr) {
|
|||||||
|
|
||||||
void Simulator::DecodeType5(Instr* instr) {
|
void Simulator::DecodeType5(Instr* instr) {
|
||||||
// Format(instr, "b'l'cond 'target");
|
// Format(instr, "b'l'cond 'target");
|
||||||
int off = (instr->SImmed24Field() << 2) + 8;
|
int off = (instr->SImmed24Field() << 2);
|
||||||
intptr_t pc = get_pc();
|
intptr_t pc_address = get_pc();
|
||||||
if (instr->HasLink()) {
|
if (instr->HasLink()) {
|
||||||
set_register(lr, pc + Instr::kInstrSize);
|
set_register(lr, pc_address + Instr::kInstrSize);
|
||||||
}
|
}
|
||||||
set_pc(pc+off);
|
int pc_reg = get_register(pc);
|
||||||
|
set_pc(pc_reg + off);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1654,14 +1665,75 @@ void Simulator::DecodeType7(Instr* instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Simulator::DecodeUnconditional(Instr* instr) {
|
||||||
|
if (instr->Bits(7, 4) == 0x0B && instr->Bits(27, 25) == 0 && instr->HasL()) {
|
||||||
|
// Load halfword instruction, either register or immediate offset.
|
||||||
|
int rd = instr->RdField();
|
||||||
|
int rn = instr->RnField();
|
||||||
|
int32_t rn_val = get_register(rn);
|
||||||
|
int32_t addr = 0;
|
||||||
|
int32_t offset;
|
||||||
|
if (instr->Bit(22) == 0) {
|
||||||
|
// Register offset.
|
||||||
|
int rm = instr->RmField();
|
||||||
|
offset = get_register(rm);
|
||||||
|
} else {
|
||||||
|
// Immediate offset
|
||||||
|
offset = instr->Bits(3, 0) + (instr->Bits(11, 8) << 4);
|
||||||
|
}
|
||||||
|
switch (instr->PUField()) {
|
||||||
|
case 0: {
|
||||||
|
// Post index, negative.
|
||||||
|
ASSERT(!instr->HasW());
|
||||||
|
addr = rn_val;
|
||||||
|
rn_val -= offset;
|
||||||
|
set_register(rn, rn_val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
// Post index, positive.
|
||||||
|
ASSERT(!instr->HasW());
|
||||||
|
addr = rn_val;
|
||||||
|
rn_val += offset;
|
||||||
|
set_register(rn, rn_val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
// Pre index or offset, negative.
|
||||||
|
rn_val -= offset;
|
||||||
|
addr = rn_val;
|
||||||
|
if (instr->HasW()) {
|
||||||
|
set_register(rn, rn_val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
// Pre index or offset, positive.
|
||||||
|
rn_val += offset;
|
||||||
|
addr = rn_val;
|
||||||
|
if (instr->HasW()) {
|
||||||
|
set_register(rn, rn_val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// The PU field is a 2-bit field.
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not sign extending, so load as unsigned.
|
||||||
|
uint16_t halfword = ReadH(addr, instr);
|
||||||
|
set_register(rd, halfword);
|
||||||
|
} else {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Executes the current instruction.
|
// Executes the current instruction.
|
||||||
void Simulator::InstructionDecode(Instr* instr) {
|
void Simulator::InstructionDecode(Instr* instr) {
|
||||||
pc_modified_ = false;
|
pc_modified_ = false;
|
||||||
if (instr->ConditionField() == special_condition) {
|
|
||||||
Debugger dbg(this);
|
|
||||||
dbg.Stop(instr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (::v8::internal::FLAG_trace_sim) {
|
if (::v8::internal::FLAG_trace_sim) {
|
||||||
disasm::NameConverter converter;
|
disasm::NameConverter converter;
|
||||||
disasm::Disassembler dasm(converter);
|
disasm::Disassembler dasm(converter);
|
||||||
@ -1671,7 +1743,9 @@ void Simulator::InstructionDecode(Instr* instr) {
|
|||||||
reinterpret_cast<byte*>(instr));
|
reinterpret_cast<byte*>(instr));
|
||||||
PrintF(" 0x%x %s\n", instr, buffer.start());
|
PrintF(" 0x%x %s\n", instr, buffer.start());
|
||||||
}
|
}
|
||||||
if (ConditionallyExecute(instr)) {
|
if (instr->ConditionField() == special_condition) {
|
||||||
|
DecodeUnconditional(instr);
|
||||||
|
} else if (ConditionallyExecute(instr)) {
|
||||||
switch (instr->TypeField()) {
|
switch (instr->TypeField()) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1: {
|
case 1: {
|
||||||
@ -1747,19 +1821,35 @@ void Simulator::Execute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
|
int32_t Simulator::Call(byte* entry, int argument_count, ...) {
|
||||||
int32_t p3, int32_t p4) {
|
va_list parameters;
|
||||||
// Setup parameters
|
va_start(parameters, argument_count);
|
||||||
set_register(r0, p0);
|
// Setup arguments
|
||||||
set_register(r1, p1);
|
|
||||||
set_register(r2, p2);
|
// First four arguments passed in registers.
|
||||||
set_register(r3, p3);
|
ASSERT(argument_count >= 4);
|
||||||
intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp));
|
set_register(r0, va_arg(parameters, int32_t));
|
||||||
*(--stack_pointer) = p4;
|
set_register(r1, va_arg(parameters, int32_t));
|
||||||
set_register(sp, reinterpret_cast<int32_t>(stack_pointer));
|
set_register(r2, va_arg(parameters, int32_t));
|
||||||
|
set_register(r3, va_arg(parameters, int32_t));
|
||||||
|
|
||||||
|
// Remaining arguments passed on stack.
|
||||||
|
int original_stack = get_register(sp);
|
||||||
|
// Compute position of stack on entry to generated code.
|
||||||
|
int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
|
||||||
|
if (OS::ActivationFrameAlignment() != 0) {
|
||||||
|
entry_stack &= -OS::ActivationFrameAlignment();
|
||||||
|
}
|
||||||
|
// Store remaining arguments on stack, from low to high memory.
|
||||||
|
intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
|
||||||
|
for (int i = 4; i < argument_count; i++) {
|
||||||
|
stack_argument[i - 4] = va_arg(parameters, int32_t);
|
||||||
|
}
|
||||||
|
va_end(parameters);
|
||||||
|
set_register(sp, entry_stack);
|
||||||
|
|
||||||
// Prepare to execute the code at entry
|
// Prepare to execute the code at entry
|
||||||
set_register(pc, entry);
|
set_register(pc, reinterpret_cast<int32_t>(entry));
|
||||||
// Put down marker for end of simulation. The simulator will stop simulation
|
// Put down marker for end of simulation. The simulator will stop simulation
|
||||||
// when the PC reaches this value. By saving the "end simulation" value into
|
// when the PC reaches this value. By saving the "end simulation" value into
|
||||||
// the LR the simulation stops when returning to this call point.
|
// the LR the simulation stops when returning to this call point.
|
||||||
@ -1793,14 +1883,14 @@ Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
|
|||||||
Execute();
|
Execute();
|
||||||
|
|
||||||
// Check that the callee-saved registers have been preserved.
|
// Check that the callee-saved registers have been preserved.
|
||||||
CHECK_EQ(get_register(r4), callee_saved_value);
|
CHECK_EQ(callee_saved_value, get_register(r4));
|
||||||
CHECK_EQ(get_register(r5), callee_saved_value);
|
CHECK_EQ(callee_saved_value, get_register(r5));
|
||||||
CHECK_EQ(get_register(r6), callee_saved_value);
|
CHECK_EQ(callee_saved_value, get_register(r6));
|
||||||
CHECK_EQ(get_register(r7), callee_saved_value);
|
CHECK_EQ(callee_saved_value, get_register(r7));
|
||||||
CHECK_EQ(get_register(r8), callee_saved_value);
|
CHECK_EQ(callee_saved_value, get_register(r8));
|
||||||
CHECK_EQ(get_register(r9), callee_saved_value);
|
CHECK_EQ(callee_saved_value, get_register(r9));
|
||||||
CHECK_EQ(get_register(r10), callee_saved_value);
|
CHECK_EQ(callee_saved_value, get_register(r10));
|
||||||
CHECK_EQ(get_register(r11), callee_saved_value);
|
CHECK_EQ(callee_saved_value, get_register(r11));
|
||||||
|
|
||||||
// Restore callee-saved registers with the original value.
|
// Restore callee-saved registers with the original value.
|
||||||
set_register(r4, r4_val);
|
set_register(r4, r4_val);
|
||||||
@ -1812,8 +1902,12 @@ Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
|
|||||||
set_register(r10, r10_val);
|
set_register(r10, r10_val);
|
||||||
set_register(r11, r11_val);
|
set_register(r11, r11_val);
|
||||||
|
|
||||||
int result = get_register(r0);
|
// Pop stack passed arguments.
|
||||||
return reinterpret_cast<Object*>(result);
|
CHECK_EQ(entry_stack, get_register(sp));
|
||||||
|
set_register(sp, original_stack);
|
||||||
|
|
||||||
|
int32_t result = get_register(r0);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} } // namespace assembler::arm
|
} } // namespace assembler::arm
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
// When running without a simulator we call the entry directly.
|
// When running without a simulator we call the entry directly.
|
||||||
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
|
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
|
||||||
reinterpret_cast<Object*>(entry(p0, p1, p2, p3, p4))
|
(entry(p0, p1, p2, p3, p4))
|
||||||
|
|
||||||
// Calculated the stack limit beyond which we will throw stack overflow errors.
|
// Calculated the stack limit beyond which we will throw stack overflow errors.
|
||||||
// This macro must be called from a C++ method. It relies on being able to take
|
// This macro must be called from a C++ method. It relies on being able to take
|
||||||
@ -49,13 +49,20 @@
|
|||||||
#define GENERATED_CODE_STACK_LIMIT(limit) \
|
#define GENERATED_CODE_STACK_LIMIT(limit) \
|
||||||
(reinterpret_cast<uintptr_t>(this) - limit)
|
(reinterpret_cast<uintptr_t>(this) - limit)
|
||||||
|
|
||||||
|
|
||||||
|
// Call the generated regexp code directly. The entry function pointer should
|
||||||
|
// expect seven int/pointer sized arguments and return an int.
|
||||||
|
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
|
||||||
|
entry(p0, p1, p2, p3, p4, p5, p6)
|
||||||
|
|
||||||
#else // defined(__arm__)
|
#else // defined(__arm__)
|
||||||
|
|
||||||
// When running with the simulator transition into simulated execution at this
|
// When running with the simulator transition into simulated execution at this
|
||||||
// point.
|
// point.
|
||||||
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
|
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
|
||||||
assembler::arm::Simulator::current()->Call((int32_t)entry, (int32_t)p0, \
|
reinterpret_cast<Object*>( \
|
||||||
(int32_t)p1, (int32_t)p2, (int32_t)p3, (int32_t)p4)
|
assembler::arm::Simulator::current()->Call(FUNCTION_ADDR(entry), 5, \
|
||||||
|
p0, p1, p2, p3, p4))
|
||||||
|
|
||||||
// The simulator has its own stack. Thus it has a different stack limit from
|
// The simulator has its own stack. Thus it has a different stack limit from
|
||||||
// the C-based native code.
|
// the C-based native code.
|
||||||
@ -63,6 +70,10 @@
|
|||||||
(assembler::arm::Simulator::current()->StackLimit())
|
(assembler::arm::Simulator::current()->StackLimit())
|
||||||
|
|
||||||
|
|
||||||
|
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
|
||||||
|
assembler::arm::Simulator::current()->Call( \
|
||||||
|
FUNCTION_ADDR(entry), 7, p0, p1, p2, p3, p4, p5, p6)
|
||||||
|
|
||||||
#include "constants-arm.h"
|
#include "constants-arm.h"
|
||||||
|
|
||||||
|
|
||||||
@ -109,11 +120,10 @@ class Simulator {
|
|||||||
// Call on program start.
|
// Call on program start.
|
||||||
static void Initialize();
|
static void Initialize();
|
||||||
|
|
||||||
// V8 generally calls into generated code with 5 parameters. This is a
|
// V8 generally calls into generated JS code with 5 parameters and into
|
||||||
// convenience function, which sets up the simulator state and grabs the
|
// generated RegExp code with 7 parameters. This is a convenience function,
|
||||||
// result on return.
|
// which sets up the simulator state and grabs the result on return.
|
||||||
v8::internal::Object* Call(int32_t entry, int32_t p0, int32_t p1,
|
int32_t Call(byte* entry, int argument_count, ...);
|
||||||
int32_t p2, int32_t p3, int32_t p4);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum special_values {
|
enum special_values {
|
||||||
@ -174,6 +184,7 @@ class Simulator {
|
|||||||
void DecodeType5(Instr* instr);
|
void DecodeType5(Instr* instr);
|
||||||
void DecodeType6(Instr* instr);
|
void DecodeType6(Instr* instr);
|
||||||
void DecodeType7(Instr* instr);
|
void DecodeType7(Instr* instr);
|
||||||
|
void DecodeUnconditional(Instr* instr);
|
||||||
|
|
||||||
// Executes one instruction.
|
// Executes one instruction.
|
||||||
void InstructionDecode(Instr* instr);
|
void InstructionDecode(Instr* instr);
|
||||||
|
@ -42,6 +42,20 @@
|
|||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "stub-cache.h"
|
#include "stub-cache.h"
|
||||||
#include "regexp-stack.h"
|
#include "regexp-stack.h"
|
||||||
|
#include "ast.h"
|
||||||
|
#include "regexp-macro-assembler.h"
|
||||||
|
// Include native regexp-macro-assembler.
|
||||||
|
#ifdef V8_NATIVE_REGEXP
|
||||||
|
#if V8_TARGET_ARCH_IA32
|
||||||
|
#include "ia32/regexp-macro-assembler-ia32.h"
|
||||||
|
#elif V8_TARGET_ARCH_X64
|
||||||
|
#include "x64/regexp-macro-assembler-x64.h"
|
||||||
|
#elif V8_TARGET_ARCH_ARM
|
||||||
|
#include "arm/regexp-macro-assembler-arm.h"
|
||||||
|
#else // Unknown architecture.
|
||||||
|
#error "Unknown architecture."
|
||||||
|
#endif // Target architecture.
|
||||||
|
#endif // V8_NATIVE_REGEXP
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -597,6 +611,34 @@ ExternalReference ExternalReference::new_space_allocation_limit_address() {
|
|||||||
return ExternalReference(Heap::NewSpaceAllocationLimitAddress());
|
return ExternalReference(Heap::NewSpaceAllocationLimitAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef V8_NATIVE_REGEXP
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::re_check_stack_guard_state() {
|
||||||
|
Address function;
|
||||||
|
#ifdef V8_TARGET_ARCH_X64
|
||||||
|
function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
|
||||||
|
#elif V8_TARGET_ARCH_IA32
|
||||||
|
function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
|
||||||
|
#elif V8_TARGET_ARCH_ARM
|
||||||
|
function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
|
||||||
|
#else
|
||||||
|
UNREACHABLE("Unexpected architecture");
|
||||||
|
#endif
|
||||||
|
return ExternalReference(Redirect(function));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::re_grow_stack() {
|
||||||
|
return ExternalReference(
|
||||||
|
Redirect(FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalReference ExternalReference::re_case_insensitive_compare_uc16() {
|
||||||
|
return ExternalReference(Redirect(
|
||||||
|
FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static double add_two_doubles(double x, double y) {
|
static double add_two_doubles(double x, double y) {
|
||||||
return x + y;
|
return x + y;
|
||||||
|
@ -431,6 +431,19 @@ class ExternalReference BASE_EMBEDDED {
|
|||||||
static ExternalReference debug_step_in_fp_address();
|
static ExternalReference debug_step_in_fp_address();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef V8_NATIVE_REGEXP
|
||||||
|
// C functions called from RegExp generated code.
|
||||||
|
|
||||||
|
// Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()
|
||||||
|
static ExternalReference re_case_insensitive_compare_uc16();
|
||||||
|
|
||||||
|
// Function RegExpMacroAssembler*::CheckStackGuardState()
|
||||||
|
static ExternalReference re_check_stack_guard_state();
|
||||||
|
|
||||||
|
// Function NativeRegExpMacroAssembler::GrowStack()
|
||||||
|
static ExternalReference re_grow_stack();
|
||||||
|
#endif
|
||||||
|
|
||||||
// This lets you register a function that rewrites all external references.
|
// This lets you register a function that rewrites all external references.
|
||||||
// Used by the ARM simulator to catch calls to external references.
|
// Used by the ARM simulator to catch calls to external references.
|
||||||
static void set_redirector(ExternalReferenceRedirector* redirector) {
|
static void set_redirector(ExternalReferenceRedirector* redirector) {
|
||||||
|
@ -57,6 +57,7 @@ class CodeStub BASE_EMBEDDED {
|
|||||||
SetProperty, // ARM only
|
SetProperty, // ARM only
|
||||||
InvokeBuiltin, // ARM only
|
InvokeBuiltin, // ARM only
|
||||||
JSExit, // ARM only
|
JSExit, // ARM only
|
||||||
|
RegExpCEntry, // ARM only
|
||||||
NUMBER_OF_IDS
|
NUMBER_OF_IDS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,7 +47,14 @@ namespace internal {
|
|||||||
#define V8_HOST_ARCH_ARM 1
|
#define V8_HOST_ARCH_ARM 1
|
||||||
#define V8_HOST_ARCH_32_BIT 1
|
#define V8_HOST_ARCH_32_BIT 1
|
||||||
#else
|
#else
|
||||||
#error Your architecture was not detected as supported by v8
|
#error Your host architecture was not detected as supported by v8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_IA32)
|
||||||
|
#define V8_TARGET_CAN_READ_UNALIGNED 1
|
||||||
|
#elif V8_TARGET_ARCH_ARM
|
||||||
|
#else
|
||||||
|
#error Your target architecture is not supported by v8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Support for alternative bool type. This is only enabled if the code is
|
// Support for alternative bool type. This is only enabled if the code is
|
||||||
|
14
src/heap.cc
14
src/heap.cc
@ -39,6 +39,9 @@
|
|||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "scopeinfo.h"
|
#include "scopeinfo.h"
|
||||||
#include "v8threads.h"
|
#include "v8threads.h"
|
||||||
|
#if V8_TARGET_ARCH_ARM && V8_NATIVE_REGEXP
|
||||||
|
#include "regexp-macro-assembler.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -1320,6 +1323,14 @@ void Heap::CreateCEntryStub() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if V8_TARGET_ARCH_ARM && V8_NATIVE_REGEXP
|
||||||
|
void Heap::CreateRegExpCEntryStub() {
|
||||||
|
RegExpCEntryStub stub;
|
||||||
|
set_re_c_entry_code(*stub.GetCode());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void Heap::CreateCEntryDebugBreakStub() {
|
void Heap::CreateCEntryDebugBreakStub() {
|
||||||
CEntryDebugBreakStub stub;
|
CEntryDebugBreakStub stub;
|
||||||
set_c_entry_debug_break_code(*stub.GetCode());
|
set_c_entry_debug_break_code(*stub.GetCode());
|
||||||
@ -1356,6 +1367,9 @@ void Heap::CreateFixedStubs() {
|
|||||||
Heap::CreateCEntryDebugBreakStub();
|
Heap::CreateCEntryDebugBreakStub();
|
||||||
Heap::CreateJSEntryStub();
|
Heap::CreateJSEntryStub();
|
||||||
Heap::CreateJSConstructEntryStub();
|
Heap::CreateJSConstructEntryStub();
|
||||||
|
#if V8_TARGET_ARCH_ARM && V8_NATIVE_REGEXP
|
||||||
|
Heap::CreateRegExpCEntryStub();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
11
src/heap.h
11
src/heap.h
@ -34,7 +34,7 @@ namespace v8 {
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Defines all the roots in Heap.
|
// Defines all the roots in Heap.
|
||||||
#define STRONG_ROOT_LIST(V) \
|
#define UNCONDITIONAL_STRONG_ROOT_LIST(V) \
|
||||||
/* Cluster the most popular ones in a few cache lines here at the top. */ \
|
/* Cluster the most popular ones in a few cache lines here at the top. */ \
|
||||||
V(Smi, stack_limit, StackLimit) \
|
V(Smi, stack_limit, StackLimit) \
|
||||||
V(Object, undefined_value, UndefinedValue) \
|
V(Object, undefined_value, UndefinedValue) \
|
||||||
@ -136,6 +136,13 @@ namespace internal {
|
|||||||
V(FixedArray, natives_source_cache, NativesSourceCache) \
|
V(FixedArray, natives_source_cache, NativesSourceCache) \
|
||||||
V(Object, last_script_id, LastScriptId) \
|
V(Object, last_script_id, LastScriptId) \
|
||||||
|
|
||||||
|
#if V8_TARGET_ARCH_ARM && V8_NATIVE_REGEXP
|
||||||
|
#define STRONG_ROOT_LIST(V) \
|
||||||
|
UNCONDITIONAL_STRONG_ROOT_LIST(V) \
|
||||||
|
V(Code, re_c_entry_code, RegExpCEntryCode)
|
||||||
|
#else
|
||||||
|
#define STRONG_ROOT_LIST(V) UNCONDITIONAL_STRONG_ROOT_LIST(V)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ROOT_LIST(V) \
|
#define ROOT_LIST(V) \
|
||||||
STRONG_ROOT_LIST(V) \
|
STRONG_ROOT_LIST(V) \
|
||||||
@ -1025,6 +1032,8 @@ class Heap : public AllStatic {
|
|||||||
static void CreateCEntryDebugBreakStub();
|
static void CreateCEntryDebugBreakStub();
|
||||||
static void CreateJSEntryStub();
|
static void CreateJSEntryStub();
|
||||||
static void CreateJSConstructEntryStub();
|
static void CreateJSConstructEntryStub();
|
||||||
|
static void CreateRegExpCEntryStub();
|
||||||
|
|
||||||
static void CreateFixedStubs();
|
static void CreateFixedStubs();
|
||||||
|
|
||||||
static Object* CreateOddball(Map* map,
|
static Object* CreateOddball(Map* map,
|
||||||
|
@ -102,6 +102,7 @@ RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(
|
|||||||
success_label_(),
|
success_label_(),
|
||||||
backtrack_label_(),
|
backtrack_label_(),
|
||||||
exit_label_() {
|
exit_label_() {
|
||||||
|
ASSERT_EQ(0, registers_to_save % 2);
|
||||||
__ jmp(&entry_label_); // We'll write the entry code later.
|
__ jmp(&entry_label_); // We'll write the entry code later.
|
||||||
__ bind(&start_label_); // And then continue from here.
|
__ bind(&start_label_); // And then continue from here.
|
||||||
}
|
}
|
||||||
@ -337,8 +338,9 @@ void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
|
|||||||
__ add(edx, Operand(esi));
|
__ add(edx, Operand(esi));
|
||||||
__ mov(Operand(esp, 0 * kPointerSize), edx);
|
__ mov(Operand(esp, 0 * kPointerSize), edx);
|
||||||
|
|
||||||
Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16);
|
ExternalReference compare =
|
||||||
CallCFunction(function_address, argument_count);
|
ExternalReference::re_case_insensitive_compare_uc16();
|
||||||
|
CallCFunction(compare, argument_count);
|
||||||
// Pop original values before reacting on result value.
|
// Pop original values before reacting on result value.
|
||||||
__ pop(ebx);
|
__ pop(ebx);
|
||||||
__ pop(backtrack_stackpointer());
|
__ pop(backtrack_stackpointer());
|
||||||
@ -745,7 +747,8 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
|
|||||||
__ lea(eax, Operand(ebp, kStackHighEnd));
|
__ lea(eax, Operand(ebp, kStackHighEnd));
|
||||||
__ mov(Operand(esp, 1 * kPointerSize), eax);
|
__ mov(Operand(esp, 1 * kPointerSize), eax);
|
||||||
__ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
|
__ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
|
||||||
CallCFunction(FUNCTION_ADDR(&GrowStack), num_arguments);
|
ExternalReference grow_stack = ExternalReference::re_grow_stack();
|
||||||
|
CallCFunction(grow_stack, num_arguments);
|
||||||
// If return NULL, we have failed to grow the stack, and
|
// If return NULL, we have failed to grow the stack, and
|
||||||
// must exit with a stack-overflow exception.
|
// must exit with a stack-overflow exception.
|
||||||
__ or_(eax, Operand(eax));
|
__ or_(eax, Operand(eax));
|
||||||
@ -817,7 +820,9 @@ void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset,
|
|||||||
int characters) {
|
int characters) {
|
||||||
ASSERT(cp_offset >= -1); // ^ and \b can look behind one character.
|
ASSERT(cp_offset >= -1); // ^ and \b can look behind one character.
|
||||||
ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
|
ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
|
||||||
CheckPosition(cp_offset + characters - 1, on_end_of_input);
|
if (check_bounds) {
|
||||||
|
CheckPosition(cp_offset + characters - 1, on_end_of_input);
|
||||||
|
}
|
||||||
LoadCurrentCharacterUnchecked(cp_offset, characters);
|
LoadCurrentCharacterUnchecked(cp_offset, characters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,7 +918,9 @@ void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
|
|||||||
// Next address on the stack (will be address of return address).
|
// Next address on the stack (will be address of return address).
|
||||||
__ lea(eax, Operand(esp, -kPointerSize));
|
__ lea(eax, Operand(esp, -kPointerSize));
|
||||||
__ mov(Operand(esp, 0 * kPointerSize), eax);
|
__ mov(Operand(esp, 0 * kPointerSize), eax);
|
||||||
CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments);
|
ExternalReference check_stack_guard =
|
||||||
|
ExternalReference::re_check_stack_guard_state();
|
||||||
|
CallCFunction(check_stack_guard, num_arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -996,22 +1003,6 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Address RegExpMacroAssemblerIA32::GrowStack(Address stack_pointer,
|
|
||||||
Address* stack_base) {
|
|
||||||
size_t size = RegExpStack::stack_capacity();
|
|
||||||
Address old_stack_base = RegExpStack::stack_base();
|
|
||||||
ASSERT(old_stack_base == *stack_base);
|
|
||||||
ASSERT(stack_pointer <= old_stack_base);
|
|
||||||
ASSERT(static_cast<size_t>(old_stack_base - stack_pointer) <= size);
|
|
||||||
Address new_stack_base = RegExpStack::EnsureCapacity(size * 2);
|
|
||||||
if (new_stack_base == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*stack_base = new_stack_base;
|
|
||||||
return new_stack_base - (old_stack_base - stack_pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
|
Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
|
||||||
ASSERT(register_index < (1<<30));
|
ASSERT(register_index < (1<<30));
|
||||||
if (num_registers_ <= register_index) {
|
if (num_registers_ <= register_index) {
|
||||||
@ -1135,9 +1126,9 @@ void RegExpMacroAssemblerIA32::FrameAlign(int num_arguments, Register scratch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerIA32::CallCFunction(Address function_address,
|
void RegExpMacroAssemblerIA32::CallCFunction(ExternalReference function,
|
||||||
int num_arguments) {
|
int num_arguments) {
|
||||||
__ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(function_address)));
|
__ mov(Operand(eax), Immediate(function));
|
||||||
__ call(Operand(eax));
|
__ call(Operand(eax));
|
||||||
if (OS::ActivationFrameAlignment() != 0) {
|
if (OS::ActivationFrameAlignment() != 0) {
|
||||||
__ mov(esp, Operand(esp, num_arguments * kPointerSize));
|
__ mov(esp, Operand(esp, num_arguments * kPointerSize));
|
||||||
@ -1172,6 +1163,10 @@ void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RegExpCEntryStub::Generate(MacroAssembler* masm_) {
|
||||||
|
__ int3(); // Unused on ia32.
|
||||||
|
}
|
||||||
|
|
||||||
#undef __
|
#undef __
|
||||||
|
|
||||||
#endif // V8_NATIVE_REGEXP
|
#endif // V8_NATIVE_REGEXP
|
||||||
|
@ -107,6 +107,13 @@ class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler {
|
|||||||
virtual void ClearRegisters(int reg_from, int reg_to);
|
virtual void ClearRegisters(int reg_from, int reg_to);
|
||||||
virtual void WriteStackPointerToRegister(int reg);
|
virtual void WriteStackPointerToRegister(int reg);
|
||||||
|
|
||||||
|
// Called from RegExp if the stack-guard is triggered.
|
||||||
|
// If the code object is relocated, the return address is fixed before
|
||||||
|
// returning.
|
||||||
|
static int CheckStackGuardState(Address* return_address,
|
||||||
|
Code* re_code,
|
||||||
|
Address re_frame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Offsets from ebp of function parameters and stored registers.
|
// Offsets from ebp of function parameters and stored registers.
|
||||||
static const int kFramePointer = 0;
|
static const int kFramePointer = 0;
|
||||||
@ -144,23 +151,9 @@ class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler {
|
|||||||
// Check whether we are exceeding the stack limit on the backtrack stack.
|
// Check whether we are exceeding the stack limit on the backtrack stack.
|
||||||
void CheckStackLimit();
|
void CheckStackLimit();
|
||||||
|
|
||||||
// Called from RegExp if the stack-guard is triggered.
|
|
||||||
// If the code object is relocated, the return address is fixed before
|
|
||||||
// returning.
|
|
||||||
static int CheckStackGuardState(Address* return_address,
|
|
||||||
Code* re_code,
|
|
||||||
Address re_frame);
|
|
||||||
|
|
||||||
// Generate a call to CheckStackGuardState.
|
// Generate a call to CheckStackGuardState.
|
||||||
void CallCheckStackGuardState(Register scratch);
|
void CallCheckStackGuardState(Register scratch);
|
||||||
|
|
||||||
// Called from RegExp if the backtrack stack limit is hit.
|
|
||||||
// Tries to expand the stack. Returns the new stack-pointer if
|
|
||||||
// successful, and updates the stack_top address, or returns 0 if unable
|
|
||||||
// to grow the stack.
|
|
||||||
// This function must not trigger a garbage collection.
|
|
||||||
static Address GrowStack(Address stack_pointer, Address* stack_top);
|
|
||||||
|
|
||||||
// The ebp-relative location of a regexp register.
|
// The ebp-relative location of a regexp register.
|
||||||
Operand register_location(int register_index);
|
Operand register_location(int register_index);
|
||||||
|
|
||||||
@ -209,7 +202,7 @@ class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler {
|
|||||||
// by FrameAlign. The called function is not allowed to trigger a garbage
|
// by FrameAlign. The called function is not allowed to trigger a garbage
|
||||||
// collection, since that might move the code and invalidate the return
|
// collection, since that might move the code and invalidate the return
|
||||||
// address (unless this is somehow accounted for).
|
// address (unless this is somehow accounted for).
|
||||||
inline void CallCFunction(Address function_address, int num_arguments);
|
inline void CallCFunction(ExternalReference function, int num_arguments);
|
||||||
|
|
||||||
MacroAssembler* masm_;
|
MacroAssembler* masm_;
|
||||||
|
|
||||||
|
@ -44,4 +44,9 @@
|
|||||||
(reinterpret_cast<uintptr_t>(this) >= limit ? \
|
(reinterpret_cast<uintptr_t>(this) >= limit ? \
|
||||||
reinterpret_cast<uintptr_t>(this) - limit : 0)
|
reinterpret_cast<uintptr_t>(this) - limit : 0)
|
||||||
|
|
||||||
|
// Call the generated regexp code directly. The entry function pointer should
|
||||||
|
// expect seven int/pointer sized arguments and return an int.
|
||||||
|
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
|
||||||
|
entry(p0, p1, p2, p3, p4, p5, p6)
|
||||||
|
|
||||||
#endif // V8_IA32_SIMULATOR_IA32_H_
|
#endif // V8_IA32_SIMULATOR_IA32_H_
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include "x64/macro-assembler-x64.h"
|
#include "x64/macro-assembler-x64.h"
|
||||||
#include "x64/regexp-macro-assembler-x64.h"
|
#include "x64/regexp-macro-assembler-x64.h"
|
||||||
#elif V8_TARGET_ARCH_ARM
|
#elif V8_TARGET_ARCH_ARM
|
||||||
|
#include "arm/macro-assembler-arm.h"
|
||||||
#include "arm/regexp-macro-assembler-arm.h"
|
#include "arm/regexp-macro-assembler-arm.h"
|
||||||
#else
|
#else
|
||||||
#error Unsupported target architecture.
|
#error Unsupported target architecture.
|
||||||
@ -419,9 +420,7 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
|
|||||||
Handle<FixedArray> regexp(FixedArray::cast(jsregexp->data()));
|
Handle<FixedArray> regexp(FixedArray::cast(jsregexp->data()));
|
||||||
|
|
||||||
#ifdef V8_NATIVE_REGEXP
|
#ifdef V8_NATIVE_REGEXP
|
||||||
#ifdef V8_TARGET_ARCH_ARM
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
#else // Native regexp supported.
|
|
||||||
OffsetsVector captures(number_of_capture_registers);
|
OffsetsVector captures(number_of_capture_registers);
|
||||||
int* captures_vector = captures.vector();
|
int* captures_vector = captures.vector();
|
||||||
NativeRegExpMacroAssembler::Result res;
|
NativeRegExpMacroAssembler::Result res;
|
||||||
@ -455,9 +454,9 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
|
|||||||
SetCapture(*array, i, captures_vector[i]);
|
SetCapture(*array, i, captures_vector[i]);
|
||||||
SetCapture(*array, i + 1, captures_vector[i + 1]);
|
SetCapture(*array, i + 1, captures_vector[i + 1]);
|
||||||
}
|
}
|
||||||
#endif // Native regexp supported.
|
|
||||||
|
|
||||||
#else // ! V8_NATIVE_REGEXP
|
#else // ! V8_NATIVE_REGEXP
|
||||||
|
|
||||||
bool is_ascii = subject->IsAsciiRepresentation();
|
bool is_ascii = subject->IsAsciiRepresentation();
|
||||||
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
|
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
|
||||||
return Handle<Object>::null();
|
return Handle<Object>::null();
|
||||||
@ -487,6 +486,7 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
|
|||||||
SetCapture(*array, i, register_vector[i]);
|
SetCapture(*array, i, register_vector[i]);
|
||||||
SetCapture(*array, i + 1, register_vector[i + 1]);
|
SetCapture(*array, i + 1, register_vector[i + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // V8_NATIVE_REGEXP
|
#endif // V8_NATIVE_REGEXP
|
||||||
|
|
||||||
SetLastCaptureCount(*array, number_of_capture_registers);
|
SetLastCaptureCount(*array, number_of_capture_registers);
|
||||||
@ -1723,6 +1723,8 @@ bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
|
|||||||
GetQuickCheckDetails(details, compiler, 0, trace->at_start() == Trace::FALSE);
|
GetQuickCheckDetails(details, compiler, 0, trace->at_start() == Trace::FALSE);
|
||||||
if (details->cannot_match()) return false;
|
if (details->cannot_match()) return false;
|
||||||
if (!details->Rationalize(compiler->ascii())) return false;
|
if (!details->Rationalize(compiler->ascii())) return false;
|
||||||
|
if (details->characters() > 1 &&
|
||||||
|
!compiler->macro_assembler()->CanReadUnaligned()) return false;
|
||||||
uint32_t mask = details->mask();
|
uint32_t mask = details->mask();
|
||||||
uint32_t value = details->value();
|
uint32_t value = details->value();
|
||||||
|
|
||||||
@ -2522,20 +2524,20 @@ void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
|||||||
|
|
||||||
int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) {
|
int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) {
|
||||||
int preload_characters = EatsAtLeast(4, 0);
|
int preload_characters = EatsAtLeast(4, 0);
|
||||||
#ifdef V8_HOST_CAN_READ_UNALIGNED
|
if (compiler->macro_assembler()->CanReadUnaligned()) {
|
||||||
bool ascii = compiler->ascii();
|
bool ascii = compiler->ascii();
|
||||||
if (ascii) {
|
if (ascii) {
|
||||||
if (preload_characters > 4) preload_characters = 4;
|
if (preload_characters > 4) preload_characters = 4;
|
||||||
// We can't preload 3 characters because there is no machine instruction
|
// We can't preload 3 characters because there is no machine instruction
|
||||||
// to do that. We can't just load 4 because we could be reading
|
// to do that. We can't just load 4 because we could be reading
|
||||||
// beyond the end of the string, which could cause a memory fault.
|
// beyond the end of the string, which could cause a memory fault.
|
||||||
if (preload_characters == 3) preload_characters = 2;
|
if (preload_characters == 3) preload_characters = 2;
|
||||||
|
} else {
|
||||||
|
if (preload_characters > 2) preload_characters = 2;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (preload_characters > 2) preload_characters = 2;
|
if (preload_characters > 1) preload_characters = 1;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (preload_characters > 1) preload_characters = 1;
|
|
||||||
#endif
|
|
||||||
return preload_characters;
|
return preload_characters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4470,16 +4472,12 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
|
|||||||
is_ascii ? NativeRegExpMacroAssembler::ASCII
|
is_ascii ? NativeRegExpMacroAssembler::ASCII
|
||||||
: NativeRegExpMacroAssembler::UC16;
|
: NativeRegExpMacroAssembler::UC16;
|
||||||
|
|
||||||
#ifdef V8_TARGET_ARCH_IA32
|
#if V8_TARGET_ARCH_IA32
|
||||||
RegExpMacroAssemblerIA32 macro_assembler(mode,
|
RegExpMacroAssemblerIA32 macro_assembler(mode, (data->capture_count + 1) * 2);
|
||||||
(data->capture_count + 1) * 2);
|
#elif V8_TARGET_ARCH_X64
|
||||||
#endif
|
RegExpMacroAssemblerX64 macro_assembler(mode, (data->capture_count + 1) * 2);
|
||||||
#ifdef V8_TARGET_ARCH_X64
|
#elif V8_TARGET_ARCH_ARM
|
||||||
RegExpMacroAssemblerX64 macro_assembler(mode,
|
RegExpMacroAssemblerARM macro_assembler(mode, (data->capture_count + 1) * 2);
|
||||||
(data->capture_count + 1) * 2);
|
|
||||||
#endif
|
|
||||||
#ifdef V8_TARGET_ARCH_ARM
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else // ! V8_NATIVE_REGEXP
|
#else // ! V8_NATIVE_REGEXP
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
#ifndef V8_NATIVE_REGEXP
|
||||||
|
|
||||||
void RegExpMacroAssemblerIrregexp::Emit(uint32_t byte,
|
void RegExpMacroAssemblerIrregexp::Emit(uint32_t byte,
|
||||||
uint32_t twenty_four_bits) {
|
uint32_t twenty_four_bits) {
|
||||||
@ -70,6 +71,7 @@ void RegExpMacroAssemblerIrregexp::Emit32(uint32_t word) {
|
|||||||
pc_ += 4;
|
pc_ += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // ! V8_NATIVE_REGEXP
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
#ifndef V8_NATIVE_REGEXP
|
||||||
|
|
||||||
RegExpMacroAssemblerIrregexp::RegExpMacroAssemblerIrregexp(Vector<byte> buffer)
|
RegExpMacroAssemblerIrregexp::RegExpMacroAssemblerIrregexp(Vector<byte> buffer)
|
||||||
: buffer_(buffer),
|
: buffer_(buffer),
|
||||||
@ -458,5 +459,6 @@ void RegExpMacroAssemblerIrregexp::Expand() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // !V8_NATIVE_REGEXP
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
#ifndef V8_NATIVE_REGEXP
|
||||||
|
|
||||||
class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
|
class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
|
||||||
public:
|
public:
|
||||||
@ -133,6 +134,8 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
|
|||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(RegExpMacroAssemblerIrregexp);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(RegExpMacroAssemblerIrregexp);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // !V8_NATIVE_REGEXP
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
|
||||||
#endif // V8_REGEXP_MACRO_ASSEMBLER_IRREGEXP_H_
|
#endif // V8_REGEXP_MACRO_ASSEMBLER_IRREGEXP_H_
|
||||||
|
@ -37,7 +37,7 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
|
|||||||
explicit RegExpMacroAssemblerTracer(RegExpMacroAssembler* assembler);
|
explicit RegExpMacroAssemblerTracer(RegExpMacroAssembler* assembler);
|
||||||
virtual ~RegExpMacroAssemblerTracer();
|
virtual ~RegExpMacroAssemblerTracer();
|
||||||
virtual int stack_limit_slack() { return assembler_->stack_limit_slack(); }
|
virtual int stack_limit_slack() { return assembler_->stack_limit_slack(); }
|
||||||
|
virtual bool CanReadUnaligned() { return assembler_->CanReadUnaligned(); }
|
||||||
virtual void AdvanceCurrentPosition(int by); // Signed cp change.
|
virtual void AdvanceCurrentPosition(int by); // Signed cp change.
|
||||||
virtual void AdvanceRegister(int reg, int by); // r[reg] += by.
|
virtual void AdvanceRegister(int reg, int by); // r[reg] += by.
|
||||||
virtual void Backtrack();
|
virtual void Backtrack();
|
||||||
|
@ -30,6 +30,13 @@
|
|||||||
#include "assembler.h"
|
#include "assembler.h"
|
||||||
#include "regexp-stack.h"
|
#include "regexp-stack.h"
|
||||||
#include "regexp-macro-assembler.h"
|
#include "regexp-macro-assembler.h"
|
||||||
|
#if V8_TARGET_ARCH_ARM
|
||||||
|
#include "arm/simulator-arm.h"
|
||||||
|
#elif V8_TARGET_ARCH_IA32
|
||||||
|
#include "ia32/simulator-ia32.h"
|
||||||
|
#elif V8_TARGET_ARCH_X64
|
||||||
|
#include "x64/simulator-x64.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -42,6 +49,15 @@ RegExpMacroAssembler::~RegExpMacroAssembler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RegExpMacroAssembler::CanReadUnaligned() {
|
||||||
|
#ifdef V8_HOST_CAN_READ_UNALIGNED
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef V8_NATIVE_REGEXP // Avoid unused code, e.g., on ARM.
|
#ifdef V8_NATIVE_REGEXP // Avoid unused code, e.g., on ARM.
|
||||||
|
|
||||||
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler() {
|
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler() {
|
||||||
@ -51,6 +67,15 @@ NativeRegExpMacroAssembler::NativeRegExpMacroAssembler() {
|
|||||||
NativeRegExpMacroAssembler::~NativeRegExpMacroAssembler() {
|
NativeRegExpMacroAssembler::~NativeRegExpMacroAssembler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NativeRegExpMacroAssembler::CanReadUnaligned() {
|
||||||
|
#ifdef V8_TARGET_CAN_READ_UNALIGNED
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
const byte* NativeRegExpMacroAssembler::StringCharacterPosition(
|
const byte* NativeRegExpMacroAssembler::StringCharacterPosition(
|
||||||
String* subject,
|
String* subject,
|
||||||
int start_index) {
|
int start_index) {
|
||||||
@ -162,13 +187,14 @@ NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Execute(
|
|||||||
RegExpStack stack;
|
RegExpStack stack;
|
||||||
Address stack_base = RegExpStack::stack_base();
|
Address stack_base = RegExpStack::stack_base();
|
||||||
|
|
||||||
int result = matcher_func(input,
|
int result = CALL_GENERATED_REGEXP_CODE(matcher_func,
|
||||||
start_offset,
|
input,
|
||||||
input_start,
|
start_offset,
|
||||||
input_end,
|
input_start,
|
||||||
output,
|
input_end,
|
||||||
at_start_val,
|
output,
|
||||||
stack_base);
|
at_start_val,
|
||||||
|
stack_base);
|
||||||
ASSERT(result <= SUCCESS);
|
ASSERT(result <= SUCCESS);
|
||||||
ASSERT(result >= RETRY);
|
ASSERT(result >= RETRY);
|
||||||
|
|
||||||
@ -213,5 +239,22 @@ int NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16(
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Address NativeRegExpMacroAssembler::GrowStack(Address stack_pointer,
|
||||||
|
Address* stack_base) {
|
||||||
|
size_t size = RegExpStack::stack_capacity();
|
||||||
|
Address old_stack_base = RegExpStack::stack_base();
|
||||||
|
ASSERT(old_stack_base == *stack_base);
|
||||||
|
ASSERT(stack_pointer <= old_stack_base);
|
||||||
|
ASSERT(static_cast<size_t>(old_stack_base - stack_pointer) <= size);
|
||||||
|
Address new_stack_base = RegExpStack::EnsureCapacity(size * 2);
|
||||||
|
if (new_stack_base == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*stack_base = new_stack_base;
|
||||||
|
intptr_t stack_content_size = old_stack_base - stack_pointer;
|
||||||
|
return new_stack_base - stack_content_size;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // V8_NATIVE_REGEXP
|
#endif // V8_NATIVE_REGEXP
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
@ -61,6 +61,7 @@ class RegExpMacroAssembler {
|
|||||||
// kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck)
|
// kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck)
|
||||||
// at least once for every stack_limit() pushes that are executed.
|
// at least once for every stack_limit() pushes that are executed.
|
||||||
virtual int stack_limit_slack() = 0;
|
virtual int stack_limit_slack() = 0;
|
||||||
|
virtual bool CanReadUnaligned();
|
||||||
virtual void AdvanceCurrentPosition(int by) = 0; // Signed cp change.
|
virtual void AdvanceCurrentPosition(int by) = 0; // Signed cp change.
|
||||||
virtual void AdvanceRegister(int reg, int by) = 0; // r[reg] += by.
|
virtual void AdvanceRegister(int reg, int by) = 0; // r[reg] += by.
|
||||||
// Continues execution from the position pushed on the top of the backtrack
|
// Continues execution from the position pushed on the top of the backtrack
|
||||||
@ -182,6 +183,7 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
|
|||||||
|
|
||||||
NativeRegExpMacroAssembler();
|
NativeRegExpMacroAssembler();
|
||||||
virtual ~NativeRegExpMacroAssembler();
|
virtual ~NativeRegExpMacroAssembler();
|
||||||
|
virtual bool CanReadUnaligned();
|
||||||
|
|
||||||
static Result Match(Handle<Code> regexp,
|
static Result Match(Handle<Code> regexp,
|
||||||
Handle<String> subject,
|
Handle<String> subject,
|
||||||
@ -195,6 +197,13 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
|
|||||||
Address byte_offset2,
|
Address byte_offset2,
|
||||||
size_t byte_length);
|
size_t byte_length);
|
||||||
|
|
||||||
|
// Called from RegExp if the backtrack stack limit is hit.
|
||||||
|
// Tries to expand the stack. Returns the new stack-pointer if
|
||||||
|
// successful, and updates the stack_top address, or returns 0 if unable
|
||||||
|
// to grow the stack.
|
||||||
|
// This function must not trigger a garbage collection.
|
||||||
|
static Address GrowStack(Address stack_pointer, Address* stack_top);
|
||||||
|
|
||||||
static const byte* StringCharacterPosition(String* subject, int start_index);
|
static const byte* StringCharacterPosition(String* subject, int start_index);
|
||||||
|
|
||||||
static Result Execute(Code* code,
|
static Result Execute(Code* code,
|
||||||
@ -205,7 +214,25 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
|
|||||||
int* output,
|
int* output,
|
||||||
bool at_start);
|
bool at_start);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Enter C code from generated RegExp code in a way that allows
|
||||||
|
// the C code to fix the return address in case of a GC.
|
||||||
|
// Currently only needed on ARM.
|
||||||
|
class RegExpCEntryStub: public CodeStub {
|
||||||
|
public:
|
||||||
|
RegExpCEntryStub() {}
|
||||||
|
virtual ~RegExpCEntryStub() {}
|
||||||
|
void Generate(MacroAssembler* masm);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Major MajorKey() { return RegExpCEntry; }
|
||||||
|
int MinorKey() { return 0; }
|
||||||
|
const char* GetName() { return "RegExpCEntryStub"; }
|
||||||
|
};
|
||||||
|
|
||||||
#endif // V8_NATIVE_REGEXP
|
#endif // V8_NATIVE_REGEXP
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
|
||||||
#endif // V8_REGEXP_MACRO_ASSEMBLER_H_
|
#endif // V8_REGEXP_MACRO_ASSEMBLER_H_
|
||||||
|
@ -734,6 +734,20 @@ void ExternalReferenceTable::PopulateTable() {
|
|||||||
UNCLASSIFIED,
|
UNCLASSIFIED,
|
||||||
17,
|
17,
|
||||||
"compare_doubles");
|
"compare_doubles");
|
||||||
|
#ifdef V8_NATIVE_REGEXP
|
||||||
|
Add(ExternalReference::re_case_insensitive_compare_uc16().address(),
|
||||||
|
UNCLASSIFIED,
|
||||||
|
18,
|
||||||
|
"NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()");
|
||||||
|
Add(ExternalReference::re_check_stack_guard_state().address(),
|
||||||
|
UNCLASSIFIED,
|
||||||
|
19,
|
||||||
|
"RegExpMacroAssembler*::CheckStackGuardState()");
|
||||||
|
Add(ExternalReference::re_grow_stack().address(),
|
||||||
|
UNCLASSIFIED,
|
||||||
|
20,
|
||||||
|
"NativeRegExpMacroAssembler::GrowStack()");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1118,6 +1132,11 @@ void Serializer::PutHeader() {
|
|||||||
writer_->PutC(FLAG_debug_serialization ? '1' : '0');
|
writer_->PutC(FLAG_debug_serialization ? '1' : '0');
|
||||||
#else
|
#else
|
||||||
writer_->PutC('0');
|
writer_->PutC('0');
|
||||||
|
#endif
|
||||||
|
#ifdef V8_NATIVE_REGEXP
|
||||||
|
writer_->PutC('N');
|
||||||
|
#else // Interpreted regexp
|
||||||
|
writer_->PutC('I');
|
||||||
#endif
|
#endif
|
||||||
// Write sizes of paged memory spaces. Allocate extra space for the old
|
// Write sizes of paged memory spaces. Allocate extra space for the old
|
||||||
// and code spaces, because objects in new space will be promoted to them.
|
// and code spaces, because objects in new space will be promoted to them.
|
||||||
@ -1474,6 +1493,11 @@ void Deserializer::GetHeader() {
|
|||||||
// In release mode, don't attempt to read a snapshot containing
|
// In release mode, don't attempt to read a snapshot containing
|
||||||
// synchronization tags.
|
// synchronization tags.
|
||||||
if (reader_.GetC() != '0') FATAL("Snapshot contains synchronization tags.");
|
if (reader_.GetC() != '0') FATAL("Snapshot contains synchronization tags.");
|
||||||
|
#endif
|
||||||
|
#ifdef V8_NATIVE_REGEXP
|
||||||
|
reader_.ExpectC('N');
|
||||||
|
#else // Interpreted regexp.
|
||||||
|
reader_.ExpectC('I');
|
||||||
#endif
|
#endif
|
||||||
// Ensure sufficient capacity in paged memory spaces to avoid growth
|
// Ensure sufficient capacity in paged memory spaces to avoid growth
|
||||||
// during deserialization.
|
// during deserialization.
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
#ifdef V8_NATIVE_REGEXP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This assembler uses the following register assignment convention
|
* This assembler uses the following register assignment convention
|
||||||
* - rdx : currently loaded character(s) as ASCII or UC16. Must be loaded using
|
* - rdx : currently loaded character(s) as ASCII or UC16. Must be loaded using
|
||||||
@ -110,6 +112,7 @@ RegExpMacroAssemblerX64::RegExpMacroAssemblerX64(
|
|||||||
success_label_(),
|
success_label_(),
|
||||||
backtrack_label_(),
|
backtrack_label_(),
|
||||||
exit_label_() {
|
exit_label_() {
|
||||||
|
ASSERT_EQ(0, registers_to_save % 2);
|
||||||
__ jmp(&entry_label_); // We'll write the entry code when we know more.
|
__ jmp(&entry_label_); // We'll write the entry code when we know more.
|
||||||
__ bind(&start_label_); // And then continue from here.
|
__ bind(&start_label_); // And then continue from here.
|
||||||
}
|
}
|
||||||
@ -350,8 +353,9 @@ void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase(
|
|||||||
// Set byte_length.
|
// Set byte_length.
|
||||||
__ movq(rdx, rbx);
|
__ movq(rdx, rbx);
|
||||||
#endif
|
#endif
|
||||||
Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16);
|
ExternalReference compare =
|
||||||
CallCFunction(function_address, num_arguments);
|
ExternalReference::re_case_insensitive_compare_uc16();
|
||||||
|
CallCFunction(compare, num_arguments);
|
||||||
|
|
||||||
// Restore original values before reacting on result value.
|
// Restore original values before reacting on result value.
|
||||||
__ Move(code_object_pointer(), masm_->CodeObject());
|
__ Move(code_object_pointer(), masm_->CodeObject());
|
||||||
@ -808,11 +812,12 @@ Handle<Object> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
|
|||||||
// First argument, backtrack stackpointer, is already in rcx.
|
// First argument, backtrack stackpointer, is already in rcx.
|
||||||
__ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument
|
__ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument
|
||||||
#else
|
#else
|
||||||
// AMD64 ABI passes paremeters in rdi, rsi.
|
// AMD64 ABI passes parameters in rdi, rsi.
|
||||||
__ movq(rdi, backtrack_stackpointer()); // First argument.
|
__ movq(rdi, backtrack_stackpointer()); // First argument.
|
||||||
__ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument.
|
__ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument.
|
||||||
#endif
|
#endif
|
||||||
CallCFunction(FUNCTION_ADDR(&GrowStack), num_arguments);
|
ExternalReference grow_stack = ExternalReference::re_grow_stack();
|
||||||
|
CallCFunction(grow_stack, num_arguments);
|
||||||
// If return NULL, we have failed to grow the stack, and
|
// If return NULL, we have failed to grow the stack, and
|
||||||
// must exit with a stack-overflow exception.
|
// must exit with a stack-overflow exception.
|
||||||
__ testq(rax, rax);
|
__ testq(rax, rax);
|
||||||
@ -889,7 +894,9 @@ void RegExpMacroAssemblerX64::LoadCurrentCharacter(int cp_offset,
|
|||||||
int characters) {
|
int characters) {
|
||||||
ASSERT(cp_offset >= -1); // ^ and \b can look behind one character.
|
ASSERT(cp_offset >= -1); // ^ and \b can look behind one character.
|
||||||
ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
|
ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
|
||||||
CheckPosition(cp_offset + characters - 1, on_end_of_input);
|
if (check_bounds) {
|
||||||
|
CheckPosition(cp_offset + characters - 1, on_end_of_input);
|
||||||
|
}
|
||||||
LoadCurrentCharacterUnchecked(cp_offset, characters);
|
LoadCurrentCharacterUnchecked(cp_offset, characters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -997,7 +1004,9 @@ void RegExpMacroAssemblerX64::CallCheckStackGuardState() {
|
|||||||
// return address).
|
// return address).
|
||||||
__ lea(rdi, Operand(rsp, -kPointerSize));
|
__ lea(rdi, Operand(rsp, -kPointerSize));
|
||||||
#endif
|
#endif
|
||||||
CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments);
|
ExternalReference stack_check =
|
||||||
|
ExternalReference::re_check_stack_guard_state();
|
||||||
|
CallCFunction(stack_check, num_arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1080,23 +1089,6 @@ int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Address RegExpMacroAssemblerX64::GrowStack(Address stack_pointer,
|
|
||||||
Address* stack_base) {
|
|
||||||
size_t size = RegExpStack::stack_capacity();
|
|
||||||
Address old_stack_base = RegExpStack::stack_base();
|
|
||||||
ASSERT(old_stack_base == *stack_base);
|
|
||||||
ASSERT(stack_pointer <= old_stack_base);
|
|
||||||
ASSERT(static_cast<size_t>(old_stack_base - stack_pointer) <= size);
|
|
||||||
Address new_stack_base = RegExpStack::EnsureCapacity(size * 2);
|
|
||||||
if (new_stack_base == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*stack_base = new_stack_base;
|
|
||||||
intptr_t stack_content_size = old_stack_base - stack_pointer;
|
|
||||||
return new_stack_base - stack_content_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Operand RegExpMacroAssemblerX64::register_location(int register_index) {
|
Operand RegExpMacroAssemblerX64::register_location(int register_index) {
|
||||||
ASSERT(register_index < (1<<30));
|
ASSERT(register_index < (1<<30));
|
||||||
if (num_registers_ <= register_index) {
|
if (num_registers_ <= register_index) {
|
||||||
@ -1256,17 +1248,16 @@ void RegExpMacroAssemblerX64::FrameAlign(int num_arguments) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerX64::CallCFunction(Address function_address,
|
void RegExpMacroAssemblerX64::CallCFunction(ExternalReference function,
|
||||||
int num_arguments) {
|
int num_arguments) {
|
||||||
// Don't compile regexps with serialization enabled. The addresses of the C++
|
__ movq(rax, function);
|
||||||
// function being called isn't relocatable.
|
|
||||||
ASSERT(!Serializer::enabled());
|
|
||||||
__ movq(rax, reinterpret_cast<intptr_t>(function_address), RelocInfo::NONE);
|
|
||||||
__ call(rax);
|
__ call(rax);
|
||||||
ASSERT(OS::ActivationFrameAlignment() != 0);
|
ASSERT(OS::ActivationFrameAlignment() != 0);
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
__ movq(rsp, Operand(rsp, num_arguments * kPointerSize));
|
__ movq(rsp, Operand(rsp, num_arguments * kPointerSize));
|
||||||
#else
|
#else
|
||||||
|
// All arguments passed in registers.
|
||||||
|
ASSERT(num_arguments <= 6);
|
||||||
__ pop(rsp);
|
__ pop(rsp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1297,5 +1288,12 @@ void RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(int cp_offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RegExpCEntryStub::Generate(MacroAssembler* masm_) {
|
||||||
|
__ int3(); // Unused on x64.
|
||||||
|
}
|
||||||
|
|
||||||
#undef __
|
#undef __
|
||||||
|
|
||||||
|
#endif // V8_NATIVE_REGEXP
|
||||||
|
|
||||||
}} // namespace v8::internal
|
}} // namespace v8::internal
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
#ifdef V8_NATIVE_REGEXP
|
||||||
|
|
||||||
class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
|
class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
|
||||||
public:
|
public:
|
||||||
RegExpMacroAssemblerX64(Mode mode, int registers_to_save);
|
RegExpMacroAssemblerX64(Mode mode, int registers_to_save);
|
||||||
@ -113,6 +115,13 @@ class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
|
|||||||
int* output,
|
int* output,
|
||||||
bool at_start);
|
bool at_start);
|
||||||
|
|
||||||
|
// Called from RegExp if the stack-guard is triggered.
|
||||||
|
// If the code object is relocated, the return address is fixed before
|
||||||
|
// returning.
|
||||||
|
static int CheckStackGuardState(Address* return_address,
|
||||||
|
Code* re_code,
|
||||||
|
Address re_frame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Offsets from rbp of function parameters and stored registers.
|
// Offsets from rbp of function parameters and stored registers.
|
||||||
static const int kFramePointer = 0;
|
static const int kFramePointer = 0;
|
||||||
@ -181,23 +190,9 @@ class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
|
|||||||
// Check whether we are exceeding the stack limit on the backtrack stack.
|
// Check whether we are exceeding the stack limit on the backtrack stack.
|
||||||
void CheckStackLimit();
|
void CheckStackLimit();
|
||||||
|
|
||||||
// Called from RegExp if the stack-guard is triggered.
|
|
||||||
// If the code object is relocated, the return address is fixed before
|
|
||||||
// returning.
|
|
||||||
static int CheckStackGuardState(Address* return_address,
|
|
||||||
Code* re_code,
|
|
||||||
Address re_frame);
|
|
||||||
|
|
||||||
// Generate a call to CheckStackGuardState.
|
// Generate a call to CheckStackGuardState.
|
||||||
void CallCheckStackGuardState();
|
void CallCheckStackGuardState();
|
||||||
|
|
||||||
// Called from RegExp if the backtrack stack limit is hit.
|
|
||||||
// Tries to expand the stack. Returns the new stack-pointer if
|
|
||||||
// successful, and updates the stack_top address, or returns 0 if unable
|
|
||||||
// to grow the stack.
|
|
||||||
// This function must not trigger a garbage collection.
|
|
||||||
static Address GrowStack(Address stack_pointer, Address* stack_top);
|
|
||||||
|
|
||||||
// The rbp-relative location of a regexp register.
|
// The rbp-relative location of a regexp register.
|
||||||
Operand register_location(int register_index);
|
Operand register_location(int register_index);
|
||||||
|
|
||||||
@ -264,7 +259,7 @@ class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
|
|||||||
// by FrameAlign. The called function is not allowed to trigger a garbage
|
// by FrameAlign. The called function is not allowed to trigger a garbage
|
||||||
// collection, since that might move the code and invalidate the return
|
// collection, since that might move the code and invalidate the return
|
||||||
// address (unless this is somehow accounted for by the called function).
|
// address (unless this is somehow accounted for by the called function).
|
||||||
inline void CallCFunction(Address function_address, int num_arguments);
|
inline void CallCFunction(ExternalReference function, int num_arguments);
|
||||||
|
|
||||||
MacroAssembler* masm_;
|
MacroAssembler* masm_;
|
||||||
|
|
||||||
@ -290,6 +285,8 @@ class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
|
|||||||
Label stack_overflow_label_;
|
Label stack_overflow_label_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // V8_NATIVE_REGEXP
|
||||||
|
|
||||||
}} // namespace v8::internal
|
}} // namespace v8::internal
|
||||||
|
|
||||||
#endif // V8_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
|
#endif // V8_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
|
||||||
|
@ -45,4 +45,9 @@
|
|||||||
(reinterpret_cast<uintptr_t>(this) >= limit ? \
|
(reinterpret_cast<uintptr_t>(this) >= limit ? \
|
||||||
reinterpret_cast<uintptr_t>(this) - limit : 0)
|
reinterpret_cast<uintptr_t>(this) - limit : 0)
|
||||||
|
|
||||||
|
// Call the generated regexp code directly. The entry function pointer should
|
||||||
|
// expect seven int/pointer sized arguments and return an int.
|
||||||
|
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
|
||||||
|
entry(p0, p1, p2, p3, p4, p5, p6)
|
||||||
|
|
||||||
#endif // V8_X64_SIMULATOR_X64_H_
|
#endif // V8_X64_SIMULATOR_X64_H_
|
||||||
|
@ -185,7 +185,7 @@ TEST(3) {
|
|||||||
Label L, C;
|
Label L, C;
|
||||||
|
|
||||||
__ mov(ip, Operand(sp));
|
__ mov(ip, Operand(sp));
|
||||||
__ stm(db_w, sp, r4.bit() | fp.bit() | sp.bit() | lr.bit());
|
__ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
|
||||||
__ sub(fp, ip, Operand(4));
|
__ sub(fp, ip, Operand(4));
|
||||||
__ mov(r4, Operand(r0));
|
__ mov(r4, Operand(r0));
|
||||||
__ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
|
__ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
|
||||||
@ -199,7 +199,7 @@ TEST(3) {
|
|||||||
__ add(r0, r2, Operand(r0));
|
__ add(r0, r2, Operand(r0));
|
||||||
__ mov(r2, Operand(r2, ASR, 3));
|
__ mov(r2, Operand(r2, ASR, 3));
|
||||||
__ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
|
__ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
|
||||||
__ ldm(ia, sp, r4.bit() | fp.bit() | sp.bit() | pc.bit());
|
__ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
|
||||||
|
|
||||||
CodeDesc desc;
|
CodeDesc desc;
|
||||||
assm.GetCode(&desc);
|
assm.GetCode(&desc);
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "regexp-macro-assembler-irregexp.h"
|
#include "regexp-macro-assembler-irregexp.h"
|
||||||
#ifdef V8_NATIVE_REGEXP
|
#ifdef V8_NATIVE_REGEXP
|
||||||
#ifdef V8_TARGET_ARCH_ARM
|
#ifdef V8_TARGET_ARCH_ARM
|
||||||
|
#include "arm/macro-assembler-arm.h"
|
||||||
#include "arm/regexp-macro-assembler-arm.h"
|
#include "arm/regexp-macro-assembler-arm.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef V8_TARGET_ARCH_X64
|
#ifdef V8_TARGET_ARCH_X64
|
||||||
@ -605,11 +606,12 @@ TEST(DispatchTableConstruction) {
|
|||||||
|
|
||||||
#ifdef V8_NATIVE_REGEXP
|
#ifdef V8_NATIVE_REGEXP
|
||||||
|
|
||||||
#ifdef V8_TARGET_ARCH_IA32
|
#if V8_TARGET_ARCH_IA32
|
||||||
typedef RegExpMacroAssemblerIA32 ArchRegExpMacroAssembler;
|
typedef RegExpMacroAssemblerIA32 ArchRegExpMacroAssembler;
|
||||||
#endif
|
#elif V8_TARGET_ARCH_X64
|
||||||
#ifdef V8_TARGET_ARCH_X64
|
|
||||||
typedef RegExpMacroAssemblerX64 ArchRegExpMacroAssembler;
|
typedef RegExpMacroAssemblerX64 ArchRegExpMacroAssembler;
|
||||||
|
#elif V8_TARGET_ARCH_ARM
|
||||||
|
typedef RegExpMacroAssemblerARM ArchRegExpMacroAssembler;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class ContextInitializer {
|
class ContextInitializer {
|
||||||
@ -845,7 +847,7 @@ TEST(MacroAssemblerNativeBackReferenceASCII) {
|
|||||||
v8::V8::Initialize();
|
v8::V8::Initialize();
|
||||||
ContextInitializer initializer;
|
ContextInitializer initializer;
|
||||||
|
|
||||||
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 3);
|
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4);
|
||||||
|
|
||||||
m.WriteCurrentPositionToRegister(0, 0);
|
m.WriteCurrentPositionToRegister(0, 0);
|
||||||
m.AdvanceCurrentPosition(2);
|
m.AdvanceCurrentPosition(2);
|
||||||
@ -870,7 +872,7 @@ TEST(MacroAssemblerNativeBackReferenceASCII) {
|
|||||||
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
|
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
|
||||||
Address start_adr = seq_input->GetCharsAddress();
|
Address start_adr = seq_input->GetCharsAddress();
|
||||||
|
|
||||||
int output[3];
|
int output[4];
|
||||||
NativeRegExpMacroAssembler::Result result =
|
NativeRegExpMacroAssembler::Result result =
|
||||||
Execute(*code,
|
Execute(*code,
|
||||||
*input,
|
*input,
|
||||||
@ -884,6 +886,7 @@ TEST(MacroAssemblerNativeBackReferenceASCII) {
|
|||||||
CHECK_EQ(0, output[0]);
|
CHECK_EQ(0, output[0]);
|
||||||
CHECK_EQ(2, output[1]);
|
CHECK_EQ(2, output[1]);
|
||||||
CHECK_EQ(6, output[2]);
|
CHECK_EQ(6, output[2]);
|
||||||
|
CHECK_EQ(-1, output[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -891,7 +894,7 @@ TEST(MacroAssemblerNativeBackReferenceUC16) {
|
|||||||
v8::V8::Initialize();
|
v8::V8::Initialize();
|
||||||
ContextInitializer initializer;
|
ContextInitializer initializer;
|
||||||
|
|
||||||
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::UC16, 3);
|
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::UC16, 4);
|
||||||
|
|
||||||
m.WriteCurrentPositionToRegister(0, 0);
|
m.WriteCurrentPositionToRegister(0, 0);
|
||||||
m.AdvanceCurrentPosition(2);
|
m.AdvanceCurrentPosition(2);
|
||||||
@ -918,7 +921,7 @@ TEST(MacroAssemblerNativeBackReferenceUC16) {
|
|||||||
Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
|
Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
|
||||||
Address start_adr = seq_input->GetCharsAddress();
|
Address start_adr = seq_input->GetCharsAddress();
|
||||||
|
|
||||||
int output[3];
|
int output[4];
|
||||||
NativeRegExpMacroAssembler::Result result =
|
NativeRegExpMacroAssembler::Result result =
|
||||||
Execute(*code,
|
Execute(*code,
|
||||||
*input,
|
*input,
|
||||||
@ -932,6 +935,7 @@ TEST(MacroAssemblerNativeBackReferenceUC16) {
|
|||||||
CHECK_EQ(0, output[0]);
|
CHECK_EQ(0, output[0]);
|
||||||
CHECK_EQ(2, output[1]);
|
CHECK_EQ(2, output[1]);
|
||||||
CHECK_EQ(6, output[2]);
|
CHECK_EQ(6, output[2]);
|
||||||
|
CHECK_EQ(-1, output[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1055,12 +1059,12 @@ TEST(MacroAssemblerNativeRegisters) {
|
|||||||
v8::V8::Initialize();
|
v8::V8::Initialize();
|
||||||
ContextInitializer initializer;
|
ContextInitializer initializer;
|
||||||
|
|
||||||
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 5);
|
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 6);
|
||||||
|
|
||||||
uc16 foo_chars[3] = {'f', 'o', 'o'};
|
uc16 foo_chars[3] = {'f', 'o', 'o'};
|
||||||
Vector<const uc16> foo(foo_chars, 3);
|
Vector<const uc16> foo(foo_chars, 3);
|
||||||
|
|
||||||
enum registers { out1, out2, out3, out4, out5, sp, loop_cnt };
|
enum registers { out1, out2, out3, out4, out5, out6, sp, loop_cnt };
|
||||||
Label fail;
|
Label fail;
|
||||||
Label backtrack;
|
Label backtrack;
|
||||||
m.WriteCurrentPositionToRegister(out1, 0); // Output: [0]
|
m.WriteCurrentPositionToRegister(out1, 0); // Output: [0]
|
||||||
@ -1114,7 +1118,7 @@ TEST(MacroAssemblerNativeRegisters) {
|
|||||||
m.GoTo(&loop3);
|
m.GoTo(&loop3);
|
||||||
m.Bind(&exit_loop3);
|
m.Bind(&exit_loop3);
|
||||||
m.PopCurrentPosition();
|
m.PopCurrentPosition();
|
||||||
m.WriteCurrentPositionToRegister(out5, 0); // [0,3,6,9,9]
|
m.WriteCurrentPositionToRegister(out5, 0); // [0,3,6,9,9,-1]
|
||||||
|
|
||||||
m.Succeed();
|
m.Succeed();
|
||||||
|
|
||||||
@ -1132,15 +1136,15 @@ TEST(MacroAssemblerNativeRegisters) {
|
|||||||
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
|
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
|
||||||
Address start_adr = seq_input->GetCharsAddress();
|
Address start_adr = seq_input->GetCharsAddress();
|
||||||
|
|
||||||
int output[5];
|
int output[6];
|
||||||
NativeRegExpMacroAssembler::Result result =
|
NativeRegExpMacroAssembler::Result result =
|
||||||
Execute(*code,
|
Execute(*code,
|
||||||
*input,
|
*input,
|
||||||
0,
|
0,
|
||||||
start_adr,
|
start_adr,
|
||||||
start_adr + input->length(),
|
start_adr + input->length(),
|
||||||
output,
|
output,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
|
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
|
||||||
CHECK_EQ(0, output[0]);
|
CHECK_EQ(0, output[0]);
|
||||||
@ -1148,6 +1152,7 @@ TEST(MacroAssemblerNativeRegisters) {
|
|||||||
CHECK_EQ(6, output[2]);
|
CHECK_EQ(6, output[2]);
|
||||||
CHECK_EQ(9, output[3]);
|
CHECK_EQ(9, output[3]);
|
||||||
CHECK_EQ(9, output[4]);
|
CHECK_EQ(9, output[4]);
|
||||||
|
CHECK_EQ(-1, output[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -433,18 +433,14 @@
|
|||||||
'../../src/ia32/jump-target-ia32.cc',
|
'../../src/ia32/jump-target-ia32.cc',
|
||||||
'../../src/ia32/macro-assembler-ia32.cc',
|
'../../src/ia32/macro-assembler-ia32.cc',
|
||||||
'../../src/ia32/macro-assembler-ia32.h',
|
'../../src/ia32/macro-assembler-ia32.h',
|
||||||
|
'../../src/ia32/regexp-macro-assembler-ia32.cc',
|
||||||
|
'../../src/ia32/regexp-macro-assembler-ia32.h',
|
||||||
'../../src/ia32/register-allocator-ia32.cc',
|
'../../src/ia32/register-allocator-ia32.cc',
|
||||||
'../../src/ia32/stub-cache-ia32.cc',
|
'../../src/ia32/stub-cache-ia32.cc',
|
||||||
'../../src/ia32/virtual-frame-ia32.cc',
|
'../../src/ia32/virtual-frame-ia32.cc',
|
||||||
'../../src/ia32/virtual-frame-ia32.h',
|
'../../src/ia32/virtual-frame-ia32.h',
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
['target_arch=="ia32" and v8_regexp=="native"', {
|
|
||||||
'sources': [
|
|
||||||
'../../src/ia32/regexp-macro-assembler-ia32.cc',
|
|
||||||
'../../src/ia32/regexp-macro-assembler-ia32.h',
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
['target_arch=="x64"', {
|
['target_arch=="x64"', {
|
||||||
'include_dirs+': [
|
'include_dirs+': [
|
||||||
'../../src/x64',
|
'../../src/x64',
|
||||||
@ -466,18 +462,14 @@
|
|||||||
'../../src/x64/jump-target-x64.cc',
|
'../../src/x64/jump-target-x64.cc',
|
||||||
'../../src/x64/macro-assembler-x64.cc',
|
'../../src/x64/macro-assembler-x64.cc',
|
||||||
'../../src/x64/macro-assembler-x64.h',
|
'../../src/x64/macro-assembler-x64.h',
|
||||||
|
'../../src/x64/regexp-macro-assembler-x64.cc',
|
||||||
|
'../../src/x64/regexp-macro-assembler-x64.h',
|
||||||
'../../src/x64/register-allocator-x64.cc',
|
'../../src/x64/register-allocator-x64.cc',
|
||||||
'../../src/x64/stub-cache-x64.cc',
|
'../../src/x64/stub-cache-x64.cc',
|
||||||
'../../src/x64/virtual-frame-x64.cc',
|
'../../src/x64/virtual-frame-x64.cc',
|
||||||
'../../src/x64/virtual-frame-x64.h',
|
'../../src/x64/virtual-frame-x64.h',
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
['target_arch=="x64" and v8_regexp=="native"', {
|
|
||||||
'sources': [
|
|
||||||
'../../src/x64/regexp-macro-assembler-x64.cc',
|
|
||||||
'../../src/x64/regexp-macro-assembler-x64.h',
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
['OS=="linux"', {
|
['OS=="linux"', {
|
||||||
'link_settings': {
|
'link_settings': {
|
||||||
'libraries': [
|
'libraries': [
|
||||||
|
Loading…
Reference in New Issue
Block a user