| Index: src/a64/regexp-macro-assembler-a64.h
|
| diff --git a/src/arm/regexp-macro-assembler-arm.h b/src/a64/regexp-macro-assembler-a64.h
|
| similarity index 60%
|
| copy from src/arm/regexp-macro-assembler-arm.h
|
| copy to src/a64/regexp-macro-assembler-a64.h
|
| index 8d9d515c76b2123f74eeb5c6d65f386263c27504..0f6b44b9fe97cdb48640858f1b13a2d788c04173 100644
|
| --- a/src/arm/regexp-macro-assembler-arm.h
|
| +++ b/src/a64/regexp-macro-assembler-a64.h
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2012 the V8 project authors. All rights reserved.
|
| +// Copyright 2013 the V8 project authors. All rights reserved.
|
| // Redistribution and use in source and binary forms, with or without
|
| // modification, are permitted provided that the following conditions are
|
| // met:
|
| @@ -25,11 +25,11 @@
|
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
| -#ifndef V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
| -#define V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
| +#ifndef V8_A64_REGEXP_MACRO_ASSEMBLER_A64_H_
|
| +#define V8_A64_REGEXP_MACRO_ASSEMBLER_A64_H_
|
|
|
| -#include "arm/assembler-arm.h"
|
| -#include "arm/assembler-arm-inl.h"
|
| +#include "a64/assembler-a64.h"
|
| +#include "a64/assembler-a64-inl.h"
|
| #include "macro-assembler.h"
|
|
|
| namespace v8 {
|
| @@ -37,10 +37,10 @@ namespace internal {
|
|
|
|
|
| #ifndef V8_INTERPRETED_REGEXP
|
| -class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
|
| +class RegExpMacroAssemblerA64: public NativeRegExpMacroAssembler {
|
| public:
|
| - RegExpMacroAssemblerARM(Mode mode, int registers_to_save, Zone* zone);
|
| - virtual ~RegExpMacroAssemblerARM();
|
| + RegExpMacroAssemblerA64(Mode mode, int registers_to_save, Zone* zone);
|
| + virtual ~RegExpMacroAssemblerA64();
|
| virtual int stack_limit_slack();
|
| virtual void AdvanceCurrentPosition(int by);
|
| virtual void AdvanceRegister(int reg, int by);
|
| @@ -53,6 +53,10 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
|
| 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);
|
| @@ -113,42 +117,48 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
|
| // returning.
|
| static int CheckStackGuardState(Address* return_address,
|
| Code* re_code,
|
| - Address re_frame);
|
| + Address re_frame,
|
| + int start_offset,
|
| + const byte** input_start,
|
| + const byte** input_end);
|
|
|
| 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;
|
| + // Callee-saved registers x19-x29, where x29 is the old frame pointer.
|
| + static const int kCalleeSavedRegisters = 0;
|
| + // Return address.
|
| + // It is placed above the 11 callee-saved registers.
|
| + static const int kReturnAddress = kCalleeSavedRegisters + 11 * kPointerSize;
|
| static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
|
| - // Stack parameters placed by caller.
|
| - static const int kRegisterOutput = kSecondaryReturnAddress + kPointerSize;
|
| - static const int kNumOutputRegisters = kRegisterOutput + kPointerSize;
|
| - static const int kStackHighEnd = kNumOutputRegisters + kPointerSize;
|
| - static const int kDirectCall = kStackHighEnd + kPointerSize;
|
| - static const int kIsolate = kDirectCall + kPointerSize;
|
| + // Stack parameter placed by caller.
|
| + static const int kIsolate = kSecondaryReturnAddress + 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;
|
| + static const int kDirectCall = kCalleeSavedRegisters - kPointerSize;
|
| + static const int kStackBase = kDirectCall - kPointerSize;
|
| + static const int kOutputSize = kStackBase - kPointerSize;
|
| + static const int kInput = kOutputSize - kPointerSize;
|
| // When adding local variables remember to push space for them in
|
| // the frame in GetCode.
|
| - static const int kSuccessfulCaptures = kInputString - kPointerSize;
|
| - static const int kInputStartMinusOne = kSuccessfulCaptures - kPointerSize;
|
| - // First register address. Following registers are below it on the stack.
|
| - static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
|
| + static const int kSuccessCounter = kInput - kPointerSize;
|
| + // First position register address on the stack. Following positions are
|
| + // below it. A position is a 32 bit value.
|
| + static const int kFirstRegisterOnStack = kSuccessCounter - kWRegSizeInBytes;
|
| + // A capture is a 64 bit value holding two position.
|
| + static const int kFirstCaptureOnStack = kSuccessCounter - kXRegSizeInBytes;
|
|
|
| // Initial size of code buffer.
|
| static const size_t kRegExpCodeSize = 1024;
|
|
|
| - static const int kBacktrackConstantPoolSize = 4;
|
| + // When initializing registers to a non-position value we can unroll
|
| + // the loop. Set the limit of registers to unroll.
|
| + static const int kNumRegistersToUnroll = 16;
|
| +
|
| + // We are using x0 to x7 as a register cache. Each hardware register must
|
| + // contain one capture, that is two 32 bit registers. We can cache at most
|
| + // 16 registers.
|
| + static const int kNumCachedRegisters = 16;
|
|
|
| // Load a number of characters at the given offset from the
|
| // current position, into the current-character register.
|
| @@ -160,46 +170,72 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
|
| // Check whether we are exceeding the stack limit on the backtrack stack.
|
| void CheckStackLimit();
|
|
|
| -
|
| // Generate a call to CheckStackGuardState.
|
| void CallCheckStackGuardState(Register scratch);
|
|
|
| - // The ebp-relative location of a regexp register.
|
| + // Location of a 32 bit position register.
|
| MemOperand register_location(int register_index);
|
|
|
| + // Location of a 64 bit capture, combining two position registers.
|
| + MemOperand capture_location(int register_index, Register scratch);
|
| +
|
| // Register holding the current input position as negative offset from
|
| // the end of the string.
|
| - inline Register current_input_offset() { return r6; }
|
| + Register current_input_offset() { return w21; }
|
|
|
| // The register containing the current character after LoadCurrentCharacter.
|
| - inline Register current_character() { return r7; }
|
| + Register current_character() { return w22; }
|
|
|
| // Register holding address of the end of the input string.
|
| - inline Register end_of_input_address() { return r10; }
|
| + Register input_end() { return x25; }
|
| +
|
| + // Register holding address of the start of the input string.
|
| + Register input_start() { return x26; }
|
| +
|
| + // Register holding the offset from the start of the string where we should
|
| + // start matching.
|
| + Register start_offset() { return w27; }
|
| +
|
| + // Pointer to the output array's first element.
|
| + Register output_array() { return x28; }
|
|
|
| // Register holding the frame address. Local variables, parameters and
|
| // regexp registers are addressed relative to this.
|
| - inline Register frame_pointer() { return fp; }
|
| + 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 backtrack_stackpointer() { return x23; }
|
|
|
| // Register holding pointer to the current code object.
|
| - inline Register code_pointer() { return r5; }
|
| + Register code_pointer() { return x20; }
|
| +
|
| + // Register holding the value used for clearing capture registers.
|
| + Register non_position_value() { return w24; }
|
| + // The top 32 bit of this register is used to store this value
|
| + // twice. This is used for clearing more than one register at a time.
|
| + Register twice_non_position_value() { return x24; }
|
|
|
| // Byte size of chars in the string to match (decided by the Mode argument)
|
| - inline int char_size() { return static_cast<int>(mode_); }
|
| + 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);
|
| + // Compares reg against immmediate before calling BranchOrBacktrack.
|
| + // It makes use of the Cbz and Cbnz instructions.
|
| + void CompareAndBranchOrBacktrack(Register reg,
|
| + int immediate,
|
| + Condition condition,
|
| + Label* to);
|
| +
|
| + inline void CallIf(Label* to, Condition condition);
|
| +
|
| + // Save and restore the link register on the stack in a way that
|
| + // is GC-safe.
|
| + inline void SaveLinkRegister();
|
| + inline void RestoreLinkRegister();
|
|
|
| // 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.
|
| @@ -209,6 +245,44 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
|
| // and increments it by a word size.
|
| inline void Pop(Register target);
|
|
|
| + // This state indicates where the register actually is.
|
| + enum RegisterState {
|
| + STACKED, // Resides in memory.
|
| + CACHED_LSW, // Least Significant Word of a 64 bit hardware register.
|
| + CACHED_MSW // Most Significant Word of a 64 bit hardware register.
|
| + };
|
| +
|
| + RegisterState GetRegisterState(int register_index) {
|
| + ASSERT(register_index >= 0);
|
| + if (register_index >= kNumCachedRegisters) {
|
| + return STACKED;
|
| + } else {
|
| + if ((register_index % 2) == 0) {
|
| + return CACHED_LSW;
|
| + } else {
|
| + return CACHED_MSW;
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Store helper that takes the state of the register into account.
|
| + inline void StoreRegister(int register_index, Register source);
|
| +
|
| + // Returns a hardware W register that holds the value of the capture
|
| + // register.
|
| + //
|
| + // This function will try to use an existing cache register (w0-w7) for the
|
| + // result. Otherwise, it will load the value into maybe_result.
|
| + //
|
| + // If the returned register is anything other than maybe_result, calling code
|
| + // must not write to it.
|
| + inline Register GetRegister(int register_index, Register maybe_result);
|
| +
|
| + // Returns the harware register (x0-x7) holding the value of the capture
|
| + // register.
|
| + // This assumes that the state of the register is not STACKED.
|
| + inline Register GetCachedRegister(int register_index);
|
| +
|
| Isolate* isolate() const { return masm_->isolate(); }
|
|
|
| MacroAssembler* masm_;
|
| @@ -238,4 +312,4 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
|
|
|
| }} // namespace v8::internal
|
|
|
| -#endif // V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
| +#endif // V8_A64_REGEXP_MACRO_ASSEMBLER_A64_H_
|
|
|