v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
stacks.cc
Go to the documentation of this file.
1// Copyright 2022 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/wasm/stacks.h"
6
10
11namespace v8::internal::wasm {
12
13// static
15 base::Vector<uint8_t> view = SimulatorStack::GetCentralStackView(isolate);
16 return new StackMemory(view.begin(), view.size());
17}
18
20 if (v8_flags.trace_wasm_stack_switching) {
21 PrintF("Delete stack #%d\n", id_);
22 }
23 auto segment = first_segment_;
24 while (segment) {
25 auto next_segment = segment->next_segment_;
26 delete segment;
27 segment = next_segment;
28 }
29}
30
31void* StackMemory::jslimit() const {
33 SimulatorStack::JSStackLimitMargin();
34}
35
36StackMemory::StackMemory() : owned_(true) {
37 static std::atomic<int> next_id(1);
38 id_ = next_id.fetch_add(1);
39 size_t kJsStackSizeKB = v8_flags.wasm_stack_switching_stack_size;
40 // v8_flags.stack_size is a size of the central stack and maximum
41 // size of a secondary stack to grow.
42 const size_t size_limit = v8_flags.stack_size;
44 auto page_size = allocator->AllocatePageSize();
45 size_t initial_size = std::min<size_t>(
46 size_limit * KB,
47 kJsStackSizeKB * KB + SimulatorStack::JSStackLimitMargin());
49 new StackSegment(RoundUp(initial_size, page_size) / page_size);
53 if (v8_flags.trace_wasm_stack_switching) {
54 PrintF("Allocate stack #%d (limit: %p, base: %p, size: %zu)\n", id_, limit_,
55 limit_ + size_, size_);
56 }
57}
58
59// Overload to represent a view of the libc stack.
60StackMemory::StackMemory(uint8_t* limit, size_t size)
61 : limit_(limit), size_(size), owned_(false) {
62 id_ = 0;
63}
64
66 DCHECK_GE(pages, 1);
68 size_ = pages * allocator->AllocatePageSize();
69 limit_ = static_cast<uint8_t*>(
70 allocator->AllocatePages(nullptr, size_, allocator->AllocatePageSize(),
72 if (limit_ == nullptr) {
74 "StackMemory::StackSegment::StackSegment");
75 }
76}
77
80 if (!allocator->DecommitPages(limit_, size_)) {
81 V8::FatalProcessOutOfMemory(nullptr, "Decommit stack memory");
82 }
83}
84
85bool StackMemory::Grow(Address current_fp) {
87 if (active_segment_->next_segment_ != nullptr) {
89 } else {
91 auto page_size = allocator->AllocatePageSize();
92 const size_t size_limit = RoundUp(v8_flags.stack_size * KB, page_size);
93 DCHECK_GE(size_limit, size_);
94 size_t room_to_grow = size_limit - size_;
95 size_t new_size = std::min(2 * active_segment_->size_, room_to_grow);
96 if (new_size < page_size) {
97 // We cannot grow less than page size.
98 if (v8_flags.trace_wasm_stack_switching) {
99 PrintF("Stack #%d reached the grow limit %zu bytes\n", id_, size_limit);
100 }
101 return false;
102 }
103 auto new_segment = new StackSegment(new_size / page_size);
104 new_segment->prev_segment_ = active_segment_;
105 active_segment_->next_segment_ = new_segment;
106 active_segment_ = new_segment;
107 }
108 active_segment_->old_fp = current_fp;
110 if (v8_flags.trace_wasm_stack_switching) {
111 PrintF("Grow stack #%d by %zu bytes (limit: %p, base: %p)\n", id_,
114 }
115 return true;
116}
117
119 DCHECK(owned_);
125 if (v8_flags.trace_wasm_stack_switching) {
126 PrintF("Shrink stack #%d (limit: %p, base: %p)\n", id_,
129 }
130 return old_fp;
131}
132
133void StackMemory::ShrinkTo(Address stack_address) {
135 while (active_segment_) {
136 if (stack_address <= active_segment_->base() &&
137 stack_address >= reinterpret_cast<Address>(active_segment_->limit_)) {
138 return;
139 }
140 Shrink();
141 }
142 UNREACHABLE();
143}
144
149
150std::unique_ptr<StackMemory> StackPool::GetOrAllocate() {
151 while (size_ > kMaxSize) {
152 size_ -= freelist_.back()->allocated_size();
153 freelist_.pop_back();
154 }
155 std::unique_ptr<StackMemory> stack;
156 if (freelist_.empty()) {
157 stack = StackMemory::New();
158 } else {
159 stack = std::move(freelist_.back());
160 freelist_.pop_back();
161 size_ -= stack->allocated_size();
162 }
163#if DEBUG
164 constexpr uint8_t kZapValue = 0xab;
165 stack->FillWith(kZapValue);
166#endif
167 return stack;
168}
169
170void StackPool::Add(std::unique_ptr<StackMemory> stack) {
171 // Add the stack to the pool regardless of kMaxSize, because the stack might
172 // still be in use by the unwinder.
173 // Shrink the freelist lazily when we get the next stack instead.
174 size_ += stack->allocated_size();
175 stack->Reset();
176 freelist_.push_back(std::move(stack));
177}
178
180 size_ = 0;
181 freelist_.clear();
182}
183
184size_t StackPool::Size() const {
185 return freelist_.size() * sizeof(decltype(freelist_)::value_type) + size_;
186}
187
188} // namespace v8::internal::wasm
constexpr size_t size() const
Definition vector.h:70
constexpr T * begin() const
Definition vector.h:96
static V8_EXPORT_PRIVATE void FatalProcessOutOfMemory(Isolate *isolate, const char *location, const OOMDetails &details=kNoOOMDetails)
static std::unique_ptr< StackMemory > New()
Definition stacks.h:54
void ShrinkTo(Address stack_address)
Definition stacks.cc:133
StackSegment * first_segment_
Definition stacks.h:198
StackSegment * active_segment_
Definition stacks.h:199
bool Grow(Address current_fp)
Definition stacks.cc:85
static StackMemory * GetCentralStackView(Isolate *isolate)
Definition stacks.cc:14
std::unique_ptr< StackMemory > GetOrAllocate()
Definition stacks.cc:150
void Add(std::unique_ptr< StackMemory > stack)
Definition stacks.cc:170
const int size_
Definition assembler.cc:132
const int limit_
Definition isolate.cc:1114
ZoneStack< RpoNumber > & stack
static ValueType value_type()
v8::PageAllocator * GetPlatformPageAllocator()
Definition allocation.cc:66
void PrintF(const char *format,...)
Definition utils.cc:39
constexpr uint32_t kZapValue
Definition globals.h:1005
V8_EXPORT_PRIVATE FlagValues v8_flags
static constexpr int kMaxSize
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
constexpr T RoundUp(T x, intptr_t m)
Definition macros.h:387