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

Side by Side Diff: src/wasm/module-decoder.cc

Issue 1783593002: [wasm] Encode function signatures, bodies, and names as separate sections. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Added unittests Created 4 years, 9 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/decoder.h ('k') | src/wasm/wasm-module.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/macro-assembler.h" 5 #include "src/macro-assembler.h"
6 #include "src/objects.h" 6 #include "src/objects.h"
7 #include "src/v8.h" 7 #include "src/v8.h"
8 8
9 #include "src/wasm/decoder.h" 9 #include "src/wasm/decoder.h"
10 #include "src/wasm/module-decoder.h" 10 #include "src/wasm/module-decoder.h"
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 // Decode signatures. 110 // Decode signatures.
111 for (uint32_t i = 0; i < signatures_count; i++) { 111 for (uint32_t i = 0; i < signatures_count; i++) {
112 if (failed()) break; 112 if (failed()) break;
113 TRACE("DecodeSignature[%d] module+%d\n", i, 113 TRACE("DecodeSignature[%d] module+%d\n", i,
114 static_cast<int>(pc_ - start_)); 114 static_cast<int>(pc_ - start_));
115 FunctionSig* s = consume_sig(); // read function sig. 115 FunctionSig* s = consume_sig(); // read function sig.
116 module->signatures.push_back(s); 116 module->signatures.push_back(s);
117 } 117 }
118 break; 118 break;
119 } 119 }
120 case kDeclFunctionSignatures: {
121 // Functions require a signature table first.
122 CheckForPreviousSection(sections, kDeclSignatures, true);
123 int length;
124 uint32_t functions_count = consume_u32v(&length, "functions count");
125 module->functions.reserve(SafeReserve(functions_count));
126 for (uint32_t i = 0; i < functions_count; i++) {
127 module->functions.push_back(
128 {nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
129 WasmFunction* function = &module->functions.back();
130 function->sig_index = consume_sig_index(module, &function->sig);
131 }
132 break;
133 }
134 case kDeclFunctionBodies: {
135 // Function bodies should follow signatures.
136 CheckForPreviousSection(sections, kDeclFunctionSignatures, true);
137 int length;
138 const byte* pos = pc_;
139 uint32_t functions_count = consume_u32v(&length, "functions count");
140 if (functions_count != module->functions.size()) {
141 error(pos, pos, "function body count %u mismatch (%u expected)",
142 functions_count,
143 static_cast<uint32_t>(module->functions.size()));
144 break;
145 }
146 for (uint32_t i = 0; i < functions_count; i++) {
147 WasmFunction* function = &module->functions[i];
148 int length;
149 uint32_t size = consume_u32v(&length, "body size");
150 function->code_start_offset = pc_offset();
151 function->code_end_offset = pc_offset() + size;
152
153 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body",
154 size);
155 pc_ += size;
156 if (pc_ > limit_) {
157 error(pc_, "function body extends beyond end of file");
158 }
159 }
160 break;
161 }
120 case kDeclFunctions: { 162 case kDeclFunctions: {
121 // Functions require a signature table first. 163 // Functions require a signature table first.
122 CheckForPreviousSection(sections, kDeclSignatures, true); 164 CheckForPreviousSection(sections, kDeclSignatures, true);
123 int length; 165 int length;
124 uint32_t functions_count = consume_u32v(&length, "functions count"); 166 uint32_t functions_count = consume_u32v(&length, "functions count");
125 module->functions.reserve(SafeReserve(functions_count)); 167 module->functions.reserve(SafeReserve(functions_count));
126 // Set up module environment for verification. 168 // Set up module environment for verification.
127 ModuleEnv menv; 169 ModuleEnv menv;
128 menv.module = module; 170 menv.module = module;
129 menv.instance = nullptr; 171 menv.instance = nullptr;
(...skipping 15 matching lines...) Expand all
145 WasmFunction* function = &module->functions[i]; 187 WasmFunction* function = &module->functions[i];
146 if (!function->external) { 188 if (!function->external) {
147 VerifyFunctionBody(i, &menv, function); 189 VerifyFunctionBody(i, &menv, function);
148 if (result_.failed()) 190 if (result_.failed())
149 error(result_.error_pc, result_.error_msg.get()); 191 error(result_.error_pc, result_.error_msg.get());
150 } 192 }
151 } 193 }
152 } 194 }
153 break; 195 break;
154 } 196 }
197 case kDeclNames: {
198 // Names correspond to functions.
199 CheckForPreviousSection(sections, kDeclFunctionSignatures, true);
200 int length;
201 const byte* pos = pc_;
202 uint32_t functions_count = consume_u32v(&length, "functions count");
203 if (functions_count != module->functions.size()) {
204 error(pos, pos, "function name count %u mismatch (%u expected)",
205 functions_count,
206 static_cast<uint32_t>(module->functions.size()));
207 break;
208 }
209
210 for (uint32_t i = 0; i < functions_count; i++) {
211 WasmFunction* function = &module->functions[i];
212 function->name_offset =
213 consume_string(&function->name_length, "function name");
214
215 uint32_t local_names_count =
216 consume_u32v(&length, "local names count");
217 for (uint32_t j = 0; j < local_names_count; j++) {
218 uint32_t unused = 0;
219 uint32_t offset = consume_string(&unused, "local name");
220 USE(unused);
221 USE(offset);
222 }
223 }
224 break;
225 }
155 case kDeclGlobals: { 226 case kDeclGlobals: {
156 int length; 227 int length;
157 uint32_t globals_count = consume_u32v(&length, "globals count"); 228 uint32_t globals_count = consume_u32v(&length, "globals count");
158 module->globals.reserve(SafeReserve(globals_count)); 229 module->globals.reserve(SafeReserve(globals_count));
159 // Decode globals. 230 // Decode globals.
160 for (uint32_t i = 0; i < globals_count; i++) { 231 for (uint32_t i = 0; i < globals_count; i++) {
161 if (failed()) break; 232 if (failed()) break;
162 TRACE("DecodeGlobal[%d] module+%d\n", i, 233 TRACE("DecodeGlobal[%d] module+%d\n", i,
163 static_cast<int>(pc_ - start_)); 234 static_cast<int>(pc_ - start_));
164 module->globals.push_back({0, 0, MachineType::Int32(), 0, false}); 235 module->globals.push_back({0, 0, MachineType::Int32(), 0, false});
(...skipping 13 matching lines...) Expand all
178 TRACE("DecodeDataSegment[%d] module+%d\n", i, 249 TRACE("DecodeDataSegment[%d] module+%d\n", i,
179 static_cast<int>(pc_ - start_)); 250 static_cast<int>(pc_ - start_));
180 module->data_segments.push_back({0, 0, 0}); 251 module->data_segments.push_back({0, 0, 0});
181 WasmDataSegment* segment = &module->data_segments.back(); 252 WasmDataSegment* segment = &module->data_segments.back();
182 DecodeDataSegmentInModule(module, segment); 253 DecodeDataSegmentInModule(module, segment);
183 } 254 }
184 break; 255 break;
185 } 256 }
186 case kDeclFunctionTable: { 257 case kDeclFunctionTable: {
187 // An indirect function table requires functions first. 258 // An indirect function table requires functions first.
188 CheckForPreviousSection(sections, kDeclFunctions, true); 259 CheckForFunctions(module, section);
189 int length; 260 int length;
190 uint32_t function_table_count = 261 uint32_t function_table_count =
191 consume_u32v(&length, "function table count"); 262 consume_u32v(&length, "function table count");
192 module->function_table.reserve(SafeReserve(function_table_count)); 263 module->function_table.reserve(SafeReserve(function_table_count));
193 // Decode function table. 264 // Decode function table.
194 for (uint32_t i = 0; i < function_table_count; i++) { 265 for (uint32_t i = 0; i < function_table_count; i++) {
195 if (failed()) break; 266 if (failed()) break;
196 TRACE("DecodeFunctionTable[%d] module+%d\n", i, 267 TRACE("DecodeFunctionTable[%d] module+%d\n", i,
197 static_cast<int>(pc_ - start_)); 268 static_cast<int>(pc_ - start_));
198 uint16_t index = consume_u32v(&length); 269 uint16_t index = consume_u32v(&length);
199 if (index >= module->functions.size()) { 270 if (index >= module->functions.size()) {
200 error(pc_ - 2, "invalid function index"); 271 error(pc_ - 2, "invalid function index");
201 break; 272 break;
202 } 273 }
203 module->function_table.push_back(index); 274 module->function_table.push_back(index);
204 } 275 }
205 break; 276 break;
206 } 277 }
207 case kDeclStartFunction: { 278 case kDeclStartFunction: {
208 // Declares a start function for a module. 279 // Declares a start function for a module.
209 CheckForPreviousSection(sections, kDeclFunctions, true); 280 CheckForFunctions(module, section);
210 if (module->start_function_index >= 0) { 281 if (module->start_function_index >= 0) {
211 error("start function already declared"); 282 error("start function already declared");
212 break; 283 break;
213 } 284 }
214 int length; 285 WasmFunction* func;
215 const byte* before = pc_; 286 const byte* pos = pc_;
216 uint32_t index = consume_u32v(&length, "start function index"); 287 module->start_function_index = consume_func_index(module, &func);
217 if (index >= module->functions.size()) { 288 if (func && func->sig->parameter_count() > 0) {
218 error(before, "invalid start function index"); 289 error(pos, "invalid start function: non-zero parameter count");
219 break;
220 }
221 module->start_function_index = static_cast<int>(index);
222 FunctionSig* sig =
223 module->signatures[module->functions[index].sig_index];
224 if (sig->parameter_count() > 0) {
225 error(before, "invalid start function: non-zero parameter count");
226 break; 290 break;
227 } 291 }
228 break; 292 break;
229 } 293 }
230 case kDeclImportTable: { 294 case kDeclImportTable: {
231 // Declares an import table. 295 // Declares an import table.
232 CheckForPreviousSection(sections, kDeclSignatures, true); 296 CheckForPreviousSection(sections, kDeclSignatures, true);
233 int length; 297 int length;
234 uint32_t import_table_count = 298 uint32_t import_table_count =
235 consume_u32v(&length, "import table count"); 299 consume_u32v(&length, "import table count");
236 module->import_table.reserve(SafeReserve(import_table_count)); 300 module->import_table.reserve(SafeReserve(import_table_count));
237 // Decode import table. 301 // Decode import table.
238 for (uint32_t i = 0; i < import_table_count; i++) { 302 for (uint32_t i = 0; i < import_table_count; i++) {
239 if (failed()) break; 303 if (failed()) break;
240 TRACE("DecodeImportTable[%d] module+%d\n", i, 304 TRACE("DecodeImportTable[%d] module+%d\n", i,
241 static_cast<int>(pc_ - start_)); 305 static_cast<int>(pc_ - start_));
242 306
243 module->import_table.push_back({nullptr, 0, 0}); 307 module->import_table.push_back({nullptr, 0, 0});
244 WasmImport* import = &module->import_table.back(); 308 WasmImport* import = &module->import_table.back();
245 309
246 const byte* sigpos = pc_; 310 import->sig_index = consume_sig_index(module, &import->sig);
247 import->sig_index = consume_u32v(&length, "signature index");
248
249 if (import->sig_index >= module->signatures.size()) {
250 error(sigpos, "invalid signature index");
251 } else {
252 import->sig = module->signatures[import->sig_index];
253 }
254 const byte* pos = pc_; 311 const byte* pos = pc_;
255 import->module_name_offset = consume_string( 312 import->module_name_offset = consume_string(
256 &import->module_name_length, "import module name"); 313 &import->module_name_length, "import module name");
257 if (import->module_name_length == 0) { 314 if (import->module_name_length == 0) {
258 error(pos, "import module name cannot be NULL"); 315 error(pos, "import module name cannot be NULL");
259 } 316 }
260 import->function_name_offset = consume_string( 317 import->function_name_offset = consume_string(
261 &import->function_name_length, "import function name"); 318 &import->function_name_length, "import function name");
262 } 319 }
263 break; 320 break;
264 } 321 }
265 case kDeclExportTable: { 322 case kDeclExportTable: {
266 // Declares an export table. 323 // Declares an export table.
267 CheckForPreviousSection(sections, kDeclFunctions, true); 324 CheckForFunctions(module, section);
268 int length; 325 int length;
269 uint32_t export_table_count = 326 uint32_t export_table_count =
270 consume_u32v(&length, "export table count"); 327 consume_u32v(&length, "export table count");
271 module->export_table.reserve(SafeReserve(export_table_count)); 328 module->export_table.reserve(SafeReserve(export_table_count));
272 // Decode export table. 329 // Decode export table.
273 for (uint32_t i = 0; i < export_table_count; i++) { 330 for (uint32_t i = 0; i < export_table_count; i++) {
274 if (failed()) break; 331 if (failed()) break;
275 TRACE("DecodeExportTable[%d] module+%d\n", i, 332 TRACE("DecodeExportTable[%d] module+%d\n", i,
276 static_cast<int>(pc_ - start_)); 333 static_cast<int>(pc_ - start_));
277 334
278 module->export_table.push_back({0, 0}); 335 module->export_table.push_back({0, 0});
279 WasmExport* exp = &module->export_table.back(); 336 WasmExport* exp = &module->export_table.back();
280 337
281 const byte* sigpos = pc_; 338 WasmFunction* func;
282 exp->func_index = consume_u32v(&length, "function index"); 339 exp->func_index = consume_func_index(module, &func);
283 if (exp->func_index >= module->functions.size()) {
284 error(sigpos, sigpos,
285 "function index %u out of bounds (%d functions)",
286 exp->func_index,
287 static_cast<int>(module->functions.size()));
288 }
289 exp->name_offset = consume_string(&exp->name_length, "export name"); 340 exp->name_offset = consume_string(&exp->name_length, "export name");
290 } 341 }
291 break; 342 break;
292 } 343 }
293 case kMaxModuleSectionCode: 344 case kMaxModuleSectionCode:
294 UNREACHABLE(); // Already skipped unknown sections. 345 UNREACHABLE(); // Already skipped unknown sections.
295 } 346 }
296 } 347 }
297 348
298 return toResult(module); 349 return toResult(module);
299 } 350 }
300 351
301 uint32_t SafeReserve(uint32_t count) { 352 uint32_t SafeReserve(uint32_t count) {
302 // Avoid OOM by only reserving up to a certain size. 353 // Avoid OOM by only reserving up to a certain size.
303 const uint32_t kMaxReserve = 20000; 354 const uint32_t kMaxReserve = 20000;
304 return count < kMaxReserve ? count : kMaxReserve; 355 return count < kMaxReserve ? count : kMaxReserve;
305 } 356 }
306 357
358 const char* SectionName(WasmSectionDeclCode section) {
359 switch (section) {
360 case kDeclMemory:
361 return "memory";
362 case kDeclSignatures:
363 return "signatures";
364 case kDeclFunctions:
365 return "function declaration";
366 case kDeclGlobals:
367 return "global variable";
368 case kDeclDataSegments:
369 return "data segment";
370 case kDeclFunctionTable:
371 return "function table";
372 default:
373 return "";
374 }
375 }
376
377 void CheckForFunctions(WasmModule* module, WasmSectionDeclCode section) {
378 if (module->functions.size() == 0) {
379 error(pc_ - 1, nullptr, "functions must appear before section %s",
380 SectionName(section));
381 }
382 }
383
307 void CheckForPreviousSection(bool* sections, WasmSectionDeclCode section, 384 void CheckForPreviousSection(bool* sections, WasmSectionDeclCode section,
308 bool present) { 385 bool present) {
309 if (section >= kMaxModuleSectionCode) return; 386 if (section >= kMaxModuleSectionCode) return;
310 if (sections[section] == present) return; 387 if (sections[section] == present) return;
311 const char* name = ""; 388 const char* name = SectionName(section);
312 switch (section) {
313 case kDeclMemory:
314 name = "memory";
315 break;
316 case kDeclSignatures:
317 name = "signatures";
318 break;
319 case kDeclFunctions:
320 name = "function declaration";
321 break;
322 case kDeclGlobals:
323 name = "global variable";
324 break;
325 case kDeclDataSegments:
326 name = "data segment";
327 break;
328 case kDeclFunctionTable:
329 name = "function table";
330 break;
331 default:
332 name = "";
333 break;
334 }
335 if (present) { 389 if (present) {
336 error(pc_ - 1, nullptr, "required %s section missing", name); 390 error(pc_ - 1, nullptr, "required %s section missing", name);
337 } else { 391 } else {
338 error(pc_ - 1, nullptr, "%s section already present", name); 392 error(pc_ - 1, nullptr, "%s section already present", name);
339 } 393 }
340 } 394 }
341 395
342 // Decodes a single anonymous function starting at {start_}. 396 // Decodes a single anonymous function starting at {start_}.
343 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, 397 FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
344 WasmFunction* function) { 398 WasmFunction* function) {
(...skipping 30 matching lines...) Expand all
375 429
376 // Decodes a single global entry inside a module starting at {pc_}. 430 // Decodes a single global entry inside a module starting at {pc_}.
377 void DecodeGlobalInModule(WasmGlobal* global) { 431 void DecodeGlobalInModule(WasmGlobal* global) {
378 global->name_offset = consume_string(&global->name_length, "global name"); 432 global->name_offset = consume_string(&global->name_length, "global name");
379 global->type = mem_type(); 433 global->type = mem_type();
380 global->offset = 0; 434 global->offset = 0;
381 global->exported = consume_u8("exported") != 0; 435 global->exported = consume_u8("exported") != 0;
382 } 436 }
383 437
384 // Decodes a single function entry inside a module starting at {pc_}. 438 // Decodes a single function entry inside a module starting at {pc_}.
439 // TODO(titzer): legacy function body; remove
385 void DecodeFunctionInModule(WasmModule* module, WasmFunction* function, 440 void DecodeFunctionInModule(WasmModule* module, WasmFunction* function,
386 bool verify_body = true) { 441 bool verify_body = true) {
387 byte decl_bits = consume_u8("function decl"); 442 byte decl_bits = consume_u8("function decl");
388 443
389 const byte* sigpos = pc_; 444 const byte* sigpos = pc_;
390 function->sig_index = consume_u16("signature index"); 445 function->sig_index = consume_u16("signature index");
391 446
392 if (function->sig_index >= module->signatures.size()) { 447 if (function->sig_index >= module->signatures.size()) {
393 return error(sigpos, "invalid signature index"); 448 return error(sigpos, "invalid signature index");
394 } else { 449 } else {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 error(pc_ - sizeof(uint32_t), "offset out of bounds of module"); 565 error(pc_ - sizeof(uint32_t), "offset out of bounds of module");
511 } 566 }
512 return offset; 567 return offset;
513 } 568 }
514 569
515 // Reads a length-prefixed string, checking that it is within bounds. Returns 570 // Reads a length-prefixed string, checking that it is within bounds. Returns
516 // the offset of the string, and the length as an out parameter. 571 // the offset of the string, and the length as an out parameter.
517 uint32_t consume_string(uint32_t* length, const char* name = nullptr) { 572 uint32_t consume_string(uint32_t* length, const char* name = nullptr) {
518 int varint_length; 573 int varint_length;
519 *length = consume_u32v(&varint_length, "string length"); 574 *length = consume_u32v(&varint_length, "string length");
520 uint32_t offset = static_cast<uint32_t>(pc_ - start_); 575 uint32_t offset = pc_offset();
576 TRACE(" +%u %-20s: (%u bytes)\n", offset, "string", *length);
521 consume_bytes(*length); 577 consume_bytes(*length);
522 return offset; 578 return offset;
523 } 579 }
524 580
581 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
582 const byte* pos = pc_;
583 int length;
584 uint32_t sig_index = consume_u32v(&length, "signature index");
585 if (sig_index >= module->signatures.size()) {
586 error(pos, pos, "signature index %u out of bounds (%d signatures)",
587 sig_index, static_cast<int>(module->signatures.size()));
588 *sig = nullptr;
589 return 0;
590 }
591 *sig = module->signatures[sig_index];
592 return sig_index;
593 }
594
595 uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
596 const byte* pos = pc_;
597 int length;
598 uint32_t func_index = consume_u32v(&length, "function index");
599 if (func_index >= module->functions.size()) {
600 error(pos, pos, "function index %u out of bounds (%d functions)",
601 func_index, static_cast<int>(module->functions.size()));
602 *func = nullptr;
603 return 0;
604 }
605 *func = &module->functions[func_index];
606 return func_index;
607 }
608
525 // Reads a single 8-bit integer, interpreting it as a local type. 609 // Reads a single 8-bit integer, interpreting it as a local type.
526 LocalType consume_local_type() { 610 LocalType consume_local_type() {
527 byte val = consume_u8("local type"); 611 byte val = consume_u8("local type");
528 LocalTypeCode t = static_cast<LocalTypeCode>(val); 612 LocalTypeCode t = static_cast<LocalTypeCode>(val);
529 switch (t) { 613 switch (t) {
530 case kLocalVoid: 614 case kLocalVoid:
531 return kAstStmt; 615 return kAstStmt;
532 case kLocalI32: 616 case kLocalI32:
533 return kAstI32; 617 return kAstI32;
534 case kLocalI64: 618 case kLocalI64:
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 if (function_start > function_end) return FunctionError("start > end"); 730 if (function_start > function_end) return FunctionError("start > end");
647 if (size > kMaxFunctionSize) 731 if (size > kMaxFunctionSize)
648 return FunctionError("size > maximum function size"); 732 return FunctionError("size > maximum function size");
649 WasmFunction* function = new WasmFunction(); 733 WasmFunction* function = new WasmFunction();
650 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin); 734 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
651 return decoder.DecodeSingleFunction(module_env, function); 735 return decoder.DecodeSingleFunction(module_env, function);
652 } 736 }
653 } // namespace wasm 737 } // namespace wasm
654 } // namespace internal 738 } // namespace internal
655 } // namespace v8 739 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/decoder.h ('k') | src/wasm/wasm-module.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698