v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
assembler.cc
Go to the documentation of this file.
1// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// - Neither the name of Sun Microsystems or the names of contributors may
16// be used to endorse or promote products derived from this software without
17// specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// The original source code covered by the above license above has been
32// modified significantly by Google Inc.
33// Copyright 2012 the V8 project authors. All rights reserved.
34
36
37#ifdef V8_CODE_COMMENTS
38#include <iomanip>
39#endif
40#include "src/base/vector.h"
45#include "src/heap/heap-inl.h" // For MemoryAllocator. TODO(jkummerow): Drop.
48#include "src/utils/ostreams.h"
49
50namespace v8 {
51namespace internal {
52
55 const bool serializer = isolate->serializer_enabled();
56 const bool generating_embedded_builtin =
57 isolate->IsGeneratingEmbeddedBuiltins();
58 options.record_reloc_info_for_serialization = serializer;
59 options.enable_root_relative_access =
60 !serializer && !generating_embedded_builtin;
61#ifdef USE_SIMULATOR
62 // Even though the simulator is enabled, we may still need to generate code
63 // that may need to run on both the simulator and real hardware. For example,
64 // if we are cross-compiling and embedding a script into the snapshot, the
65 // script will need to run on the host causing the embedded builtins to run in
66 // the simulator. While the final cross-compiled V8 will not have a simulator.
67
68 // So here we enable simulator specific code if not generating the snapshot or
69 // if we are but we are targetting the simulator *only*.
70 options.enable_simulator_code = !serializer || v8_flags.target_is_simulator;
71#endif
72
73#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_LOONG64 || \
74 V8_TARGET_ARCH_RISCV64
75 options.code_range_base = isolate->heap()->code_range_base();
76#endif
77 bool short_builtin_calls =
78 isolate->is_short_builtin_calls_enabled() &&
79 !generating_embedded_builtin &&
80 (options.code_range_base != kNullAddress) &&
81 // Serialization of NEAR_BUILTIN_ENTRY reloc infos is not supported yet.
82 !serializer;
83 if (short_builtin_calls) {
84 options.builtin_call_jump_mode = BuiltinCallJumpMode::kPCRelative;
85 }
86 return options;
87}
88
89namespace {
90
91class DefaultAssemblerBuffer : public AssemblerBuffer {
92 public:
93 explicit DefaultAssemblerBuffer(int size)
94 : buffer_(base::OwnedVector<uint8_t>::NewForOverwrite(
95 std::max(AssemblerBase::kMinimalBufferSize, size))) {
96#ifdef DEBUG
97 ZapCode(reinterpret_cast<Address>(buffer_.begin()), buffer_.size());
98#endif
99 }
100
101 uint8_t* start() const override { return buffer_.begin(); }
102
103 int size() const override { return static_cast<int>(buffer_.size()); }
104
105 std::unique_ptr<AssemblerBuffer> Grow(int new_size) override {
106 DCHECK_LT(size(), new_size);
107 return std::make_unique<DefaultAssemblerBuffer>(new_size);
108 }
109
110 private:
111 base::OwnedVector<uint8_t> buffer_;
112};
113
114class ExternalAssemblerBufferImpl : public AssemblerBuffer {
115 public:
116 ExternalAssemblerBufferImpl(uint8_t* start, int size)
117 : start_(start), size_(size) {}
118
119 uint8_t* start() const override { return start_; }
120
121 int size() const override { return size_; }
122
123 std::unique_ptr<AssemblerBuffer> Grow(int new_size) override {
124 FATAL("Cannot grow external assembler buffer");
125 }
126
127 void* operator new(std::size_t count);
128 void operator delete(void* ptr) noexcept;
129
130 private:
131 uint8_t* const start_;
132 const int size_;
133};
134
135alignas(
136 ExternalAssemblerBufferImpl) static thread_local char tls_singleton_storage
137 [sizeof(ExternalAssemblerBufferImpl)];
138
139static thread_local bool tls_singleton_taken{false};
140
141void* ExternalAssemblerBufferImpl::operator new(std::size_t count) {
142 DCHECK_EQ(count, sizeof(ExternalAssemblerBufferImpl));
143 if (V8_LIKELY(!tls_singleton_taken)) {
144 tls_singleton_taken = true;
145 return tls_singleton_storage;
146 }
147 return ::operator new(count);
148}
149
150void ExternalAssemblerBufferImpl::operator delete(void* ptr) noexcept {
151 if (V8_LIKELY(ptr == tls_singleton_storage)) {
152 DCHECK(tls_singleton_taken);
153 tls_singleton_taken = false;
154 return;
155 }
156 ::operator delete(ptr);
157}
158
159} // namespace
160
161std::unique_ptr<AssemblerBuffer> ExternalAssemblerBuffer(void* start,
162 int size) {
163 return std::make_unique<ExternalAssemblerBufferImpl>(
164 reinterpret_cast<uint8_t*>(start), size);
165}
166
167std::unique_ptr<AssemblerBuffer> NewAssemblerBuffer(int size) {
168 return std::make_unique<DefaultAssemblerBuffer>(size);
169}
170
171// -----------------------------------------------------------------------------
172// Implementation of AssemblerBase
173
174// static
176
177// static
179
181 std::unique_ptr<AssemblerBuffer> buffer)
182 : buffer_(std::move(buffer)),
183 options_(options),
184 enabled_cpu_features_(0),
185 predictable_code_size_(false),
186 constant_pool_available_(false),
187 jump_optimization_info_(nullptr) {
189 buffer_start_ = buffer_->start();
191}
192
194
199
200// -----------------------------------------------------------------------------
201// Implementation of CpuFeatureScope
202
203#ifdef DEBUG
205 CheckPolicy check)
206 : assembler_(assembler) {
207 DCHECK_IMPLIES(check == kCheckSupported, CpuFeatures::IsSupported(f));
208 old_enabled_ = assembler_->enabled_cpu_features();
209 assembler_->EnableCpuFeature(f);
210}
211
213 assembler_->set_enabled_cpu_features(old_enabled_);
214}
215#endif
216
217bool CpuFeatures::initialized_ = false;
220unsigned CpuFeatures::supported_ = 0;
223
229
230// Platform specific but identical code for all the platforms.
231
232void Assembler::RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
233 SourcePosition position, int id) {
234 static_assert(RelocInfoWriter::kMaxSize * 2 <= kGap);
235 {
236 EnsureSpace space(this);
237 DCHECK(position.IsKnown());
240 }
241 {
242 EnsureSpace space(this);
243 RecordRelocInfo(RelocInfo::DEOPT_REASON, static_cast<int>(reason));
245 }
246#ifdef DEBUG
247 EnsureSpace space(this);
249#endif // DEBUG
250}
251
254 while ((pc_offset() & (m - 1)) != 0) {
255 // Pad with 0xcc (= int3 on ia32 and x64); the primary motivation is that
256 // the disassembler expects to find valid instructions, but this is also
257 // nice from a security point of view.
258 db(0xcc);
259 }
260}
261
263 request.set_offset(pc_offset());
264 heap_number_requests_.push_front(request);
265}
266
268 int current = static_cast<int>(code_targets_.size());
269 if (current > 0 && !target.is_null() &&
270 code_targets_.back().address() == target.address()) {
271 // Optimization if we keep jumping to the same code target.
272 return current - 1;
273 } else {
274 code_targets_.push_back(target);
275 return current;
276 }
277}
278
280 intptr_t code_target_index) const {
281 DCHECK_LT(static_cast<size_t>(code_target_index), code_targets_.size());
282 return code_targets_[code_target_index];
283}
284
287 EmbeddedObjectIndex current = embedded_objects_.size();
288 // Do not deduplicate invalid handles, they are to heap object requests.
289 if (!object.is_null()) {
290 auto entry = embedded_objects_map_.find(object);
291 if (entry != embedded_objects_map_.end()) {
292 return entry->second;
293 }
295 }
296 embedded_objects_.push_back(object);
297 return current;
298}
299
305
307 if (!v8_flags.code_comments) return 0;
309 options().emit_code_comments);
310 if (code_comments_writer_.entry_count() == 0) return 0;
311 int offset = pc_offset();
313 int size = pc_offset() - offset;
315 return size;
316}
317
318#ifdef V8_CODE_COMMENTS
319int Assembler::CodeComment::depth() const { return assembler_->comment_depth_; }
320void Assembler::CodeComment::Open(const std::string& comment,
321 const SourceLocation& loc) {
322 std::stringstream sstream;
323 sstream << std::setfill(' ') << std::setw(depth() * kIndentWidth + 2);
324 sstream << "[ " << comment;
325 assembler_->comment_depth_++;
326 assembler_->RecordComment(sstream.str(), loc);
327}
328
329void Assembler::CodeComment::Close() {
330 assembler_->comment_depth_--;
331 std::string comment = "]";
332 comment.insert(0, depth() * kIndentWidth, ' ');
333 DCHECK_LE(0, depth());
334 // Don't record source information for the closed comment.
335 assembler_->RecordComment(comment, SourceLocation());
336}
337#endif
338
339} // namespace internal
340} // namespace v8
void RequestHeapNumber(HeapNumberRequest request)
Definition assembler.cc:262
std::unique_ptr< AssemblerBuffer > buffer_
Definition assembler.h:504
static constexpr int kDefaultBufferSize
Definition assembler.h:489
IndirectHandle< Code > GetCodeTarget(intptr_t code_target_index) const
Definition assembler.cc:279
AssemblerBase(const AssemblerOptions &options, std::unique_ptr< AssemblerBuffer >)
Definition assembler.cc:180
EmbeddedObjectIndex AddEmbeddedObject(IndirectHandle< HeapObject > object)
Definition assembler.cc:285
std::unordered_map< IndirectHandle< HeapObject >, EmbeddedObjectIndex, IndirectHandle< HeapObject >::hash, IndirectHandle< HeapObject >::equal_to > embedded_objects_map_
Definition assembler.h:561
void Print(Isolate *isolate)
Definition assembler.cc:195
std::vector< IndirectHandle< HeapObject > > embedded_objects_
Definition assembler.h:553
std::forward_list< HeapNumberRequest > heap_number_requests_
Definition assembler.h:507
CodeCommentsWriter code_comments_writer_
Definition assembler.h:538
int AddCodeTarget(IndirectHandle< Code > target)
Definition assembler.cc:267
IndirectHandle< HeapObject > GetEmbeddedObject(EmbeddedObjectIndex index) const
Definition assembler.cc:300
static constexpr int kMinimalBufferSize
Definition assembler.h:485
std::vector< IndirectHandle< Code > > code_targets_
Definition assembler.h:547
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data=0)
static constexpr int kGap
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id, SourcePosition position, int id)
Definition assembler.cc:232
CpuFeatureScope(AssemblerBase *assembler, CpuFeature f, CheckPolicy check=kCheckSupported)
Definition assembler.h:599
static bool IsSupported(CpuFeature f)
static bool supports_wasm_simd_128_
static unsigned supported_
static unsigned icache_line_size_
static unsigned dcache_line_size_
static V8_EXPORT_PRIVATE int Decode(Isolate *isolate, std::ostream &os, uint8_t *begin, uint8_t *end, CodeReference code={}, Address current_pc=kNullAddress, size_t range_limit=0)
HeapNumberRequest(double heap_number, int offset=-1)
Definition assembler.cc:224
static constexpr int kMaxSize
Definition reloc-info.h:488
Operand const offset_
base::OwnedVector< uint8_t > buffer_
Definition assembler.cc:111
const int size_
Definition assembler.cc:132
uint8_t *const start_
Definition assembler.cc:131
int start
uint32_t count
LineAndColumn current
BytecodeAssembler & assembler_
GCOptions options_
int32_t offset
DirectHandle< JSReceiver > options
int position
Definition liveedit.cc:290
int m
Definition mul-fft.cc:294
STL namespace.
constexpr bool IsPowerOfTwo(T value)
Definition bits.h:187
V8_INLINE void ZapCode(Address addr, size_t size_in_bytes)
Definition utils.h:839
bool IsSmiDouble(double value)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available space
Definition flags.cc:2128
std::unique_ptr< AssemblerBuffer > NewAssemblerBuffer(int size)
Definition assembler.cc:167
constexpr BlockAddrMode db
V8_EXPORT_PRIVATE FlagValues v8_flags
static constexpr Address kNullAddress
Definition v8-internal.h:53
std::unique_ptr< AssemblerBuffer > ExternalAssemblerBuffer(void *start, int size)
Definition assembler.cc:161
#define FATAL(...)
Definition logging.h:47
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK_IMPLIES(lhs, rhs)
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
static AssemblerOptions Default(Isolate *isolate)
Definition assembler.cc:53
other heap size max size of the shared heap(in Mbytes)
#define V8_LIKELY(condition)
Definition v8config.h:661