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

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

Issue 1900153002: [wasm] Enforce strict ordering of WASM module sections. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix OOB Created 4 years, 8 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
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/wasm/module-decoder.h" 5 #include "src/wasm/module-decoder.h"
6 6
7 #include "src/base/functional.h" 7 #include "src/base/functional.h"
8 #include "src/base/platform/platform.h" 8 #include "src/base/platform/platform.h"
9 #include "src/macro-assembler.h" 9 #include "src/macro-assembler.h"
10 #include "src/objects.h" 10 #include "src/objects.h"
11 #include "src/v8.h" 11 #include "src/v8.h"
12 12
13 #include "src/wasm/decoder.h" 13 #include "src/wasm/decoder.h"
14 14
15 namespace v8 { 15 namespace v8 {
16 namespace internal { 16 namespace internal {
17 namespace wasm { 17 namespace wasm {
18 18
19 #if DEBUG 19 #if DEBUG
20 #define TRACE(...) \ 20 #define TRACE(...) \
21 do { \ 21 do { \
22 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ 22 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
23 } while (false) 23 } while (false)
24 #else 24 #else
25 #define TRACE(...) 25 #define TRACE(...)
26 #endif 26 #endif
27 27
28
29 // The main logic for decoding the bytes of a module. 28 // The main logic for decoding the bytes of a module.
30 class ModuleDecoder : public Decoder { 29 class ModuleDecoder : public Decoder {
31 public: 30 public:
32 ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end, 31 ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end,
33 ModuleOrigin origin) 32 ModuleOrigin origin)
34 : Decoder(module_start, module_end), module_zone(zone), origin_(origin) { 33 : Decoder(module_start, module_end), module_zone(zone), origin_(origin) {
35 result_.start = start_; 34 result_.start = start_;
36 if (limit_ < start_) { 35 if (limit_ < start_) {
37 error(start_, "end is less than start"); 36 error(start_, "end is less than start");
38 limit_ = start_; 37 limit_ = start_;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) { 71 ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) {
73 pc_ = start_; 72 pc_ = start_;
74 module->module_start = start_; 73 module->module_start = start_;
75 module->module_end = limit_; 74 module->module_end = limit_;
76 module->min_mem_pages = 0; 75 module->min_mem_pages = 0;
77 module->max_mem_pages = 0; 76 module->max_mem_pages = 0;
78 module->mem_export = false; 77 module->mem_export = false;
79 module->mem_external = false; 78 module->mem_external = false;
80 module->origin = origin_; 79 module->origin = origin_;
81 80
82 bool sections[(size_t)WasmSection::Code::Max] = {false};
83
84 const byte* pos = pc_; 81 const byte* pos = pc_;
82 int current_order = 0;
85 uint32_t magic_word = consume_u32("wasm magic"); 83 uint32_t magic_word = consume_u32("wasm magic");
86 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff 84 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff
87 if (magic_word != kWasmMagic) { 85 if (magic_word != kWasmMagic) {
88 error(pos, pos, 86 error(pos, pos,
89 "expected magic word %02x %02x %02x %02x, " 87 "expected magic word %02x %02x %02x %02x, "
90 "found %02x %02x %02x %02x", 88 "found %02x %02x %02x %02x",
91 BYTES(kWasmMagic), BYTES(magic_word)); 89 BYTES(kWasmMagic), BYTES(magic_word));
92 goto done; 90 goto done;
93 } 91 }
94 92
95 pos = pc_; 93 pos = pc_;
96 { 94 {
97 uint32_t magic_version = consume_u32("wasm version"); 95 uint32_t magic_version = consume_u32("wasm version");
98 if (magic_version != kWasmVersion) { 96 if (magic_version != kWasmVersion) {
99 error(pos, pos, 97 error(pos, pos,
100 "expected version %02x %02x %02x %02x, " 98 "expected version %02x %02x %02x %02x, "
101 "found %02x %02x %02x %02x", 99 "found %02x %02x %02x %02x",
102 BYTES(kWasmVersion), BYTES(magic_version)); 100 BYTES(kWasmVersion), BYTES(magic_version));
103 goto done; 101 goto done;
104 } 102 }
105 } 103 }
106 104
107 // Decode the module sections. 105 // Decode the module sections.
108 while (pc_ < limit_) { 106 while (pc_ < limit_) {
109 TRACE("DecodeSection\n"); 107 TRACE("DecodeSection\n");
110 pos = pc_; 108 pos = pc_;
111 109
112 int length; 110 // Read and check the section size.
113 uint32_t section_length = consume_u32v(&length, "section size"); 111 int section_leb_length = 0;
114 112 uint32_t section_length =
115 int section_string_leb_length = 0; 113 consume_u32v(&section_leb_length, "section length");
116 uint32_t section_string_length = 0; 114 if (!checkAvailable(section_length)) {
117 WasmSection::Code section = consume_section_name( 115 // The section would extend beyond the end of the module.
118 &section_string_leb_length, &section_string_length);
119 uint32_t string_and_leb_length =
120 section_string_leb_length + section_string_length;
121 if (string_and_leb_length > section_length) {
122 error(pos, pos,
123 "section string of size %u longer than total section bytes %u",
124 string_and_leb_length, section_length);
125 break; 116 break;
126 } 117 }
118 const byte* section_start = pc_;
119 const byte* expected_section_end = pc_ + section_length;
127 120
128 if (section == WasmSection::Code::Max) { 121 // Read the section name.
129 // Skip unknown section. 122 int string_leb_length = 0;
130 uint32_t skip = section_length - string_and_leb_length; 123 uint32_t string_length =
131 TRACE("skipping %u bytes from unknown section\n", skip); 124 consume_u32v(&string_leb_length, "section name length");
132 consume_bytes(skip); 125 const byte* section_name_start = pc_;
133 continue; 126 consume_bytes(string_length);
127 if (failed()) {
128 TRACE("Section name of length %u couldn't be read\n", string_length);
129 break;
130 }
131 if (pc_ > expected_section_end) {
132 error(section_name_start, pc_,
133 "section name string %u longer than total section bytes %u",
134 string_length, section_length);
134 } 135 }
135 136
136 // Each section should appear at most once. 137 WasmSection::Code section =
137 CheckForPreviousSection(sections, section, false); 138 WasmSection::lookup(section_name_start, string_length);
138 sections[(size_t)section] = true; 139
140 current_order = CheckSectionOrder(current_order, section);
139 141
140 switch (section) { 142 switch (section) {
141 case WasmSection::Code::End: 143 case WasmSection::Code::End:
142 // Terminate section decoding. 144 // Terminate section decoding.
143 limit_ = pc_; 145 limit_ = pc_;
144 break; 146 break;
145 case WasmSection::Code::Memory: 147 case WasmSection::Code::Memory:
146 int length; 148 int length;
147 module->min_mem_pages = consume_u32v(&length, "min memory"); 149 module->min_mem_pages = consume_u32v(&length, "min memory");
148 module->max_mem_pages = consume_u32v(&length, "max memory"); 150 module->max_mem_pages = consume_u32v(&length, "max memory");
149 module->mem_export = consume_u8("export memory") != 0; 151 module->mem_export = consume_u8("export memory") != 0;
150 break; 152 break;
151 case WasmSection::Code::Signatures: { 153 case WasmSection::Code::Signatures: {
152 int length; 154 int length;
153 uint32_t signatures_count = consume_u32v(&length, "signatures count"); 155 uint32_t signatures_count = consume_u32v(&length, "signatures count");
154 module->signatures.reserve(SafeReserve(signatures_count)); 156 module->signatures.reserve(SafeReserve(signatures_count));
155 // Decode signatures. 157 // Decode signatures.
156 for (uint32_t i = 0; i < signatures_count; i++) { 158 for (uint32_t i = 0; i < signatures_count; i++) {
157 if (failed()) break; 159 if (failed()) break;
158 TRACE("DecodeSignature[%d] module+%d\n", i, 160 TRACE("DecodeSignature[%d] module+%d\n", i,
159 static_cast<int>(pc_ - start_)); 161 static_cast<int>(pc_ - start_));
160 FunctionSig* s = consume_sig(); // read function sig. 162 FunctionSig* s = consume_sig(); // read function sig.
161 module->signatures.push_back(s); 163 module->signatures.push_back(s);
162 } 164 }
163 break; 165 break;
164 } 166 }
165 case WasmSection::Code::FunctionSignatures: { 167 case WasmSection::Code::FunctionSignatures: {
166 // Functions require a signature table first.
167 CheckForPreviousSection(sections, WasmSection::Code::Signatures,
168 true);
169 int length; 168 int length;
170 uint32_t functions_count = consume_u32v(&length, "functions count"); 169 uint32_t functions_count = consume_u32v(&length, "functions count");
171 module->functions.reserve(SafeReserve(functions_count)); 170 module->functions.reserve(SafeReserve(functions_count));
172 for (uint32_t i = 0; i < functions_count; i++) { 171 for (uint32_t i = 0; i < functions_count; i++) {
173 module->functions.push_back( 172 module->functions.push_back(
174 {nullptr, i, 0, 0, 0, 0, 0, 0, false, false}); 173 {nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
175 WasmFunction* function = &module->functions.back(); 174 WasmFunction* function = &module->functions.back();
176 function->sig_index = consume_sig_index(module, &function->sig); 175 function->sig_index = consume_sig_index(module, &function->sig);
177 } 176 }
178 break; 177 break;
179 } 178 }
180 case WasmSection::Code::FunctionBodies: { 179 case WasmSection::Code::FunctionBodies: {
181 // Function bodies should follow signatures.
182 CheckForPreviousSection(sections,
183 WasmSection::Code::FunctionSignatures, true);
184 int length; 180 int length;
185 const byte* pos = pc_; 181 const byte* pos = pc_;
186 uint32_t functions_count = consume_u32v(&length, "functions count"); 182 uint32_t functions_count = consume_u32v(&length, "functions count");
187 if (functions_count != module->functions.size()) { 183 if (functions_count != module->functions.size()) {
188 error(pos, pos, "function body count %u mismatch (%u expected)", 184 error(pos, pos, "function body count %u mismatch (%u expected)",
189 functions_count, 185 functions_count,
190 static_cast<uint32_t>(module->functions.size())); 186 static_cast<uint32_t>(module->functions.size()));
191 break; 187 break;
192 } 188 }
193 for (uint32_t i = 0; i < functions_count; i++) { 189 for (uint32_t i = 0; i < functions_count; i++) {
194 WasmFunction* function = &module->functions[i]; 190 WasmFunction* function = &module->functions[i];
195 int length; 191 int length;
196 uint32_t size = consume_u32v(&length, "body size"); 192 uint32_t size = consume_u32v(&length, "body size");
197 function->code_start_offset = pc_offset(); 193 function->code_start_offset = pc_offset();
198 function->code_end_offset = pc_offset() + size; 194 function->code_end_offset = pc_offset() + size;
199 195
200 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body", 196 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body",
201 size); 197 size);
202 pc_ += size; 198 pc_ += size;
203 if (pc_ > limit_) { 199 if (pc_ > limit_) {
204 error(pc_, "function body extends beyond end of file"); 200 error(pc_, "function body extends beyond end of file");
205 } 201 }
206 } 202 }
207 break; 203 break;
208 } 204 }
209 case WasmSection::Code::Functions: { 205 case WasmSection::Code::Functions: {
210 // Functions require a signature table first.
211 CheckForPreviousSection(sections, WasmSection::Code::Signatures,
212 true);
213 int length; 206 int length;
214 uint32_t functions_count = consume_u32v(&length, "functions count"); 207 uint32_t functions_count = consume_u32v(&length, "functions count");
215 module->functions.reserve(SafeReserve(functions_count)); 208 module->functions.reserve(SafeReserve(functions_count));
216 // Set up module environment for verification. 209 // Set up module environment for verification.
217 ModuleEnv menv; 210 ModuleEnv menv;
218 menv.module = module; 211 menv.module = module;
219 menv.instance = nullptr; 212 menv.instance = nullptr;
220 menv.origin = origin_; 213 menv.origin = origin_;
221 // Decode functions. 214 // Decode functions.
222 for (uint32_t i = 0; i < functions_count; i++) { 215 for (uint32_t i = 0; i < functions_count; i++) {
(...skipping 13 matching lines...) Expand all
236 if (!function->external) { 229 if (!function->external) {
237 VerifyFunctionBody(i, &menv, function); 230 VerifyFunctionBody(i, &menv, function);
238 if (result_.failed()) 231 if (result_.failed())
239 error(result_.error_pc, result_.error_msg.get()); 232 error(result_.error_pc, result_.error_msg.get());
240 } 233 }
241 } 234 }
242 } 235 }
243 break; 236 break;
244 } 237 }
245 case WasmSection::Code::Names: { 238 case WasmSection::Code::Names: {
246 // Names correspond to functions.
247 CheckForPreviousSection(sections,
248 WasmSection::Code::FunctionSignatures, true);
249 int length; 239 int length;
250 const byte* pos = pc_; 240 const byte* pos = pc_;
251 uint32_t functions_count = consume_u32v(&length, "functions count"); 241 uint32_t functions_count = consume_u32v(&length, "functions count");
252 if (functions_count != module->functions.size()) { 242 if (functions_count != module->functions.size()) {
253 error(pos, pos, "function name count %u mismatch (%u expected)", 243 error(pos, pos, "function name count %u mismatch (%u expected)",
254 functions_count, 244 functions_count,
255 static_cast<uint32_t>(module->functions.size())); 245 static_cast<uint32_t>(module->functions.size()));
256 break; 246 break;
257 } 247 }
258 248
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 WasmFunction* func; 324 WasmFunction* func;
335 const byte* pos = pc_; 325 const byte* pos = pc_;
336 module->start_function_index = consume_func_index(module, &func); 326 module->start_function_index = consume_func_index(module, &func);
337 if (func && func->sig->parameter_count() > 0) { 327 if (func && func->sig->parameter_count() > 0) {
338 error(pos, "invalid start function: non-zero parameter count"); 328 error(pos, "invalid start function: non-zero parameter count");
339 break; 329 break;
340 } 330 }
341 break; 331 break;
342 } 332 }
343 case WasmSection::Code::ImportTable: { 333 case WasmSection::Code::ImportTable: {
344 // Declares an import table.
345 CheckForPreviousSection(sections, WasmSection::Code::Signatures,
346 true);
347 int length; 334 int length;
348 uint32_t import_table_count = 335 uint32_t import_table_count =
349 consume_u32v(&length, "import table count"); 336 consume_u32v(&length, "import table count");
350 module->import_table.reserve(SafeReserve(import_table_count)); 337 module->import_table.reserve(SafeReserve(import_table_count));
351 // Decode import table. 338 // Decode import table.
352 for (uint32_t i = 0; i < import_table_count; i++) { 339 for (uint32_t i = 0; i < import_table_count; i++) {
353 if (failed()) break; 340 if (failed()) break;
354 TRACE("DecodeImportTable[%d] module+%d\n", i, 341 TRACE("DecodeImportTable[%d] module+%d\n", i,
355 static_cast<int>(pc_ - start_)); 342 static_cast<int>(pc_ - start_));
356 343
(...skipping 28 matching lines...) Expand all
385 module->export_table.push_back({0, 0}); 372 module->export_table.push_back({0, 0});
386 WasmExport* exp = &module->export_table.back(); 373 WasmExport* exp = &module->export_table.back();
387 374
388 WasmFunction* func; 375 WasmFunction* func;
389 exp->func_index = consume_func_index(module, &func); 376 exp->func_index = consume_func_index(module, &func);
390 exp->name_offset = consume_string(&exp->name_length, "export name"); 377 exp->name_offset = consume_string(&exp->name_length, "export name");
391 } 378 }
392 break; 379 break;
393 } 380 }
394 case WasmSection::Code::Max: 381 case WasmSection::Code::Max:
395 UNREACHABLE(); // Already skipped unknown sections. 382 // Skip unknown sections.
383 TRACE("Unknown section: '");
384 for (uint32_t i = 0; i != string_length; ++i) {
385 TRACE("%c", *(section_name_start + i));
386 }
387 TRACE("'\n");
388 consume_bytes(section_length - string_length - string_leb_length);
389 break;
390 }
391
392 if (pc_ != expected_section_end) {
393 const char* diff = pc_ < expected_section_end ? "shorter" : "longer";
394 size_t expected_length = static_cast<size_t>(section_length);
395 size_t actual_length = static_cast<size_t>(pc_ - section_start);
396 error(pc_, pc_,
397 "section \"%s\" %s (%zu bytes) than specified (%zu bytes)",
398 WasmSection::getName(section), diff, actual_length,
399 expected_length);
JF 2016/04/20 17:59:54 If section is Code::Max then it'll print a slightl
titzer 2016/04/21 10:59:22 Acknowledged.
400 break;
396 } 401 }
397 } 402 }
398 403
399 done: 404 done:
400 ModuleResult result = toResult(module); 405 ModuleResult result = toResult(module);
401 if (FLAG_dump_wasm_module) { 406 if (FLAG_dump_wasm_module) {
402 DumpModule(module, result); 407 DumpModule(module, result);
403 } 408 }
404 return result; 409 return result;
405 } 410 }
406 411
407 uint32_t SafeReserve(uint32_t count) { 412 uint32_t SafeReserve(uint32_t count) {
408 // Avoid OOM by only reserving up to a certain size. 413 // Avoid OOM by only reserving up to a certain size.
409 const uint32_t kMaxReserve = 20000; 414 const uint32_t kMaxReserve = 20000;
410 return count < kMaxReserve ? count : kMaxReserve; 415 return count < kMaxReserve ? count : kMaxReserve;
411 } 416 }
412 417
413 void CheckForFunctions(WasmModule* module, WasmSection::Code section) { 418 void CheckForFunctions(WasmModule* module, WasmSection::Code section) {
414 if (module->functions.size() == 0) { 419 if (module->functions.size() == 0) {
415 error(pc_ - 1, nullptr, "functions must appear before section %s", 420 error(pc_ - 1, nullptr, "functions must appear before section %s",
416 WasmSection::getName(section)); 421 WasmSection::getName(section));
417 } 422 }
418 } 423 }
419 424
420 void CheckForPreviousSection(bool* sections, WasmSection::Code section, 425 int CheckSectionOrder(int current_order, WasmSection::Code section) {
421 bool present) { 426 if (section == WasmSection::Code::Max) return current_order;
422 if (section >= WasmSection::Code::Max) return; 427 int next_order = WasmSection::getOrder(section);
423 if (sections[(size_t)section] == present) return; 428 if (next_order == 0) return current_order;
424 if (present) { 429 if (next_order == current_order) {
425 error(pc_ - 1, nullptr, "required %s section missing", 430 error(pc_, pc_, "section \"%s\" already defined",
426 WasmSection::getName(section));
427 } else {
428 error(pc_ - 1, nullptr, "%s section already present",
429 WasmSection::getName(section)); 431 WasmSection::getName(section));
430 } 432 }
433 if (next_order < current_order) {
434 error(pc_, pc_, "section \"%s\" out of order",
435 WasmSection::getName(section));
436 }
437 return next_order;
431 } 438 }
432 439
433 // Decodes a single anonymous function starting at {start_}. 440 // Decodes a single anonymous function starting at {start_}.
434 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, 441 FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
435 WasmFunction* function) { 442 WasmFunction* function) {
436 pc_ = start_; 443 pc_ = start_;
437 function->sig = consume_sig(); // read signature 444 function->sig = consume_sig(); // read signature
438 function->name_offset = 0; // ---- name 445 function->name_offset = 0; // ---- name
439 function->name_length = 0; // ---- name length 446 function->name_length = 0; // ---- name length
440 function->code_start_offset = off(pc_); // ---- code start 447 function->code_start_offset = off(pc_); // ---- code start
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 if (func_index >= module->functions.size()) { 643 if (func_index >= module->functions.size()) {
637 error(pos, pos, "function index %u out of bounds (%d functions)", 644 error(pos, pos, "function index %u out of bounds (%d functions)",
638 func_index, static_cast<int>(module->functions.size())); 645 func_index, static_cast<int>(module->functions.size()));
639 *func = nullptr; 646 *func = nullptr;
640 return 0; 647 return 0;
641 } 648 }
642 *func = &module->functions[func_index]; 649 *func = &module->functions[func_index];
643 return func_index; 650 return func_index;
644 } 651 }
645 652
646 // Reads a section name.
647 WasmSection::Code consume_section_name(int* string_leb_length,
648 uint32_t* string_length) {
649 *string_length = consume_u32v(string_leb_length, "name length");
650 const byte* start = pc_;
651 consume_bytes(*string_length);
652 if (failed()) {
653 TRACE("Section name of length %u couldn't be read\n", *string_length);
654 return WasmSection::Code::Max;
655 }
656 // TODO(jfb) Linear search, it may be better to do a common-prefix search.
657 for (WasmSection::Code i = WasmSection::begin(); i != WasmSection::end();
658 i = WasmSection::next(i)) {
659 if (WasmSection::getNameLength(i) == *string_length &&
660 0 == memcmp(WasmSection::getName(i), start, *string_length)) {
661 return i;
662 }
663 }
664 TRACE("Unknown section: '");
665 for (uint32_t i = 0; i != *string_length; ++i) TRACE("%c", *(start + i));
666 TRACE("'\n");
667 return WasmSection::Code::Max;
668 }
669
670 // Reads a single 8-bit integer, interpreting it as a local type. 653 // Reads a single 8-bit integer, interpreting it as a local type.
671 LocalType consume_local_type() { 654 LocalType consume_local_type() {
672 byte val = consume_u8("local type"); 655 byte val = consume_u8("local type");
673 LocalTypeCode t = static_cast<LocalTypeCode>(val); 656 LocalTypeCode t = static_cast<LocalTypeCode>(val);
674 switch (t) { 657 switch (t) {
675 case kLocalVoid: 658 case kLocalVoid:
676 return kAstStmt; 659 return kAstStmt;
677 case kLocalI32: 660 case kLocalI32:
678 return kAstI32; 661 return kAstI32;
679 case kLocalI64: 662 case kLocalI64:
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 return FunctionError("size > maximum function size"); 787 return FunctionError("size > maximum function size");
805 isolate->counters()->wasm_function_size_bytes()->AddSample( 788 isolate->counters()->wasm_function_size_bytes()->AddSample(
806 static_cast<int>(size)); 789 static_cast<int>(size));
807 WasmFunction* function = new WasmFunction(); 790 WasmFunction* function = new WasmFunction();
808 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin); 791 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
809 return decoder.DecodeSingleFunction(module_env, function); 792 return decoder.DecodeSingleFunction(module_env, function);
810 } 793 }
811 } // namespace wasm 794 } // namespace wasm
812 } // namespace internal 795 } // namespace internal
813 } // namespace v8 796 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/encoder.cc ('k') | src/wasm/wasm-module.h » ('j') | src/wasm/wasm-module.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698