4028fec3b5
This work pulls in v8 support for these features with appropriate changes for Dart and closes https://github.com/dart-lang/sdk/issues/34935. This adds support for the following features: * Interpreting patterns as Unicode patterns instead of BMP patterns * the dotAll flag (`/s`) for changing the behavior of '.' to also match line terminators * Escapes for character classes described by Unicode property groups (e.g., \p{Greek} to match all Greek characters, or \P{Greek} for all non-Greek characters). The following TC39 proposals describe some of the added features: * https://github.com/tc39/proposal-regexp-dotall-flag * https://github.com/tc39/proposal-regexp-unicode-property-escapes These additional changes are included: * Extends named capture group names to include the full range of identifier characters supported by ECMAScript, not just ASCII. * Changing the RegExp interface to return RegExpMatch objects, not Match objects, so that downcasting is not necessary to use named capture groups from Dart **Note**: The changes to the RegExp interface are a breaking change for implementers of the RegExp interface. Current users of the RegExp interface (i.e., code using Dart RegExp objects) will not be affected. Change-Id: Ie62e6082a0e2fedc1680ef2576ce0c6db80fc19a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100641 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Stevie Strickland <sstrickl@google.com>
147 lines
6.4 KiB
C++
147 lines
6.4 KiB
C++
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#ifndef RUNTIME_VM_REGEXP_ASSEMBLER_BYTECODE_H_
|
|
#define RUNTIME_VM_REGEXP_ASSEMBLER_BYTECODE_H_
|
|
|
|
#include "vm/object.h"
|
|
#include "vm/regexp_assembler.h"
|
|
|
|
namespace dart {
|
|
|
|
class BytecodeRegExpMacroAssembler : public RegExpMacroAssembler {
|
|
public:
|
|
// Create an assembler. Instructions and relocation information are emitted
|
|
// into a buffer, with the instructions starting from the beginning and the
|
|
// relocation information starting from the end of the buffer. See CodeDesc
|
|
// for a detailed comment on the layout (globals.h).
|
|
//
|
|
// If the provided buffer is NULL, the assembler allocates and grows its own
|
|
// buffer, and buffer_size determines the initial buffer size. The buffer is
|
|
// owned by the assembler and deallocated upon destruction of the assembler.
|
|
//
|
|
// If the provided buffer is not NULL, the assembler uses the provided buffer
|
|
// for code generation and assumes its size to be buffer_size. If the buffer
|
|
// is too small, a fatal error occurs. No deallocation of the buffer is done
|
|
// upon destruction of the assembler.
|
|
BytecodeRegExpMacroAssembler(ZoneGrowableArray<uint8_t>* buffer, Zone* zone);
|
|
virtual ~BytecodeRegExpMacroAssembler();
|
|
|
|
// The byte-code interpreter checks on each push anyway.
|
|
virtual intptr_t stack_limit_slack() { return 1; }
|
|
virtual bool CanReadUnaligned() { return false; }
|
|
virtual void BindBlock(BlockLabel* label);
|
|
virtual void AdvanceCurrentPosition(intptr_t by); // Signed cp change.
|
|
virtual void PopCurrentPosition();
|
|
virtual void PushCurrentPosition();
|
|
virtual void Backtrack();
|
|
virtual void GoTo(BlockLabel* label);
|
|
virtual void PushBacktrack(BlockLabel* label);
|
|
virtual bool Succeed();
|
|
virtual void Fail();
|
|
virtual void PopRegister(intptr_t register_index);
|
|
virtual void PushRegister(intptr_t register_index);
|
|
virtual void AdvanceRegister(intptr_t reg, intptr_t by); // r[reg] += by.
|
|
virtual void SetCurrentPositionFromEnd(intptr_t by);
|
|
virtual void SetRegister(intptr_t register_index, intptr_t to);
|
|
virtual void WriteCurrentPositionToRegister(intptr_t reg, intptr_t cp_offset);
|
|
virtual void ClearRegisters(intptr_t reg_from, intptr_t reg_to);
|
|
virtual void ReadCurrentPositionFromRegister(intptr_t reg);
|
|
virtual void WriteStackPointerToRegister(intptr_t reg);
|
|
virtual void ReadStackPointerFromRegister(intptr_t reg);
|
|
virtual void LoadCurrentCharacter(intptr_t cp_offset,
|
|
BlockLabel* on_end_of_input,
|
|
bool check_bounds = true,
|
|
intptr_t characters = 1);
|
|
virtual void CheckCharacter(unsigned c, BlockLabel* on_equal);
|
|
virtual void CheckCharacterAfterAnd(unsigned c,
|
|
unsigned mask,
|
|
BlockLabel* on_equal);
|
|
virtual void CheckCharacterGT(uint16_t limit, BlockLabel* on_greater);
|
|
virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less);
|
|
virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position);
|
|
virtual void CheckAtStart(BlockLabel* on_at_start);
|
|
virtual void CheckNotAtStart(intptr_t cp_offset, BlockLabel* on_not_at_start);
|
|
virtual void CheckNotCharacter(unsigned c, BlockLabel* on_not_equal);
|
|
virtual void CheckNotCharacterAfterAnd(unsigned c,
|
|
unsigned mask,
|
|
BlockLabel* on_not_equal);
|
|
virtual void CheckNotCharacterAfterMinusAnd(uint16_t c,
|
|
uint16_t minus,
|
|
uint16_t mask,
|
|
BlockLabel* on_not_equal);
|
|
virtual void CheckCharacterInRange(uint16_t from,
|
|
uint16_t to,
|
|
BlockLabel* on_in_range);
|
|
virtual void CheckCharacterNotInRange(uint16_t from,
|
|
uint16_t to,
|
|
BlockLabel* on_not_in_range);
|
|
virtual void CheckBitInTable(const TypedData& table, BlockLabel* on_bit_set);
|
|
virtual void CheckNotBackReference(intptr_t start_reg,
|
|
bool read_backward,
|
|
BlockLabel* on_no_match);
|
|
virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
|
|
bool read_backward,
|
|
bool unicode,
|
|
BlockLabel* on_no_match);
|
|
virtual void IfRegisterLT(intptr_t register_index,
|
|
intptr_t comparand,
|
|
BlockLabel* if_lt);
|
|
virtual void IfRegisterGE(intptr_t register_index,
|
|
intptr_t comparand,
|
|
BlockLabel* if_ge);
|
|
virtual void IfRegisterEqPos(intptr_t register_index, BlockLabel* if_eq);
|
|
|
|
virtual IrregexpImplementation Implementation();
|
|
// virtual Handle<HeapObject> GetCode(Handle<String> source);
|
|
RawTypedData* GetBytecode();
|
|
|
|
// New
|
|
virtual bool IsClosed() const {
|
|
// Added by Dart for the IR version. Bytecode version should never need an
|
|
// extra goto.
|
|
return true;
|
|
}
|
|
virtual void Print(const char* str) { UNIMPLEMENTED(); }
|
|
virtual void PrintBlocks() { UNIMPLEMENTED(); }
|
|
/////
|
|
|
|
static RawInstance* Interpret(const RegExp& regexp,
|
|
const String& str,
|
|
const Smi& start_index,
|
|
bool is_sticky,
|
|
Zone* zone);
|
|
|
|
private:
|
|
void Expand();
|
|
// Code and bitmap emission.
|
|
inline void EmitOrLink(BlockLabel* label);
|
|
inline void Emit32(uint32_t x);
|
|
inline void Emit16(uint32_t x);
|
|
inline void Emit8(uint32_t x);
|
|
inline void Emit(uint32_t bc, uint32_t arg);
|
|
// Bytecode buffer.
|
|
intptr_t length();
|
|
|
|
// The buffer into which code and relocation info are generated.
|
|
ZoneGrowableArray<uint8_t>* buffer_;
|
|
|
|
// The program counter.
|
|
intptr_t pc_;
|
|
|
|
BlockLabel backtrack_;
|
|
|
|
intptr_t advance_current_start_;
|
|
intptr_t advance_current_offset_;
|
|
intptr_t advance_current_end_;
|
|
|
|
static const int kInvalidPC = -1;
|
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeRegExpMacroAssembler);
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_REGEXP_ASSEMBLER_BYTECODE_H_
|