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/flags.h" | 9 #include "src/flags.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 if (limit_ < start_) { | 182 if (limit_ < start_) { |
183 error(start_, "end is less than start"); | 183 error(start_, "end is less than start"); |
184 limit_ = start_; | 184 limit_ = start_; |
185 } | 185 } |
186 } | 186 } |
187 | 187 |
188 virtual void onFirstError() { | 188 virtual void onFirstError() { |
189 pc_ = limit_; // On error, terminate section decoding loop. | 189 pc_ = limit_; // On error, terminate section decoding loop. |
190 } | 190 } |
191 | 191 |
192 static void DumpModule(WasmModule* module, const ModuleResult& result) { | 192 void DumpModule(const ModuleResult& result) { |
193 std::string path; | 193 std::string path; |
194 if (FLAG_dump_wasm_module_path) { | 194 if (FLAG_dump_wasm_module_path) { |
195 path = FLAG_dump_wasm_module_path; | 195 path = FLAG_dump_wasm_module_path; |
196 if (path.size() && | 196 if (path.size() && |
197 !base::OS::isDirectorySeparator(path[path.size() - 1])) { | 197 !base::OS::isDirectorySeparator(path[path.size() - 1])) { |
198 path += base::OS::DirectorySeparator(); | 198 path += base::OS::DirectorySeparator(); |
199 } | 199 } |
200 } | 200 } |
201 // File are named `HASH.{ok,failed}.wasm`. | 201 // File are named `HASH.{ok,failed}.wasm`. |
202 size_t hash = base::hash_range(module->module_start, module->module_end); | 202 size_t hash = base::hash_range(start_, limit_); |
203 char buf[32] = {'\0'}; | 203 char buf[32] = {'\0'}; |
204 #if V8_OS_WIN && _MSC_VER < 1900 | 204 #if V8_OS_WIN && _MSC_VER < 1900 |
205 #define snprintf sprintf_s | 205 #define snprintf sprintf_s |
206 #endif | 206 #endif |
207 snprintf(buf, sizeof(buf) - 1, "%016zx.%s.wasm", hash, | 207 snprintf(buf, sizeof(buf) - 1, "%016zx.%s.wasm", hash, |
208 result.ok() ? "ok" : "failed"); | 208 result.ok() ? "ok" : "failed"); |
209 std::string name(buf); | 209 std::string name(buf); |
210 if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) { | 210 if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) { |
211 fwrite(module->module_start, module->module_end - module->module_start, 1, | 211 fwrite(start_, limit_ - start_, 1, wasm_file); |
212 wasm_file); | |
213 fclose(wasm_file); | 212 fclose(wasm_file); |
214 } | 213 } |
215 } | 214 } |
216 | 215 |
217 // Decodes an entire module. | 216 // Decodes an entire module. |
218 ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) { | 217 ModuleResult DecodeModule(bool verify_functions = true) { |
219 pc_ = start_; | 218 pc_ = start_; |
220 module->module_start = start_; | 219 WasmModule* module = new WasmModule(module_zone); |
221 module->module_end = limit_; | |
222 module->min_mem_pages = 0; | 220 module->min_mem_pages = 0; |
223 module->max_mem_pages = 0; | 221 module->max_mem_pages = 0; |
224 module->mem_export = false; | 222 module->mem_export = false; |
225 module->origin = origin_; | 223 module->origin = origin_; |
226 | 224 |
227 const byte* pos = pc_; | 225 const byte* pos = pc_; |
228 uint32_t magic_word = consume_u32("wasm magic"); | 226 uint32_t magic_word = consume_u32("wasm magic"); |
229 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff | 227 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff |
230 if (magic_word != kWasmMagic) { | 228 if (magic_word != kWasmMagic) { |
231 error(pos, pos, | 229 error(pos, pos, |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 error(pos, pos, "function body count %u mismatch (%u expected)", | 578 error(pos, pos, "function body count %u mismatch (%u expected)", |
581 functions_count, module->num_declared_functions); | 579 functions_count, module->num_declared_functions); |
582 } | 580 } |
583 for (uint32_t i = 0; ok() && i < functions_count; ++i) { | 581 for (uint32_t i = 0; ok() && i < functions_count; ++i) { |
584 WasmFunction* function = | 582 WasmFunction* function = |
585 &module->functions[i + module->num_imported_functions]; | 583 &module->functions[i + module->num_imported_functions]; |
586 uint32_t size = consume_u32v("body size"); | 584 uint32_t size = consume_u32v("body size"); |
587 function->code_start_offset = pc_offset(); | 585 function->code_start_offset = pc_offset(); |
588 function->code_end_offset = pc_offset() + size; | 586 function->code_end_offset = pc_offset() + size; |
589 if (verify_functions) { | 587 if (verify_functions) { |
590 ModuleEnv module_env; | 588 ModuleBytesEnv module_env(module, nullptr, |
591 module_env.module = module; | 589 ModuleWireBytes(start_, limit_)); |
592 module_env.origin = module->origin; | |
593 | |
594 VerifyFunctionBody(i + module->num_imported_functions, &module_env, | 590 VerifyFunctionBody(i + module->num_imported_functions, &module_env, |
595 function); | 591 function); |
596 } | 592 } |
597 consume_bytes(size, "function body"); | 593 consume_bytes(size, "function body"); |
598 } | 594 } |
599 section_iter.advance(); | 595 section_iter.advance(); |
600 } | 596 } |
601 | 597 |
602 // ===== Data section ==================================================== | 598 // ===== Data section ==================================================== |
603 if (section_iter.section_code() == kDataSectionCode) { | 599 if (section_iter.section_code() == kDataSectionCode) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 } | 645 } |
650 | 646 |
651 if (ok()) { | 647 if (ok()) { |
652 CalculateGlobalOffsets(module); | 648 CalculateGlobalOffsets(module); |
653 } | 649 } |
654 const WasmModule* finished_module = module; | 650 const WasmModule* finished_module = module; |
655 ModuleResult result = toResult(finished_module); | 651 ModuleResult result = toResult(finished_module); |
656 if (verify_functions && result.ok()) { | 652 if (verify_functions && result.ok()) { |
657 result.MoveFrom(result_); // Copy error code and location. | 653 result.MoveFrom(result_); // Copy error code and location. |
658 } | 654 } |
659 if (FLAG_dump_wasm_module) DumpModule(module, result); | 655 if (FLAG_dump_wasm_module) DumpModule(result); |
660 return result; | 656 return result; |
661 } | 657 } |
662 | 658 |
663 uint32_t SafeReserve(uint32_t count) { | 659 uint32_t SafeReserve(uint32_t count) { |
664 // Avoid OOM by only reserving up to a certain size. | 660 // Avoid OOM by only reserving up to a certain size. |
665 const uint32_t kMaxReserve = 20000; | 661 const uint32_t kMaxReserve = 20000; |
666 return count < kMaxReserve ? count : kMaxReserve; | 662 return count < kMaxReserve ? count : kMaxReserve; |
667 } | 663 } |
668 | 664 |
669 // Decodes a single anonymous function starting at {start_}. | 665 // Decodes a single anonymous function starting at {start_}. |
670 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, | 666 FunctionResult DecodeSingleFunction(ModuleBytesEnv* module_env, |
671 WasmFunction* function) { | 667 WasmFunction* function) { |
672 pc_ = start_; | 668 pc_ = start_; |
673 function->sig = consume_sig(); // read signature | 669 function->sig = consume_sig(); // read signature |
674 function->name_offset = 0; // ---- name | 670 function->name_offset = 0; // ---- name |
675 function->name_length = 0; // ---- name length | 671 function->name_length = 0; // ---- name length |
676 function->code_start_offset = off(pc_); // ---- code start | 672 function->code_start_offset = off(pc_); // ---- code start |
677 function->code_end_offset = off(limit_); // ---- code end | 673 function->code_end_offset = off(limit_); // ---- code end |
678 | 674 |
679 if (ok()) VerifyFunctionBody(0, module_env, function); | 675 if (ok()) VerifyFunctionBody(0, module_env, function); |
680 | 676 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 byte size = | 768 byte size = |
773 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type)); | 769 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type)); |
774 offset = (offset + size - 1) & ~(size - 1); // align | 770 offset = (offset + size - 1) & ~(size - 1); // align |
775 global.offset = offset; | 771 global.offset = offset; |
776 offset += size; | 772 offset += size; |
777 } | 773 } |
778 module->globals_size = offset; | 774 module->globals_size = offset; |
779 } | 775 } |
780 | 776 |
781 // Verifies the body (code) of a given function. | 777 // Verifies the body (code) of a given function. |
782 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv, | 778 void VerifyFunctionBody(uint32_t func_num, ModuleBytesEnv* menv, |
783 WasmFunction* function) { | 779 WasmFunction* function) { |
784 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { | 780 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { |
785 OFStream os(stdout); | 781 OFStream os(stdout); |
786 os << "Verifying WASM function " << WasmFunctionName(function, menv) | 782 os << "Verifying WASM function " << WasmFunctionName(function, menv) |
787 << std::endl; | 783 << std::endl; |
788 } | 784 } |
789 FunctionBody body = {menv, function->sig, start_, | 785 FunctionBody body = {menv, function->sig, start_, |
790 start_ + function->code_start_offset, | 786 start_ + function->code_start_offset, |
791 start_ + function->code_end_offset}; | 787 start_ + function->code_end_offset}; |
792 DecodeResult result = VerifyWasmCode(module_zone->allocator(), body); | 788 DecodeResult result = VerifyWasmCode(module_zone->allocator(), body); |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1113 isolate->counters()->wasm_decode_module_time()); | 1109 isolate->counters()->wasm_decode_module_time()); |
1114 size_t size = module_end - module_start; | 1110 size_t size = module_end - module_start; |
1115 if (module_start > module_end) return ModuleError("start > end"); | 1111 if (module_start > module_end) return ModuleError("start > end"); |
1116 if (size >= kMaxModuleSize) return ModuleError("size > maximum module size"); | 1112 if (size >= kMaxModuleSize) return ModuleError("size > maximum module size"); |
1117 // TODO(bradnelson): Improve histogram handling of size_t. | 1113 // TODO(bradnelson): Improve histogram handling of size_t. |
1118 isolate->counters()->wasm_module_size_bytes()->AddSample( | 1114 isolate->counters()->wasm_module_size_bytes()->AddSample( |
1119 static_cast<int>(size)); | 1115 static_cast<int>(size)); |
1120 // Signatures are stored in zone memory, which have the same lifetime | 1116 // Signatures are stored in zone memory, which have the same lifetime |
1121 // as the {module}. | 1117 // as the {module}. |
1122 Zone* zone = new Zone(isolate->allocator(), ZONE_NAME); | 1118 Zone* zone = new Zone(isolate->allocator(), ZONE_NAME); |
1123 WasmModule* module = new WasmModule(zone, module_start); | |
1124 ModuleDecoder decoder(zone, module_start, module_end, origin); | 1119 ModuleDecoder decoder(zone, module_start, module_end, origin); |
1125 ModuleResult result = decoder.DecodeModule(module, verify_functions); | 1120 ModuleResult result = decoder.DecodeModule(verify_functions); |
1126 // TODO(bradnelson): Improve histogram handling of size_t. | 1121 // TODO(bradnelson): Improve histogram handling of size_t. |
1127 // TODO(titzer): this isn't accurate, since it doesn't count the data | 1122 // TODO(titzer): this isn't accurate, since it doesn't count the data |
1128 // allocated on the C++ heap. | 1123 // allocated on the C++ heap. |
1129 // https://bugs.chromium.org/p/chromium/issues/detail?id=657320 | 1124 // https://bugs.chromium.org/p/chromium/issues/detail?id=657320 |
1130 isolate->counters()->wasm_decode_module_peak_memory_bytes()->AddSample( | 1125 isolate->counters()->wasm_decode_module_peak_memory_bytes()->AddSample( |
1131 static_cast<int>(zone->allocation_size())); | 1126 static_cast<int>(zone->allocation_size())); |
1132 return result; | 1127 return result; |
1133 } | 1128 } |
1134 | 1129 |
1135 FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start, | 1130 FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start, |
1136 const byte* end) { | 1131 const byte* end) { |
1137 ModuleDecoder decoder(zone, start, end, kWasmOrigin); | 1132 ModuleDecoder decoder(zone, start, end, kWasmOrigin); |
1138 return decoder.DecodeFunctionSignature(start); | 1133 return decoder.DecodeFunctionSignature(start); |
1139 } | 1134 } |
1140 | 1135 |
1141 WasmInitExpr DecodeWasmInitExprForTesting(const byte* start, const byte* end) { | 1136 WasmInitExpr DecodeWasmInitExprForTesting(const byte* start, const byte* end) { |
1142 AccountingAllocator allocator; | 1137 AccountingAllocator allocator; |
1143 Zone zone(&allocator, ZONE_NAME); | 1138 Zone zone(&allocator, ZONE_NAME); |
1144 ModuleDecoder decoder(&zone, start, end, kWasmOrigin); | 1139 ModuleDecoder decoder(&zone, start, end, kWasmOrigin); |
1145 return decoder.DecodeInitExpr(start); | 1140 return decoder.DecodeInitExpr(start); |
1146 } | 1141 } |
1147 | 1142 |
1148 FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone, | 1143 FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone, |
1149 ModuleEnv* module_env, | 1144 ModuleBytesEnv* module_env, |
1150 const byte* function_start, | 1145 const byte* function_start, |
1151 const byte* function_end) { | 1146 const byte* function_end) { |
1152 HistogramTimerScope wasm_decode_function_time_scope( | 1147 HistogramTimerScope wasm_decode_function_time_scope( |
1153 isolate->counters()->wasm_decode_function_time()); | 1148 isolate->counters()->wasm_decode_function_time()); |
1154 size_t size = function_end - function_start; | 1149 size_t size = function_end - function_start; |
1155 if (function_start > function_end) return FunctionError("start > end"); | 1150 if (function_start > function_end) return FunctionError("start > end"); |
1156 if (size > kMaxFunctionSize) | 1151 if (size > kMaxFunctionSize) |
1157 return FunctionError("size > maximum function size"); | 1152 return FunctionError("size > maximum function size"); |
1158 isolate->counters()->wasm_function_size_bytes()->AddSample( | 1153 isolate->counters()->wasm_function_size_bytes()->AddSample( |
1159 static_cast<int>(size)); | 1154 static_cast<int>(size)); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 table.push_back(std::move(func_asm_offsets)); | 1226 table.push_back(std::move(func_asm_offsets)); |
1232 } | 1227 } |
1233 if (decoder.more()) decoder.error("unexpected additional bytes"); | 1228 if (decoder.more()) decoder.error("unexpected additional bytes"); |
1234 | 1229 |
1235 return decoder.toResult(std::move(table)); | 1230 return decoder.toResult(std::move(table)); |
1236 } | 1231 } |
1237 | 1232 |
1238 } // namespace wasm | 1233 } // namespace wasm |
1239 } // namespace internal | 1234 } // namespace internal |
1240 } // namespace v8 | 1235 } // namespace v8 |
OLD | NEW |