|
@@ -1,1736 +0,0 @@
|
|
|
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
-From: Jakob Gruber <[email protected]>
|
|
|
-Date: Thu, 23 Sep 2021 07:26:38 +0200
|
|
|
-Subject: Allow reentrant irregexp execution
|
|
|
-
|
|
|
-.. by reusing the regexp stack from potentially multiple nested
|
|
|
-irregexp activations.
|
|
|
-
|
|
|
-To do this, we now maintain a stack pointer in RegExpStack. This stack
|
|
|
-pointer is synchronized at all boundaries between generated irregexp
|
|
|
-code and the outside world, i.e. when entering or returning from
|
|
|
-irregexp code, and when calling into C functions such as GrowStack.
|
|
|
-
|
|
|
-Fixed: v8:11382
|
|
|
-Change-Id: I5ed27630c1a64ebf3afb9ddf80fb60ea067c0c40
|
|
|
-Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3162604
|
|
|
-Reviewed-by: Toon Verwaest <[email protected]>
|
|
|
-Reviewed-by: Patrick Thier <[email protected]>
|
|
|
-Commit-Queue: Toon Verwaest <[email protected]>
|
|
|
-Auto-Submit: Jakob Gruber <[email protected]>
|
|
|
-Cr-Commit-Position: refs/heads/main@{#77013}
|
|
|
-
|
|
|
-diff --git a/src/api/api.cc b/src/api/api.cc
|
|
|
-index d09a84023ba633d3506ba0d49860da015b9104a6..882581b69ea0c46690e9971f73f76f014b3279f0 100644
|
|
|
---- a/src/api/api.cc
|
|
|
-+++ b/src/api/api.cc
|
|
|
-@@ -108,7 +108,6 @@
|
|
|
- #include "src/profiler/heap-snapshot-generator-inl.h"
|
|
|
- #include "src/profiler/profile-generator-inl.h"
|
|
|
- #include "src/profiler/tick-sample.h"
|
|
|
--#include "src/regexp/regexp-stack.h"
|
|
|
- #include "src/regexp/regexp-utils.h"
|
|
|
- #include "src/runtime/runtime.h"
|
|
|
- #include "src/snapshot/code-serializer.h"
|
|
|
-diff --git a/src/codegen/external-reference.cc b/src/codegen/external-reference.cc
|
|
|
-index b58157b16357040dd11fa4a4b8dbcd9d12244e81..b9a6cb6def990c8cc6c61b64f548964fa2483a37 100644
|
|
|
---- a/src/codegen/external-reference.cc
|
|
|
-+++ b/src/codegen/external-reference.cc
|
|
|
-@@ -761,6 +761,11 @@ ExternalReference ExternalReference::address_of_regexp_stack_memory_top_address(
|
|
|
- isolate->regexp_stack()->memory_top_address_address());
|
|
|
- }
|
|
|
-
|
|
|
-+ExternalReference ExternalReference::address_of_regexp_stack_stack_pointer(
|
|
|
-+ Isolate* isolate) {
|
|
|
-+ return ExternalReference(isolate->regexp_stack()->stack_pointer_address());
|
|
|
-+}
|
|
|
-+
|
|
|
- ExternalReference ExternalReference::javascript_execution_assert(
|
|
|
- Isolate* isolate) {
|
|
|
- return ExternalReference(isolate->javascript_execution_assert_address());
|
|
|
-diff --git a/src/codegen/external-reference.h b/src/codegen/external-reference.h
|
|
|
-index ca62ff9d7a32b6782e86b1b2bf24dddf69a0be6d..9f112240d215e3288a3dfb4051ae69d36dd340c1 100644
|
|
|
---- a/src/codegen/external-reference.h
|
|
|
-+++ b/src/codegen/external-reference.h
|
|
|
-@@ -72,6 +72,8 @@ class StatsCounter;
|
|
|
- "RegExpStack::limit_address_address()") \
|
|
|
- V(address_of_regexp_stack_memory_top_address, \
|
|
|
- "RegExpStack::memory_top_address_address()") \
|
|
|
-+ V(address_of_regexp_stack_stack_pointer, \
|
|
|
-+ "RegExpStack::stack_pointer_address()") \
|
|
|
- V(address_of_static_offsets_vector, "OffsetsVector::static_offsets_vector") \
|
|
|
- V(thread_in_wasm_flag_address_address, \
|
|
|
- "Isolate::thread_in_wasm_flag_address_address") \
|
|
|
-diff --git a/src/debug/debug-interface.cc b/src/debug/debug-interface.cc
|
|
|
-index add2b3dbb4dc2e71a6dec717c29d957809797abf..e6ae32f9d2c11152c5184775f26e48a6870091ab 100644
|
|
|
---- a/src/debug/debug-interface.cc
|
|
|
-+++ b/src/debug/debug-interface.cc
|
|
|
-@@ -17,7 +17,6 @@
|
|
|
- #include "src/objects/js-generator-inl.h"
|
|
|
- #include "src/objects/stack-frame-info-inl.h"
|
|
|
- #include "src/profiler/heap-profiler.h"
|
|
|
--#include "src/regexp/regexp-stack.h"
|
|
|
- #include "src/strings/string-builder-inl.h"
|
|
|
-
|
|
|
- #if V8_ENABLE_WEBASSEMBLY
|
|
|
-@@ -304,10 +303,7 @@ void SetTerminateOnResume(Isolate* v8_isolate) {
|
|
|
- bool CanBreakProgram(Isolate* v8_isolate) {
|
|
|
- i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
|
|
- ENTER_V8_DO_NOT_USE(isolate);
|
|
|
-- // We cannot break a program if we are currently running a regexp.
|
|
|
-- // TODO(yangguo): fix this exception.
|
|
|
-- return !isolate->regexp_stack()->is_in_use() &&
|
|
|
-- isolate->debug()->AllFramesOnStackAreBlackboxed();
|
|
|
-+ return isolate->debug()->AllFramesOnStackAreBlackboxed();
|
|
|
- }
|
|
|
-
|
|
|
- Isolate* Script::GetIsolate() const {
|
|
|
-diff --git a/src/execution/isolate.cc b/src/execution/isolate.cc
|
|
|
-index 474ea612bda4bf44776b919fd20e86e85ba3e3ce..ffcf10e4d282b85f1a22fa656113709f09ef34f2 100644
|
|
|
---- a/src/execution/isolate.cc
|
|
|
-+++ b/src/execution/isolate.cc
|
|
|
-@@ -3596,7 +3596,6 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data,
|
|
|
- store_stub_cache_ = new StubCache(this);
|
|
|
- materialized_object_store_ = new MaterializedObjectStore(this);
|
|
|
- regexp_stack_ = new RegExpStack();
|
|
|
-- regexp_stack_->isolate_ = this;
|
|
|
- date_cache_ = new DateCache();
|
|
|
- heap_profiler_ = new HeapProfiler(heap());
|
|
|
- interpreter_ = new interpreter::Interpreter(this);
|
|
|
-diff --git a/src/regexp/arm/regexp-macro-assembler-arm.cc b/src/regexp/arm/regexp-macro-assembler-arm.cc
|
|
|
-index 6c90e00817342a115ec49a21b561a7014e0ce8f8..10766db4cf1d41ad0fee0754c6eaeebe46ace500 100644
|
|
|
---- a/src/regexp/arm/regexp-macro-assembler-arm.cc
|
|
|
-+++ b/src/regexp/arm/regexp-macro-assembler-arm.cc
|
|
|
-@@ -6,15 +6,13 @@
|
|
|
-
|
|
|
- #include "src/regexp/arm/regexp-macro-assembler-arm.h"
|
|
|
-
|
|
|
--#include "src/codegen/assembler-inl.h"
|
|
|
-+#include "src/codegen/arm/assembler-arm-inl.h"
|
|
|
- #include "src/codegen/macro-assembler.h"
|
|
|
- #include "src/heap/factory.h"
|
|
|
- #include "src/logging/log.h"
|
|
|
--#include "src/objects/objects-inl.h"
|
|
|
--#include "src/regexp/regexp-macro-assembler.h"
|
|
|
-+#include "src/objects/code-inl.h"
|
|
|
- #include "src/regexp/regexp-stack.h"
|
|
|
- #include "src/snapshot/embedded/embedded-data.h"
|
|
|
--#include "src/strings/unicode.h"
|
|
|
-
|
|
|
- namespace v8 {
|
|
|
- namespace internal {
|
|
|
-@@ -102,6 +100,7 @@ RegExpMacroAssemblerARM::RegExpMacroAssemblerARM(Isolate* isolate, Zone* zone,
|
|
|
- : NativeRegExpMacroAssembler(isolate, zone),
|
|
|
- masm_(new MacroAssembler(isolate, CodeObjectRequired::kYes,
|
|
|
- NewAssemblerBuffer(kRegExpCodeSize))),
|
|
|
-+ no_root_array_scope_(masm_),
|
|
|
- mode_(mode),
|
|
|
- num_registers_(registers_to_save),
|
|
|
- num_saved_registers_(registers_to_save),
|
|
|
-@@ -110,8 +109,6 @@ RegExpMacroAssemblerARM::RegExpMacroAssemblerARM(Isolate* isolate, Zone* zone,
|
|
|
- success_label_(),
|
|
|
- backtrack_label_(),
|
|
|
- exit_label_() {
|
|
|
-- masm_->set_root_array_available(false);
|
|
|
--
|
|
|
- DCHECK_EQ(0, registers_to_save % 2);
|
|
|
- __ jmp(&entry_label_); // We'll write the entry code later.
|
|
|
- __ bind(&start_label_); // And then continue from here.
|
|
|
-@@ -619,6 +616,42 @@ void RegExpMacroAssemblerARM::Fail() {
|
|
|
- __ jmp(&exit_label_);
|
|
|
- }
|
|
|
-
|
|
|
-+void RegExpMacroAssemblerARM::LoadRegExpStackPointerFromMemory(Register dst) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
|
|
|
-+ __ mov(dst, Operand(ref));
|
|
|
-+ __ ldr(dst, MemOperand(dst));
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerARM::StoreRegExpStackPointerToMemory(
|
|
|
-+ Register src, Register scratch) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
|
|
|
-+ __ mov(scratch, Operand(ref));
|
|
|
-+ __ str(src, MemOperand(scratch));
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerARM::PushRegExpBasePointer(Register scratch1,
|
|
|
-+ Register scratch2) {
|
|
|
-+ LoadRegExpStackPointerFromMemory(scratch1);
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ mov(scratch2, Operand(ref));
|
|
|
-+ __ ldr(scratch2, MemOperand(scratch2));
|
|
|
-+ __ sub(scratch2, scratch1, scratch2);
|
|
|
-+ __ str(scratch2, MemOperand(frame_pointer(), kRegExpStackBasePointer));
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerARM::PopRegExpBasePointer(Register scratch1,
|
|
|
-+ Register scratch2) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ ldr(scratch1, MemOperand(frame_pointer(), kRegExpStackBasePointer));
|
|
|
-+ __ mov(scratch2, Operand(ref));
|
|
|
-+ __ ldr(scratch2, MemOperand(scratch2));
|
|
|
-+ __ add(scratch1, scratch1, scratch2);
|
|
|
-+ StoreRegExpStackPointerToMemory(scratch1, scratch2);
|
|
|
-+}
|
|
|
-
|
|
|
- Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
|
|
|
- Label return_r0;
|
|
|
-@@ -654,6 +687,13 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
|
|
|
- __ push(r0); // Make room for "string start - 1" constant.
|
|
|
- STATIC_ASSERT(kBacktrackCount == kStringStartMinusOne - kSystemPointerSize);
|
|
|
- __ push(r0); // The backtrack counter.
|
|
|
-+ STATIC_ASSERT(kRegExpStackBasePointer ==
|
|
|
-+ kBacktrackCount - kSystemPointerSize);
|
|
|
-+ __ push(r0); // The regexp stack base ptr.
|
|
|
-+
|
|
|
-+ // Store the regexp base pointer - we'll later restore it / write it to
|
|
|
-+ // memory when returning from this irregexp code object.
|
|
|
-+ PushRegExpBasePointer(r0, r1);
|
|
|
-
|
|
|
- // Check if we have space on the stack for registers.
|
|
|
- Label stack_limit_hit;
|
|
|
-@@ -736,7 +776,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
|
|
|
- }
|
|
|
-
|
|
|
- // Initialize backtrack stack pointer.
|
|
|
-- __ ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd));
|
|
|
-+ LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
|
|
|
-
|
|
|
- __ jmp(&start_label_);
|
|
|
-
|
|
|
-@@ -834,6 +874,10 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
|
|
|
- }
|
|
|
-
|
|
|
- __ bind(&return_r0);
|
|
|
-+ // Restore the original regexp stack pointer value (effectively, pop the
|
|
|
-+ // stored base pointer).
|
|
|
-+ PopRegExpBasePointer(r1, r2);
|
|
|
-+
|
|
|
- // Skip sp past regexp registers and local variables..
|
|
|
- __ mov(sp, frame_pointer());
|
|
|
- // Restore registers r4..r11 and return (restoring lr to pc).
|
|
|
-@@ -851,12 +895,16 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
|
|
|
- if (check_preempt_label_.is_linked()) {
|
|
|
- SafeCallTarget(&check_preempt_label_);
|
|
|
-
|
|
|
-+ StoreRegExpStackPointerToMemory(backtrack_stackpointer(), r1);
|
|
|
-+
|
|
|
- CallCheckStackGuardState();
|
|
|
- __ cmp(r0, Operand::Zero());
|
|
|
- // If returning non-zero, we should end execution with the given
|
|
|
- // result as return value.
|
|
|
- __ b(ne, &return_r0);
|
|
|
-
|
|
|
-+ LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
|
|
|
-+
|
|
|
- // String might have moved: Reload end of string from frame.
|
|
|
- __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
|
|
|
- SafeReturn();
|
|
|
-@@ -867,17 +915,18 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
|
|
|
- SafeCallTarget(&stack_overflow_label_);
|
|
|
- // Reached if the backtrack-stack limit has been hit.
|
|
|
-
|
|
|
-- // Call GrowStack(backtrack_stackpointer(), &stack_base)
|
|
|
-- static const int num_arguments = 3;
|
|
|
-- __ PrepareCallCFunction(num_arguments);
|
|
|
-- __ mov(r0, backtrack_stackpointer());
|
|
|
-- __ add(r1, frame_pointer(), Operand(kStackHighEnd));
|
|
|
-- __ mov(r2, Operand(ExternalReference::isolate_address(isolate())));
|
|
|
-+ // Call GrowStack(isolate).
|
|
|
-+
|
|
|
-+ StoreRegExpStackPointerToMemory(backtrack_stackpointer(), r1);
|
|
|
-+
|
|
|
-+ static constexpr int kNumArguments = 1;
|
|
|
-+ __ PrepareCallCFunction(kNumArguments);
|
|
|
-+ __ mov(r0, Operand(ExternalReference::isolate_address(isolate())));
|
|
|
- ExternalReference grow_stack =
|
|
|
- ExternalReference::re_grow_stack(isolate());
|
|
|
-- __ CallCFunction(grow_stack, num_arguments);
|
|
|
-- // If return nullptr, we have failed to grow the stack, and
|
|
|
-- // must exit with a stack-overflow exception.
|
|
|
-+ __ CallCFunction(grow_stack, kNumArguments);
|
|
|
-+ // If nullptr is returned, we have failed to grow the stack, and must exit
|
|
|
-+ // with a stack-overflow exception.
|
|
|
- __ cmp(r0, Operand::Zero());
|
|
|
- __ b(eq, &exit_with_exception);
|
|
|
- // Otherwise use return value as new stack pointer.
|
|
|
-@@ -984,14 +1033,24 @@ void RegExpMacroAssemblerARM::ReadCurrentPositionFromRegister(int reg) {
|
|
|
- __ ldr(current_input_offset(), register_location(reg));
|
|
|
- }
|
|
|
-
|
|
|
-+void RegExpMacroAssemblerARM::WriteStackPointerToRegister(int reg) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ mov(r1, Operand(ref));
|
|
|
-+ __ ldr(r1, MemOperand(r1));
|
|
|
-+ __ sub(r0, backtrack_stackpointer(), r1);
|
|
|
-+ __ str(r0, register_location(reg));
|
|
|
-+}
|
|
|
-
|
|
|
- void RegExpMacroAssemblerARM::ReadStackPointerFromRegister(int reg) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ mov(r0, Operand(ref));
|
|
|
-+ __ ldr(r0, MemOperand(r0));
|
|
|
- __ ldr(backtrack_stackpointer(), register_location(reg));
|
|
|
-- __ ldr(r0, MemOperand(frame_pointer(), kStackHighEnd));
|
|
|
-- __ add(backtrack_stackpointer(), backtrack_stackpointer(), Operand(r0));
|
|
|
-+ __ add(backtrack_stackpointer(), backtrack_stackpointer(), r0);
|
|
|
- }
|
|
|
-
|
|
|
--
|
|
|
- void RegExpMacroAssemblerARM::SetCurrentPositionFromEnd(int by) {
|
|
|
- Label after_position;
|
|
|
- __ cmp(current_input_offset(), Operand(-by * char_size()));
|
|
|
-@@ -1037,14 +1096,6 @@ void RegExpMacroAssemblerARM::ClearRegisters(int reg_from, int reg_to) {
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
--
|
|
|
--void RegExpMacroAssemblerARM::WriteStackPointerToRegister(int reg) {
|
|
|
-- __ ldr(r1, MemOperand(frame_pointer(), kStackHighEnd));
|
|
|
-- __ sub(r0, backtrack_stackpointer(), r1);
|
|
|
-- __ str(r0, register_location(reg));
|
|
|
--}
|
|
|
--
|
|
|
--
|
|
|
- // Private methods:
|
|
|
-
|
|
|
- void RegExpMacroAssemblerARM::CallCheckStackGuardState() {
|
|
|
-diff --git a/src/regexp/arm/regexp-macro-assembler-arm.h b/src/regexp/arm/regexp-macro-assembler-arm.h
|
|
|
-index a02a4dc2af546e53a89161aad9f3500a51c062f8..a76f9dea70264d79d57ebd6c60b100bc9e0a499d 100644
|
|
|
---- a/src/regexp/arm/regexp-macro-assembler-arm.h
|
|
|
-+++ b/src/regexp/arm/regexp-macro-assembler-arm.h
|
|
|
-@@ -5,8 +5,6 @@
|
|
|
- #ifndef V8_REGEXP_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
|
|
- #define V8_REGEXP_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
|
|
-
|
|
|
--#include "src/base/strings.h"
|
|
|
--#include "src/codegen/arm/assembler-arm.h"
|
|
|
- #include "src/codegen/macro-assembler.h"
|
|
|
- #include "src/regexp/regexp-macro-assembler.h"
|
|
|
-
|
|
|
-@@ -115,8 +113,14 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
|
|
|
- static const int kSuccessfulCaptures = kInputString - kPointerSize;
|
|
|
- static const int kStringStartMinusOne = kSuccessfulCaptures - kPointerSize;
|
|
|
- static const int kBacktrackCount = kStringStartMinusOne - kSystemPointerSize;
|
|
|
-+ // Stores the initial value of the regexp stack pointer in a
|
|
|
-+ // position-independent representation (in case the regexp stack grows and
|
|
|
-+ // thus moves).
|
|
|
-+ static const int kRegExpStackBasePointer =
|
|
|
-+ kBacktrackCount - kSystemPointerSize;
|
|
|
-+
|
|
|
- // First register address. Following registers are below it on the stack.
|
|
|
-- static const int kRegisterZero = kBacktrackCount - kSystemPointerSize;
|
|
|
-+ static const int kRegisterZero = kRegExpStackBasePointer - kSystemPointerSize;
|
|
|
-
|
|
|
- // Initial size of code buffer.
|
|
|
- static const int kRegExpCodeSize = 1024;
|
|
|
-@@ -129,7 +133,6 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
|
|
|
- // Check whether we are exceeding the stack limit on the backtrack stack.
|
|
|
- void CheckStackLimit();
|
|
|
-
|
|
|
--
|
|
|
- // Generate a call to CheckStackGuardState.
|
|
|
- void CallCheckStackGuardState();
|
|
|
-
|
|
|
-@@ -138,27 +141,27 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
|
|
|
-
|
|
|
- // Register holding the current input position as negative offset from
|
|
|
- // the end of the string.
|
|
|
-- inline Register current_input_offset() { return r6; }
|
|
|
-+ static constexpr Register current_input_offset() { return r6; }
|
|
|
-
|
|
|
- // The register containing the current character after LoadCurrentCharacter.
|
|
|
-- inline Register current_character() { return r7; }
|
|
|
-+ static constexpr Register current_character() { return r7; }
|
|
|
-
|
|
|
- // Register holding address of the end of the input string.
|
|
|
-- inline Register end_of_input_address() { return r10; }
|
|
|
-+ static constexpr 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; }
|
|
|
-+ static constexpr 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; }
|
|
|
-+ static constexpr Register backtrack_stackpointer() { return r8; }
|
|
|
-
|
|
|
- // Register holding pointer to the current code object.
|
|
|
-- inline Register code_pointer() { return r5; }
|
|
|
-+ static constexpr 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_); }
|
|
|
-+ inline int char_size() const { return static_cast<int>(mode_); }
|
|
|
-
|
|
|
- // Equivalent to a conditional branch to the label, unless the label
|
|
|
- // is nullptr, in which case it is a conditional Backtrack.
|
|
|
-@@ -178,19 +181,25 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
|
|
|
- // and increments it by a word size.
|
|
|
- inline void Pop(Register target);
|
|
|
-
|
|
|
-+ void LoadRegExpStackPointerFromMemory(Register dst);
|
|
|
-+ void StoreRegExpStackPointerToMemory(Register src, Register scratch);
|
|
|
-+ void PushRegExpBasePointer(Register scratch1, Register scratch2);
|
|
|
-+ void PopRegExpBasePointer(Register scratch1, Register scratch2);
|
|
|
-+
|
|
|
- Isolate* isolate() const { return masm_->isolate(); }
|
|
|
-
|
|
|
-- MacroAssembler* masm_;
|
|
|
-+ MacroAssembler* const masm_;
|
|
|
-+ const NoRootArrayScope no_root_array_scope_;
|
|
|
-
|
|
|
- // Which mode to generate code for (Latin1 or UC16).
|
|
|
-- Mode mode_;
|
|
|
-+ const 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_;
|
|
|
-+ const int num_saved_registers_;
|
|
|
-
|
|
|
- // Labels used internally.
|
|
|
- Label entry_label_;
|
|
|
-diff --git a/src/regexp/arm64/regexp-macro-assembler-arm64.cc b/src/regexp/arm64/regexp-macro-assembler-arm64.cc
|
|
|
-index 67793ffc411ccb9c32f67fff393e6b77d094b325..6192461fa32879469d56d36fb788b5de33038d77 100644
|
|
|
---- a/src/regexp/arm64/regexp-macro-assembler-arm64.cc
|
|
|
-+++ b/src/regexp/arm64/regexp-macro-assembler-arm64.cc
|
|
|
-@@ -113,6 +113,7 @@ RegExpMacroAssemblerARM64::RegExpMacroAssemblerARM64(Isolate* isolate,
|
|
|
- : NativeRegExpMacroAssembler(isolate, zone),
|
|
|
- masm_(new MacroAssembler(isolate, CodeObjectRequired::kYes,
|
|
|
- NewAssemblerBuffer(kRegExpCodeSize))),
|
|
|
-+ no_root_array_scope_(masm_),
|
|
|
- mode_(mode),
|
|
|
- num_registers_(registers_to_save),
|
|
|
- num_saved_registers_(registers_to_save),
|
|
|
-@@ -121,8 +122,6 @@ RegExpMacroAssemblerARM64::RegExpMacroAssemblerARM64(Isolate* isolate,
|
|
|
- success_label_(),
|
|
|
- backtrack_label_(),
|
|
|
- exit_label_() {
|
|
|
-- masm_->set_root_array_available(false);
|
|
|
--
|
|
|
- DCHECK_EQ(0, registers_to_save % 2);
|
|
|
- // We can cache at most 16 W registers in x0-x7.
|
|
|
- STATIC_ASSERT(kNumCachedRegisters <= 16);
|
|
|
-@@ -699,6 +698,42 @@ void RegExpMacroAssemblerARM64::Fail() {
|
|
|
- __ B(&exit_label_);
|
|
|
- }
|
|
|
-
|
|
|
-+void RegExpMacroAssemblerARM64::LoadRegExpStackPointerFromMemory(Register dst) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
|
|
|
-+ __ Mov(dst, ref);
|
|
|
-+ __ Ldr(dst, MemOperand(dst));
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerARM64::StoreRegExpStackPointerToMemory(
|
|
|
-+ Register src, Register scratch) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
|
|
|
-+ __ Mov(scratch, ref);
|
|
|
-+ __ Str(src, MemOperand(scratch));
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerARM64::PushRegExpBasePointer(Register scratch1,
|
|
|
-+ Register scratch2) {
|
|
|
-+ LoadRegExpStackPointerFromMemory(scratch1);
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ Mov(scratch2, ref);
|
|
|
-+ __ Ldr(scratch2, MemOperand(scratch2));
|
|
|
-+ __ Sub(scratch2, scratch1, scratch2);
|
|
|
-+ __ Str(scratch2, MemOperand(frame_pointer(), kRegExpStackBasePointer));
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerARM64::PopRegExpBasePointer(Register scratch1,
|
|
|
-+ Register scratch2) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ Ldr(scratch1, MemOperand(frame_pointer(), kRegExpStackBasePointer));
|
|
|
-+ __ Mov(scratch2, ref);
|
|
|
-+ __ Ldr(scratch2, MemOperand(scratch2));
|
|
|
-+ __ Add(scratch1, scratch1, scratch2);
|
|
|
-+ StoreRegExpStackPointerToMemory(scratch1, scratch2);
|
|
|
-+}
|
|
|
-
|
|
|
- Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
|
|
|
- Label return_w0;
|
|
|
-@@ -744,22 +779,27 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
|
|
|
- __ Mov(input_end(), x3);
|
|
|
- __ Mov(output_array(), x4);
|
|
|
-
|
|
|
-- // Set the number of registers we will need to allocate, that is:
|
|
|
-- // - kSuccessCounter / success_counter (X register)
|
|
|
-- // - kBacktrackCount (X register)
|
|
|
-- // - (num_registers_ - kNumCachedRegisters) (W registers)
|
|
|
-- int num_wreg_to_allocate = num_registers_ - kNumCachedRegisters;
|
|
|
-- // Do not allocate registers on the stack if they can all be cached.
|
|
|
-- if (num_wreg_to_allocate < 0) { num_wreg_to_allocate = 0; }
|
|
|
-- // Make room for the success_counter and kBacktrackCount. Each X (64-bit)
|
|
|
-- // register is equivalent to two W (32-bit) registers.
|
|
|
-- num_wreg_to_allocate += 2 + 2;
|
|
|
--
|
|
|
- // Make sure the stack alignment will be respected.
|
|
|
-- int alignment = masm_->ActivationFrameAlignment();
|
|
|
-+ const int alignment = masm_->ActivationFrameAlignment();
|
|
|
- DCHECK_EQ(alignment % 16, 0);
|
|
|
-- int align_mask = (alignment / kWRegSize) - 1;
|
|
|
-- num_wreg_to_allocate = (num_wreg_to_allocate + align_mask) & ~align_mask;
|
|
|
-+ const int align_mask = (alignment / kWRegSize) - 1;
|
|
|
-+
|
|
|
-+ // Make room for stack locals.
|
|
|
-+ static constexpr int kWRegPerXReg = kXRegSize / kWRegSize;
|
|
|
-+ DCHECK_EQ(kNumberOfStackLocals * kWRegPerXReg,
|
|
|
-+ ((kNumberOfStackLocals * kWRegPerXReg) + align_mask) & ~align_mask);
|
|
|
-+ __ Claim(kNumberOfStackLocals * kWRegPerXReg);
|
|
|
-+
|
|
|
-+ // Store the regexp base pointer - we'll later restore it / write it to
|
|
|
-+ // memory when returning from this irregexp code object.
|
|
|
-+ PushRegExpBasePointer(x10, x11);
|
|
|
-+
|
|
|
-+ // Set the number of registers we will need to allocate, that is:
|
|
|
-+ // - (num_registers_ - kNumCachedRegisters) (W registers)
|
|
|
-+ const int num_stack_registers =
|
|
|
-+ std::max(0, num_registers_ - kNumCachedRegisters);
|
|
|
-+ const int num_wreg_to_allocate =
|
|
|
-+ (num_stack_registers + align_mask) & ~align_mask;
|
|
|
-
|
|
|
- // Check if we have space on the stack.
|
|
|
- Label stack_limit_hit;
|
|
|
-@@ -839,9 +879,9 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
|
|
|
- }
|
|
|
-
|
|
|
- // Initialize backtrack stack pointer.
|
|
|
-- __ Ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackBase));
|
|
|
-+ LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
|
|
|
-
|
|
|
-- // Execute
|
|
|
-+ // Execute.
|
|
|
- __ B(&start_label_);
|
|
|
-
|
|
|
- if (backtrack_label_.is_linked()) {
|
|
|
-@@ -1013,7 +1053,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
|
|
|
- }
|
|
|
-
|
|
|
- if (exit_label_.is_linked()) {
|
|
|
-- // Exit and return w0
|
|
|
-+ // Exit and return w0.
|
|
|
- __ Bind(&exit_label_);
|
|
|
- if (global()) {
|
|
|
- __ Ldr(w0, MemOperand(frame_pointer(), kSuccessCounter));
|
|
|
-@@ -1021,8 +1061,11 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
|
|
|
- }
|
|
|
-
|
|
|
- __ Bind(&return_w0);
|
|
|
-+ // Restore the original regexp stack pointer value (effectively, pop the
|
|
|
-+ // stored base pointer).
|
|
|
-+ PopRegExpBasePointer(x10, x11);
|
|
|
-
|
|
|
-- // Set stack pointer back to first register to retain
|
|
|
-+ // Set stack pointer back to first register to retain.
|
|
|
- __ Mov(sp, fp);
|
|
|
- __ Pop<TurboAssembler::kAuthLR>(fp, lr);
|
|
|
-
|
|
|
-@@ -1039,6 +1082,9 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
|
|
|
-
|
|
|
- if (check_preempt_label_.is_linked()) {
|
|
|
- __ Bind(&check_preempt_label_);
|
|
|
-+
|
|
|
-+ StoreRegExpStackPointerToMemory(backtrack_stackpointer(), x10);
|
|
|
-+
|
|
|
- SaveLinkRegister();
|
|
|
- // The cached registers need to be retained.
|
|
|
- __ PushCPURegList(cached_registers);
|
|
|
-@@ -1048,26 +1094,30 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
|
|
|
- __ Cbnz(w0, &return_w0);
|
|
|
- // Reset the cached registers.
|
|
|
- __ PopCPURegList(cached_registers);
|
|
|
-+
|
|
|
-+ LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
|
|
|
-+
|
|
|
- RestoreLinkRegister();
|
|
|
- __ Ret();
|
|
|
- }
|
|
|
-
|
|
|
- if (stack_overflow_label_.is_linked()) {
|
|
|
- __ Bind(&stack_overflow_label_);
|
|
|
-+
|
|
|
-+ StoreRegExpStackPointerToMemory(backtrack_stackpointer(), x10);
|
|
|
-+
|
|
|
- SaveLinkRegister();
|
|
|
- // The cached registers need to be retained.
|
|
|
- __ PushCPURegList(cached_registers);
|
|
|
-- // Call GrowStack(backtrack_stackpointer(), &stack_base)
|
|
|
-- __ Mov(x2, ExternalReference::isolate_address(isolate()));
|
|
|
-- __ Add(x1, frame_pointer(), kStackBase);
|
|
|
-- __ Mov(x0, backtrack_stackpointer());
|
|
|
-- ExternalReference grow_stack =
|
|
|
-- ExternalReference::re_grow_stack(isolate());
|
|
|
-- __ CallCFunction(grow_stack, 3);
|
|
|
-- // If return nullptr, we have failed to grow the stack, and
|
|
|
-- // must exit with a stack-overflow exception.
|
|
|
-- // Returning from the regexp code restores the stack (sp <- fp)
|
|
|
-- // so we don't need to drop the link register from it before exiting.
|
|
|
-+ // Call GrowStack(isolate)
|
|
|
-+ static constexpr int kNumArguments = 1;
|
|
|
-+ __ Mov(x0, ExternalReference::isolate_address(isolate()));
|
|
|
-+ __ CallCFunction(ExternalReference::re_grow_stack(isolate()),
|
|
|
-+ kNumArguments);
|
|
|
-+ // If return nullptr, we have failed to grow the stack, and must exit with
|
|
|
-+ // a stack-overflow exception. Returning from the regexp code restores the
|
|
|
-+ // stack (sp <- fp) so we don't need to drop the link register from it
|
|
|
-+ // before exiting.
|
|
|
- __ Cbz(w0, &exit_with_exception);
|
|
|
- // Otherwise use return value as new stack pointer.
|
|
|
- __ Mov(backtrack_stackpointer(), x0);
|
|
|
-@@ -1191,14 +1241,29 @@ void RegExpMacroAssemblerARM64::ReadCurrentPositionFromRegister(int reg) {
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-+void RegExpMacroAssemblerARM64::WriteStackPointerToRegister(int reg) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ Mov(x10, ref);
|
|
|
-+ __ Ldr(x10, MemOperand(x10));
|
|
|
-+ __ Sub(x10, backtrack_stackpointer(), x10);
|
|
|
-+ if (FLAG_debug_code) {
|
|
|
-+ __ Cmp(x10, Operand(w10, SXTW));
|
|
|
-+ // The stack offset needs to fit in a W register.
|
|
|
-+ __ Check(eq, AbortReason::kOffsetOutOfRange);
|
|
|
-+ }
|
|
|
-+ StoreRegister(reg, w10);
|
|
|
-+}
|
|
|
-
|
|
|
- void RegExpMacroAssemblerARM64::ReadStackPointerFromRegister(int reg) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
- Register read_from = GetRegister(reg, w10);
|
|
|
-- __ Ldr(x11, MemOperand(frame_pointer(), kStackBase));
|
|
|
-+ __ Mov(x11, ref);
|
|
|
-+ __ Ldr(x11, MemOperand(x11));
|
|
|
- __ Add(backtrack_stackpointer(), x11, Operand(read_from, SXTW));
|
|
|
- }
|
|
|
-
|
|
|
--
|
|
|
- void RegExpMacroAssemblerARM64::SetCurrentPositionFromEnd(int by) {
|
|
|
- Label after_position;
|
|
|
- __ Cmp(current_input_offset(), -by * char_size());
|
|
|
-@@ -1300,19 +1365,6 @@ void RegExpMacroAssemblerARM64::ClearRegisters(int reg_from, int reg_to) {
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
--
|
|
|
--void RegExpMacroAssemblerARM64::WriteStackPointerToRegister(int reg) {
|
|
|
-- __ Ldr(x10, MemOperand(frame_pointer(), kStackBase));
|
|
|
-- __ Sub(x10, backtrack_stackpointer(), x10);
|
|
|
-- if (FLAG_debug_code) {
|
|
|
-- __ Cmp(x10, Operand(w10, SXTW));
|
|
|
-- // The stack offset needs to fit in a W register.
|
|
|
-- __ Check(eq, AbortReason::kOffsetOutOfRange);
|
|
|
-- }
|
|
|
-- StoreRegister(reg, w10);
|
|
|
--}
|
|
|
--
|
|
|
--
|
|
|
- // Helper function for reading a value out of a stack frame.
|
|
|
- template <typename T>
|
|
|
- static T& frame_entry(Address re_frame, int frame_offset) {
|
|
|
-diff --git a/src/regexp/arm64/regexp-macro-assembler-arm64.h b/src/regexp/arm64/regexp-macro-assembler-arm64.h
|
|
|
-index 80931e3ca42f7d85a3dea067ca203b252a0f78f0..204ee68dc868142693e9959170c71df3f72f97ce 100644
|
|
|
---- a/src/regexp/arm64/regexp-macro-assembler-arm64.h
|
|
|
-+++ b/src/regexp/arm64/regexp-macro-assembler-arm64.h
|
|
|
-@@ -110,18 +110,28 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
|
|
|
- // Below the frame pointer.
|
|
|
- // Register parameters stored by setup code.
|
|
|
- static const int kDirectCall = -kSystemPointerSize;
|
|
|
-- static const int kStackBase = kDirectCall - kSystemPointerSize;
|
|
|
-- static const int kOutputSize = kStackBase - kSystemPointerSize;
|
|
|
-+ static const int kStackHighEnd = kDirectCall - kSystemPointerSize;
|
|
|
-+ static const int kOutputSize = kStackHighEnd - kSystemPointerSize;
|
|
|
- static const int kInput = kOutputSize - kSystemPointerSize;
|
|
|
- // When adding local variables remember to push space for them in
|
|
|
- // the frame in GetCode.
|
|
|
- static const int kSuccessCounter = kInput - kSystemPointerSize;
|
|
|
- static const int kBacktrackCount = kSuccessCounter - kSystemPointerSize;
|
|
|
-+ // Stores the initial value of the regexp stack pointer in a
|
|
|
-+ // position-independent representation (in case the regexp stack grows and
|
|
|
-+ // thus moves).
|
|
|
-+ static const int kRegExpStackBasePointer =
|
|
|
-+ kBacktrackCount - kSystemPointerSize;
|
|
|
-+ // A padding slot to preserve alignment.
|
|
|
-+ static const int kStackLocalPadding =
|
|
|
-+ kRegExpStackBasePointer - kSystemPointerSize;
|
|
|
-+ static constexpr int kNumberOfStackLocals = 4;
|
|
|
-+
|
|
|
- // First position register address on the stack. Following positions are
|
|
|
- // below it. A position is a 32 bit value.
|
|
|
-- static const int kFirstRegisterOnStack = kBacktrackCount - kWRegSize;
|
|
|
-+ static const int kFirstRegisterOnStack = kStackLocalPadding - kWRegSize;
|
|
|
- // A capture is a 64 bit value holding two position.
|
|
|
-- static const int kFirstCaptureOnStack = kBacktrackCount - kXRegSize;
|
|
|
-+ static const int kFirstCaptureOnStack = kStackLocalPadding - kXRegSize;
|
|
|
-
|
|
|
- // Initial size of code buffer.
|
|
|
- static const int kRegExpCodeSize = 1024;
|
|
|
-@@ -152,43 +162,43 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
|
|
|
-
|
|
|
- // Register holding the current input position as negative offset from
|
|
|
- // the end of the string.
|
|
|
-- Register current_input_offset() { return w21; }
|
|
|
-+ static constexpr Register current_input_offset() { return w21; }
|
|
|
-
|
|
|
- // The register containing the current character after LoadCurrentCharacter.
|
|
|
-- Register current_character() { return w22; }
|
|
|
-+ static constexpr Register current_character() { return w22; }
|
|
|
-
|
|
|
- // Register holding address of the end of the input string.
|
|
|
-- Register input_end() { return x25; }
|
|
|
-+ static constexpr Register input_end() { return x25; }
|
|
|
-
|
|
|
- // Register holding address of the start of the input string.
|
|
|
-- Register input_start() { return x26; }
|
|
|
-+ static constexpr 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; }
|
|
|
-+ static constexpr Register start_offset() { return w27; }
|
|
|
-
|
|
|
- // Pointer to the output array's first element.
|
|
|
-- Register output_array() { return x28; }
|
|
|
-+ static constexpr Register output_array() { return x28; }
|
|
|
-
|
|
|
- // Register holding the frame address. Local variables, parameters and
|
|
|
- // regexp registers are addressed relative to this.
|
|
|
-- Register frame_pointer() { return fp; }
|
|
|
-+ static constexpr Register frame_pointer() { return fp; }
|
|
|
-
|
|
|
- // The register containing the backtrack stack top. Provides a meaningful
|
|
|
- // name to the register.
|
|
|
-- Register backtrack_stackpointer() { return x23; }
|
|
|
-+ static constexpr Register backtrack_stackpointer() { return x23; }
|
|
|
-
|
|
|
- // Register holding pointer to the current code object.
|
|
|
-- Register code_pointer() { return x20; }
|
|
|
-+ static constexpr Register code_pointer() { return x20; }
|
|
|
-
|
|
|
- // Register holding the value used for clearing capture registers.
|
|
|
-- Register string_start_minus_one() { return w24; }
|
|
|
-+ static constexpr Register string_start_minus_one() { 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; }
|
|
|
-+ static constexpr Register twice_non_position_value() { return x24; }
|
|
|
-
|
|
|
- // Byte size of chars in the string to match (decided by the Mode argument)
|
|
|
-- int char_size() { return static_cast<int>(mode_); }
|
|
|
-+ int char_size() const { return static_cast<int>(mode_); }
|
|
|
-
|
|
|
- // Equivalent to a conditional branch to the label, unless the label
|
|
|
- // is nullptr, in which case it is a conditional Backtrack.
|
|
|
-@@ -254,19 +264,25 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
|
|
|
- // This assumes that the state of the register is not STACKED.
|
|
|
- inline Register GetCachedRegister(int register_index);
|
|
|
-
|
|
|
-+ void LoadRegExpStackPointerFromMemory(Register dst);
|
|
|
-+ void StoreRegExpStackPointerToMemory(Register src, Register scratch);
|
|
|
-+ void PushRegExpBasePointer(Register scratch1, Register scratch2);
|
|
|
-+ void PopRegExpBasePointer(Register scratch1, Register scratch2);
|
|
|
-+
|
|
|
- Isolate* isolate() const { return masm_->isolate(); }
|
|
|
-
|
|
|
-- MacroAssembler* masm_;
|
|
|
-+ MacroAssembler* const masm_;
|
|
|
-+ const NoRootArrayScope no_root_array_scope_;
|
|
|
-
|
|
|
- // Which mode to generate code for (LATIN1 or UC16).
|
|
|
-- Mode mode_;
|
|
|
-+ const 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_;
|
|
|
-+ const int num_saved_registers_;
|
|
|
-
|
|
|
- // Labels used internally.
|
|
|
- Label entry_label_;
|
|
|
-diff --git a/src/regexp/ia32/regexp-macro-assembler-ia32.cc b/src/regexp/ia32/regexp-macro-assembler-ia32.cc
|
|
|
-index 6af1d02eed36af46a7e0d819d006361f51411ba6..51d63b2531e2bc85fb115de23d7b6a6f40b36f11 100644
|
|
|
---- a/src/regexp/ia32/regexp-macro-assembler-ia32.cc
|
|
|
-+++ b/src/regexp/ia32/regexp-macro-assembler-ia32.cc
|
|
|
-@@ -90,6 +90,7 @@ RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(Isolate* isolate, Zone* zone,
|
|
|
- : NativeRegExpMacroAssembler(isolate, zone),
|
|
|
- masm_(new MacroAssembler(isolate, CodeObjectRequired::kYes,
|
|
|
- NewAssemblerBuffer(kRegExpCodeSize))),
|
|
|
-+ no_root_array_scope_(masm_),
|
|
|
- mode_(mode),
|
|
|
- num_registers_(registers_to_save),
|
|
|
- num_saved_registers_(registers_to_save),
|
|
|
-@@ -98,9 +99,6 @@ RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(Isolate* isolate, Zone* zone,
|
|
|
- success_label_(),
|
|
|
- backtrack_label_(),
|
|
|
- exit_label_() {
|
|
|
-- // Irregexp code clobbers ebx and spills/restores it at all boundaries.
|
|
|
-- masm_->set_root_array_available(false);
|
|
|
--
|
|
|
- DCHECK_EQ(0, registers_to_save % 2);
|
|
|
- __ jmp(&entry_label_); // We'll write the entry code later.
|
|
|
- __ bind(&start_label_); // And then continue from here.
|
|
|
-@@ -655,6 +653,38 @@ void RegExpMacroAssemblerIA32::Fail() {
|
|
|
- __ jmp(&exit_label_);
|
|
|
- }
|
|
|
-
|
|
|
-+void RegExpMacroAssemblerIA32::LoadRegExpStackPointerFromMemory(Register dst) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
|
|
|
-+ __ mov(dst, __ ExternalReferenceAsOperand(ref, dst));
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerIA32::StoreRegExpStackPointerToMemory(
|
|
|
-+ Register src, Register scratch) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
|
|
|
-+ __ mov(__ ExternalReferenceAsOperand(ref, scratch), src);
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerIA32::PushRegExpBasePointer(Register scratch1,
|
|
|
-+ Register scratch2) {
|
|
|
-+ LoadRegExpStackPointerFromMemory(scratch1);
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ mov(scratch2, __ ExternalReferenceAsOperand(ref, scratch2));
|
|
|
-+ __ sub(scratch1, scratch2);
|
|
|
-+ __ mov(Operand(ebp, kRegExpStackBasePointer), scratch1);
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerIA32::PopRegExpBasePointer(Register scratch1,
|
|
|
-+ Register scratch2) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ mov(scratch1, Operand(ebp, kRegExpStackBasePointer));
|
|
|
-+ __ mov(scratch2, __ ExternalReferenceAsOperand(ref, scratch2));
|
|
|
-+ __ add(scratch1, scratch2);
|
|
|
-+ StoreRegExpStackPointerToMemory(scratch1, scratch2);
|
|
|
-+}
|
|
|
-
|
|
|
- Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
|
|
|
- Label return_eax;
|
|
|
-@@ -676,14 +706,23 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
|
|
|
- __ push(esi);
|
|
|
- __ push(edi);
|
|
|
- __ push(ebx); // Callee-save on MacOS.
|
|
|
-+ STATIC_ASSERT(kLastCalleeSaveRegister == kBackup_ebx);
|
|
|
-
|
|
|
-- STATIC_ASSERT(kSuccessfulCaptures == kBackup_ebx - kSystemPointerSize);
|
|
|
-+ STATIC_ASSERT(kSuccessfulCaptures ==
|
|
|
-+ kLastCalleeSaveRegister - kSystemPointerSize);
|
|
|
- __ push(Immediate(0)); // Number of successful matches in a global regexp.
|
|
|
- STATIC_ASSERT(kStringStartMinusOne ==
|
|
|
- kSuccessfulCaptures - kSystemPointerSize);
|
|
|
- __ push(Immediate(0)); // Make room for "string start - 1" constant.
|
|
|
- STATIC_ASSERT(kBacktrackCount == kStringStartMinusOne - kSystemPointerSize);
|
|
|
- __ push(Immediate(0)); // The backtrack counter.
|
|
|
-+ STATIC_ASSERT(kRegExpStackBasePointer ==
|
|
|
-+ kBacktrackCount - kSystemPointerSize);
|
|
|
-+ __ push(Immediate(0)); // The regexp stack base ptr.
|
|
|
-+
|
|
|
-+ // Store the regexp base pointer - we'll later restore it / write it to
|
|
|
-+ // memory when returning from this irregexp code object.
|
|
|
-+ PushRegExpBasePointer(ecx, eax);
|
|
|
-
|
|
|
- // Check if we have space on the stack for registers.
|
|
|
- Label stack_limit_hit;
|
|
|
-@@ -769,7 +808,7 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
|
|
|
- }
|
|
|
-
|
|
|
- // Initialize backtrack stack pointer.
|
|
|
-- __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
|
|
|
-+ LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
|
|
|
-
|
|
|
- __ jmp(&start_label_);
|
|
|
-
|
|
|
-@@ -855,8 +894,12 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
|
|
|
- }
|
|
|
-
|
|
|
- __ bind(&return_eax);
|
|
|
-+ // Restore the original regexp stack pointer value (effectively, pop the
|
|
|
-+ // stored base pointer).
|
|
|
-+ PopRegExpBasePointer(ecx, ebx);
|
|
|
-+
|
|
|
- // Skip esp past regexp registers.
|
|
|
-- __ lea(esp, Operand(ebp, kBackup_ebx));
|
|
|
-+ __ lea(esp, Operand(ebp, kLastCalleeSaveRegister));
|
|
|
- // Restore callee-save registers.
|
|
|
- __ pop(ebx);
|
|
|
- __ pop(edi);
|
|
|
-@@ -877,7 +920,8 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
|
|
|
- if (check_preempt_label_.is_linked()) {
|
|
|
- SafeCallTarget(&check_preempt_label_);
|
|
|
-
|
|
|
-- __ push(backtrack_stackpointer());
|
|
|
-+ StoreRegExpStackPointerToMemory(backtrack_stackpointer(), edi);
|
|
|
-+
|
|
|
- __ push(edi);
|
|
|
-
|
|
|
- CallCheckStackGuardState(ebx);
|
|
|
-@@ -887,7 +931,9 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
|
|
|
- __ j(not_zero, &return_eax);
|
|
|
-
|
|
|
- __ pop(edi);
|
|
|
-- __ pop(backtrack_stackpointer());
|
|
|
-+
|
|
|
-+ LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
|
|
|
-+
|
|
|
- // String might have moved: Reload esi from frame.
|
|
|
- __ mov(esi, Operand(ebp, kInputEnd));
|
|
|
- SafeReturn();
|
|
|
-@@ -898,21 +944,19 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
|
|
|
- SafeCallTarget(&stack_overflow_label_);
|
|
|
- // Reached if the backtrack-stack limit has been hit.
|
|
|
-
|
|
|
-- // Save registers before calling C function
|
|
|
-+ // Save registers before calling C function.
|
|
|
- __ push(esi);
|
|
|
- __ push(edi);
|
|
|
-
|
|
|
-- // Call GrowStack(backtrack_stackpointer())
|
|
|
-- static const int num_arguments = 3;
|
|
|
-- __ PrepareCallCFunction(num_arguments, ebx);
|
|
|
-- __ mov(Operand(esp, 2 * kSystemPointerSize),
|
|
|
-+ StoreRegExpStackPointerToMemory(backtrack_stackpointer(), edi);
|
|
|
-+
|
|
|
-+ // Call GrowStack(isolate).
|
|
|
-+ static const int kNumArguments = 1;
|
|
|
-+ __ PrepareCallCFunction(kNumArguments, ebx);
|
|
|
-+ __ mov(Operand(esp, 0 * kSystemPointerSize),
|
|
|
- Immediate(ExternalReference::isolate_address(isolate())));
|
|
|
-- __ lea(eax, Operand(ebp, kStackHighEnd));
|
|
|
-- __ mov(Operand(esp, 1 * kSystemPointerSize), eax);
|
|
|
-- __ mov(Operand(esp, 0 * kSystemPointerSize), backtrack_stackpointer());
|
|
|
-- ExternalReference grow_stack =
|
|
|
-- ExternalReference::re_grow_stack(isolate());
|
|
|
-- __ CallCFunction(grow_stack, num_arguments);
|
|
|
-+ __ CallCFunction(ExternalReference::re_grow_stack(isolate()),
|
|
|
-+ kNumArguments);
|
|
|
- // If return nullptr, we have failed to grow the stack, and
|
|
|
- // must exit with a stack-overflow exception.
|
|
|
- __ or_(eax, eax);
|
|
|
-@@ -1019,10 +1063,21 @@ void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) {
|
|
|
- __ mov(edi, register_location(reg));
|
|
|
- }
|
|
|
-
|
|
|
-+void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
|
|
|
-+ ExternalReference stack_top_address =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ mov(eax, __ ExternalReferenceAsOperand(stack_top_address, eax));
|
|
|
-+ __ sub(eax, backtrack_stackpointer());
|
|
|
-+ __ mov(register_location(reg), eax);
|
|
|
-+}
|
|
|
-
|
|
|
- void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
|
|
|
-- __ mov(backtrack_stackpointer(), register_location(reg));
|
|
|
-- __ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
|
|
|
-+ ExternalReference stack_top_address =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ mov(backtrack_stackpointer(),
|
|
|
-+ __ ExternalReferenceAsOperand(stack_top_address,
|
|
|
-+ backtrack_stackpointer()));
|
|
|
-+ __ sub(backtrack_stackpointer(), register_location(reg));
|
|
|
- }
|
|
|
-
|
|
|
- void RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by) {
|
|
|
-@@ -1069,14 +1124,6 @@ void RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) {
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
--
|
|
|
--void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
|
|
|
-- __ mov(eax, backtrack_stackpointer());
|
|
|
-- __ sub(eax, Operand(ebp, kStackHighEnd));
|
|
|
-- __ mov(register_location(reg), eax);
|
|
|
--}
|
|
|
--
|
|
|
--
|
|
|
- // Private methods:
|
|
|
-
|
|
|
- void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
|
|
|
-diff --git a/src/regexp/ia32/regexp-macro-assembler-ia32.h b/src/regexp/ia32/regexp-macro-assembler-ia32.h
|
|
|
-index 93fb2c9aba32ab48e335c41dd9dbe0bac94d73ed..861795da900d91111386e4f8e660f7f94ea46a33 100644
|
|
|
---- a/src/regexp/ia32/regexp-macro-assembler-ia32.h
|
|
|
-+++ b/src/regexp/ia32/regexp-macro-assembler-ia32.h
|
|
|
-@@ -114,12 +114,20 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32
|
|
|
- static const int kBackup_esi = kFramePointer - kSystemPointerSize;
|
|
|
- static const int kBackup_edi = kBackup_esi - kSystemPointerSize;
|
|
|
- static const int kBackup_ebx = kBackup_edi - kSystemPointerSize;
|
|
|
-- static const int kSuccessfulCaptures = kBackup_ebx - kSystemPointerSize;
|
|
|
-+ static const int kLastCalleeSaveRegister = kBackup_ebx;
|
|
|
-+
|
|
|
-+ static const int kSuccessfulCaptures =
|
|
|
-+ kLastCalleeSaveRegister - kSystemPointerSize;
|
|
|
- static const int kStringStartMinusOne =
|
|
|
- kSuccessfulCaptures - kSystemPointerSize;
|
|
|
- static const int kBacktrackCount = kStringStartMinusOne - kSystemPointerSize;
|
|
|
-+ // Stores the initial value of the regexp stack pointer in a
|
|
|
-+ // position-independent representation (in case the regexp stack grows and
|
|
|
-+ // thus moves).
|
|
|
-+ static const int kRegExpStackBasePointer =
|
|
|
-+ kBacktrackCount - kSystemPointerSize;
|
|
|
- // First register address. Following registers are below it on the stack.
|
|
|
-- static const int kRegisterZero = kBacktrackCount - kSystemPointerSize;
|
|
|
-+ static const int kRegisterZero = kRegExpStackBasePointer - kSystemPointerSize;
|
|
|
-
|
|
|
- // Initial size of code buffer.
|
|
|
- static const int kRegExpCodeSize = 1024;
|
|
|
-@@ -137,14 +145,14 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32
|
|
|
- Operand register_location(int register_index);
|
|
|
-
|
|
|
- // The register containing the current character after LoadCurrentCharacter.
|
|
|
-- inline Register current_character() { return edx; }
|
|
|
-+ static constexpr Register current_character() { return edx; }
|
|
|
-
|
|
|
- // The register containing the backtrack stack top. Provides a meaningful
|
|
|
- // name to the register.
|
|
|
-- inline Register backtrack_stackpointer() { return ecx; }
|
|
|
-+ static constexpr Register backtrack_stackpointer() { return ecx; }
|
|
|
-
|
|
|
- // Byte size of chars in the string to match (decided by the Mode argument)
|
|
|
-- inline int char_size() { return static_cast<int>(mode_); }
|
|
|
-+ inline int char_size() const { return static_cast<int>(mode_); }
|
|
|
-
|
|
|
- // Equivalent to a conditional branch to the label, unless the label
|
|
|
- // is nullptr, in which case it is a conditional Backtrack.
|
|
|
-@@ -168,19 +176,25 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32
|
|
|
- // (ecx) and increments it by a word size.
|
|
|
- inline void Pop(Register target);
|
|
|
-
|
|
|
-+ void LoadRegExpStackPointerFromMemory(Register dst);
|
|
|
-+ void StoreRegExpStackPointerToMemory(Register src, Register scratch);
|
|
|
-+ void PushRegExpBasePointer(Register scratch1, Register scratch2);
|
|
|
-+ void PopRegExpBasePointer(Register scratch1, Register scratch2);
|
|
|
-+
|
|
|
- Isolate* isolate() const { return masm_->isolate(); }
|
|
|
-
|
|
|
-- MacroAssembler* masm_;
|
|
|
-+ MacroAssembler* const masm_;
|
|
|
-+ const NoRootArrayScope no_root_array_scope_;
|
|
|
-
|
|
|
- // Which mode to generate code for (LATIN1 or UC16).
|
|
|
-- Mode mode_;
|
|
|
-+ const 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_;
|
|
|
-+ // are always 0..num_saved_registers_-1).
|
|
|
-+ const int num_saved_registers_;
|
|
|
-
|
|
|
- // Labels used internally.
|
|
|
- Label entry_label_;
|
|
|
-diff --git a/src/regexp/regexp-macro-assembler.cc b/src/regexp/regexp-macro-assembler.cc
|
|
|
-index 891079b357a0191e20ea31b68df3a123b4d1b8d2..1f5875afb8850da4136da6633d5b0ad9f52803e3 100644
|
|
|
---- a/src/regexp/regexp-macro-assembler.cc
|
|
|
-+++ b/src/regexp/regexp-macro-assembler.cc
|
|
|
-@@ -308,7 +308,7 @@ int NativeRegExpMacroAssembler::Execute(
|
|
|
- int* output, int output_size, Isolate* isolate, JSRegExp regexp) {
|
|
|
- // Ensure that the minimum stack has been allocated.
|
|
|
- RegExpStackScope stack_scope(isolate);
|
|
|
-- Address stack_base = stack_scope.stack()->stack_base();
|
|
|
-+ Address stack_base = stack_scope.stack()->memory_top();
|
|
|
-
|
|
|
- bool is_one_byte = String::IsOneByteRepresentationUnderneath(input);
|
|
|
- Code code = FromCodeT(CodeT::cast(regexp.Code(is_one_byte)));
|
|
|
-@@ -382,22 +382,23 @@ const byte NativeRegExpMacroAssembler::word_character_map[] = {
|
|
|
- };
|
|
|
- // clang-format on
|
|
|
-
|
|
|
--Address NativeRegExpMacroAssembler::GrowStack(Address stack_pointer,
|
|
|
-- Address* stack_base,
|
|
|
-- Isolate* isolate) {
|
|
|
-+Address NativeRegExpMacroAssembler::GrowStack(Isolate* isolate) {
|
|
|
-+ DisallowGarbageCollection no_gc;
|
|
|
-+
|
|
|
- RegExpStack* regexp_stack = isolate->regexp_stack();
|
|
|
-- size_t size = regexp_stack->stack_capacity();
|
|
|
-- Address old_stack_base = regexp_stack->stack_base();
|
|
|
-- DCHECK(old_stack_base == *stack_base);
|
|
|
-- DCHECK(stack_pointer <= old_stack_base);
|
|
|
-- DCHECK(static_cast<size_t>(old_stack_base - stack_pointer) <= size);
|
|
|
-- Address new_stack_base = regexp_stack->EnsureCapacity(size * 2);
|
|
|
-- if (new_stack_base == kNullAddress) {
|
|
|
-- return kNullAddress;
|
|
|
-- }
|
|
|
-- *stack_base = new_stack_base;
|
|
|
-- intptr_t stack_content_size = old_stack_base - stack_pointer;
|
|
|
-- return new_stack_base - stack_content_size;
|
|
|
-+ const size_t old_size = regexp_stack->memory_size();
|
|
|
-+
|
|
|
-+#ifdef DEBUG
|
|
|
-+ const Address old_stack_top = regexp_stack->memory_top();
|
|
|
-+ const Address old_stack_pointer = regexp_stack->stack_pointer();
|
|
|
-+ CHECK_LE(old_stack_pointer, old_stack_top);
|
|
|
-+ CHECK_LE(static_cast<size_t>(old_stack_top - old_stack_pointer), old_size);
|
|
|
-+#endif // DEBUG
|
|
|
-+
|
|
|
-+ Address new_stack_base = regexp_stack->EnsureCapacity(old_size * 2);
|
|
|
-+ if (new_stack_base == kNullAddress) return kNullAddress;
|
|
|
-+
|
|
|
-+ return regexp_stack->stack_pointer();
|
|
|
- }
|
|
|
-
|
|
|
- } // namespace internal
|
|
|
-diff --git a/src/regexp/regexp-macro-assembler.h b/src/regexp/regexp-macro-assembler.h
|
|
|
-index 9bd9ba615e32ad9e34e246a7c4788fdf89375476..af3cc2f5caab97a3a57589d0c54011c07269227f 100644
|
|
|
---- a/src/regexp/regexp-macro-assembler.h
|
|
|
-+++ b/src/regexp/regexp-macro-assembler.h
|
|
|
-@@ -281,13 +281,11 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
|
|
|
- int* offsets_vector, int offsets_vector_length,
|
|
|
- int previous_index, Isolate* isolate);
|
|
|
-
|
|
|
-- // 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.
|
|
|
-+ // Called from RegExp if the backtrack stack limit is hit. Tries to expand
|
|
|
-+ // the stack. Returns the new stack-pointer if successful, 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,
|
|
|
-- Isolate* isolate);
|
|
|
-+ static Address GrowStack(Isolate* isolate);
|
|
|
-
|
|
|
- static int CheckStackGuardState(Isolate* isolate, int start_index,
|
|
|
- RegExp::CallOrigin call_origin,
|
|
|
-diff --git a/src/regexp/regexp-stack.cc b/src/regexp/regexp-stack.cc
|
|
|
-index 6d73b7c03d63f9358f54453aba3c52ec5da29c3b..9c403eed089c890df0098875763da62bce15fd64 100644
|
|
|
---- a/src/regexp/regexp-stack.cc
|
|
|
-+++ b/src/regexp/regexp-stack.cc
|
|
|
-@@ -11,23 +11,17 @@ namespace v8 {
|
|
|
- namespace internal {
|
|
|
-
|
|
|
- RegExpStackScope::RegExpStackScope(Isolate* isolate)
|
|
|
-- : regexp_stack_(isolate->regexp_stack()) {
|
|
|
-+ : regexp_stack_(isolate->regexp_stack()),
|
|
|
-+ old_sp_top_delta_(regexp_stack_->sp_top_delta()) {
|
|
|
- DCHECK(regexp_stack_->IsValid());
|
|
|
-- // Irregexp is not reentrant in several ways; in particular, the
|
|
|
-- // RegExpStackScope is not reentrant since the destructor frees allocated
|
|
|
-- // memory. Protect against reentrancy here.
|
|
|
-- CHECK(!regexp_stack_->is_in_use());
|
|
|
-- regexp_stack_->set_is_in_use(true);
|
|
|
- }
|
|
|
-
|
|
|
--
|
|
|
- RegExpStackScope::~RegExpStackScope() {
|
|
|
-- // Reset the buffer if it has grown.
|
|
|
-- regexp_stack_->Reset();
|
|
|
-- DCHECK(!regexp_stack_->is_in_use());
|
|
|
-+ CHECK_EQ(old_sp_top_delta_, regexp_stack_->sp_top_delta());
|
|
|
-+ regexp_stack_->ResetIfEmpty();
|
|
|
- }
|
|
|
-
|
|
|
--RegExpStack::RegExpStack() : thread_local_(this), isolate_(nullptr) {}
|
|
|
-+RegExpStack::RegExpStack() : thread_local_(this) {}
|
|
|
-
|
|
|
- RegExpStack::~RegExpStack() { thread_local_.FreeAndInvalidate(); }
|
|
|
-
|
|
|
-@@ -52,18 +46,16 @@ char* RegExpStack::RestoreStack(char* from) {
|
|
|
- return from + kThreadLocalSize;
|
|
|
- }
|
|
|
-
|
|
|
--void RegExpStack::Reset() { thread_local_.ResetToStaticStack(this); }
|
|
|
--
|
|
|
- void RegExpStack::ThreadLocal::ResetToStaticStack(RegExpStack* regexp_stack) {
|
|
|
- if (owns_memory_) DeleteArray(memory_);
|
|
|
-
|
|
|
- memory_ = regexp_stack->static_stack_;
|
|
|
- memory_top_ = regexp_stack->static_stack_ + kStaticStackSize;
|
|
|
- memory_size_ = kStaticStackSize;
|
|
|
-+ stack_pointer_ = memory_top_;
|
|
|
- limit_ = reinterpret_cast<Address>(regexp_stack->static_stack_) +
|
|
|
- kStackLimitSlack * kSystemPointerSize;
|
|
|
- owns_memory_ = false;
|
|
|
-- is_in_use_ = false;
|
|
|
- }
|
|
|
-
|
|
|
- void RegExpStack::ThreadLocal::FreeAndInvalidate() {
|
|
|
-@@ -74,6 +66,7 @@ void RegExpStack::ThreadLocal::FreeAndInvalidate() {
|
|
|
- memory_ = nullptr;
|
|
|
- memory_top_ = nullptr;
|
|
|
- memory_size_ = 0;
|
|
|
-+ stack_pointer_ = nullptr;
|
|
|
- limit_ = kMemoryTop;
|
|
|
- }
|
|
|
-
|
|
|
-@@ -88,9 +81,11 @@ Address RegExpStack::EnsureCapacity(size_t size) {
|
|
|
- thread_local_.memory_, thread_local_.memory_size_);
|
|
|
- if (thread_local_.owns_memory_) DeleteArray(thread_local_.memory_);
|
|
|
- }
|
|
|
-+ ptrdiff_t delta = sp_top_delta();
|
|
|
- thread_local_.memory_ = new_memory;
|
|
|
- thread_local_.memory_top_ = new_memory + size;
|
|
|
- thread_local_.memory_size_ = size;
|
|
|
-+ thread_local_.stack_pointer_ = thread_local_.memory_top_ + delta;
|
|
|
- thread_local_.limit_ = reinterpret_cast<Address>(new_memory) +
|
|
|
- kStackLimitSlack * kSystemPointerSize;
|
|
|
- thread_local_.owns_memory_ = true;
|
|
|
-diff --git a/src/regexp/regexp-stack.h b/src/regexp/regexp-stack.h
|
|
|
-index adca683ff890c82d7cfdf9e10c7a5d7e78d2d650..d52ca3e1d079d8953a753e2db1e835f214b980f3 100644
|
|
|
---- a/src/regexp/regexp-stack.h
|
|
|
-+++ b/src/regexp/regexp-stack.h
|
|
|
-@@ -16,10 +16,7 @@ class RegExpStack;
|
|
|
-
|
|
|
- // Maintains a per-v8thread stack area that can be used by irregexp
|
|
|
- // implementation for its backtracking stack.
|
|
|
--// Since there is only one stack area, the Irregexp implementation is not
|
|
|
--// re-entrant. I.e., no regular expressions may be executed in the same thread
|
|
|
--// during a preempted Irregexp execution.
|
|
|
--class V8_NODISCARD RegExpStackScope {
|
|
|
-+class V8_NODISCARD RegExpStackScope final {
|
|
|
- public:
|
|
|
- // Create and delete an instance to control the life-time of a growing stack.
|
|
|
-
|
|
|
-@@ -32,46 +29,45 @@ class V8_NODISCARD RegExpStackScope {
|
|
|
- RegExpStack* stack() const { return regexp_stack_; }
|
|
|
-
|
|
|
- private:
|
|
|
-- RegExpStack* regexp_stack_;
|
|
|
-+ RegExpStack* const regexp_stack_;
|
|
|
-+ const ptrdiff_t old_sp_top_delta_;
|
|
|
- };
|
|
|
-
|
|
|
--class RegExpStack {
|
|
|
-+class RegExpStack final {
|
|
|
- public:
|
|
|
- RegExpStack();
|
|
|
- ~RegExpStack();
|
|
|
- RegExpStack(const RegExpStack&) = delete;
|
|
|
- RegExpStack& operator=(const RegExpStack&) = delete;
|
|
|
-
|
|
|
-- // Number of allocated locations on the stack below the limit.
|
|
|
-- // No sequence of pushes must be longer that this without doing a stack-limit
|
|
|
-- // check.
|
|
|
-+ // Number of allocated locations on the stack below the limit. No sequence of
|
|
|
-+ // pushes must be longer than this without doing a stack-limit check.
|
|
|
- static constexpr int kStackLimitSlack = 32;
|
|
|
-
|
|
|
-- // Gives the top of the memory used as stack.
|
|
|
-- Address stack_base() {
|
|
|
-+ Address memory_top() const {
|
|
|
- DCHECK_NE(0, thread_local_.memory_size_);
|
|
|
- DCHECK_EQ(thread_local_.memory_top_,
|
|
|
- thread_local_.memory_ + thread_local_.memory_size_);
|
|
|
- return reinterpret_cast<Address>(thread_local_.memory_top_);
|
|
|
- }
|
|
|
-
|
|
|
-- // The total size of the memory allocated for the stack.
|
|
|
-- size_t stack_capacity() { return thread_local_.memory_size_; }
|
|
|
-+ Address stack_pointer() const {
|
|
|
-+ return reinterpret_cast<Address>(thread_local_.stack_pointer_);
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ size_t memory_size() const { return thread_local_.memory_size_; }
|
|
|
-
|
|
|
- // If the stack pointer gets below the limit, we should react and
|
|
|
- // either grow the stack or report an out-of-stack exception.
|
|
|
- // There is only a limited number of locations below the stack limit,
|
|
|
- // so users of the stack should check the stack limit during any
|
|
|
- // sequence of pushes longer that this.
|
|
|
-- Address* limit_address_address() { return &(thread_local_.limit_); }
|
|
|
-+ Address* limit_address_address() { return &thread_local_.limit_; }
|
|
|
-
|
|
|
- // Ensures that there is a memory area with at least the specified size.
|
|
|
- // If passing zero, the default/minimum size buffer is allocated.
|
|
|
- Address EnsureCapacity(size_t size);
|
|
|
-
|
|
|
-- bool is_in_use() const { return thread_local_.is_in_use_; }
|
|
|
-- void set_is_in_use(bool v) { thread_local_.is_in_use_ = v; }
|
|
|
--
|
|
|
- // Thread local archiving.
|
|
|
- static constexpr int ArchiveSpacePerThread() {
|
|
|
- return static_cast<int>(kThreadLocalSize);
|
|
|
-@@ -103,44 +99,59 @@ class RegExpStack {
|
|
|
-
|
|
|
- STATIC_ASSERT(kStaticStackSize <= kMaximumStackSize);
|
|
|
-
|
|
|
-- // Structure holding the allocated memory, size and limit.
|
|
|
-+ // Structure holding the allocated memory, size and limit. Thread switching
|
|
|
-+ // archives and restores this struct.
|
|
|
- struct ThreadLocal {
|
|
|
- explicit ThreadLocal(RegExpStack* regexp_stack) {
|
|
|
- ResetToStaticStack(regexp_stack);
|
|
|
- }
|
|
|
-
|
|
|
-- // If memory_size_ > 0 then memory_ and memory_top_ must be non-nullptr
|
|
|
-- // and memory_top_ = memory_ + memory_size_
|
|
|
-+ // If memory_size_ > 0 then
|
|
|
-+ // - memory_, memory_top_, stack_pointer_ must be non-nullptr
|
|
|
-+ // - memory_top_ = memory_ + memory_size_
|
|
|
-+ // - memory_ <= stack_pointer_ <= memory_top_
|
|
|
- byte* memory_ = nullptr;
|
|
|
- byte* memory_top_ = nullptr;
|
|
|
- size_t memory_size_ = 0;
|
|
|
-+ byte* stack_pointer_ = nullptr;
|
|
|
- Address limit_ = kNullAddress;
|
|
|
- bool owns_memory_ = false; // Whether memory_ is owned and must be freed.
|
|
|
-- bool is_in_use_ = false; // To guard against reentrancy.
|
|
|
-
|
|
|
- void ResetToStaticStack(RegExpStack* regexp_stack);
|
|
|
-+ void ResetToStaticStackIfEmpty(RegExpStack* regexp_stack) {
|
|
|
-+ if (stack_pointer_ == memory_top_) ResetToStaticStack(regexp_stack);
|
|
|
-+ }
|
|
|
- void FreeAndInvalidate();
|
|
|
- };
|
|
|
- static constexpr size_t kThreadLocalSize = sizeof(ThreadLocal);
|
|
|
-
|
|
|
-- // Address of top of memory used as stack.
|
|
|
- Address memory_top_address_address() {
|
|
|
- return reinterpret_cast<Address>(&thread_local_.memory_top_);
|
|
|
- }
|
|
|
-
|
|
|
-- // Resets the buffer if it has grown beyond the default/minimum size.
|
|
|
-- // After this, the buffer is either the default size, or it is empty, so
|
|
|
-- // you have to call EnsureCapacity before using it again.
|
|
|
-- void Reset();
|
|
|
-+ Address stack_pointer_address() {
|
|
|
-+ return reinterpret_cast<Address>(&thread_local_.stack_pointer_);
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ // A position-independent representation of the stack pointer.
|
|
|
-+ ptrdiff_t sp_top_delta() const {
|
|
|
-+ ptrdiff_t result =
|
|
|
-+ reinterpret_cast<intptr_t>(thread_local_.stack_pointer_) -
|
|
|
-+ reinterpret_cast<intptr_t>(thread_local_.memory_top_);
|
|
|
-+ DCHECK_LE(result, 0);
|
|
|
-+ return result;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ // Resets the buffer if it has grown beyond the default/minimum size and is
|
|
|
-+ // empty.
|
|
|
-+ void ResetIfEmpty() { thread_local_.ResetToStaticStackIfEmpty(this); }
|
|
|
-
|
|
|
- // Whether the ThreadLocal storage has been invalidated.
|
|
|
- bool IsValid() const { return thread_local_.memory_ != nullptr; }
|
|
|
-
|
|
|
- ThreadLocal thread_local_;
|
|
|
-- Isolate* isolate_;
|
|
|
-
|
|
|
- friend class ExternalReference;
|
|
|
-- friend class Isolate;
|
|
|
- friend class RegExpStackScope;
|
|
|
- };
|
|
|
-
|
|
|
-diff --git a/src/regexp/x64/regexp-macro-assembler-x64.cc b/src/regexp/x64/regexp-macro-assembler-x64.cc
|
|
|
-index 6f0cb53e8f52e4cad5997993b7fb00f2d8b8127a..abcbed18aaa9bdc4a497962714bffde74d581173 100644
|
|
|
---- a/src/regexp/x64/regexp-macro-assembler-x64.cc
|
|
|
-+++ b/src/regexp/x64/regexp-macro-assembler-x64.cc
|
|
|
-@@ -6,13 +6,13 @@
|
|
|
-
|
|
|
- #include "src/regexp/x64/regexp-macro-assembler-x64.h"
|
|
|
-
|
|
|
-+#include "src/codegen/code-desc.h"
|
|
|
- #include "src/codegen/macro-assembler.h"
|
|
|
- #include "src/heap/factory.h"
|
|
|
- #include "src/logging/log.h"
|
|
|
--#include "src/objects/objects-inl.h"
|
|
|
-+#include "src/objects/code-inl.h"
|
|
|
- #include "src/regexp/regexp-macro-assembler.h"
|
|
|
- #include "src/regexp/regexp-stack.h"
|
|
|
--#include "src/strings/unicode.h"
|
|
|
-
|
|
|
- namespace v8 {
|
|
|
- namespace internal {
|
|
|
-@@ -664,31 +664,64 @@ void RegExpMacroAssemblerX64::Fail() {
|
|
|
- __ jmp(&exit_label_);
|
|
|
- }
|
|
|
-
|
|
|
-+void RegExpMacroAssemblerX64::LoadRegExpStackPointerFromMemory(Register dst) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
|
|
|
-+ __ movq(dst, __ ExternalReferenceAsOperand(ref, dst));
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerX64::StoreRegExpStackPointerToMemory(
|
|
|
-+ Register src, Register scratch) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
|
|
|
-+ __ movq(__ ExternalReferenceAsOperand(ref, scratch), src);
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerX64::PushRegExpBasePointer(Register scratch1,
|
|
|
-+ Register scratch2) {
|
|
|
-+ LoadRegExpStackPointerFromMemory(scratch1);
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ movq(scratch2, __ ExternalReferenceAsOperand(ref, scratch2));
|
|
|
-+ __ subq(scratch1, scratch2);
|
|
|
-+ __ movq(Operand(rbp, kRegExpStackBasePointer), scratch1);
|
|
|
-+}
|
|
|
-+
|
|
|
-+void RegExpMacroAssemblerX64::PopRegExpBasePointer(Register scratch1,
|
|
|
-+ Register scratch2) {
|
|
|
-+ ExternalReference ref =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ movq(scratch1, Operand(rbp, kRegExpStackBasePointer));
|
|
|
-+ __ movq(scratch2, __ ExternalReferenceAsOperand(ref, scratch2));
|
|
|
-+ __ addq(scratch1, scratch2);
|
|
|
-+ StoreRegExpStackPointerToMemory(scratch1, scratch2);
|
|
|
-+}
|
|
|
-
|
|
|
- Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
|
|
|
- Label return_rax;
|
|
|
-- // Finalize code - write the entry point code now we know how many
|
|
|
-- // registers we need.
|
|
|
-- // Entry code:
|
|
|
-+ // Finalize code - write the entry point code now we know how many registers
|
|
|
-+ // we need.
|
|
|
- __ bind(&entry_label_);
|
|
|
-
|
|
|
-- // Tell the system that we have a stack frame. Because the type is MANUAL, no
|
|
|
-- // is generated.
|
|
|
-+ // Tell the system that we have a stack frame. Because the type is MANUAL, no
|
|
|
-+ // physical frame is generated.
|
|
|
- FrameScope scope(&masm_, StackFrame::MANUAL);
|
|
|
-
|
|
|
- // Actually emit code to start a new stack frame.
|
|
|
- __ pushq(rbp);
|
|
|
- __ movq(rbp, rsp);
|
|
|
-+
|
|
|
- // Save parameters and callee-save registers. Order here should correspond
|
|
|
- // to order of kBackup_ebx etc.
|
|
|
- #ifdef V8_TARGET_OS_WIN
|
|
|
- // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots.
|
|
|
-- // Store register parameters in pre-allocated stack slots,
|
|
|
-- __ movq(Operand(rbp, kInputString), rcx);
|
|
|
-- __ movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx.
|
|
|
-- __ movq(Operand(rbp, kInputStart), r8);
|
|
|
-- __ movq(Operand(rbp, kInputEnd), r9);
|
|
|
-- // Callee-save on Win64.
|
|
|
-+ // Store register parameters in pre-allocated stack slots.
|
|
|
-+ __ movq(Operand(rbp, kInputString), arg_reg_1);
|
|
|
-+ __ movq(Operand(rbp, kStartIndex), arg_reg_2); // Passed as int32 in edx.
|
|
|
-+ __ movq(Operand(rbp, kInputStart), arg_reg_3);
|
|
|
-+ __ movq(Operand(rbp, kInputEnd), arg_reg_4);
|
|
|
-+
|
|
|
-+ STATIC_ASSERT(kNumCalleeSaveRegisters == 3);
|
|
|
- __ pushq(rsi);
|
|
|
- __ pushq(rdi);
|
|
|
- __ pushq(rbx);
|
|
|
-@@ -701,14 +734,15 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
|
|
|
- DCHECK_EQ(kInputEnd, -4 * kSystemPointerSize);
|
|
|
- DCHECK_EQ(kRegisterOutput, -5 * kSystemPointerSize);
|
|
|
- DCHECK_EQ(kNumOutputRegisters, -6 * kSystemPointerSize);
|
|
|
-- __ pushq(rdi);
|
|
|
-- __ pushq(rsi);
|
|
|
-- __ pushq(rdx);
|
|
|
-- __ pushq(rcx);
|
|
|
-+ __ pushq(arg_reg_1);
|
|
|
-+ __ pushq(arg_reg_2);
|
|
|
-+ __ pushq(arg_reg_3);
|
|
|
-+ __ pushq(arg_reg_4);
|
|
|
- __ pushq(r8);
|
|
|
- __ pushq(r9);
|
|
|
-
|
|
|
-- __ pushq(rbx); // Callee-save
|
|
|
-+ STATIC_ASSERT(kNumCalleeSaveRegisters == 1);
|
|
|
-+ __ pushq(rbx);
|
|
|
- #endif
|
|
|
-
|
|
|
- STATIC_ASSERT(kSuccessfulCaptures ==
|
|
|
-@@ -719,6 +753,13 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
|
|
|
- __ Push(Immediate(0)); // Make room for "string start - 1" constant.
|
|
|
- STATIC_ASSERT(kBacktrackCount == kStringStartMinusOne - kSystemPointerSize);
|
|
|
- __ Push(Immediate(0)); // The backtrack counter.
|
|
|
-+ STATIC_ASSERT(kRegExpStackBasePointer ==
|
|
|
-+ kBacktrackCount - kSystemPointerSize);
|
|
|
-+ __ Push(Immediate(0)); // The regexp stack base ptr.
|
|
|
-+
|
|
|
-+ // Store the regexp base pointer - we'll later restore it / write it to
|
|
|
-+ // memory when returning from this irregexp code object.
|
|
|
-+ PushRegExpBasePointer(rcx, kScratchRegister);
|
|
|
-
|
|
|
- // Check if we have space on the stack for registers.
|
|
|
- Label stack_limit_hit;
|
|
|
-@@ -808,7 +849,9 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
|
|
|
- }
|
|
|
-
|
|
|
- // Initialize backtrack stack pointer.
|
|
|
-- __ movq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd));
|
|
|
-+ // TODO(jgruber): Remove the kStackHighEnd parameter (and others like
|
|
|
-+ // kIsolate).
|
|
|
-+ LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
|
|
|
-
|
|
|
- __ jmp(&start_label_);
|
|
|
-
|
|
|
-@@ -894,19 +937,26 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
|
|
|
- }
|
|
|
-
|
|
|
- __ bind(&return_rax);
|
|
|
-+ // Restore the original regexp stack pointer value (effectively, pop the
|
|
|
-+ // stored base pointer).
|
|
|
-+ PopRegExpBasePointer(rcx, kScratchRegister);
|
|
|
-+
|
|
|
- #ifdef V8_TARGET_OS_WIN
|
|
|
- // Restore callee save registers.
|
|
|
- __ leaq(rsp, Operand(rbp, kLastCalleeSaveRegister));
|
|
|
-+ STATIC_ASSERT(kNumCalleeSaveRegisters == 3);
|
|
|
- __ popq(rbx);
|
|
|
- __ popq(rdi);
|
|
|
- __ popq(rsi);
|
|
|
- // Stack now at rbp.
|
|
|
- #else
|
|
|
- // Restore callee save register.
|
|
|
-+ STATIC_ASSERT(kNumCalleeSaveRegisters == 1);
|
|
|
- __ movq(rbx, Operand(rbp, kBackup_rbx));
|
|
|
- // Skip rsp to rbp.
|
|
|
- __ movq(rsp, rbp);
|
|
|
- #endif
|
|
|
-+
|
|
|
- // Exit function frame, restore previous one.
|
|
|
- __ popq(rbp);
|
|
|
- __ ret(0);
|
|
|
-@@ -923,9 +973,10 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
|
|
|
- if (check_preempt_label_.is_linked()) {
|
|
|
- SafeCallTarget(&check_preempt_label_);
|
|
|
-
|
|
|
-- __ pushq(backtrack_stackpointer());
|
|
|
- __ pushq(rdi);
|
|
|
-
|
|
|
-+ StoreRegExpStackPointerToMemory(backtrack_stackpointer(), kScratchRegister);
|
|
|
-+
|
|
|
- CallCheckStackGuardState();
|
|
|
- __ testq(rax, rax);
|
|
|
- // If returning non-zero, we should end execution with the given
|
|
|
-@@ -935,7 +986,9 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
|
|
|
- // Restore registers.
|
|
|
- __ Move(code_object_pointer(), masm_.CodeObject());
|
|
|
- __ popq(rdi);
|
|
|
-- __ popq(backtrack_stackpointer());
|
|
|
-+
|
|
|
-+ LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
|
|
|
-+
|
|
|
- // String might have moved: Reload esi from frame.
|
|
|
- __ movq(rsi, Operand(rbp, kInputEnd));
|
|
|
- SafeReturn();
|
|
|
-@@ -953,25 +1006,19 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
|
|
|
- __ pushq(rdi);
|
|
|
- #endif
|
|
|
-
|
|
|
-- // Call GrowStack(backtrack_stackpointer())
|
|
|
-- static const int num_arguments = 3;
|
|
|
-- __ PrepareCallCFunction(num_arguments);
|
|
|
--#ifdef V8_TARGET_OS_WIN
|
|
|
-- // Microsoft passes parameters in rcx, rdx, r8.
|
|
|
-- // First argument, backtrack stackpointer, is already in rcx.
|
|
|
-- __ leaq(rdx, Operand(rbp, kStackHighEnd)); // Second argument
|
|
|
-- __ LoadAddress(r8, ExternalReference::isolate_address(isolate()));
|
|
|
--#else
|
|
|
-- // AMD64 ABI passes parameters in rdi, rsi, rdx.
|
|
|
-- __ movq(rdi, backtrack_stackpointer()); // First argument.
|
|
|
-- __ leaq(rsi, Operand(rbp, kStackHighEnd)); // Second argument.
|
|
|
-- __ LoadAddress(rdx, ExternalReference::isolate_address(isolate()));
|
|
|
--#endif
|
|
|
-+ // Call GrowStack(isolate).
|
|
|
-+
|
|
|
-+ StoreRegExpStackPointerToMemory(backtrack_stackpointer(), kScratchRegister);
|
|
|
-+
|
|
|
-+ static constexpr int kNumArguments = 1;
|
|
|
-+ __ PrepareCallCFunction(kNumArguments);
|
|
|
-+ __ LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate()));
|
|
|
-+
|
|
|
- ExternalReference grow_stack =
|
|
|
- ExternalReference::re_grow_stack(isolate());
|
|
|
-- __ CallCFunction(grow_stack, num_arguments);
|
|
|
-- // If return nullptr, we have failed to grow the stack, and
|
|
|
-- // must exit with a stack-overflow exception.
|
|
|
-+ __ CallCFunction(grow_stack, kNumArguments);
|
|
|
-+ // If nullptr is returned, we have failed to grow the stack, and must exit
|
|
|
-+ // with a stack-overflow exception.
|
|
|
- __ testq(rax, rax);
|
|
|
- __ j(equal, &exit_with_exception);
|
|
|
- // Otherwise use return value as new stack pointer.
|
|
|
-@@ -1085,13 +1132,25 @@ void RegExpMacroAssemblerX64::ReadPositionFromRegister(Register dst, int reg) {
|
|
|
- __ movq(dst, register_location(reg));
|
|
|
- }
|
|
|
-
|
|
|
-+// Preserves a position-independent representation of the stack pointer in reg:
|
|
|
-+// reg = top - sp.
|
|
|
-+void RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) {
|
|
|
-+ ExternalReference stack_top_address =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ movq(rax, __ ExternalReferenceAsOperand(stack_top_address, rax));
|
|
|
-+ __ subq(rax, backtrack_stackpointer());
|
|
|
-+ __ movq(register_location(reg), rax);
|
|
|
-+}
|
|
|
-
|
|
|
- void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) {
|
|
|
-- __ movq(backtrack_stackpointer(), register_location(reg));
|
|
|
-- __ addq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd));
|
|
|
-+ ExternalReference stack_top_address =
|
|
|
-+ ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
|
|
|
-+ __ movq(backtrack_stackpointer(),
|
|
|
-+ __ ExternalReferenceAsOperand(stack_top_address,
|
|
|
-+ backtrack_stackpointer()));
|
|
|
-+ __ subq(backtrack_stackpointer(), register_location(reg));
|
|
|
- }
|
|
|
-
|
|
|
--
|
|
|
- void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) {
|
|
|
- Label after_position;
|
|
|
- __ cmpq(rdi, Immediate(-by * char_size()));
|
|
|
-@@ -1136,14 +1195,6 @@ void RegExpMacroAssemblerX64::ClearRegisters(int reg_from, int reg_to) {
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
--
|
|
|
--void RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) {
|
|
|
-- __ movq(rax, backtrack_stackpointer());
|
|
|
-- __ subq(rax, Operand(rbp, kStackHighEnd));
|
|
|
-- __ movq(register_location(reg), rax);
|
|
|
--}
|
|
|
--
|
|
|
--
|
|
|
- // Private methods:
|
|
|
-
|
|
|
- void RegExpMacroAssemblerX64::CallCheckStackGuardState() {
|
|
|
-diff --git a/src/regexp/x64/regexp-macro-assembler-x64.h b/src/regexp/x64/regexp-macro-assembler-x64.h
|
|
|
-index c3a3cb90f2a9d865057af80801e2a95bbb873140..74a3c95b06c771078ab03e6787e5912315421bb2 100644
|
|
|
---- a/src/regexp/x64/regexp-macro-assembler-x64.h
|
|
|
-+++ b/src/regexp/x64/regexp-macro-assembler-x64.h
|
|
|
-@@ -5,9 +5,7 @@
|
|
|
- #ifndef V8_REGEXP_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
|
|
|
- #define V8_REGEXP_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
|
|
|
-
|
|
|
--#include "src/base/strings.h"
|
|
|
- #include "src/codegen/macro-assembler.h"
|
|
|
--#include "src/codegen/x64/assembler-x64.h"
|
|
|
- #include "src/regexp/regexp-macro-assembler.h"
|
|
|
- #include "src/zone/zone-chunk-list.h"
|
|
|
-
|
|
|
-@@ -133,18 +131,17 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
|
|
|
- static const int kIsolate = kDirectCall + kSystemPointerSize;
|
|
|
- #endif
|
|
|
-
|
|
|
-+ // We push callee-save registers that we use after the frame pointer (and
|
|
|
-+ // after the parameters).
|
|
|
- #ifdef V8_TARGET_OS_WIN
|
|
|
-- // Microsoft calling convention has three callee-saved registers
|
|
|
-- // (that we are using). We push these after the frame pointer.
|
|
|
- static const int kBackup_rsi = kFramePointer - kSystemPointerSize;
|
|
|
- static const int kBackup_rdi = kBackup_rsi - kSystemPointerSize;
|
|
|
- static const int kBackup_rbx = kBackup_rdi - kSystemPointerSize;
|
|
|
-+ static const int kNumCalleeSaveRegisters = 3;
|
|
|
- static const int kLastCalleeSaveRegister = kBackup_rbx;
|
|
|
- #else
|
|
|
-- // AMD64 Calling Convention has only one callee-save register that
|
|
|
-- // we use. We push this after the frame pointer (and after the
|
|
|
-- // parameters).
|
|
|
- static const int kBackup_rbx = kNumOutputRegisters - kSystemPointerSize;
|
|
|
-+ static const int kNumCalleeSaveRegisters = 1;
|
|
|
- static const int kLastCalleeSaveRegister = kBackup_rbx;
|
|
|
- #endif
|
|
|
-
|
|
|
-@@ -155,9 +152,14 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
|
|
|
- static const int kStringStartMinusOne =
|
|
|
- kSuccessfulCaptures - kSystemPointerSize;
|
|
|
- static const int kBacktrackCount = kStringStartMinusOne - kSystemPointerSize;
|
|
|
-+ // Stores the initial value of the regexp stack pointer in a
|
|
|
-+ // position-independent representation (in case the regexp stack grows and
|
|
|
-+ // thus moves).
|
|
|
-+ static const int kRegExpStackBasePointer =
|
|
|
-+ kBacktrackCount - kSystemPointerSize;
|
|
|
-
|
|
|
- // First register address. Following registers are below it on the stack.
|
|
|
-- static const int kRegisterZero = kBacktrackCount - kSystemPointerSize;
|
|
|
-+ static const int kRegisterZero = kRegExpStackBasePointer - kSystemPointerSize;
|
|
|
-
|
|
|
- // Initial size of code buffer.
|
|
|
- static const int kRegExpCodeSize = 1024;
|
|
|
-@@ -175,14 +177,14 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
|
|
|
- Operand register_location(int register_index);
|
|
|
-
|
|
|
- // The register containing the current character after LoadCurrentCharacter.
|
|
|
-- inline Register current_character() { return rdx; }
|
|
|
-+ static constexpr Register current_character() { return rdx; }
|
|
|
-
|
|
|
- // The register containing the backtrack stack top. Provides a meaningful
|
|
|
- // name to the register.
|
|
|
-- inline Register backtrack_stackpointer() { return rcx; }
|
|
|
-+ static constexpr Register backtrack_stackpointer() { return rcx; }
|
|
|
-
|
|
|
- // The registers containing a self pointer to this code's Code object.
|
|
|
-- inline Register code_object_pointer() { return r8; }
|
|
|
-+ static constexpr Register code_object_pointer() { return r8; }
|
|
|
-
|
|
|
- // Byte size of chars in the string to match (decided by the Mode argument)
|
|
|
- inline int char_size() { return static_cast<int>(mode_); }
|
|
|
-@@ -224,24 +226,36 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
|
|
|
- // Increments the stack pointer (rcx) by a word size.
|
|
|
- inline void Drop();
|
|
|
-
|
|
|
-+ void LoadRegExpStackPointerFromMemory(Register dst);
|
|
|
-+ void StoreRegExpStackPointerToMemory(Register src, Register scratch);
|
|
|
-+ void PushRegExpBasePointer(Register scratch1, Register scratch2);
|
|
|
-+ void PopRegExpBasePointer(Register scratch1, Register scratch2);
|
|
|
-+
|
|
|
- inline void ReadPositionFromRegister(Register dst, int reg);
|
|
|
-
|
|
|
- Isolate* isolate() const { return masm_.isolate(); }
|
|
|
-
|
|
|
- MacroAssembler masm_;
|
|
|
-- NoRootArrayScope no_root_array_scope_;
|
|
|
-+
|
|
|
-+ // On x64, there is no reason to keep the kRootRegister uninitialized; we
|
|
|
-+ // could easily use it by 1. initializing it and 2. storing/restoring it
|
|
|
-+ // as callee-save on entry/exit.
|
|
|
-+ // But: on other platforms, specifically ia32, it would be tricky to enable
|
|
|
-+ // the kRootRegister since it's currently used for other purposes. Thus, for
|
|
|
-+ // consistency, we also keep it uninitialized here.
|
|
|
-+ const NoRootArrayScope no_root_array_scope_;
|
|
|
-
|
|
|
- ZoneChunkList<int> code_relative_fixup_positions_;
|
|
|
-
|
|
|
- // Which mode to generate code for (LATIN1 or UC16).
|
|
|
-- Mode mode_;
|
|
|
-+ const 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_;
|
|
|
-+ const int num_saved_registers_;
|
|
|
-
|
|
|
- // Labels used internally.
|
|
|
- Label entry_label_;
|
|
|
-diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
|
|
|
-index e87644e89b7d87fb95917a58fef5f019d3ce7fc9..597ee4248bdd9e2dbb1ce05b322cd253dd403603 100644
|
|
|
---- a/test/cctest/cctest.status
|
|
|
-+++ b/test/cctest/cctest.status
|
|
|
-@@ -136,9 +136,6 @@
|
|
|
- 'test-strings/Traverse': [PASS, HEAVY],
|
|
|
- 'test-swiss-name-dictionary-csa/DeleteAtBoundaries': [PASS, HEAVY],
|
|
|
- 'test-swiss-name-dictionary-csa/SameH2': [PASS, HEAVY],
|
|
|
--
|
|
|
-- # TODO(v8:11382): Reenable once irregexp is reentrant.
|
|
|
-- 'test-regexp/RegExpInterruptReentrantExecution': [FAIL],
|
|
|
- }], # ALWAYS
|
|
|
-
|
|
|
- ##############################################################################
|