11cb0ef41Sopenharmony_ci// Copyright 2009 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/regexp/regexp-stack.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/execution/isolate.h"
81cb0ef41Sopenharmony_ci#include "src/utils/memcopy.h"
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_cinamespace v8 {
111cb0ef41Sopenharmony_cinamespace internal {
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciRegExpStackScope::RegExpStackScope(Isolate* isolate)
141cb0ef41Sopenharmony_ci    : regexp_stack_(isolate->regexp_stack()),
151cb0ef41Sopenharmony_ci      old_sp_top_delta_(regexp_stack_->sp_top_delta()) {
161cb0ef41Sopenharmony_ci  DCHECK(regexp_stack_->IsValid());
171cb0ef41Sopenharmony_ci}
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciRegExpStackScope::~RegExpStackScope() {
201cb0ef41Sopenharmony_ci  CHECK_EQ(old_sp_top_delta_, regexp_stack_->sp_top_delta());
211cb0ef41Sopenharmony_ci  regexp_stack_->ResetIfEmpty();
221cb0ef41Sopenharmony_ci}
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciRegExpStack::RegExpStack() : thread_local_(this) {}
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciRegExpStack::~RegExpStack() { thread_local_.FreeAndInvalidate(); }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_cichar* RegExpStack::ArchiveStack(char* to) {
291cb0ef41Sopenharmony_ci  if (!thread_local_.owns_memory_) {
301cb0ef41Sopenharmony_ci    // Force dynamic stacks prior to archiving. Any growth will do. A dynamic
311cb0ef41Sopenharmony_ci    // stack is needed because stack archival & restoration rely on `memory_`
321cb0ef41Sopenharmony_ci    // pointing at a fixed-location backing store, whereas the static stack is
331cb0ef41Sopenharmony_ci    // tied to a RegExpStack instance.
341cb0ef41Sopenharmony_ci    EnsureCapacity(thread_local_.memory_size_ + 1);
351cb0ef41Sopenharmony_ci    DCHECK(thread_local_.owns_memory_);
361cb0ef41Sopenharmony_ci  }
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  MemCopy(reinterpret_cast<void*>(to), &thread_local_, kThreadLocalSize);
391cb0ef41Sopenharmony_ci  thread_local_ = ThreadLocal(this);
401cb0ef41Sopenharmony_ci  return to + kThreadLocalSize;
411cb0ef41Sopenharmony_ci}
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_cichar* RegExpStack::RestoreStack(char* from) {
451cb0ef41Sopenharmony_ci  MemCopy(&thread_local_, reinterpret_cast<void*>(from), kThreadLocalSize);
461cb0ef41Sopenharmony_ci  return from + kThreadLocalSize;
471cb0ef41Sopenharmony_ci}
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_civoid RegExpStack::ThreadLocal::ResetToStaticStack(RegExpStack* regexp_stack) {
501cb0ef41Sopenharmony_ci  if (owns_memory_) DeleteArray(memory_);
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  memory_ = regexp_stack->static_stack_;
531cb0ef41Sopenharmony_ci  memory_top_ = regexp_stack->static_stack_ + kStaticStackSize;
541cb0ef41Sopenharmony_ci  memory_size_ = kStaticStackSize;
551cb0ef41Sopenharmony_ci  stack_pointer_ = memory_top_;
561cb0ef41Sopenharmony_ci  limit_ = reinterpret_cast<Address>(regexp_stack->static_stack_) +
571cb0ef41Sopenharmony_ci           kStackLimitSlack * kSystemPointerSize;
581cb0ef41Sopenharmony_ci  owns_memory_ = false;
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_civoid RegExpStack::ThreadLocal::FreeAndInvalidate() {
621cb0ef41Sopenharmony_ci  if (owns_memory_) DeleteArray(memory_);
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  // This stack may not be used after being freed. Just reset to invalid values
651cb0ef41Sopenharmony_ci  // to ensure we don't accidentally use old memory areas.
661cb0ef41Sopenharmony_ci  memory_ = nullptr;
671cb0ef41Sopenharmony_ci  memory_top_ = nullptr;
681cb0ef41Sopenharmony_ci  memory_size_ = 0;
691cb0ef41Sopenharmony_ci  stack_pointer_ = nullptr;
701cb0ef41Sopenharmony_ci  limit_ = kMemoryTop;
711cb0ef41Sopenharmony_ci}
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ciAddress RegExpStack::EnsureCapacity(size_t size) {
741cb0ef41Sopenharmony_ci  if (size > kMaximumStackSize) return kNullAddress;
751cb0ef41Sopenharmony_ci  if (thread_local_.memory_size_ < size) {
761cb0ef41Sopenharmony_ci    if (size < kMinimumDynamicStackSize) size = kMinimumDynamicStackSize;
771cb0ef41Sopenharmony_ci    byte* new_memory = NewArray<byte>(size);
781cb0ef41Sopenharmony_ci    if (thread_local_.memory_size_ > 0) {
791cb0ef41Sopenharmony_ci      // Copy original memory into top of new memory.
801cb0ef41Sopenharmony_ci      MemCopy(new_memory + size - thread_local_.memory_size_,
811cb0ef41Sopenharmony_ci              thread_local_.memory_, thread_local_.memory_size_);
821cb0ef41Sopenharmony_ci      if (thread_local_.owns_memory_) DeleteArray(thread_local_.memory_);
831cb0ef41Sopenharmony_ci    }
841cb0ef41Sopenharmony_ci    ptrdiff_t delta = sp_top_delta();
851cb0ef41Sopenharmony_ci    thread_local_.memory_ = new_memory;
861cb0ef41Sopenharmony_ci    thread_local_.memory_top_ = new_memory + size;
871cb0ef41Sopenharmony_ci    thread_local_.memory_size_ = size;
881cb0ef41Sopenharmony_ci    thread_local_.stack_pointer_ = thread_local_.memory_top_ + delta;
891cb0ef41Sopenharmony_ci    thread_local_.limit_ = reinterpret_cast<Address>(new_memory) +
901cb0ef41Sopenharmony_ci                           kStackLimitSlack * kSystemPointerSize;
911cb0ef41Sopenharmony_ci    thread_local_.owns_memory_ = true;
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci  return reinterpret_cast<Address>(thread_local_.memory_top_);
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci}  // namespace internal
981cb0ef41Sopenharmony_ci}  // namespace v8
99