v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
embedded-file-writer.cc
Go to the documentation of this file.
1// Copyright 2018 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
6
7#include <algorithm>
8#include <cinttypes>
9
11#include "src/flags/flags.h" // For ENABLE_CONTROL_FLOW_INTEGRITY_BOOL
14
15namespace v8 {
16namespace internal {
17
18namespace {
19
20int WriteDirectiveOrSeparator(PlatformEmbeddedFileWriterBase* w,
21 int current_line_length,
22 DataDirective directive) {
23 int printed_chars;
24 if (current_line_length == 0) {
25 printed_chars = w->IndentedDataDirective(directive);
26 DCHECK_LT(0, printed_chars);
27 } else {
28 printed_chars = fprintf(w->fp(), ",");
29 DCHECK_EQ(1, printed_chars);
30 }
31 return current_line_length + printed_chars;
32}
33
34int WriteLineEndIfNeeded(PlatformEmbeddedFileWriterBase* w,
35 int current_line_length, int write_size) {
36 static const int kTextWidth = 100;
37 // Check if adding ',0xFF...FF\n"' would force a line wrap. This doesn't use
38 // the actual size of the string to be written to determine this so it's
39 // more conservative than strictly needed.
40 if (current_line_length + strlen(",0x") + write_size * 2 > kTextWidth) {
41 fprintf(w->fp(), "\n");
42 return 0;
43 } else {
44 return current_line_length;
45 }
46}
47
48} // namespace
49
51 const i::EmbeddedData* blob,
52 const Builtin builtin) const {
53 const bool is_default_variant =
55
57 if (is_default_variant) {
58 // Create nicer symbol names for the default mode.
59 base::SNPrintF(builtin_symbol, "Builtins_%s", i::Builtins::name(builtin));
60 } else {
61 base::SNPrintF(builtin_symbol, "%s_Builtins_%s", embedded_variant_,
62 i::Builtins::name(builtin));
63 }
64
65 // Labels created here will show up in backtraces. We check in
66 // Isolate::SetEmbeddedBlob that the blob layout remains unchanged, i.e.
67 // that labels do not insert bytes into the middle of the blob byte
68 // stream.
69 w->DeclareFunctionBegin(builtin_symbol.begin(),
70 blob->InstructionSizeOf(builtin));
71 const int builtin_id = static_cast<int>(builtin);
72 const std::vector<uint8_t>& current_positions = source_positions_[builtin_id];
73 // The code below interleaves bytes of assembly code for the builtin
74 // function with source positions at the appropriate offsets.
75 base::Vector<const uint8_t> vpos(current_positions.data(),
76 current_positions.size());
79
80#ifndef DEBUG
81 CHECK(positions.done()); // Release builds must not contain debug infos.
82#endif
83
84 // Some builtins (InterpreterPushArgsThenFastConstructFunction,
85 // JSConstructStubGeneric) have entry points located in the middle of them, we
86 // need to store their addresses since they are part of the list of allowed
87 // return addresses in the deoptimizer.
88 const std::vector<LabelInfo>& current_labels = label_info_[builtin_id];
89 auto label = current_labels.begin();
90
91 const uint8_t* data =
92 reinterpret_cast<const uint8_t*>(blob->InstructionStartOf(builtin));
93 uint32_t size = blob->PaddedInstructionSizeOf(builtin);
94 uint32_t i = 0;
95 uint32_t next_source_pos_offset =
96 static_cast<uint32_t>(positions.done() ? size : positions.code_offset());
97 uint32_t next_label_offset = static_cast<uint32_t>(
98 (label == current_labels.end()) ? size : label->offset);
99 uint32_t next_offset = 0;
100 while (i < size) {
101 if (i == next_source_pos_offset) {
102 // Write source directive.
103 w->SourceInfo(positions.source_position().ExternalFileId(),
105 positions.source_position().ExternalFileId()),
106 positions.source_position().ExternalLine());
107 positions.Advance();
108 next_source_pos_offset = static_cast<uint32_t>(
109 positions.done() ? size : positions.code_offset());
110 CHECK_GE(next_source_pos_offset, i);
111 }
112 if (i == next_label_offset) {
113 WriteBuiltinLabels(w, label->name);
114 label++;
115 next_label_offset = static_cast<uint32_t>(
116 (label == current_labels.end()) ? size : label->offset);
117 CHECK_GE(next_label_offset, i);
118 }
119 next_offset = std::min(next_source_pos_offset, next_label_offset);
120 WriteBinaryContentsAsInlineAssembly(w, data + i, next_offset - i);
121 i = next_offset;
122 }
123
124 w->DeclareFunctionEnd(builtin_symbol.begin());
125}
126
128 std::string name) const {
129 w->DeclareLabel(name.c_str());
130}
131
133 const i::EmbeddedData* blob) const {
134 w->Comment(
135 "The embedded blob code section starts here. It contains the builtin");
136 w->Comment("instruction streams.");
137 w->SectionText();
138
139#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
140 // UMA needs an exposed function-type label at the start of the embedded
141 // code section.
142 static const char* kCodeStartForProfilerSymbolName =
143 "v8_code_start_for_profiler_";
144 static constexpr int kDummyFunctionLength = 1;
145 static constexpr int kDummyFunctionData = 0xcc;
146 w->DeclareFunctionBegin(kCodeStartForProfilerSymbolName,
147 kDummyFunctionLength);
148 // The label must not be at the same address as the first builtin, insert
149 // padding bytes.
150 WriteDirectiveOrSeparator(w, 0, kByte);
151 w->HexLiteral(kDummyFunctionData);
152 w->Newline();
153 w->DeclareFunctionEnd(kCodeStartForProfilerSymbolName);
154#endif
155
160
162 for (ReorderedBuiltinIndex embedded_index = 0;
163 embedded_index < Builtins::kBuiltinCount; embedded_index++) {
164 Builtin builtin = blob->GetBuiltinId(embedded_index);
165 WriteBuiltin(w, blob, builtin);
166 }
169 w->Newline();
170}
171
173 const i::EmbeddedData* blob) const {
174 {
176 embedded_blob_code_size_symbol;
177 base::SNPrintF(embedded_blob_code_size_symbol,
178 "v8_%s_embedded_blob_code_size_", embedded_variant_);
179
180 w->Comment("The size of the embedded blob code in bytes.");
181 w->SectionRoData();
183 w->DeclareUint32(embedded_blob_code_size_symbol.begin(), blob->code_size());
184 w->Newline();
185
187 embedded_blob_data_size_symbol;
188 base::SNPrintF(embedded_blob_data_size_symbol,
189 "v8_%s_embedded_blob_data_size_", embedded_variant_);
190
191 w->Comment("The size of the embedded blob data section in bytes.");
192 w->DeclareUint32(embedded_blob_data_size_symbol.begin(), blob->data_size());
193 w->Newline();
194 }
195
196#if defined(V8_OS_WIN64)
197 {
199 base::SNPrintF(unwind_info_symbol, "%s_Builtins_UnwindInfo",
201
202 w->MaybeEmitUnwindData(unwind_info_symbol.begin(),
203 EmbeddedBlobCodeSymbol().c_str(), blob,
204 reinterpret_cast<const void*>(&unwind_infos_[0]));
205 }
206#endif // V8_OS_WIN64
207
208 w->FileEpilogue();
209}
210
211// static
213 PlatformEmbeddedFileWriterBase* w, const uint8_t* data, uint32_t size) {
214#if V8_OS_ZOS
215 // HLASM source must end at column 71 (followed by an optional
216 // line-continuation char on column 72), so write the binary data
217 // in 32 byte chunks (length 64):
218 uint32_t chunks = (size + 31) / 32;
219 uint32_t i, j;
220 uint32_t offset = 0;
221 for (i = 0; i < chunks; ++i) {
222 fprintf(w->fp(), " DC x'");
223 for (j = 0; offset < size && j < 32; ++j) {
224 fprintf(w->fp(), "%02x", data[offset++]);
225 }
226 fprintf(w->fp(), "'\n");
227 }
228#else
229 int current_line_length = 0;
230 uint32_t i = 0;
231
232 // Begin by writing out byte chunks.
233 const DataDirective directive = w->ByteChunkDataDirective();
234 const int byte_chunk_size = DataDirectiveSize(directive);
235 for (; i + byte_chunk_size < size; i += byte_chunk_size) {
236 current_line_length =
237 WriteDirectiveOrSeparator(w, current_line_length, directive);
238 current_line_length += w->WriteByteChunk(data + i);
239 current_line_length =
240 WriteLineEndIfNeeded(w, current_line_length, byte_chunk_size);
241 }
242 if (current_line_length != 0) w->Newline();
243 current_line_length = 0;
244
245 // Write any trailing bytes one-by-one.
246 for (; i < size; i++) {
247 current_line_length =
248 WriteDirectiveOrSeparator(w, current_line_length, kByte);
249 current_line_length += w->HexLiteral(data[i]);
250 current_line_length = WriteLineEndIfNeeded(w, current_line_length, 1);
251 }
252
253 if (current_line_length != 0) w->Newline();
254#endif // V8_OS_ZOS
255}
256
258 const char* filename) {
260 if (result != external_filenames_.end()) {
261 return result->second;
262 }
263 int new_id =
264 ExternalFilenameIndexToId(static_cast<int>(external_filenames_.size()));
265 external_filenames_.insert(std::make_pair(filename, new_id));
268 return new_id;
269}
270
272 int fileid) const {
273 size_t index = static_cast<size_t>(ExternalFilenameIdToIndex(fileid));
274 DCHECK_GE(index, 0);
276
278}
279
281 return static_cast<int>(external_filenames_.size());
282}
283
285 for (Builtin builtin = Builtins::kFirst; builtin <= Builtins::kLast;
286 ++builtin) {
287 // Retrieve the SourcePositionTable and copy it.
288 Tagged<Code> code = builtins->code(builtin);
289 if (!code->has_source_position_table()) continue;
290 Tagged<TrustedByteArray> source_position_table =
291 code->source_position_table();
292 std::vector<unsigned char> data(source_position_table->begin(),
293 source_position_table->end());
294 source_positions_[static_cast<int>(builtin)] = data;
295 }
296}
297
298} // namespace internal
299} // namespace v8
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
constexpr T * begin() const
Definition vector.h:96
static constexpr int kBuiltinCount
Definition builtins.h:105
static constexpr Builtin kFirst
Definition builtins.h:112
static constexpr bool kAllBuiltinsAreIsolateIndependent
Definition builtins.h:262
static constexpr Builtin kLast
Definition builtins.h:113
void PrepareBuiltinSourcePositionMap(Builtins *builtins) override
void WriteCodeSection(PlatformEmbeddedFileWriterBase *w, const i::EmbeddedData *blob) const
std::vector< LabelInfo > label_info_[Builtins::kBuiltinCount]
void WriteFileEpilogue(PlatformEmbeddedFileWriterBase *w, const i::EmbeddedData *blob) const
std::vector< uint8_t > source_positions_[Builtins::kBuiltinCount]
static int ExternalFilenameIndexToId(int index)
std::vector< const char * > external_filenames_by_index_
int GetExternallyCompiledFilenameCount() const override
std::map< const char *, int > external_filenames_
static void WriteBinaryContentsAsInlineAssembly(PlatformEmbeddedFileWriterBase *w, const uint8_t *data, uint32_t size)
void WriteBuiltinLabels(PlatformEmbeddedFileWriterBase *w, std::string name) const
int LookupOrAddExternallyCompiledFilename(const char *filename) override
void WriteBuiltin(PlatformEmbeddedFileWriterBase *w, const i::EmbeddedData *blob, const Builtin builtin) const
const char * GetExternallyCompiledFilename(int fileid) const override
virtual void Comment(const char *string)=0
virtual void DeclareFunctionEnd(const char *name)=0
virtual void DeclareUint32(const char *name, uint32_t value)=0
virtual void SourceInfo(int fileid, const char *filename, int line)=0
virtual void MaybeEmitUnwindData(const char *unwind_info_symbol, const char *embedded_blob_data_symbol, const EmbeddedData *blob, const void *unwind_infos)
virtual void DeclareSymbolGlobal(const char *name)=0
virtual void DeclareLabel(const char *name)=0
virtual void DeclareFunctionBegin(const char *name, uint32_t size)=0
Label label
std::string filename
int32_t offset
ZoneVector< RpoNumber > & result
Builtin builtin
int SNPrintF(Vector< char > str, const char *format,...)
Definition strings.cc:20
int DataDirectiveSize(DataDirective directive)
uint32_t ReorderedBuiltinIndex
static constexpr char kDefaultEmbeddedVariant[]
#define CHECK_GE(lhs, rhs)
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485