| 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/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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 } | 154 } |
| 155 case kDeclGlobals: { | 155 case kDeclGlobals: { |
| 156 int length; | 156 int length; |
| 157 uint32_t globals_count = consume_u32v(&length, "globals count"); | 157 uint32_t globals_count = consume_u32v(&length, "globals count"); |
| 158 module->globals.reserve(SafeReserve(globals_count)); | 158 module->globals.reserve(SafeReserve(globals_count)); |
| 159 // Decode globals. | 159 // Decode globals. |
| 160 for (uint32_t i = 0; i < globals_count; i++) { | 160 for (uint32_t i = 0; i < globals_count; i++) { |
| 161 if (failed()) break; | 161 if (failed()) break; |
| 162 TRACE("DecodeGlobal[%d] module+%d\n", i, | 162 TRACE("DecodeGlobal[%d] module+%d\n", i, |
| 163 static_cast<int>(pc_ - start_)); | 163 static_cast<int>(pc_ - start_)); |
| 164 module->globals.push_back({0, MachineType::Int32(), 0, false}); | 164 module->globals.push_back({0, 0, MachineType::Int32(), 0, false}); |
| 165 WasmGlobal* global = &module->globals.back(); | 165 WasmGlobal* global = &module->globals.back(); |
| 166 DecodeGlobalInModule(global); | 166 DecodeGlobalInModule(global); |
| 167 } | 167 } |
| 168 break; | 168 break; |
| 169 } | 169 } |
| 170 case kDeclDataSegments: { | 170 case kDeclDataSegments: { |
| 171 int length; | 171 int length; |
| 172 uint32_t data_segments_count = | 172 uint32_t data_segments_count = |
| 173 consume_u32v(&length, "data segments count"); | 173 consume_u32v(&length, "data segments count"); |
| 174 module->data_segments.reserve(SafeReserve(data_segments_count)); | 174 module->data_segments.reserve(SafeReserve(data_segments_count)); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 | 245 |
| 246 const byte* sigpos = pc_; | 246 const byte* sigpos = pc_; |
| 247 import->sig_index = consume_u32v(&length, "signature index"); | 247 import->sig_index = consume_u32v(&length, "signature index"); |
| 248 | 248 |
| 249 if (import->sig_index >= module->signatures.size()) { | 249 if (import->sig_index >= module->signatures.size()) { |
| 250 error(sigpos, "invalid signature index"); | 250 error(sigpos, "invalid signature index"); |
| 251 } else { | 251 } else { |
| 252 import->sig = module->signatures[import->sig_index]; | 252 import->sig = module->signatures[import->sig_index]; |
| 253 } | 253 } |
| 254 const byte* pos = pc_; | 254 const byte* pos = pc_; |
| 255 import->module_name_offset = consume_string("import module name"); | 255 import->module_name_offset = consume_string( |
| 256 if (import->module_name_offset == 0) { | 256 &import->module_name_length, "import module name"); |
| 257 if (import->module_name_length == 0) { |
| 257 error(pos, "import module name cannot be NULL"); | 258 error(pos, "import module name cannot be NULL"); |
| 258 } | 259 } |
| 259 import->function_name_offset = | 260 import->function_name_offset = consume_string( |
| 260 consume_string("import function name"); | 261 &import->function_name_length, "import function name"); |
| 261 } | 262 } |
| 262 break; | 263 break; |
| 263 } | 264 } |
| 264 case kDeclExportTable: { | 265 case kDeclExportTable: { |
| 265 // Declares an export table. | 266 // Declares an export table. |
| 266 CheckForPreviousSection(sections, kDeclFunctions, true); | 267 CheckForPreviousSection(sections, kDeclFunctions, true); |
| 267 int length; | 268 int length; |
| 268 uint32_t export_table_count = | 269 uint32_t export_table_count = |
| 269 consume_u32v(&length, "export table count"); | 270 consume_u32v(&length, "export table count"); |
| 270 module->export_table.reserve(SafeReserve(export_table_count)); | 271 module->export_table.reserve(SafeReserve(export_table_count)); |
| 271 // Decode export table. | 272 // Decode export table. |
| 272 for (uint32_t i = 0; i < export_table_count; i++) { | 273 for (uint32_t i = 0; i < export_table_count; i++) { |
| 273 if (failed()) break; | 274 if (failed()) break; |
| 274 TRACE("DecodeExportTable[%d] module+%d\n", i, | 275 TRACE("DecodeExportTable[%d] module+%d\n", i, |
| 275 static_cast<int>(pc_ - start_)); | 276 static_cast<int>(pc_ - start_)); |
| 276 | 277 |
| 277 module->export_table.push_back({0, 0}); | 278 module->export_table.push_back({0, 0}); |
| 278 WasmExport* exp = &module->export_table.back(); | 279 WasmExport* exp = &module->export_table.back(); |
| 279 | 280 |
| 280 const byte* sigpos = pc_; | 281 const byte* sigpos = pc_; |
| 281 exp->func_index = consume_u32v(&length, "function index"); | 282 exp->func_index = consume_u32v(&length, "function index"); |
| 282 if (exp->func_index >= module->functions.size()) { | 283 if (exp->func_index >= module->functions.size()) { |
| 283 error(sigpos, sigpos, | 284 error(sigpos, sigpos, |
| 284 "function index %u out of bounds (%d functions)", | 285 "function index %u out of bounds (%d functions)", |
| 285 exp->func_index, | 286 exp->func_index, |
| 286 static_cast<int>(module->functions.size())); | 287 static_cast<int>(module->functions.size())); |
| 287 } | 288 } |
| 288 exp->name_offset = consume_string("export name"); | 289 exp->name_offset = consume_string(&exp->name_length, "export name"); |
| 289 } | 290 } |
| 290 break; | 291 break; |
| 291 } | 292 } |
| 292 case kMaxModuleSectionCode: | 293 case kMaxModuleSectionCode: |
| 293 UNREACHABLE(); // Already skipped unknown sections. | 294 UNREACHABLE(); // Already skipped unknown sections. |
| 294 } | 295 } |
| 295 } | 296 } |
| 296 | 297 |
| 297 return toResult(module); | 298 return toResult(module); |
| 298 } | 299 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 error(pc_ - 1, nullptr, "%s section already present", name); | 338 error(pc_ - 1, nullptr, "%s section already present", name); |
| 338 } | 339 } |
| 339 } | 340 } |
| 340 | 341 |
| 341 // Decodes a single anonymous function starting at {start_}. | 342 // Decodes a single anonymous function starting at {start_}. |
| 342 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, | 343 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, |
| 343 WasmFunction* function) { | 344 WasmFunction* function) { |
| 344 pc_ = start_; | 345 pc_ = start_; |
| 345 function->sig = consume_sig(); // read signature | 346 function->sig = consume_sig(); // read signature |
| 346 function->name_offset = 0; // ---- name | 347 function->name_offset = 0; // ---- name |
| 348 function->name_length = 0; // ---- name length |
| 347 function->code_start_offset = off(pc_); // ---- code start | 349 function->code_start_offset = off(pc_); // ---- code start |
| 348 function->code_end_offset = off(limit_); // ---- code end | 350 function->code_end_offset = off(limit_); // ---- code end |
| 349 function->exported = false; // ---- exported | 351 function->exported = false; // ---- exported |
| 350 function->external = false; // ---- external | 352 function->external = false; // ---- external |
| 351 | 353 |
| 352 if (ok()) VerifyFunctionBody(0, module_env, function); | 354 if (ok()) VerifyFunctionBody(0, module_env, function); |
| 353 | 355 |
| 354 FunctionResult result; | 356 FunctionResult result; |
| 355 result.CopyFrom(result_); // Copy error code and location. | 357 result.CopyFrom(result_); // Copy error code and location. |
| 356 result.val = function; | 358 result.val = function; |
| 357 return result; | 359 return result; |
| 358 } | 360 } |
| 359 | 361 |
| 360 // Decodes a single function signature at {start}. | 362 // Decodes a single function signature at {start}. |
| 361 FunctionSig* DecodeFunctionSignature(const byte* start) { | 363 FunctionSig* DecodeFunctionSignature(const byte* start) { |
| 362 pc_ = start; | 364 pc_ = start; |
| 363 FunctionSig* result = consume_sig(); | 365 FunctionSig* result = consume_sig(); |
| 364 return ok() ? result : nullptr; | 366 return ok() ? result : nullptr; |
| 365 } | 367 } |
| 366 | 368 |
| 367 private: | 369 private: |
| 368 Zone* module_zone; | 370 Zone* module_zone; |
| 369 ModuleResult result_; | 371 ModuleResult result_; |
| 370 ModuleOrigin origin_; | 372 ModuleOrigin origin_; |
| 371 | 373 |
| 372 uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); } | 374 uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); } |
| 373 | 375 |
| 374 // Decodes a single global entry inside a module starting at {pc_}. | 376 // Decodes a single global entry inside a module starting at {pc_}. |
| 375 void DecodeGlobalInModule(WasmGlobal* global) { | 377 void DecodeGlobalInModule(WasmGlobal* global) { |
| 376 global->name_offset = consume_string("global name"); | 378 global->name_offset = consume_string(&global->name_length, "global name"); |
| 377 global->type = mem_type(); | 379 global->type = mem_type(); |
| 378 global->offset = 0; | 380 global->offset = 0; |
| 379 global->exported = consume_u8("exported") != 0; | 381 global->exported = consume_u8("exported") != 0; |
| 380 } | 382 } |
| 381 | 383 |
| 382 // Decodes a single function entry inside a module starting at {pc_}. | 384 // Decodes a single function entry inside a module starting at {pc_}. |
| 383 void DecodeFunctionInModule(WasmModule* module, WasmFunction* function, | 385 void DecodeFunctionInModule(WasmModule* module, WasmFunction* function, |
| 384 bool verify_body = true) { | 386 bool verify_body = true) { |
| 385 byte decl_bits = consume_u8("function decl"); | 387 byte decl_bits = consume_u8("function decl"); |
| 386 | 388 |
| 387 const byte* sigpos = pc_; | 389 const byte* sigpos = pc_; |
| 388 function->sig_index = consume_u16("signature index"); | 390 function->sig_index = consume_u16("signature index"); |
| 389 | 391 |
| 390 if (function->sig_index >= module->signatures.size()) { | 392 if (function->sig_index >= module->signatures.size()) { |
| 391 return error(sigpos, "invalid signature index"); | 393 return error(sigpos, "invalid signature index"); |
| 392 } else { | 394 } else { |
| 393 function->sig = module->signatures[function->sig_index]; | 395 function->sig = module->signatures[function->sig_index]; |
| 394 } | 396 } |
| 395 | 397 |
| 396 TRACE(" +%d <function attributes:%s%s%s%s%s>\n", | 398 TRACE(" +%d <function attributes:%s%s%s%s%s>\n", |
| 397 static_cast<int>(pc_ - start_), | 399 static_cast<int>(pc_ - start_), |
| 398 decl_bits & kDeclFunctionName ? " name" : "", | 400 decl_bits & kDeclFunctionName ? " name" : "", |
| 399 decl_bits & kDeclFunctionImport ? " imported" : "", | 401 decl_bits & kDeclFunctionImport ? " imported" : "", |
| 400 decl_bits & kDeclFunctionLocals ? " locals" : "", | 402 decl_bits & kDeclFunctionLocals ? " locals" : "", |
| 401 decl_bits & kDeclFunctionExport ? " exported" : "", | 403 decl_bits & kDeclFunctionExport ? " exported" : "", |
| 402 (decl_bits & kDeclFunctionImport) == 0 ? " body" : ""); | 404 (decl_bits & kDeclFunctionImport) == 0 ? " body" : ""); |
| 403 | 405 |
| 404 if (decl_bits & kDeclFunctionName) { | 406 if (decl_bits & kDeclFunctionName) { |
| 405 function->name_offset = consume_string("function name"); | 407 function->name_offset = |
| 408 consume_string(&function->name_length, "function name"); |
| 406 } | 409 } |
| 407 | 410 |
| 408 function->exported = decl_bits & kDeclFunctionExport; | 411 function->exported = decl_bits & kDeclFunctionExport; |
| 409 | 412 |
| 410 // Imported functions have no locals or body. | 413 // Imported functions have no locals or body. |
| 411 if (decl_bits & kDeclFunctionImport) { | 414 if (decl_bits & kDeclFunctionImport) { |
| 412 function->external = true; | 415 function->external = true; |
| 413 return; | 416 return; |
| 414 } | 417 } |
| 415 | 418 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 // Reads a single 32-bit unsigned integer interpreted as an offset, checking | 501 // Reads a single 32-bit unsigned integer interpreted as an offset, checking |
| 499 // the offset is within bounds and advances. | 502 // the offset is within bounds and advances. |
| 500 uint32_t consume_offset(const char* name = nullptr) { | 503 uint32_t consume_offset(const char* name = nullptr) { |
| 501 uint32_t offset = consume_u32(name ? name : "offset"); | 504 uint32_t offset = consume_u32(name ? name : "offset"); |
| 502 if (offset > static_cast<uint32_t>(limit_ - start_)) { | 505 if (offset > static_cast<uint32_t>(limit_ - start_)) { |
| 503 error(pc_ - sizeof(uint32_t), "offset out of bounds of module"); | 506 error(pc_ - sizeof(uint32_t), "offset out of bounds of module"); |
| 504 } | 507 } |
| 505 return offset; | 508 return offset; |
| 506 } | 509 } |
| 507 | 510 |
| 508 // Reads a single 32-bit unsigned integer interpreted as an offset into the | 511 // Reads a length-prefixed string, checking that it is within bounds. Returns |
| 509 // data and validating the string there and advances. | 512 // the offset of the string, and the length as an out parameter. |
| 510 uint32_t consume_string(const char* name = nullptr) { | 513 uint32_t consume_string(uint32_t* length, const char* name = nullptr) { |
| 511 // TODO(titzer): validate string | 514 int varint_length; |
| 512 return consume_offset(name ? name : "string"); | 515 *length = consume_u32v(&varint_length, "string length"); |
| 516 uint32_t offset = static_cast<uint32_t>(pc_ - start_); |
| 517 consume_bytes(*length); |
| 518 return offset; |
| 513 } | 519 } |
| 514 | 520 |
| 515 // Reads a single 8-bit integer, interpreting it as a local type. | 521 // Reads a single 8-bit integer, interpreting it as a local type. |
| 516 LocalType consume_local_type() { | 522 LocalType consume_local_type() { |
| 517 byte val = consume_u8("local type"); | 523 byte val = consume_u8("local type"); |
| 518 LocalTypeCode t = static_cast<LocalTypeCode>(val); | 524 LocalTypeCode t = static_cast<LocalTypeCode>(val); |
| 519 switch (t) { | 525 switch (t) { |
| 520 case kLocalVoid: | 526 case kLocalVoid: |
| 521 return kAstStmt; | 527 return kAstStmt; |
| 522 case kLocalI32: | 528 case kLocalI32: |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 if (function_start > function_end) return FunctionError("start > end"); | 642 if (function_start > function_end) return FunctionError("start > end"); |
| 637 if (size > kMaxFunctionSize) | 643 if (size > kMaxFunctionSize) |
| 638 return FunctionError("size > maximum function size"); | 644 return FunctionError("size > maximum function size"); |
| 639 WasmFunction* function = new WasmFunction(); | 645 WasmFunction* function = new WasmFunction(); |
| 640 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin); | 646 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin); |
| 641 return decoder.DecodeSingleFunction(module_env, function); | 647 return decoder.DecodeSingleFunction(module_env, function); |
| 642 } | 648 } |
| 643 } // namespace wasm | 649 } // namespace wasm |
| 644 } // namespace internal | 650 } // namespace internal |
| 645 } // namespace v8 | 651 } // namespace v8 |
| OLD | NEW |