OLD | NEW |
---|---|
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 Loading... | |
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(§ion_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 §ion_string_leb_length, §ion_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 } |
127 | 118 |
119 // Read the section name. | |
120 int string_leb_length = 0; | |
121 uint32_t string_length = | |
122 consume_u32v(&string_leb_length, "section name length"); | |
123 if (static_cast<uint32_t>(string_leb_length) + string_length > | |
124 section_length) { | |
JF
2016/04/19 15:48:47
This seems pretty impossible to cause to overflow,
titzer
2016/04/20 08:51:24
Done. (I've refactored this a bit so the check is
| |
125 error(pc_, pc_, | |
126 "section name string %u longer than total section bytes %u", | |
127 string_length, section_length); | |
128 break; | |
129 } | |
130 | |
131 const byte* section_name_start = pc_; | |
132 consume_bytes(string_length); | |
133 if (failed()) { | |
134 TRACE("Section name of length %u couldn't be read\n", string_length); | |
135 break; | |
136 } | |
137 | |
138 WasmSection::Code section = | |
139 WasmSection::lookup(section_name_start, string_length); | |
140 // TODO(jfb) Linear search, it may be better to do a common-prefix search. | |
141 for (WasmSection::Code i = WasmSection::begin(); i != WasmSection::end(); | |
142 i = WasmSection::next(i)) { | |
143 if (WasmSection::getNameLength(i) == string_length && | |
144 0 == memcmp(WasmSection::getName(i), section_name_start, | |
145 string_length)) { | |
146 section = i; | |
147 break; | |
148 } | |
149 } | |
JF
2016/04/19 15:48:47
Duplicate.
titzer
2016/04/20 08:51:24
Done.
| |
150 | |
128 if (section == WasmSection::Code::Max) { | 151 if (section == WasmSection::Code::Max) { |
129 // Skip unknown section. | 152 // Skip unknown sections. |
130 uint32_t skip = section_length - string_and_leb_length; | 153 TRACE("Unknown section: '"); |
131 TRACE("skipping %u bytes from unknown section\n", skip); | 154 for (uint32_t i = 0; i != string_length; ++i) { |
132 consume_bytes(skip); | 155 TRACE("%c", *(section_name_start + i)); |
156 } | |
157 TRACE("'\n"); | |
158 consume_bytes(section_length - string_length - string_leb_length); | |
133 continue; | 159 continue; |
134 } | 160 } |
135 | 161 |
136 // Each section should appear at most once. | 162 current_order = CheckSectionOrder(current_order, section); |
137 CheckForPreviousSection(sections, section, false); | |
138 sections[(size_t)section] = true; | |
139 | 163 |
140 switch (section) { | 164 switch (section) { |
141 case WasmSection::Code::End: | 165 case WasmSection::Code::End: |
142 // Terminate section decoding. | 166 // Terminate section decoding. |
143 limit_ = pc_; | 167 limit_ = pc_; |
144 break; | 168 break; |
145 case WasmSection::Code::Memory: | 169 case WasmSection::Code::Memory: |
146 int length; | 170 int length; |
147 module->min_mem_pages = consume_u32v(&length, "min memory"); | 171 module->min_mem_pages = consume_u32v(&length, "min memory"); |
148 module->max_mem_pages = consume_u32v(&length, "max memory"); | 172 module->max_mem_pages = consume_u32v(&length, "max memory"); |
149 module->mem_export = consume_u8("export memory") != 0; | 173 module->mem_export = consume_u8("export memory") != 0; |
150 break; | 174 break; |
151 case WasmSection::Code::Signatures: { | 175 case WasmSection::Code::Signatures: { |
152 int length; | 176 int length; |
153 uint32_t signatures_count = consume_u32v(&length, "signatures count"); | 177 uint32_t signatures_count = consume_u32v(&length, "signatures count"); |
154 module->signatures.reserve(SafeReserve(signatures_count)); | 178 module->signatures.reserve(SafeReserve(signatures_count)); |
155 // Decode signatures. | 179 // Decode signatures. |
156 for (uint32_t i = 0; i < signatures_count; i++) { | 180 for (uint32_t i = 0; i < signatures_count; i++) { |
157 if (failed()) break; | 181 if (failed()) break; |
158 TRACE("DecodeSignature[%d] module+%d\n", i, | 182 TRACE("DecodeSignature[%d] module+%d\n", i, |
159 static_cast<int>(pc_ - start_)); | 183 static_cast<int>(pc_ - start_)); |
160 FunctionSig* s = consume_sig(); // read function sig. | 184 FunctionSig* s = consume_sig(); // read function sig. |
161 module->signatures.push_back(s); | 185 module->signatures.push_back(s); |
162 } | 186 } |
163 break; | 187 break; |
164 } | 188 } |
165 case WasmSection::Code::FunctionSignatures: { | 189 case WasmSection::Code::FunctionSignatures: { |
166 // Functions require a signature table first. | |
167 CheckForPreviousSection(sections, WasmSection::Code::Signatures, | |
168 true); | |
169 int length; | 190 int length; |
170 uint32_t functions_count = consume_u32v(&length, "functions count"); | 191 uint32_t functions_count = consume_u32v(&length, "functions count"); |
171 module->functions.reserve(SafeReserve(functions_count)); | 192 module->functions.reserve(SafeReserve(functions_count)); |
172 for (uint32_t i = 0; i < functions_count; i++) { | 193 for (uint32_t i = 0; i < functions_count; i++) { |
173 module->functions.push_back( | 194 module->functions.push_back( |
174 {nullptr, i, 0, 0, 0, 0, 0, 0, false, false}); | 195 {nullptr, i, 0, 0, 0, 0, 0, 0, false, false}); |
175 WasmFunction* function = &module->functions.back(); | 196 WasmFunction* function = &module->functions.back(); |
176 function->sig_index = consume_sig_index(module, &function->sig); | 197 function->sig_index = consume_sig_index(module, &function->sig); |
177 } | 198 } |
178 break; | 199 break; |
179 } | 200 } |
180 case WasmSection::Code::FunctionBodies: { | 201 case WasmSection::Code::FunctionBodies: { |
181 // Function bodies should follow signatures. | |
182 CheckForPreviousSection(sections, | |
183 WasmSection::Code::FunctionSignatures, true); | |
184 int length; | 202 int length; |
185 const byte* pos = pc_; | 203 const byte* pos = pc_; |
186 uint32_t functions_count = consume_u32v(&length, "functions count"); | 204 uint32_t functions_count = consume_u32v(&length, "functions count"); |
187 if (functions_count != module->functions.size()) { | 205 if (functions_count != module->functions.size()) { |
188 error(pos, pos, "function body count %u mismatch (%u expected)", | 206 error(pos, pos, "function body count %u mismatch (%u expected)", |
189 functions_count, | 207 functions_count, |
190 static_cast<uint32_t>(module->functions.size())); | 208 static_cast<uint32_t>(module->functions.size())); |
191 break; | 209 break; |
192 } | 210 } |
193 for (uint32_t i = 0; i < functions_count; i++) { | 211 for (uint32_t i = 0; i < functions_count; i++) { |
194 WasmFunction* function = &module->functions[i]; | 212 WasmFunction* function = &module->functions[i]; |
195 int length; | 213 int length; |
196 uint32_t size = consume_u32v(&length, "body size"); | 214 uint32_t size = consume_u32v(&length, "body size"); |
197 function->code_start_offset = pc_offset(); | 215 function->code_start_offset = pc_offset(); |
198 function->code_end_offset = pc_offset() + size; | 216 function->code_end_offset = pc_offset() + size; |
199 | 217 |
200 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body", | 218 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body", |
201 size); | 219 size); |
202 pc_ += size; | 220 pc_ += size; |
203 if (pc_ > limit_) { | 221 if (pc_ > limit_) { |
204 error(pc_, "function body extends beyond end of file"); | 222 error(pc_, "function body extends beyond end of file"); |
205 } | 223 } |
206 } | 224 } |
207 break; | 225 break; |
208 } | 226 } |
209 case WasmSection::Code::Functions: { | 227 case WasmSection::Code::Functions: { |
210 // Functions require a signature table first. | |
211 CheckForPreviousSection(sections, WasmSection::Code::Signatures, | |
212 true); | |
213 int length; | 228 int length; |
214 uint32_t functions_count = consume_u32v(&length, "functions count"); | 229 uint32_t functions_count = consume_u32v(&length, "functions count"); |
215 module->functions.reserve(SafeReserve(functions_count)); | 230 module->functions.reserve(SafeReserve(functions_count)); |
216 // Set up module environment for verification. | 231 // Set up module environment for verification. |
217 ModuleEnv menv; | 232 ModuleEnv menv; |
218 menv.module = module; | 233 menv.module = module; |
219 menv.instance = nullptr; | 234 menv.instance = nullptr; |
220 menv.origin = origin_; | 235 menv.origin = origin_; |
221 // Decode functions. | 236 // Decode functions. |
222 for (uint32_t i = 0; i < functions_count; i++) { | 237 for (uint32_t i = 0; i < functions_count; i++) { |
(...skipping 13 matching lines...) Expand all Loading... | |
236 if (!function->external) { | 251 if (!function->external) { |
237 VerifyFunctionBody(i, &menv, function); | 252 VerifyFunctionBody(i, &menv, function); |
238 if (result_.failed()) | 253 if (result_.failed()) |
239 error(result_.error_pc, result_.error_msg.get()); | 254 error(result_.error_pc, result_.error_msg.get()); |
240 } | 255 } |
241 } | 256 } |
242 } | 257 } |
243 break; | 258 break; |
244 } | 259 } |
245 case WasmSection::Code::Names: { | 260 case WasmSection::Code::Names: { |
246 // Names correspond to functions. | |
247 CheckForPreviousSection(sections, | |
248 WasmSection::Code::FunctionSignatures, true); | |
249 int length; | 261 int length; |
250 const byte* pos = pc_; | 262 const byte* pos = pc_; |
251 uint32_t functions_count = consume_u32v(&length, "functions count"); | 263 uint32_t functions_count = consume_u32v(&length, "functions count"); |
252 if (functions_count != module->functions.size()) { | 264 if (functions_count != module->functions.size()) { |
253 error(pos, pos, "function name count %u mismatch (%u expected)", | 265 error(pos, pos, "function name count %u mismatch (%u expected)", |
254 functions_count, | 266 functions_count, |
255 static_cast<uint32_t>(module->functions.size())); | 267 static_cast<uint32_t>(module->functions.size())); |
256 break; | 268 break; |
257 } | 269 } |
258 | 270 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 WasmFunction* func; | 346 WasmFunction* func; |
335 const byte* pos = pc_; | 347 const byte* pos = pc_; |
336 module->start_function_index = consume_func_index(module, &func); | 348 module->start_function_index = consume_func_index(module, &func); |
337 if (func && func->sig->parameter_count() > 0) { | 349 if (func && func->sig->parameter_count() > 0) { |
338 error(pos, "invalid start function: non-zero parameter count"); | 350 error(pos, "invalid start function: non-zero parameter count"); |
339 break; | 351 break; |
340 } | 352 } |
341 break; | 353 break; |
342 } | 354 } |
343 case WasmSection::Code::ImportTable: { | 355 case WasmSection::Code::ImportTable: { |
344 // Declares an import table. | |
345 CheckForPreviousSection(sections, WasmSection::Code::Signatures, | |
346 true); | |
347 int length; | 356 int length; |
348 uint32_t import_table_count = | 357 uint32_t import_table_count = |
349 consume_u32v(&length, "import table count"); | 358 consume_u32v(&length, "import table count"); |
350 module->import_table.reserve(SafeReserve(import_table_count)); | 359 module->import_table.reserve(SafeReserve(import_table_count)); |
351 // Decode import table. | 360 // Decode import table. |
352 for (uint32_t i = 0; i < import_table_count; i++) { | 361 for (uint32_t i = 0; i < import_table_count; i++) { |
353 if (failed()) break; | 362 if (failed()) break; |
354 TRACE("DecodeImportTable[%d] module+%d\n", i, | 363 TRACE("DecodeImportTable[%d] module+%d\n", i, |
355 static_cast<int>(pc_ - start_)); | 364 static_cast<int>(pc_ - start_)); |
356 | 365 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
410 return count < kMaxReserve ? count : kMaxReserve; | 419 return count < kMaxReserve ? count : kMaxReserve; |
411 } | 420 } |
412 | 421 |
413 void CheckForFunctions(WasmModule* module, WasmSection::Code section) { | 422 void CheckForFunctions(WasmModule* module, WasmSection::Code section) { |
414 if (module->functions.size() == 0) { | 423 if (module->functions.size() == 0) { |
415 error(pc_ - 1, nullptr, "functions must appear before section %s", | 424 error(pc_ - 1, nullptr, "functions must appear before section %s", |
416 WasmSection::getName(section)); | 425 WasmSection::getName(section)); |
417 } | 426 } |
418 } | 427 } |
419 | 428 |
420 void CheckForPreviousSection(bool* sections, WasmSection::Code section, | 429 int CheckSectionOrder(int current_order, WasmSection::Code section) { |
421 bool present) { | 430 int next_order = WasmSection::getOrder(section); |
422 if (section >= WasmSection::Code::Max) return; | 431 if (next_order == 0) return current_order; |
423 if (sections[(size_t)section] == present) return; | 432 if (next_order == current_order) { |
424 if (present) { | 433 error(pc_, pc_, "section \"%s\" already defined", |
425 error(pc_ - 1, nullptr, "required %s section missing", | |
426 WasmSection::getName(section)); | |
427 } else { | |
428 error(pc_ - 1, nullptr, "%s section already present", | |
429 WasmSection::getName(section)); | 434 WasmSection::getName(section)); |
430 } | 435 } |
436 if (next_order < current_order) { | |
437 error(pc_, pc_, "section \"%s\" out of order", | |
438 WasmSection::getName(section)); | |
439 } | |
440 return next_order; | |
431 } | 441 } |
432 | 442 |
433 // Decodes a single anonymous function starting at {start_}. | 443 // Decodes a single anonymous function starting at {start_}. |
434 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, | 444 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, |
435 WasmFunction* function) { | 445 WasmFunction* function) { |
436 pc_ = start_; | 446 pc_ = start_; |
437 function->sig = consume_sig(); // read signature | 447 function->sig = consume_sig(); // read signature |
438 function->name_offset = 0; // ---- name | 448 function->name_offset = 0; // ---- name |
439 function->name_length = 0; // ---- name length | 449 function->name_length = 0; // ---- name length |
440 function->code_start_offset = off(pc_); // ---- code start | 450 function->code_start_offset = off(pc_); // ---- code start |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
636 if (func_index >= module->functions.size()) { | 646 if (func_index >= module->functions.size()) { |
637 error(pos, pos, "function index %u out of bounds (%d functions)", | 647 error(pos, pos, "function index %u out of bounds (%d functions)", |
638 func_index, static_cast<int>(module->functions.size())); | 648 func_index, static_cast<int>(module->functions.size())); |
639 *func = nullptr; | 649 *func = nullptr; |
640 return 0; | 650 return 0; |
641 } | 651 } |
642 *func = &module->functions[func_index]; | 652 *func = &module->functions[func_index]; |
643 return func_index; | 653 return func_index; |
644 } | 654 } |
645 | 655 |
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. | 656 // Reads a single 8-bit integer, interpreting it as a local type. |
671 LocalType consume_local_type() { | 657 LocalType consume_local_type() { |
672 byte val = consume_u8("local type"); | 658 byte val = consume_u8("local type"); |
673 LocalTypeCode t = static_cast<LocalTypeCode>(val); | 659 LocalTypeCode t = static_cast<LocalTypeCode>(val); |
674 switch (t) { | 660 switch (t) { |
675 case kLocalVoid: | 661 case kLocalVoid: |
676 return kAstStmt; | 662 return kAstStmt; |
677 case kLocalI32: | 663 case kLocalI32: |
678 return kAstI32; | 664 return kAstI32; |
679 case kLocalI64: | 665 case kLocalI64: |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
804 return FunctionError("size > maximum function size"); | 790 return FunctionError("size > maximum function size"); |
805 isolate->counters()->wasm_function_size_bytes()->AddSample( | 791 isolate->counters()->wasm_function_size_bytes()->AddSample( |
806 static_cast<int>(size)); | 792 static_cast<int>(size)); |
807 WasmFunction* function = new WasmFunction(); | 793 WasmFunction* function = new WasmFunction(); |
808 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin); | 794 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin); |
809 return decoder.DecodeSingleFunction(module_env, function); | 795 return decoder.DecodeSingleFunction(module_env, function); |
810 } | 796 } |
811 } // namespace wasm | 797 } // namespace wasm |
812 } // namespace internal | 798 } // namespace internal |
813 } // namespace v8 | 799 } // namespace v8 |
OLD | NEW |