Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: src/wasm/encoder.cc

Issue 1980543002: [wasm] Remove renumbering of local variables from asm->wasm. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@wasm_renumber
Patch Set: Fix memory leak by using a zone Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/encoder.h ('k') | src/wasm/wasm-macro-gen.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/signature.h" 5 #include "src/signature.h"
6 6
7 #include "src/handles.h" 7 #include "src/handles.h"
8 #include "src/v8.h" 8 #include "src/v8.h"
9 #include "src/zone-containers.h" 9 #include "src/zone-containers.h"
10 10
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 // Emit a placeholder for the length. 88 // Emit a placeholder for the length.
89 byte* start = *b; 89 byte* start = *b;
90 for (size_t padding = 0; padding != kPaddedVarintSize; ++padding) { 90 for (size_t padding = 0; padding != kPaddedVarintSize; ++padding) {
91 EmitUint8(b, 0xff); // Will get fixed up later. 91 EmitUint8(b, 0xff); // Will get fixed up later.
92 } 92 }
93 93
94 return start; 94 return start;
95 } 95 }
96 } // namespace 96 } // namespace
97 97
98 struct WasmFunctionBuilder::Type {
99 bool param_;
100 LocalType type_;
101 };
102
103 WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone) 98 WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone)
104 : return_type_(kAstI32), 99 : locals_(zone), exported_(0), body_(zone), name_(zone) {}
105 locals_(zone),
106 exported_(0),
107 body_(zone),
108 local_indices_(zone),
109 name_(zone) {}
110 100
111 void WasmFunctionBuilder::EmitVarInt(uint32_t val) { 101 void WasmFunctionBuilder::EmitVarInt(uint32_t val) {
112 byte buffer[8]; 102 byte buffer[8];
113 byte* ptr = buffer; 103 byte* ptr = buffer;
114 LEBHelper::write_u32v(&ptr, val); 104 LEBHelper::write_u32v(&ptr, val);
115 for (byte* p = buffer; p < ptr; p++) { 105 for (byte* p = buffer; p < ptr; p++) {
116 body_.push_back(*p); 106 body_.push_back(*p);
117 } 107 }
118 } 108 }
119 109
120 uint16_t WasmFunctionBuilder::AddParam(LocalType type) { 110 void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
121 return AddVar(type, true); 111 DCHECK(!locals_.has_sig());
112 locals_.set_sig(sig);
122 } 113 }
123 114
124 uint16_t WasmFunctionBuilder::AddLocal(LocalType type) { 115 uint32_t WasmFunctionBuilder::AddLocal(LocalType type) {
125 return AddVar(type, false); 116 DCHECK(locals_.has_sig());
126 } 117 return locals_.AddLocals(1, type);
127
128 uint16_t WasmFunctionBuilder::AddVar(LocalType type, bool param) {
129 locals_.push_back({param, type});
130 return static_cast<uint16_t>(locals_.size() - 1);
131 }
132
133 void WasmFunctionBuilder::ReturnType(LocalType type) { return_type_ = type; }
134
135 void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
136 EmitCode(code, code_size, nullptr, 0);
137 } 118 }
138 119
139 void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) { 120 void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
140 local_indices_.push_back(static_cast<uint32_t>(body_.size() + 1));
141 EmitWithVarInt(kExprGetLocal, local_index); 121 EmitWithVarInt(kExprGetLocal, local_index);
142 } 122 }
143 123
144 void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) { 124 void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
145 local_indices_.push_back(static_cast<uint32_t>(body_.size() + 1));
146 EmitWithVarInt(kExprSetLocal, local_index); 125 EmitWithVarInt(kExprSetLocal, local_index);
147 } 126 }
148 127
149 void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size, 128 void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
150 const uint32_t* local_indices,
151 uint32_t indices_size) {
152 size_t size = body_.size();
153 for (size_t i = 0; i < code_size; i++) { 129 for (size_t i = 0; i < code_size; i++) {
154 body_.push_back(code[i]); 130 body_.push_back(code[i]);
155 } 131 }
156 for (size_t i = 0; i < indices_size; i++) {
157 local_indices_.push_back(local_indices[i] + static_cast<uint32_t>(size));
158 }
159 } 132 }
160 133
161 void WasmFunctionBuilder::Emit(WasmOpcode opcode) { 134 void WasmFunctionBuilder::Emit(WasmOpcode opcode) {
162 body_.push_back(static_cast<byte>(opcode)); 135 body_.push_back(static_cast<byte>(opcode));
163 } 136 }
164 137
165 void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) { 138 void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
166 body_.push_back(static_cast<byte>(opcode)); 139 body_.push_back(static_cast<byte>(opcode));
167 body_.push_back(immediate); 140 body_.push_back(immediate);
168 } 141 }
(...skipping 14 matching lines...) Expand all
183 void WasmFunctionBuilder::EmitI32Const(int32_t value) { 156 void WasmFunctionBuilder::EmitI32Const(int32_t value) {
184 // TODO(titzer): variable-length signed and unsigned i32 constants. 157 // TODO(titzer): variable-length signed and unsigned i32 constants.
185 if (-128 <= value && value <= 127) { 158 if (-128 <= value && value <= 127) {
186 EmitWithU8(kExprI8Const, static_cast<byte>(value)); 159 EmitWithU8(kExprI8Const, static_cast<byte>(value));
187 } else { 160 } else {
188 byte code[] = {WASM_I32V_5(value)}; 161 byte code[] = {WASM_I32V_5(value)};
189 EmitCode(code, sizeof(code)); 162 EmitCode(code, sizeof(code));
190 } 163 }
191 } 164 }
192 165
193 uint32_t WasmFunctionBuilder::EmitEditableVarIntImmediate() {
194 // Guess that the immediate will be 1 byte. If it is more, we'll have to
195 // shift everything down.
196 body_.push_back(0);
197 return static_cast<uint32_t>(body_.size()) - 1;
198 }
199
200 void WasmFunctionBuilder::EditVarIntImmediate(uint32_t offset,
201 const uint32_t immediate) {
202 uint32_t immediate_size =
203 static_cast<uint32_t>(LEBHelper::sizeof_u32v(immediate));
204 // In EmitEditableVarIntImmediate, we guessed that we'd only need one byte.
205 // If we need more, shift everything down to make room for the larger
206 // immediate.
207 if (immediate_size > 1) {
208 uint32_t diff = immediate_size - 1;
209 body_.insert(body_.begin() + offset, diff, 0);
210
211 for (size_t i = 0; i < local_indices_.size(); ++i) {
212 if (local_indices_[i] >= offset) {
213 local_indices_[i] += diff;
214 }
215 }
216 }
217 DCHECK(offset + immediate_size <= body_.size());
218 byte* p = &body_[offset];
219 v8::internal::wasm::EmitVarInt(&p, immediate);
220 }
221
222 void WasmFunctionBuilder::Exported(uint8_t flag) { exported_ = flag; } 166 void WasmFunctionBuilder::Exported(uint8_t flag) { exported_ = flag; }
223 167
224 void WasmFunctionBuilder::SetName(const char* name, int name_length) { 168 void WasmFunctionBuilder::SetName(const char* name, int name_length) {
225 name_.clear(); 169 name_.clear();
226 if (name_length > 0) { 170 if (name_length > 0) {
227 for (int i = 0; i < name_length; i++) { 171 for (int i = 0; i < name_length; i++) {
228 name_.push_back(*(name + i)); 172 name_.push_back(*(name + i));
229 } 173 }
230 } 174 }
231 } 175 }
232 176
233 WasmFunctionEncoder* WasmFunctionBuilder::Build(Zone* zone, 177 WasmFunctionEncoder* WasmFunctionBuilder::Build(Zone* zone,
234 WasmModuleBuilder* mb) const { 178 WasmModuleBuilder* mb) const {
235 WasmFunctionEncoder* e = 179 WasmFunctionEncoder* e =
236 new (zone) WasmFunctionEncoder(zone, return_type_, exported_); 180 new (zone) WasmFunctionEncoder(zone, locals_, exported_);
237 uint16_t* var_index = zone->NewArray<uint16_t>(locals_.size()); 181 // TODO(titzer): lame memcpy here.
238 IndexVars(e, var_index); 182 e->body_.insert(e->body_.begin(), body_.begin(), body_.end());
239 if (body_.size() > 0) { 183 e->signature_index_ = mb->AddSignature(locals_.get_sig());
240 // TODO(titzer): iterate over local indexes, not the bytes.
241 const byte* start = &body_[0];
242 size_t local_index = 0;
243 for (size_t i = 0; i < body_.size();) {
244 if (local_index < local_indices_.size() &&
245 i == local_indices_[local_index]) {
246 // Read the old index.
247 uint32_t index = 0;
248 uint8_t b = 0;
249 uint32_t shift = 0;
250 while ((b = start[i++]) >= 0x80) {
251 index |= (b & 0x7F) << shift;
252 shift += 7;
253 }
254 index |= b << shift;
255
256 // Write the new index.
257 uint16_t new_index = var_index[index];
258 while (new_index >= 0x80) {
259 e->body_.push_back(new_index | 0x80);
260 new_index >>= 7;
261 }
262 e->body_.push_back(new_index);
263
264 local_index++;
265 } else {
266 e->body_.push_back(*(start + i));
267 i++;
268 }
269 }
270 }
271 FunctionSig::Builder sig(zone, return_type_ == kAstStmt ? 0 : 1,
272 e->params_.size());
273 if (return_type_ != kAstStmt) {
274 sig.AddReturn(static_cast<LocalType>(return_type_));
275 }
276 for (size_t i = 0; i < e->params_.size(); i++) {
277 sig.AddParam(static_cast<LocalType>(e->params_[i]));
278 }
279 e->signature_index_ = mb->AddSignature(sig.Build());
280 e->name_.insert(e->name_.begin(), name_.begin(), name_.end()); 184 e->name_.insert(e->name_.begin(), name_.begin(), name_.end());
281 return e; 185 return e;
282 } 186 }
283 187
284 void WasmFunctionBuilder::IndexVars(WasmFunctionEncoder* e, 188 WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalDeclEncoder locals,
285 uint16_t* var_index) const {
286 uint16_t param = 0;
287 uint16_t i32 = 0;
288 uint16_t i64 = 0;
289 uint16_t f32 = 0;
290 uint16_t f64 = 0;
291 for (size_t i = 0; i < locals_.size(); i++) {
292 if (locals_.at(i).param_) {
293 param++;
294 } else if (locals_.at(i).type_ == kAstI32) {
295 i32++;
296 } else if (locals_.at(i).type_ == kAstI64) {
297 i64++;
298 } else if (locals_.at(i).type_ == kAstF32) {
299 f32++;
300 } else if (locals_.at(i).type_ == kAstF64) {
301 f64++;
302 }
303 }
304 e->local_i32_count_ = i32;
305 e->local_i64_count_ = i64;
306 e->local_f32_count_ = f32;
307 e->local_f64_count_ = f64;
308 f64 = param + i32 + i64 + f32;
309 f32 = param + i32 + i64;
310 i64 = param + i32;
311 i32 = param;
312 param = 0;
313 for (size_t i = 0; i < locals_.size(); i++) {
314 if (locals_.at(i).param_) {
315 e->params_.push_back(locals_.at(i).type_);
316 var_index[i] = param++;
317 } else if (locals_.at(i).type_ == kAstI32) {
318 var_index[i] = i32++;
319 } else if (locals_.at(i).type_ == kAstI64) {
320 var_index[i] = i64++;
321 } else if (locals_.at(i).type_ == kAstF32) {
322 var_index[i] = f32++;
323 } else if (locals_.at(i).type_ == kAstF64) {
324 var_index[i] = f64++;
325 }
326 }
327 }
328
329 WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalType return_type,
330 bool exported) 189 bool exported)
331 : params_(zone), exported_(exported), body_(zone), name_(zone) {} 190 : locals_(locals), exported_(exported), body_(zone), name_(zone) {}
332 191
333 uint32_t WasmFunctionEncoder::HeaderSize() const { 192 uint32_t WasmFunctionEncoder::HeaderSize() const {
334 uint32_t size = 3; 193 uint32_t size = 3;
335 size += 2; 194 size += 2;
336 if (HasName()) { 195 if (HasName()) {
337 uint32_t name_size = NameSize(); 196 uint32_t name_size = NameSize();
338 size += 197 size +=
339 static_cast<uint32_t>(LEBHelper::sizeof_u32v(name_size)) + name_size; 198 static_cast<uint32_t>(LEBHelper::sizeof_u32v(name_size)) + name_size;
340 } 199 }
341 return size; 200 return size;
342 } 201 }
343 202
344 uint32_t WasmFunctionEncoder::BodySize(void) const { 203 uint32_t WasmFunctionEncoder::BodySize(void) const {
345 // TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder 204 return static_cast<uint32_t>(body_.size() + locals_.Size());
346 LocalDeclEncoder local_decl;
347 local_decl.AddLocals(local_i32_count_, kAstI32);
348 local_decl.AddLocals(local_i64_count_, kAstI64);
349 local_decl.AddLocals(local_f32_count_, kAstF32);
350 local_decl.AddLocals(local_f64_count_, kAstF64);
351
352 return static_cast<uint32_t>(body_.size() + local_decl.Size());
353 } 205 }
354 206
355 uint32_t WasmFunctionEncoder::NameSize() const { 207 uint32_t WasmFunctionEncoder::NameSize() const {
356 return HasName() ? static_cast<uint32_t>(name_.size()) : 0; 208 return HasName() ? static_cast<uint32_t>(name_.size()) : 0;
357 } 209 }
358 210
359 void WasmFunctionEncoder::Serialize(byte* buffer, byte** header, 211 void WasmFunctionEncoder::Serialize(byte* buffer, byte** header,
360 byte** body) const { 212 byte** body) const {
361 uint8_t decl_bits = (exported_ ? kDeclFunctionExport : 0) | 213 uint8_t decl_bits = (exported_ ? kDeclFunctionExport : 0) |
362 (HasName() ? kDeclFunctionName : 0); 214 (HasName() ? kDeclFunctionName : 0);
363 215
364 EmitUint8(header, decl_bits); 216 EmitUint8(header, decl_bits);
365 EmitUint16(header, signature_index_); 217 EmitUint16(header, signature_index_);
366 218
367 if (HasName()) { 219 if (HasName()) {
368 EmitVarInt(header, NameSize()); 220 EmitVarInt(header, NameSize());
369 for (size_t i = 0; i < name_.size(); ++i) { 221 for (size_t i = 0; i < name_.size(); ++i) {
370 EmitUint8(header, name_[i]); 222 EmitUint8(header, name_[i]);
371 } 223 }
372 } 224 }
373 225
374 // TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder 226 EmitUint16(header, static_cast<uint16_t>(body_.size() + locals_.Size()));
375 LocalDeclEncoder local_decl; 227 (*header) += locals_.Emit(*header);
376 local_decl.AddLocals(local_i32_count_, kAstI32);
377 local_decl.AddLocals(local_i64_count_, kAstI64);
378 local_decl.AddLocals(local_f32_count_, kAstF32);
379 local_decl.AddLocals(local_f64_count_, kAstF64);
380
381 EmitUint16(header, static_cast<uint16_t>(body_.size() + local_decl.Size()));
382 (*header) += local_decl.Emit(*header);
383 if (body_.size() > 0) { 228 if (body_.size() > 0) {
384 std::memcpy(*header, &body_[0], body_.size()); 229 std::memcpy(*header, &body_[0], body_.size());
385 (*header) += body_.size(); 230 (*header) += body_.size();
386 } 231 }
387 } 232 }
388 233
389 WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data, 234 WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data,
390 uint32_t size, uint32_t dest) 235 uint32_t size, uint32_t dest)
391 : data_(zone), dest_(dest) { 236 : data_(zone), dest_(dest) {
392 for (size_t i = 0; i < size; i++) { 237 for (size_t i = 0; i < size; i++) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 if (a->GetParam(p) > b->GetParam(p)) return false; 300 if (a->GetParam(p) > b->GetParam(p)) return false;
456 } 301 }
457 return false; 302 return false;
458 } 303 }
459 304
460 uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) { 305 uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
461 SignatureMap::iterator pos = signature_map_.find(sig); 306 SignatureMap::iterator pos = signature_map_.find(sig);
462 if (pos != signature_map_.end()) { 307 if (pos != signature_map_.end()) {
463 return pos->second; 308 return pos->second;
464 } else { 309 } else {
465 uint16_t index = static_cast<uint16_t>(signatures_.size()); 310 uint32_t index = static_cast<uint32_t>(signatures_.size());
466 signature_map_[sig] = index; 311 signature_map_[sig] = index;
467 signatures_.push_back(sig); 312 signatures_.push_back(sig);
468 return index; 313 return index;
469 } 314 }
470 } 315 }
471 316
472 void WasmModuleBuilder::AddIndirectFunction(uint16_t index) { 317 void WasmModuleBuilder::AddIndirectFunction(uint32_t index) {
473 indirect_functions_.push_back(index); 318 indirect_functions_.push_back(index);
474 } 319 }
475 320
476 uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, 321 uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length,
477 FunctionSig* sig) { 322 FunctionSig* sig) {
478 imports_.push_back({AddSignature(sig), name, name_length}); 323 imports_.push_back({AddSignature(sig), name, name_length});
479 return static_cast<uint32_t>(imports_.size() - 1); 324 return static_cast<uint32_t>(imports_.size() - 1);
480 } 325 }
481 326
482 void WasmModuleBuilder::MarkStartFunction(uint16_t index) { 327 void WasmModuleBuilder::MarkStartFunction(uint32_t index) {
483 start_function_index_ = index; 328 start_function_index_ = index;
484 } 329 }
485 330
486 WasmModuleWriter* WasmModuleBuilder::Build(Zone* zone) { 331 WasmModuleWriter* WasmModuleBuilder::Build(Zone* zone) {
487 WasmModuleWriter* writer = new (zone) WasmModuleWriter(zone); 332 WasmModuleWriter* writer = new (zone) WasmModuleWriter(zone);
488 for (auto import : imports_) { 333 for (auto import : imports_) {
489 writer->imports_.push_back(import); 334 writer->imports_.push_back(import);
490 } 335 }
491 for (auto function : functions_) { 336 for (auto function : functions_) {
492 writer->functions_.push_back(function->Build(zone, this)); 337 writer->functions_.push_back(function->Build(zone, this));
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 if (sizes.body_size > 0) { 579 if (sizes.body_size > 0) {
735 byte* section = EmitSection(WasmSection::Code::End, &header); 580 byte* section = EmitSection(WasmSection::Code::End, &header);
736 FixupSection(section, header); 581 FixupSection(section, header);
737 } 582 }
738 583
739 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total()); 584 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total());
740 } 585 }
741 } // namespace wasm 586 } // namespace wasm
742 } // namespace internal 587 } // namespace internal
743 } // namespace v8 588 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/encoder.h ('k') | src/wasm/wasm-macro-gen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698