[nojit] Ship the regexp interpreter unconditionally

For jitless mode, we must be able to switch between the native regexp
engine and interpreted regexps at runtime since --jitless is itself a
runtime flag.

This CL unconditionally compiles in the regexp interpreter in all
builds. It can be toggled through the --regexp-interpret-all flag.

Bug: v8:7777, v8:8678
Change-Id: Iadd21a152de7c07586d5af32bee5fdf9931f1a01
Reviewed-on: https://chromium-review.googlesource.com/c/1408929
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59041}
This commit is contained in:
Jakob Gruber 2019-01-23 14:55:31 +01:00 committed by Commit Bot
parent 584f0b43b2
commit 7e616f2b6e
36 changed files with 202 additions and 329 deletions

View File

@ -324,13 +324,6 @@ void RegExpBuiltinsAssembler::GetStringPointers(
TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal(
TNode<Context> context, TNode<JSRegExp> regexp, TNode<String> string,
TNode<Number> last_index, TNode<RegExpMatchInfo> match_info) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
// at compilation.
#ifdef V8_INTERPRETED_REGEXP
return CAST(CallRuntime(Runtime::kRegExpExec, context, regexp, string,
last_index, match_info));
#else // V8_INTERPRETED_REGEXP
ToDirectStringAssembler to_direct(state(), string);
TVARIABLE(HeapObject, var_result);
@ -460,6 +453,7 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal(
#endif
GotoIf(TaggedIsSmi(var_code.value()), &runtime);
GotoIfNot(IsCode(CAST(var_code.value())), &runtime);
TNode<Code> code = CAST(var_code.value());
Label if_success(this), if_exception(this, Label::kDeferred);
@ -639,7 +633,6 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal(
BIND(&out);
return var_result.value();
#endif // V8_INTERPRETED_REGEXP
}
// ES#sec-regexp.prototype.exec

View File

@ -27,7 +27,6 @@
#include "src/wasm/wasm-external-refs.h"
// Include native regexp-macro-assembler.
#ifndef V8_INTERPRETED_REGEXP
#if V8_TARGET_ARCH_IA32
#include "src/regexp/ia32/regexp-macro-assembler-ia32.h" // NOLINT
#elif V8_TARGET_ARCH_X64
@ -47,7 +46,6 @@
#else // Unknown architecture.
#error "Unknown architecture."
#endif // Target architecture.
#endif // V8_INTERPRETED_REGEXP
#ifdef V8_INTL_SUPPORT
#include "src/objects/intl-objects.h"
@ -473,8 +471,6 @@ ExternalReference ExternalReference::invoke_accessor_getter_callback() {
return ExternalReference::Create(&thunk_fun, thunk_type);
}
#ifndef V8_INTERPRETED_REGEXP
#if V8_TARGET_ARCH_X64
#define re_stack_check_func RegExpMacroAssemblerX64::CheckStackGuardState
#elif V8_TARGET_ARCH_IA32
@ -531,8 +527,6 @@ ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
return ExternalReference(isolate->regexp_stack()->memory_size_address());
}
#endif // V8_INTERPRETED_REGEXP
FUNCTION_REFERENCE_WITH_TYPE(ieee754_acos_function, base::ieee754::acos,
BUILTIN_FP_CALL)
FUNCTION_REFERENCE_WITH_TYPE(ieee754_acosh_function, base::ieee754::acosh,

View File

@ -72,7 +72,16 @@ class StatsCounter;
"IsolateData::fast_c_call_caller_fp_address") \
V(fast_c_call_caller_pc_address, \
"IsolateData::fast_c_call_caller_pc_address") \
EXTERNAL_REFERENCE_LIST_NON_INTERPRETED_REGEXP(V)
V(address_of_regexp_stack_limit, "RegExpStack::limit_address()") \
V(address_of_regexp_stack_memory_address, "RegExpStack::memory_address()") \
V(address_of_regexp_stack_memory_size, "RegExpStack::memory_size()") \
V(address_of_static_offsets_vector, "OffsetsVector::static_offsets_vector") \
V(re_case_insensitive_compare_uc16, \
"NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()") \
V(re_check_stack_guard_state, \
"RegExpMacroAssembler*::CheckStackGuardState()") \
V(re_grow_stack, "NativeRegExpMacroAssembler::GrowStack()") \
V(re_word_character_map, "NativeRegExpMacroAssembler::word_character_map")
#define EXTERNAL_REFERENCE_LIST(V) \
V(abort_with_reason, "abort_with_reason") \
@ -197,22 +206,6 @@ class StatsCounter;
"atomic_pair_compare_exchange_function") \
EXTERNAL_REFERENCE_LIST_INTL(V)
#ifndef V8_INTERPRETED_REGEXP
#define EXTERNAL_REFERENCE_LIST_NON_INTERPRETED_REGEXP(V) \
V(address_of_regexp_stack_limit, "RegExpStack::limit_address()") \
V(address_of_regexp_stack_memory_address, "RegExpStack::memory_address()") \
V(address_of_regexp_stack_memory_size, "RegExpStack::memory_size()") \
V(address_of_static_offsets_vector, "OffsetsVector::static_offsets_vector") \
V(re_case_insensitive_compare_uc16, \
"NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()") \
V(re_check_stack_guard_state, \
"RegExpMacroAssembler*::CheckStackGuardState()") \
V(re_grow_stack, "NativeRegExpMacroAssembler::GrowStack()") \
V(re_word_character_map, "NativeRegExpMacroAssembler::word_character_map")
#else
#define EXTERNAL_REFERENCE_LIST_NON_INTERPRETED_REGEXP(V)
#endif // V8_INTERPRETED_REGEXP
#ifdef V8_INTL_SUPPORT
#define EXTERNAL_REFERENCE_LIST_INTL(V) \
V(intl_convert_one_byte_to_lower, "intl_convert_one_byte_to_lower") \

View File

@ -1093,6 +1093,15 @@ DEFINE_UINT(serialization_chunk_size, 4096,
DEFINE_BOOL(regexp_optimization, true, "generate optimized regexp code")
DEFINE_BOOL(regexp_mode_modifiers, false, "enable inline flags in regexp.")
#ifdef V8_INTERPRETED_REGEXP
#define V8_INTERPRETED_REGEXP_BOOL true
#else
#define V8_INTERPRETED_REGEXP_BOOL false
#endif
DEFINE_BOOL(regexp_interpret_all, V8_INTERPRETED_REGEXP_BOOL,
"interpret all regexp code")
#undef V8_INTERPRETED_REGEXP_BOOL
// Testing flags test/cctest/test-{flags,api,serialization}.cc
DEFINE_BOOL(testing_bool_flag, true, "testing_bool_flag")
DEFINE_MAYBE_BOOL(testing_maybe_bool_flag, "testing_maybe_bool_flag")
@ -1158,6 +1167,8 @@ DEFINE_BOOL(jitless, V8_LITE_BOOL,
// Optimizations (i.e. jitting) are disabled.
DEFINE_NEG_IMPLICATION(jitless, opt)
#endif
// Regexps are interpreted.
DEFINE_IMPLICATION(jitless, regexp_interpret_all)
// asm.js validation is disabled since it triggers wasm code generation.
DEFINE_NEG_IMPLICATION(jitless, validate_asm)
// Wasm is put into interpreter-only mode. We repeat flag implications down

View File

@ -79,8 +79,18 @@ void JSRegExp::SetDataAt(int index, Object value) {
}
bool JSRegExp::HasCompiledCode() const {
return TypeTag() == IRREGEXP && (DataAt(kIrregexpLatin1CodeIndex)->IsCode() ||
DataAt(kIrregexpUC16CodeIndex)->IsCode());
if (TypeTag() != IRREGEXP) return false;
#ifdef DEBUG
DCHECK(DataAt(kIrregexpLatin1CodeIndex)->IsCode() ||
DataAt(kIrregexpLatin1CodeIndex)->IsByteArray() ||
DataAt(kIrregexpLatin1CodeIndex) == Smi::FromInt(kUninitializedValue));
DCHECK(DataAt(kIrregexpUC16CodeIndex)->IsCode() ||
DataAt(kIrregexpUC16CodeIndex)->IsByteArray() ||
DataAt(kIrregexpUC16CodeIndex) == Smi::FromInt(kUninitializedValue));
#endif // DEBUG
Smi uninitialized = Smi::FromInt(kUninitializedValue);
return (DataAt(kIrregexpLatin1CodeIndex) != uninitialized ||
DataAt(kIrregexpUC16CodeIndex) != uninitialized);
}
void JSRegExp::DiscardCompiledCodeForSerialization() {

View File

@ -19,7 +19,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
/*
* This assembler uses the following register assignment convention
* - r4 : Temporarily stores the index of capture start after a matching pass
@ -1252,8 +1251,6 @@ void RegExpMacroAssemblerARM::LoadCurrentCharacterUnchecked(int cp_offset,
#undef __
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -12,8 +12,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerARM(Isolate* isolate, Zone* zone, Mode mode,
@ -211,9 +209,6 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
Label stack_overflow_label_;
};
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -18,7 +18,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
/*
* This assembler uses the following register assignment convention:
* - w19 : Used to temporarely store a value before a call to C code.
@ -1658,8 +1657,6 @@ void RegExpMacroAssemblerARM64::LoadCurrentCharacterUnchecked(int cp_offset,
}
}
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -12,8 +12,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
class RegExpMacroAssemblerARM64: public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerARM64(Isolate* isolate, Zone* zone, Mode mode,
@ -285,9 +283,6 @@ class RegExpMacroAssemblerARM64: public NativeRegExpMacroAssembler {
Label stack_overflow_label_;
};
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -6,8 +6,6 @@
#ifndef V8_REGEXP_BYTECODES_IRREGEXP_H_
#define V8_REGEXP_BYTECODES_IRREGEXP_H_
#ifdef V8_INTERPRETED_REGEXP
namespace v8 {
namespace internal {
@ -86,6 +84,4 @@ BYTECODE_ITERATOR(DECLARE_BYTECODE_LENGTH)
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETED_REGEXP
#endif // V8_REGEXP_BYTECODES_IRREGEXP_H_

View File

@ -17,7 +17,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
/*
* This assembler uses the following register assignment convention
* - edx : Current character. Must be loaded using LoadCurrentCharacter
@ -1277,8 +1276,6 @@ void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
#undef __
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -12,7 +12,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerIA32(Isolate* isolate, Zone* zone, Mode mode,
@ -197,7 +196,6 @@ class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler {
Label check_preempt_label_;
Label stack_overflow_label_;
};
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -4,8 +4,6 @@
// A simple interpreter for the Irregexp byte code.
#ifdef V8_INTERPRETED_REGEXP
#include "src/regexp/interpreter-irregexp.h"
#include "src/ast/ast.h"
@ -623,5 +621,3 @@ RegExpImpl::IrregexpResult IrregexpInterpreter::Match(
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETED_REGEXP

View File

@ -7,8 +7,6 @@
#ifndef V8_REGEXP_INTERPRETER_IRREGEXP_H_
#define V8_REGEXP_INTERPRETER_IRREGEXP_H_
#ifdef V8_INTERPRETED_REGEXP
#include "src/regexp/jsregexp.h"
namespace v8 {
@ -27,6 +25,4 @@ class IrregexpInterpreter {
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETED_REGEXP
#endif // V8_REGEXP_INTERPRETER_IRREGEXP_H_

View File

@ -34,7 +34,6 @@
#include "unicode/utypes.h"
#endif // V8_INTL_SUPPORT
#ifndef V8_INTERPRETED_REGEXP
#if V8_TARGET_ARCH_IA32
#include "src/regexp/ia32/regexp-macro-assembler-ia32.h"
#elif V8_TARGET_ARCH_X64
@ -54,8 +53,6 @@
#else
#error Unsupported target architecture.
#endif
#endif
namespace v8 {
namespace internal {
@ -300,11 +297,11 @@ bool RegExpImpl::EnsureCompiledIrregexp(Isolate* isolate, Handle<JSRegExp> re,
Handle<String> sample_subject,
bool is_one_byte) {
Object compiled_code = re->DataAt(JSRegExp::code_index(is_one_byte));
#ifdef V8_INTERPRETED_REGEXP
if (compiled_code->IsByteArray()) return true;
#else // V8_INTERPRETED_REGEXP (RegExp native code)
if (compiled_code->IsCode()) return true;
#endif
if (compiled_code != Smi::FromInt(JSRegExp::kUninitializedValue)) {
DCHECK(FLAG_regexp_interpret_all ? compiled_code->IsByteArray()
: compiled_code->IsCode());
return true;
}
return CompileIrregexp(isolate, re, sample_subject, is_one_byte);
}
@ -413,18 +410,18 @@ int RegExpImpl::IrregexpPrepare(Isolate* isolate, Handle<JSRegExp> regexp,
bool is_one_byte = String::IsOneByteRepresentationUnderneath(*subject);
if (!EnsureCompiledIrregexp(isolate, regexp, subject, is_one_byte)) return -1;
#ifdef V8_INTERPRETED_REGEXP
// Byte-code regexp needs space allocated for all its registers.
// The result captures are copied to the start of the registers array
// if the match succeeds. This way those registers are not clobbered
// when we set the last match info from last successful match.
return IrregexpNumberOfRegisters(FixedArray::cast(regexp->data())) +
(IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())) + 1) * 2;
#else // V8_INTERPRETED_REGEXP
// Native regexp only needs room to output captures. Registers are handled
// internally.
return (IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())) + 1) * 2;
#endif // V8_INTERPRETED_REGEXP
if (FLAG_regexp_interpret_all) {
// Byte-code regexp needs space allocated for all its registers.
// The result captures are copied to the start of the registers array
// if the match succeeds. This way those registers are not clobbered
// when we set the last match info from last successful match.
return IrregexpNumberOfRegisters(FixedArray::cast(regexp->data())) +
(IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())) + 1) * 2;
} else {
// Native regexp only needs room to output captures. Registers are handled
// internally.
return (IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())) + 1) * 2;
}
}
int RegExpImpl::IrregexpExecRaw(Isolate* isolate, Handle<JSRegExp> regexp,
@ -438,75 +435,69 @@ int RegExpImpl::IrregexpExecRaw(Isolate* isolate, Handle<JSRegExp> regexp,
bool is_one_byte = String::IsOneByteRepresentationUnderneath(*subject);
#ifndef V8_INTERPRETED_REGEXP
DCHECK(output_size >= (IrregexpNumberOfCaptures(*irregexp) + 1) * 2);
do {
EnsureCompiledIrregexp(isolate, regexp, subject, is_one_byte);
Handle<Code> code(IrregexpNativeCode(*irregexp, is_one_byte), isolate);
// The stack is used to allocate registers for the compiled regexp code.
// This means that in case of failure, the output registers array is left
// untouched and contains the capture results from the previous successful
// match. We can use that to set the last match info lazily.
NativeRegExpMacroAssembler::Result res =
NativeRegExpMacroAssembler::Match(code,
subject,
output,
output_size,
index,
isolate);
if (res != NativeRegExpMacroAssembler::RETRY) {
DCHECK(res != NativeRegExpMacroAssembler::EXCEPTION ||
isolate->has_pending_exception());
STATIC_ASSERT(
static_cast<int>(NativeRegExpMacroAssembler::SUCCESS) == RE_SUCCESS);
STATIC_ASSERT(
static_cast<int>(NativeRegExpMacroAssembler::FAILURE) == RE_FAILURE);
STATIC_ASSERT(static_cast<int>(NativeRegExpMacroAssembler::EXCEPTION)
== RE_EXCEPTION);
return static_cast<IrregexpResult>(res);
if (!FLAG_regexp_interpret_all) {
DCHECK(output_size >= (IrregexpNumberOfCaptures(*irregexp) + 1) * 2);
do {
EnsureCompiledIrregexp(isolate, regexp, subject, is_one_byte);
Handle<Code> code(IrregexpNativeCode(*irregexp, is_one_byte), isolate);
// The stack is used to allocate registers for the compiled regexp code.
// This means that in case of failure, the output registers array is left
// untouched and contains the capture results from the previous successful
// match. We can use that to set the last match info lazily.
NativeRegExpMacroAssembler::Result res =
NativeRegExpMacroAssembler::Match(code, subject, output, output_size,
index, isolate);
if (res != NativeRegExpMacroAssembler::RETRY) {
DCHECK(res != NativeRegExpMacroAssembler::EXCEPTION ||
isolate->has_pending_exception());
STATIC_ASSERT(static_cast<int>(NativeRegExpMacroAssembler::SUCCESS) ==
RE_SUCCESS);
STATIC_ASSERT(static_cast<int>(NativeRegExpMacroAssembler::FAILURE) ==
RE_FAILURE);
STATIC_ASSERT(static_cast<int>(NativeRegExpMacroAssembler::EXCEPTION) ==
RE_EXCEPTION);
return static_cast<IrregexpResult>(res);
}
// If result is RETRY, the string has changed representation, and we
// must restart from scratch.
// In this case, it means we must make sure we are prepared to handle
// the, potentially, different subject (the string can switch between
// being internal and external, and even between being Latin1 and UC16,
// but the characters are always the same).
IrregexpPrepare(isolate, regexp, subject);
is_one_byte = String::IsOneByteRepresentationUnderneath(*subject);
} while (true);
UNREACHABLE();
} else {
DCHECK(FLAG_regexp_interpret_all);
DCHECK(output_size >= IrregexpNumberOfRegisters(*irregexp));
// We must have done EnsureCompiledIrregexp, so we can get the number of
// registers.
int number_of_capture_registers =
(IrregexpNumberOfCaptures(*irregexp) + 1) * 2;
int32_t* raw_output = &output[number_of_capture_registers];
// We do not touch the actual capture result registers until we know there
// has been a match so that we can use those capture results to set the
// last match info.
for (int i = number_of_capture_registers - 1; i >= 0; i--) {
raw_output[i] = -1;
}
// If result is RETRY, the string has changed representation, and we
// must restart from scratch.
// In this case, it means we must make sure we are prepared to handle
// the, potentially, different subject (the string can switch between
// being internal and external, and even between being Latin1 and UC16,
// but the characters are always the same).
IrregexpPrepare(isolate, regexp, subject);
is_one_byte = String::IsOneByteRepresentationUnderneath(*subject);
} while (true);
UNREACHABLE();
#else // V8_INTERPRETED_REGEXP
Handle<ByteArray> byte_codes(IrregexpByteCode(*irregexp, is_one_byte),
isolate);
DCHECK(output_size >= IrregexpNumberOfRegisters(*irregexp));
// We must have done EnsureCompiledIrregexp, so we can get the number of
// registers.
int number_of_capture_registers =
(IrregexpNumberOfCaptures(*irregexp) + 1) * 2;
int32_t* raw_output = &output[number_of_capture_registers];
// We do not touch the actual capture result registers until we know there
// has been a match so that we can use those capture results to set the
// last match info.
for (int i = number_of_capture_registers - 1; i >= 0; i--) {
raw_output[i] = -1;
IrregexpResult result = IrregexpInterpreter::Match(
isolate, byte_codes, subject, raw_output, index);
if (result == RE_SUCCESS) {
// Copy capture results to the start of the registers array.
MemCopy(output, raw_output,
number_of_capture_registers * sizeof(int32_t));
}
if (result == RE_EXCEPTION) {
DCHECK(!isolate->has_pending_exception());
isolate->StackOverflow();
}
return result;
}
Handle<ByteArray> byte_codes(IrregexpByteCode(*irregexp, is_one_byte),
isolate);
IrregexpResult result = IrregexpInterpreter::Match(isolate,
byte_codes,
subject,
raw_output,
index);
if (result == RE_SUCCESS) {
// Copy capture results to the start of the registers array.
MemCopy(output, raw_output, number_of_capture_registers * sizeof(int32_t));
}
if (result == RE_EXCEPTION) {
DCHECK(!isolate->has_pending_exception());
isolate->StackOverflow();
}
return result;
#endif // V8_INTERPRETED_REGEXP
}
MaybeHandle<Object> RegExpImpl::IrregexpExec(
@ -517,8 +508,8 @@ MaybeHandle<Object> RegExpImpl::IrregexpExec(
subject = String::Flatten(isolate, subject);
// Prepare space for the return values.
#if defined(V8_INTERPRETED_REGEXP) && defined(DEBUG)
if (FLAG_trace_regexp_bytecodes) {
#ifdef DEBUG
if (FLAG_regexp_interpret_all && FLAG_trace_regexp_bytecodes) {
String pattern = regexp->Pattern();
PrintF("\n\nRegexp match: /%s/\n\n", pattern->ToCString().get());
PrintF("\n\nSubject string: '%s'\n\n", subject->ToCString().get());
@ -600,11 +591,7 @@ RegExpImpl::GlobalCache::GlobalCache(Handle<JSRegExp> regexp,
regexp_(regexp),
subject_(subject),
isolate_(isolate) {
#ifdef V8_INTERPRETED_REGEXP
bool interpreted = true;
#else
bool interpreted = false;
#endif // V8_INTERPRETED_REGEXP
bool interpreted = FLAG_regexp_interpret_all;
if (regexp_->TypeTag() == JSRegExp::ATOM) {
static const int kAtomRegistersPerMatch = 2;
@ -1076,8 +1063,8 @@ RegExpEngine::CompilationResult RegExpCompiler::Assemble(
Handle<HeapObject> code = macro_assembler_->GetCode(pattern);
isolate->IncreaseTotalRegexpCodeGenerated(code->Size());
work_list_ = nullptr;
#if defined(ENABLE_DISASSEMBLER) && !defined(V8_INTERPRETED_REGEXP)
if (FLAG_print_code) {
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_code && !FLAG_regexp_interpret_all) {
CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
OFStream os(trace_scope.file());
Handle<Code>::cast(code)->Disassemble(pattern->ToCString().get(), os);
@ -6698,57 +6685,57 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(
}
// Create the correct assembler for the architecture.
#ifndef V8_INTERPRETED_REGEXP
DCHECK(!FLAG_jitless);
std::unique_ptr<RegExpMacroAssembler> macro_assembler;
if (!FLAG_regexp_interpret_all) {
// Native regexp implementation.
DCHECK(!FLAG_jitless);
// Native regexp implementation.
NativeRegExpMacroAssembler::Mode mode =
is_one_byte ? NativeRegExpMacroAssembler::LATIN1
: NativeRegExpMacroAssembler::UC16;
NativeRegExpMacroAssembler::Mode mode =
is_one_byte ? NativeRegExpMacroAssembler::LATIN1
: NativeRegExpMacroAssembler::UC16;
#if V8_TARGET_ARCH_IA32
RegExpMacroAssemblerIA32 macro_assembler(isolate, zone, mode,
(data->capture_count + 1) * 2);
macro_assembler.reset(new RegExpMacroAssemblerIA32(
isolate, zone, mode, (data->capture_count + 1) * 2));
#elif V8_TARGET_ARCH_X64
RegExpMacroAssemblerX64 macro_assembler(isolate, zone, mode,
(data->capture_count + 1) * 2);
macro_assembler.reset(new RegExpMacroAssemblerX64(
isolate, zone, mode, (data->capture_count + 1) * 2));
#elif V8_TARGET_ARCH_ARM
RegExpMacroAssemblerARM macro_assembler(isolate, zone, mode,
(data->capture_count + 1) * 2);
macro_assembler.reset(new RegExpMacroAssemblerARM(
isolate, zone, mode, (data->capture_count + 1) * 2));
#elif V8_TARGET_ARCH_ARM64
RegExpMacroAssemblerARM64 macro_assembler(isolate, zone, mode,
(data->capture_count + 1) * 2);
macro_assembler.reset(new RegExpMacroAssemblerARM64(
isolate, zone, mode, (data->capture_count + 1) * 2));
#elif V8_TARGET_ARCH_S390
RegExpMacroAssemblerS390 macro_assembler(isolate, zone, mode,
(data->capture_count + 1) * 2);
macro_assembler.reset(new RegExpMacroAssemblerS390(
isolate, zone, mode, (data->capture_count + 1) * 2));
#elif V8_TARGET_ARCH_PPC
RegExpMacroAssemblerPPC macro_assembler(isolate, zone, mode,
(data->capture_count + 1) * 2);
macro_assembler.reset(new RegExpMacroAssemblerPPC(
isolate, zone, mode, (data->capture_count + 1) * 2));
#elif V8_TARGET_ARCH_MIPS
RegExpMacroAssemblerMIPS macro_assembler(isolate, zone, mode,
(data->capture_count + 1) * 2);
macro_assembler.reset(new RegExpMacroAssemblerMIPS(
isolate, zone, mode, (data->capture_count + 1) * 2));
#elif V8_TARGET_ARCH_MIPS64
RegExpMacroAssemblerMIPS macro_assembler(isolate, zone, mode,
(data->capture_count + 1) * 2);
macro_assembler.reset(new RegExpMacroAssemblerMIPS(
isolate, zone, mode, (data->capture_count + 1) * 2));
#else
#error "Unsupported architecture"
#endif
} else {
DCHECK(FLAG_regexp_interpret_all);
#else // V8_INTERPRETED_REGEXP
// Interpreted regexp implementation.
EmbeddedVector<byte, 1024> codes;
RegExpMacroAssemblerIrregexp macro_assembler(isolate, codes, zone);
#endif // V8_INTERPRETED_REGEXP
// Interpreted regexp implementation.
macro_assembler.reset(new RegExpMacroAssemblerIrregexp(isolate, zone));
}
macro_assembler.set_slow_safe(TooMuchRegExpCode(isolate, pattern));
macro_assembler->set_slow_safe(TooMuchRegExpCode(isolate, pattern));
// Inserted here, instead of in Assembler, because it depends on information
// in the AST that isn't replicated in the Node structure.
static const int kMaxBacksearchLimit = 1024;
if (is_end_anchored && !is_start_anchored && !is_sticky &&
max_length < kMaxBacksearchLimit) {
macro_assembler.SetCurrentPositionFromEnd(max_length);
macro_assembler->SetCurrentPositionFromEnd(max_length);
}
if (is_global) {
@ -6758,11 +6745,11 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(
} else if (is_unicode) {
mode = RegExpMacroAssembler::GLOBAL_UNICODE;
}
macro_assembler.set_global_mode(mode);
macro_assembler->set_global_mode(mode);
}
return compiler.Assemble(isolate, &macro_assembler, node, data->capture_count,
pattern);
return compiler.Assemble(isolate, macro_assembler.get(), node,
data->capture_count, pattern);
}
bool RegExpEngine::TooMuchRegExpCode(Isolate* isolate, Handle<String> pattern) {

View File

@ -53,14 +53,8 @@ inline bool NeedsUnicodeCaseEquivalents(JSRegExp::Flags flags) {
class RegExpImpl {
public:
// Whether V8 is compiled with native regexp support or not.
static bool UsesNativeRegExp() {
#ifdef V8_INTERPRETED_REGEXP
return false;
#else
return true;
#endif
}
// Whether the irregexp engine generates native code or interpreter bytecode.
static bool UsesNativeRegExp() { return !FLAG_regexp_interpret_all; }
// Returns a string representation of a regular expression.
// Implements RegExp.prototype.toString, see ECMA-262 section 15.10.6.4.

View File

@ -18,7 +18,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
/*
* This assembler uses the following register assignment convention
* - t7 : Temporarily stores the index of capture start after a matching pass
@ -1308,8 +1307,6 @@ void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset,
#undef __
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -12,7 +12,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
class RegExpMacroAssemblerMIPS: public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerMIPS(Isolate* isolate, Zone* zone, Mode mode,
@ -218,9 +217,6 @@ class RegExpMacroAssemblerMIPS: public NativeRegExpMacroAssembler {
Label internal_failure_label_;
};
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -18,8 +18,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
/* clang-format off
*
* This assembler uses the following register assignment convention
@ -1345,8 +1343,6 @@ void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset,
#undef __
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -12,7 +12,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
class RegExpMacroAssemblerMIPS: public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerMIPS(Isolate* isolate, Zone* zone, Mode mode,
@ -223,9 +222,6 @@ class RegExpMacroAssemblerMIPS: public NativeRegExpMacroAssembler {
Label internal_failure_label_;
};
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -18,7 +18,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
/*
* This assembler uses the following register assignment convention
* - r25: Temporarily stores the index of capture start after a matching pass
@ -1327,10 +1326,8 @@ void RegExpMacroAssemblerPPC::LoadCurrentCharacterUnchecked(int cp_offset,
#endif
}
#undef __
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -12,8 +12,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
class RegExpMacroAssemblerPPC : public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerPPC(Isolate* isolate, Zone* zone, Mode mode,
@ -207,7 +205,6 @@ class RegExpMacroAssemblerPPC : public NativeRegExpMacroAssembler {
const RegList kRegExpCalleeSaved =
1 << 25 | 1 << 26 | 1 << 27 | 1 << 28 | 1 << 29 | 1 << 30 | 1 << 31;
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -5,8 +5,6 @@
#ifndef V8_REGEXP_REGEXP_MACRO_ASSEMBLER_IRREGEXP_INL_H_
#define V8_REGEXP_REGEXP_MACRO_ASSEMBLER_IRREGEXP_INL_H_
#ifdef V8_INTERPRETED_REGEXP
#include "src/regexp/regexp-macro-assembler-irregexp.h"
#include "src/ast/ast.h"
@ -59,6 +57,4 @@ void RegExpMacroAssemblerIrregexp::Emit32(uint32_t word) {
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETED_REGEXP
#endif // V8_REGEXP_REGEXP_MACRO_ASSEMBLER_IRREGEXP_INL_H_

View File

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef V8_INTERPRETED_REGEXP
#include "src/regexp/regexp-macro-assembler-irregexp.h"
#include "src/ast/ast.h"
@ -16,16 +14,14 @@ namespace v8 {
namespace internal {
RegExpMacroAssemblerIrregexp::RegExpMacroAssemblerIrregexp(Isolate* isolate,
Vector<byte> buffer,
Zone* zone)
: RegExpMacroAssembler(isolate, zone),
buffer_(buffer),
buffer_(Vector<byte>::New(1024)),
pc_(0),
own_buffer_(false),
own_buffer_(true),
advance_current_end_(kInvalidPC),
isolate_(isolate) {}
RegExpMacroAssemblerIrregexp::~RegExpMacroAssemblerIrregexp() {
if (backtrack_.is_linked()) backtrack_.Unuse();
if (own_buffer_) buffer_.Dispose();
@ -457,5 +453,3 @@ void RegExpMacroAssemblerIrregexp::Expand() {
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETED_REGEXP

View File

@ -5,8 +5,6 @@
#ifndef V8_REGEXP_REGEXP_MACRO_ASSEMBLER_IRREGEXP_H_
#define V8_REGEXP_REGEXP_MACRO_ASSEMBLER_IRREGEXP_H_
#ifdef V8_INTERPRETED_REGEXP
#include "src/regexp/regexp-macro-assembler.h"
namespace v8 {
@ -20,17 +18,10 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
// 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 nullptr, 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 nullptr, 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.
RegExpMacroAssemblerIrregexp(Isolate* isolate, Vector<byte> buffer,
Zone* zone);
// 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.
RegExpMacroAssemblerIrregexp(Isolate* isolate, Zone* zone);
virtual ~RegExpMacroAssemblerIrregexp();
// The byte-code interpreter checks on each push anyway.
virtual int stack_limit_slack() { return 1; }
@ -129,6 +120,4 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETED_REGEXP
#endif // V8_REGEXP_REGEXP_MACRO_ASSEMBLER_IRREGEXP_H_

View File

@ -108,8 +108,6 @@ bool RegExpMacroAssembler::CheckSpecialCharacterClass(uc16 type,
return false;
}
#ifndef V8_INTERPRETED_REGEXP // Avoid unused code, e.g., on ARM.
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(Isolate* isolate,
Zone* zone)
: RegExpMacroAssembler(isolate, zone) {}
@ -360,7 +358,5 @@ Address NativeRegExpMacroAssembler::GrowStack(Address stack_pointer,
return new_stack_base - stack_content_size;
}
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -192,9 +192,6 @@ class RegExpMacroAssembler {
Zone* zone_;
};
#ifndef V8_INTERPRETED_REGEXP // Avoid compiling unused code.
class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
public:
// Type of input string to generate code for.
@ -253,8 +250,6 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
int* output, int output_size, Isolate* isolate);
};
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -19,7 +19,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
/*
* This assembler uses the following register assignment convention
* - r6: Temporarily stores the index of capture start after a matching pass
@ -1293,7 +1292,6 @@ void RegExpMacroAssemblerS390::LoadCurrentCharacterUnchecked(int cp_offset,
#undef __
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -12,7 +12,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
class RegExpMacroAssemblerS390 : public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerS390(Isolate* isolate, Zone* zone, Mode mode,
@ -207,7 +206,6 @@ class RegExpMacroAssemblerS390 : public NativeRegExpMacroAssembler {
const RegList kRegExpCalleeSaved =
1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 | 1 << 11 | 1 << 13;
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -17,8 +17,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
/*
* This assembler uses the following register assignment convention
* - rdx : Currently loaded character(s) as Latin1 or UC16. Must be loaded
@ -1396,8 +1394,6 @@ void RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(int cp_offset,
#undef __
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -13,8 +13,6 @@
namespace v8 {
namespace internal {
#ifndef V8_INTERPRETED_REGEXP
class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerX64(Isolate* isolate, Zone* zone, Mode mode,
@ -255,8 +253,6 @@ class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
Label stack_overflow_label_;
};
#endif // V8_INTERPRETED_REGEXP
} // namespace internal
} // namespace v8

View File

@ -537,10 +537,22 @@
# Tests that generate code at runtime.
'codegen-tester/*': [SKIP],
'test-api/RegExpInterruption': [SKIP],
'test-assembler-*': [SKIP],
'test-basic-block-profiler/*': [SKIP],
'test-branch-combine/*': [SKIP],
'test-multiple-return/*': [SKIP],
'test-regexp/MacroAssemblernativeAtStart': [SKIP],
'test-regexp/MacroAssemblerNativeBackReferenceLATIN1': [SKIP],
'test-regexp/MacroAssemblerNativeBackReferenceUC16': [SKIP],
'test-regexp/MacroAssemblerNativeBackRefNoCase': [SKIP],
'test-regexp/MacroAssemblerNativeBacktrack': [SKIP],
'test-regexp/MacroAssemblerNativeLotsOfRegisters': [SKIP],
'test-regexp/MacroAssemblerNativeRegisters': [SKIP],
'test-regexp/MacroAssemblerNativeSimple': [SKIP],
'test-regexp/MacroAssemblerNativeSimpleUC16': [SKIP],
'test-regexp/MacroAssemblerNativeSuccess': [SKIP],
'test-regexp/MacroAssemblerStackOverflow': [SKIP],
'test-run-calls-to-external-references/*': [SKIP],
}], # lite_mode

View File

@ -15690,9 +15690,6 @@ TEST(CompileExternalTwoByteSource) {
}
}
#ifndef V8_INTERPRETED_REGEXP
struct RegExpInterruptionData {
v8::base::Atomic32 loop_count;
UC16VectorResource* string_resource;
@ -15768,9 +15765,6 @@ TEST(RegExpInterruption) {
i::DeleteArray(uc16_content);
}
#endif // V8_INTERPRETED_REGEXP
// Test that we cannot set a property on the global object if there
// is a read-only property in the prototype chain.
TEST(ReadOnlyPropertyInGlobalProto) {

View File

@ -34,8 +34,10 @@
#include "src/assembler-arch.h"
#include "src/ast/ast.h"
#include "src/char-predicates-inl.h"
#include "src/macro-assembler.h"
#include "src/objects-inl.h"
#include "src/ostreams.h"
#include "src/regexp/interpreter-irregexp.h"
#include "src/regexp/jsregexp.h"
#include "src/regexp/regexp-macro-assembler-irregexp.h"
#include "src/regexp/regexp-macro-assembler.h"
@ -45,35 +47,26 @@
#include "src/unicode-inl.h"
#include "src/v8.h"
#ifdef V8_INTERPRETED_REGEXP
#include "src/regexp/interpreter-irregexp.h"
#else // V8_INTERPRETED_REGEXP
#include "src/macro-assembler.h"
#if V8_TARGET_ARCH_ARM
#include "src/regexp/arm/regexp-macro-assembler-arm.h"
#endif
#if V8_TARGET_ARCH_ARM64
#elif V8_TARGET_ARCH_ARM64
#include "src/regexp/arm64/regexp-macro-assembler-arm64.h"
#endif
#if V8_TARGET_ARCH_S390
#elif V8_TARGET_ARCH_S390
#include "src/regexp/s390/regexp-macro-assembler-s390.h"
#endif
#if V8_TARGET_ARCH_PPC
#elif V8_TARGET_ARCH_PPC
#include "src/regexp/ppc/regexp-macro-assembler-ppc.h"
#endif
#if V8_TARGET_ARCH_MIPS
#elif V8_TARGET_ARCH_MIPS
#include "src/regexp/mips/regexp-macro-assembler-mips.h"
#endif
#if V8_TARGET_ARCH_MIPS64
#elif V8_TARGET_ARCH_MIPS64
#include "src/regexp/mips64/regexp-macro-assembler-mips64.h"
#endif
#if V8_TARGET_ARCH_X64
#elif V8_TARGET_ARCH_X64
#include "src/regexp/x64/regexp-macro-assembler-x64.h"
#endif
#if V8_TARGET_ARCH_IA32
#elif V8_TARGET_ARCH_IA32
#include "src/regexp/ia32/regexp-macro-assembler-ia32.h"
#else
#error Unknown architecture.
#endif
#endif // V8_INTERPRETED_REGEXP
#include "test/cctest/cctest.h"
namespace v8 {
@ -738,9 +731,6 @@ TEST(ParsePossessiveRepetition) {
// Tests of interpreter.
#ifndef V8_INTERPRETED_REGEXP
#if V8_TARGET_ARCH_IA32
typedef RegExpMacroAssemblerIA32 ArchRegExpMacroAssembler;
#elif V8_TARGET_ARCH_X64
@ -1397,13 +1387,9 @@ TEST(MacroAssemblerNativeLotsOfRegisters) {
isolate->clear_pending_exception();
}
#else // V8_INTERPRETED_REGEXP
TEST(MacroAssembler) {
byte codes[1024];
Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
RegExpMacroAssemblerIrregexp m(CcTest::i_isolate(), Vector<byte>(codes, 1024),
&zone);
RegExpMacroAssemblerIrregexp m(CcTest::i_isolate(), &zone);
// ^f(o)o.
Label start, fail, backtrack;
@ -1462,9 +1448,6 @@ TEST(MacroAssembler) {
CHECK_EQ(42, captures[0]);
}
#endif // V8_INTERPRETED_REGEXP
TEST(AddInverseToTable) {
static const int kLimit = 1000;
static const int kRangeCount = 16;

View File

@ -860,7 +860,6 @@ UNINITIALIZED_TEST(CustomSnapshotDataBlobStringNotInternalized) {
FreeCurrentEmbeddedBlob();
}
#ifndef V8_INTERPRETED_REGEXP
namespace {
void TestCustomSnapshotDataBlobWithIrregexpCode(
@ -937,7 +936,6 @@ UNINITIALIZED_TEST(CustomSnapshotDataBlobWithIrregexpCodeClearCode) {
TestCustomSnapshotDataBlobWithIrregexpCode(
v8::SnapshotCreator::FunctionCodeHandling::kClear);
}
#endif // V8_INTERPRETED_REGEXP
UNINITIALIZED_TEST(SnapshotChecksum) {
DisableAlwaysOpt();

View File

@ -854,26 +854,26 @@ class TerminatorSleeperThread : public v8::base::Thread {
};
TEST(TerminateRegExp) {
// regexp interpreter does not support preemption.
#ifndef V8_INTERPRETED_REGEXP
i::FLAG_allow_natives_syntax = true;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::Local<v8::ObjectTemplate> global = CreateGlobalTemplate(
isolate, TerminateCurrentThread, DoLoopCancelTerminate);
v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
v8::Context::Scope context_scope(context);
CHECK(!isolate->IsExecutionTerminating());
v8::TryCatch try_catch(isolate);
CHECK(!isolate->IsExecutionTerminating());
CHECK(!CompileRun("var re = /(x+)+y$/; re.test('x');").IsEmpty());
TerminatorSleeperThread terminator(isolate, 100);
terminator.Start();
CHECK(CompileRun("re.test('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); fail();")
.IsEmpty());
CHECK(try_catch.HasCaught());
CHECK(isolate->IsExecutionTerminating());
#endif // V8_INTERPRETED_REGEXP
// The regexp interpreter does not support preemption.
if (!i::FLAG_regexp_interpret_all) {
i::FLAG_allow_natives_syntax = true;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::Local<v8::ObjectTemplate> global = CreateGlobalTemplate(
isolate, TerminateCurrentThread, DoLoopCancelTerminate);
v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
v8::Context::Scope context_scope(context);
CHECK(!isolate->IsExecutionTerminating());
v8::TryCatch try_catch(isolate);
CHECK(!isolate->IsExecutionTerminating());
CHECK(!CompileRun("var re = /(x+)+y$/; re.test('x');").IsEmpty());
TerminatorSleeperThread terminator(isolate, 100);
terminator.Start();
CHECK(CompileRun("re.test('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); fail();")
.IsEmpty());
CHECK(try_catch.HasCaught());
CHECK(isolate->IsExecutionTerminating());
}
}
TEST(TerminateInMicrotask) {