| 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/signature.h" | 5 #include "src/signature.h" |
| 6 | 6 |
| 7 #include "src/bit-vector.h" | 7 #include "src/bit-vector.h" |
| 8 #include "src/flags.h" | 8 #include "src/flags.h" |
| 9 #include "src/handles.h" | 9 #include "src/handles.h" |
| 10 #include "src/zone/zone-containers.h" | 10 #include "src/zone/zone-containers.h" |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 | 162 |
| 163 // Generic Wasm bytecode decoder with utilities for decoding operands, | 163 // Generic Wasm bytecode decoder with utilities for decoding operands, |
| 164 // lengths, etc. | 164 // lengths, etc. |
| 165 class WasmDecoder : public Decoder { | 165 class WasmDecoder : public Decoder { |
| 166 public: | 166 public: |
| 167 WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start, | 167 WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start, |
| 168 const byte* end) | 168 const byte* end) |
| 169 : Decoder(start, end), | 169 : Decoder(start, end), |
| 170 module_(module), | 170 module_(module), |
| 171 sig_(sig), | 171 sig_(sig), |
| 172 total_locals_(0), | |
| 173 local_types_(nullptr) {} | 172 local_types_(nullptr) {} |
| 174 const WasmModule* module_; | 173 const WasmModule* module_; |
| 175 FunctionSig* sig_; | 174 FunctionSig* sig_; |
| 176 size_t total_locals_; | 175 |
| 177 ZoneVector<ValueType>* local_types_; | 176 ZoneVector<ValueType>* local_types_; |
| 178 | 177 |
| 178 size_t total_locals() const { |
| 179 return local_types_ == nullptr ? 0 : local_types_->size(); |
| 180 } |
| 181 |
| 182 static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig, |
| 183 ZoneVector<ValueType>* type_list) { |
| 184 DCHECK_NOT_NULL(type_list); |
| 185 // Initialize from signature. |
| 186 if (sig != nullptr) { |
| 187 type_list->reserve(sig->parameter_count()); |
| 188 for (size_t i = 0; i < sig->parameter_count(); ++i) { |
| 189 type_list->push_back(sig->GetParam(i)); |
| 190 } |
| 191 } |
| 192 // Decode local declarations, if any. |
| 193 uint32_t entries = decoder->consume_u32v("local decls count"); |
| 194 if (decoder->failed()) return false; |
| 195 |
| 196 TRACE("local decls count: %u\n", entries); |
| 197 while (entries-- > 0 && decoder->ok() && decoder->more()) { |
| 198 uint32_t count = decoder->consume_u32v("local count"); |
| 199 if (decoder->failed()) return false; |
| 200 |
| 201 if ((count + type_list->size()) > kMaxNumWasmLocals) { |
| 202 decoder->error(decoder->pc() - 1, "local count too large"); |
| 203 return false; |
| 204 } |
| 205 byte code = decoder->consume_u8("local type"); |
| 206 if (decoder->failed()) return false; |
| 207 |
| 208 ValueType type; |
| 209 switch (code) { |
| 210 case kLocalI32: |
| 211 type = kWasmI32; |
| 212 break; |
| 213 case kLocalI64: |
| 214 type = kWasmI64; |
| 215 break; |
| 216 case kLocalF32: |
| 217 type = kWasmF32; |
| 218 break; |
| 219 case kLocalF64: |
| 220 type = kWasmF64; |
| 221 break; |
| 222 case kLocalS128: |
| 223 type = kWasmS128; |
| 224 break; |
| 225 default: |
| 226 decoder->error(decoder->pc() - 1, "invalid local type"); |
| 227 return false; |
| 228 } |
| 229 type_list->insert(type_list->end(), count, type); |
| 230 } |
| 231 DCHECK(decoder->ok()); |
| 232 return true; |
| 233 } |
| 234 |
| 235 static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc, |
| 236 int locals_count, Zone* zone) { |
| 237 if (pc >= decoder->end()) return nullptr; |
| 238 if (*pc != kExprLoop) return nullptr; |
| 239 |
| 240 BitVector* assigned = new (zone) BitVector(locals_count, zone); |
| 241 int depth = 0; |
| 242 // Iteratively process all AST nodes nested inside the loop. |
| 243 while (pc < decoder->end() && decoder->ok()) { |
| 244 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); |
| 245 unsigned length = 1; |
| 246 switch (opcode) { |
| 247 case kExprLoop: |
| 248 case kExprIf: |
| 249 case kExprBlock: |
| 250 case kExprTry: |
| 251 length = OpcodeLength(decoder, pc); |
| 252 depth++; |
| 253 break; |
| 254 case kExprSetLocal: // fallthru |
| 255 case kExprTeeLocal: { |
| 256 LocalIndexOperand operand(decoder, pc); |
| 257 if (assigned->length() > 0 && |
| 258 operand.index < static_cast<uint32_t>(assigned->length())) { |
| 259 // Unverified code might have an out-of-bounds index. |
| 260 assigned->Add(operand.index); |
| 261 } |
| 262 length = 1 + operand.length; |
| 263 break; |
| 264 } |
| 265 case kExprEnd: |
| 266 depth--; |
| 267 break; |
| 268 default: |
| 269 length = OpcodeLength(decoder, pc); |
| 270 break; |
| 271 } |
| 272 if (depth <= 0) break; |
| 273 pc += length; |
| 274 } |
| 275 return decoder->ok() ? assigned : nullptr; |
| 276 } |
| 277 |
| 179 inline bool Validate(const byte* pc, LocalIndexOperand& operand) { | 278 inline bool Validate(const byte* pc, LocalIndexOperand& operand) { |
| 180 if (operand.index < total_locals_) { | 279 if (operand.index < total_locals()) { |
| 181 if (local_types_) { | 280 if (local_types_) { |
| 182 operand.type = local_types_->at(operand.index); | 281 operand.type = local_types_->at(operand.index); |
| 183 } else { | 282 } else { |
| 184 operand.type = kWasmStmt; | 283 operand.type = kWasmStmt; |
| 185 } | 284 } |
| 186 return true; | 285 return true; |
| 187 } | 286 } |
| 188 error(pc, pc + 1, "invalid local index: %u", operand.index); | 287 error(pc, pc + 1, "invalid local index: %u", operand.index); |
| 189 return false; | 288 return false; |
| 190 } | 289 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 | 352 |
| 254 inline bool Validate(const byte* pc, LaneOperand& operand) { | 353 inline bool Validate(const byte* pc, LaneOperand& operand) { |
| 255 if (operand.lane < 0 || operand.lane > 3) { | 354 if (operand.lane < 0 || operand.lane > 3) { |
| 256 error(pc_, pc_ + 2, "invalid extract lane value"); | 355 error(pc_, pc_ + 2, "invalid extract lane value"); |
| 257 return false; | 356 return false; |
| 258 } else { | 357 } else { |
| 259 return true; | 358 return true; |
| 260 } | 359 } |
| 261 } | 360 } |
| 262 | 361 |
| 263 unsigned OpcodeLength(const byte* pc) { | 362 static unsigned OpcodeLength(Decoder* decoder, const byte* pc) { |
| 264 switch (static_cast<byte>(*pc)) { | 363 switch (static_cast<byte>(*pc)) { |
| 265 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: | 364 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: |
| 266 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) | 365 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) |
| 267 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) | 366 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) |
| 268 #undef DECLARE_OPCODE_CASE | 367 #undef DECLARE_OPCODE_CASE |
| 269 { | 368 { |
| 270 MemoryAccessOperand operand(this, pc, UINT32_MAX); | 369 MemoryAccessOperand operand(decoder, pc, UINT32_MAX); |
| 271 return 1 + operand.length; | 370 return 1 + operand.length; |
| 272 } | 371 } |
| 273 case kExprBr: | 372 case kExprBr: |
| 274 case kExprBrIf: { | 373 case kExprBrIf: { |
| 275 BreakDepthOperand operand(this, pc); | 374 BreakDepthOperand operand(decoder, pc); |
| 276 return 1 + operand.length; | 375 return 1 + operand.length; |
| 277 } | 376 } |
| 278 case kExprSetGlobal: | 377 case kExprSetGlobal: |
| 279 case kExprGetGlobal: { | 378 case kExprGetGlobal: { |
| 280 GlobalIndexOperand operand(this, pc); | 379 GlobalIndexOperand operand(decoder, pc); |
| 281 return 1 + operand.length; | 380 return 1 + operand.length; |
| 282 } | 381 } |
| 283 | 382 |
| 284 case kExprCallFunction: { | 383 case kExprCallFunction: { |
| 285 CallFunctionOperand operand(this, pc); | 384 CallFunctionOperand operand(decoder, pc); |
| 286 return 1 + operand.length; | 385 return 1 + operand.length; |
| 287 } | 386 } |
| 288 case kExprCallIndirect: { | 387 case kExprCallIndirect: { |
| 289 CallIndirectOperand operand(this, pc); | 388 CallIndirectOperand operand(decoder, pc); |
| 290 return 1 + operand.length; | 389 return 1 + operand.length; |
| 291 } | 390 } |
| 292 | 391 |
| 293 case kExprTry: | 392 case kExprTry: |
| 294 case kExprIf: // fall thru | 393 case kExprIf: // fall thru |
| 295 case kExprLoop: | 394 case kExprLoop: |
| 296 case kExprBlock: { | 395 case kExprBlock: { |
| 297 BlockTypeOperand operand(this, pc); | 396 BlockTypeOperand operand(decoder, pc); |
| 298 return 1 + operand.length; | 397 return 1 + operand.length; |
| 299 } | 398 } |
| 300 | 399 |
| 301 case kExprSetLocal: | 400 case kExprSetLocal: |
| 302 case kExprTeeLocal: | 401 case kExprTeeLocal: |
| 303 case kExprGetLocal: | 402 case kExprGetLocal: |
| 304 case kExprCatch: { | 403 case kExprCatch: { |
| 305 LocalIndexOperand operand(this, pc); | 404 LocalIndexOperand operand(decoder, pc); |
| 306 return 1 + operand.length; | 405 return 1 + operand.length; |
| 307 } | 406 } |
| 308 case kExprBrTable: { | 407 case kExprBrTable: { |
| 309 BranchTableOperand operand(this, pc); | 408 BranchTableOperand operand(decoder, pc); |
| 310 BranchTableIterator iterator(this, operand); | 409 BranchTableIterator iterator(decoder, operand); |
| 311 return 1 + iterator.length(); | 410 return 1 + iterator.length(); |
| 312 } | 411 } |
| 313 case kExprI32Const: { | 412 case kExprI32Const: { |
| 314 ImmI32Operand operand(this, pc); | 413 ImmI32Operand operand(decoder, pc); |
| 315 return 1 + operand.length; | 414 return 1 + operand.length; |
| 316 } | 415 } |
| 317 case kExprI64Const: { | 416 case kExprI64Const: { |
| 318 ImmI64Operand operand(this, pc); | 417 ImmI64Operand operand(decoder, pc); |
| 319 return 1 + operand.length; | 418 return 1 + operand.length; |
| 320 } | 419 } |
| 321 case kExprGrowMemory: | 420 case kExprGrowMemory: |
| 322 case kExprMemorySize: { | 421 case kExprMemorySize: { |
| 323 MemoryIndexOperand operand(this, pc); | 422 MemoryIndexOperand operand(decoder, pc); |
| 324 return 1 + operand.length; | 423 return 1 + operand.length; |
| 325 } | 424 } |
| 326 case kExprI8Const: | 425 case kExprI8Const: |
| 327 return 2; | 426 return 2; |
| 328 case kExprF32Const: | 427 case kExprF32Const: |
| 329 return 5; | 428 return 5; |
| 330 case kExprF64Const: | 429 case kExprF64Const: |
| 331 return 9; | 430 return 9; |
| 332 case kSimdPrefix: { | 431 case kSimdPrefix: { |
| 333 byte simd_index = checked_read_u8(pc, 1, "simd_index"); | 432 byte simd_index = decoder->checked_read_u8(pc, 1, "simd_index"); |
| 334 WasmOpcode opcode = | 433 WasmOpcode opcode = |
| 335 static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index); | 434 static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index); |
| 336 switch (opcode) { | 435 switch (opcode) { |
| 337 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: | 436 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: |
| 338 FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE) | 437 FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE) |
| 339 #undef DECLARE_OPCODE_CASE | 438 #undef DECLARE_OPCODE_CASE |
| 340 { | 439 { |
| 341 return 2; | 440 return 2; |
| 342 } | 441 } |
| 343 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: | 442 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: |
| 344 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) | 443 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) |
| 345 #undef DECLARE_OPCODE_CASE | 444 #undef DECLARE_OPCODE_CASE |
| 346 { | 445 { |
| 347 return 3; | 446 return 3; |
| 348 } | 447 } |
| 349 default: | 448 default: |
| 350 error("invalid SIMD opcode"); | 449 decoder->error(pc, "invalid SIMD opcode"); |
| 351 return 2; | 450 return 2; |
| 352 } | 451 } |
| 353 } | 452 } |
| 354 default: | 453 default: |
| 355 return 1; | 454 return 1; |
| 356 } | 455 } |
| 357 } | 456 } |
| 358 }; | 457 }; |
| 359 | 458 |
| 360 static const int32_t kNullCatch = -1; | 459 static const int32_t kNullCatch = -1; |
| 361 | 460 |
| 362 // The full WASM decoder for bytecode. Verifies bytecode and, optionally, | 461 // The full WASM decoder for bytecode. Verifies bytecode and, optionally, |
| 363 // generates a TurboFan IR graph. | 462 // generates a TurboFan IR graph. |
| 364 class WasmFullDecoder : public WasmDecoder { | 463 class WasmFullDecoder : public WasmDecoder { |
| 365 public: | 464 public: |
| 366 WasmFullDecoder(Zone* zone, const FunctionBody& body) | |
| 367 : WasmFullDecoder(zone, nullptr, nullptr, body) {} | |
| 368 | |
| 369 WasmFullDecoder(Zone* zone, const wasm::WasmModule* module, | 465 WasmFullDecoder(Zone* zone, const wasm::WasmModule* module, |
| 370 const FunctionBody& body) | 466 const FunctionBody& body) |
| 371 : WasmFullDecoder(zone, module, nullptr, body) {} | 467 : WasmFullDecoder(zone, module, nullptr, body) {} |
| 372 | 468 |
| 373 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) | 469 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) |
| 374 : WasmFullDecoder(zone, builder->module_env() == nullptr | 470 : WasmFullDecoder(zone, builder->module_env() == nullptr |
| 375 ? nullptr | 471 ? nullptr |
| 376 : builder->module_env()->module, | 472 : builder->module_env()->module, |
| 377 builder, body) {} | 473 builder, body) {} |
| 378 | 474 |
| 379 bool Decode() { | 475 bool Decode() { |
| 380 if (FLAG_wasm_code_fuzzer_gen_test) { | 476 if (FLAG_wasm_code_fuzzer_gen_test) { |
| 381 PrintWasmCodeForDebugging(start_, end_); | 477 PrintWasmCodeForDebugging(start_, end_); |
| 382 } | 478 } |
| 383 base::ElapsedTimer decode_timer; | 479 base::ElapsedTimer decode_timer; |
| 384 if (FLAG_trace_wasm_decode_time) { | 480 if (FLAG_trace_wasm_decode_time) { |
| 385 decode_timer.Start(); | 481 decode_timer.Start(); |
| 386 } | 482 } |
| 387 stack_.clear(); | 483 stack_.clear(); |
| 388 control_.clear(); | 484 control_.clear(); |
| 389 | 485 |
| 390 if (end_ < pc_) { | 486 if (end_ < pc_) { |
| 391 error("function body end < start"); | 487 error("function body end < start"); |
| 392 return false; | 488 return false; |
| 393 } | 489 } |
| 394 | 490 |
| 395 DecodeLocalDecls(); | 491 DCHECK_EQ(0, local_types_->size()); |
| 492 WasmDecoder::DecodeLocals(this, sig_, local_types_); |
| 396 InitSsaEnv(); | 493 InitSsaEnv(); |
| 397 DecodeFunctionBody(); | 494 DecodeFunctionBody(); |
| 398 | 495 |
| 399 if (failed()) return TraceFailed(); | 496 if (failed()) return TraceFailed(); |
| 400 | 497 |
| 401 #if IMPLICIT_FUNCTION_END | 498 #if IMPLICIT_FUNCTION_END |
| 402 // With implicit end support (old style), the function block | 499 // With implicit end support (old style), the function block |
| 403 // remains on the stack. Other control blocks are an error. | 500 // remains on the stack. Other control blocks are an error. |
| 404 if (control_.size() > 1) { | 501 if (control_.size() > 1) { |
| 405 error(pc_, control_.back().pc, "unterminated control structure"); | 502 error(pc_, control_.back().pc, "unterminated control structure"); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 | 548 |
| 452 return true; | 549 return true; |
| 453 } | 550 } |
| 454 | 551 |
| 455 bool TraceFailed() { | 552 bool TraceFailed() { |
| 456 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_), | 553 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_), |
| 457 startrel(error_pc_), error_msg_.get()); | 554 startrel(error_pc_), error_msg_.get()); |
| 458 return false; | 555 return false; |
| 459 } | 556 } |
| 460 | 557 |
| 461 bool DecodeLocalDecls(BodyLocalDecls& decls) { | |
| 462 DecodeLocalDecls(); | |
| 463 if (failed()) return false; | |
| 464 decls.decls_encoded_size = pc_offset(); | |
| 465 decls.local_types.reserve(local_type_vec_.size()); | |
| 466 for (size_t pos = 0; pos < local_type_vec_.size();) { | |
| 467 uint32_t count = 0; | |
| 468 ValueType type = local_type_vec_[pos]; | |
| 469 while (pos < local_type_vec_.size() && local_type_vec_[pos] == type) { | |
| 470 pos++; | |
| 471 count++; | |
| 472 } | |
| 473 decls.local_types.push_back(std::pair<ValueType, uint32_t>(type, count)); | |
| 474 } | |
| 475 decls.total_local_count = static_cast<uint32_t>(local_type_vec_.size()); | |
| 476 return true; | |
| 477 } | |
| 478 | |
| 479 BitVector* AnalyzeLoopAssignmentForTesting(const byte* pc, | |
| 480 size_t num_locals) { | |
| 481 total_locals_ = num_locals; | |
| 482 local_type_vec_.reserve(num_locals); | |
| 483 if (num_locals > local_type_vec_.size()) { | |
| 484 local_type_vec_.insert(local_type_vec_.end(), | |
| 485 num_locals - local_type_vec_.size(), kWasmI32); | |
| 486 } | |
| 487 return AnalyzeLoopAssignment(pc); | |
| 488 } | |
| 489 | |
| 490 private: | 558 private: |
| 491 WasmFullDecoder(Zone* zone, const wasm::WasmModule* module, | 559 WasmFullDecoder(Zone* zone, const wasm::WasmModule* module, |
| 492 TFBuilder* builder, const FunctionBody& body) | 560 TFBuilder* builder, const FunctionBody& body) |
| 493 : WasmDecoder(module, body.sig, body.start, body.end), | 561 : WasmDecoder(module, body.sig, body.start, body.end), |
| 494 zone_(zone), | 562 zone_(zone), |
| 495 builder_(builder), | 563 builder_(builder), |
| 496 base_(body.base), | 564 base_(body.base), |
| 497 local_type_vec_(zone), | 565 local_type_vec_(zone), |
| 498 stack_(zone), | 566 stack_(zone), |
| 499 control_(zone), | 567 control_(zone), |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 static const int kMaxIndent = 64; | 645 static const int kMaxIndent = 64; |
| 578 static char bytes[kMaxIndent + 1]; | 646 static char bytes[kMaxIndent + 1]; |
| 579 for (int i = 0; i < kMaxIndent; ++i) bytes[i] = ' '; | 647 for (int i = 0; i < kMaxIndent; ++i) bytes[i] = ' '; |
| 580 bytes[kMaxIndent] = 0; | 648 bytes[kMaxIndent] = 0; |
| 581 if (stack_.size() < kMaxIndent / 2) { | 649 if (stack_.size() < kMaxIndent / 2) { |
| 582 bytes[stack_.size() * 2] = 0; | 650 bytes[stack_.size() * 2] = 0; |
| 583 } | 651 } |
| 584 return bytes; | 652 return bytes; |
| 585 } | 653 } |
| 586 | 654 |
| 587 // Decodes the locals declarations, if any, populating {local_type_vec_}. | |
| 588 void DecodeLocalDecls() { | |
| 589 DCHECK_EQ(0, local_type_vec_.size()); | |
| 590 // Initialize {local_type_vec} from signature. | |
| 591 if (sig_) { | |
| 592 local_type_vec_.reserve(sig_->parameter_count()); | |
| 593 for (size_t i = 0; i < sig_->parameter_count(); ++i) { | |
| 594 local_type_vec_.push_back(sig_->GetParam(i)); | |
| 595 } | |
| 596 } | |
| 597 // Decode local declarations, if any. | |
| 598 uint32_t entries = consume_u32v("local decls count"); | |
| 599 TRACE("local decls count: %u\n", entries); | |
| 600 while (entries-- > 0 && pc_ < end_) { | |
| 601 uint32_t count = consume_u32v("local count"); | |
| 602 if ((count + local_type_vec_.size()) > kMaxNumWasmLocals) { | |
| 603 error(pc_ - 1, "local count too large"); | |
| 604 return; | |
| 605 } | |
| 606 byte code = consume_u8("local type"); | |
| 607 ValueType type; | |
| 608 switch (code) { | |
| 609 case kLocalI32: | |
| 610 type = kWasmI32; | |
| 611 break; | |
| 612 case kLocalI64: | |
| 613 type = kWasmI64; | |
| 614 break; | |
| 615 case kLocalF32: | |
| 616 type = kWasmF32; | |
| 617 break; | |
| 618 case kLocalF64: | |
| 619 type = kWasmF64; | |
| 620 break; | |
| 621 case kLocalS128: | |
| 622 type = kWasmS128; | |
| 623 break; | |
| 624 default: | |
| 625 error(pc_ - 1, "invalid local type"); | |
| 626 return; | |
| 627 } | |
| 628 local_type_vec_.insert(local_type_vec_.end(), count, type); | |
| 629 } | |
| 630 total_locals_ = local_type_vec_.size(); | |
| 631 } | |
| 632 | |
| 633 // Decodes the body of a function. | 655 // Decodes the body of a function. |
| 634 void DecodeFunctionBody() { | 656 void DecodeFunctionBody() { |
| 635 TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n", | 657 TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n", |
| 636 reinterpret_cast<const void*>(start_), | 658 reinterpret_cast<const void*>(start_), |
| 637 reinterpret_cast<const void*>(end_), baserel(pc_), | 659 reinterpret_cast<const void*>(end_), baserel(pc_), |
| 638 static_cast<int>(end_ - start_), builder_ ? "graph building" : ""); | 660 static_cast<int>(end_ - start_), builder_ ? "graph building" : ""); |
| 639 | 661 |
| 640 { | 662 { |
| 641 // Set up initial function block. | 663 // Set up initial function block. |
| 642 SsaEnv* break_env = ssa_env_; | 664 SsaEnv* break_env = ssa_env_; |
| (...skipping 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1737 | 1759 |
| 1738 SsaEnv* PrepareForLoop(const byte* pc, SsaEnv* env) { | 1760 SsaEnv* PrepareForLoop(const byte* pc, SsaEnv* env) { |
| 1739 if (!builder_) return Split(env); | 1761 if (!builder_) return Split(env); |
| 1740 if (!env->go()) return Split(env); | 1762 if (!env->go()) return Split(env); |
| 1741 env->state = SsaEnv::kMerged; | 1763 env->state = SsaEnv::kMerged; |
| 1742 | 1764 |
| 1743 env->control = builder_->Loop(env->control); | 1765 env->control = builder_->Loop(env->control); |
| 1744 env->effect = builder_->EffectPhi(1, &env->effect, env->control); | 1766 env->effect = builder_->EffectPhi(1, &env->effect, env->control); |
| 1745 builder_->Terminate(env->effect, env->control); | 1767 builder_->Terminate(env->effect, env->control); |
| 1746 if (FLAG_wasm_loop_assignment_analysis) { | 1768 if (FLAG_wasm_loop_assignment_analysis) { |
| 1747 BitVector* assigned = AnalyzeLoopAssignment(pc); | 1769 BitVector* assigned = AnalyzeLoopAssignment( |
| 1770 this, pc, static_cast<int>(total_locals()), zone_); |
| 1748 if (failed()) return env; | 1771 if (failed()) return env; |
| 1749 if (assigned != nullptr) { | 1772 if (assigned != nullptr) { |
| 1750 // Only introduce phis for variables assigned in this loop. | 1773 // Only introduce phis for variables assigned in this loop. |
| 1751 for (int i = EnvironmentCount() - 1; i >= 0; i--) { | 1774 for (int i = EnvironmentCount() - 1; i >= 0; i--) { |
| 1752 if (!assigned->Contains(i)) continue; | 1775 if (!assigned->Contains(i)) continue; |
| 1753 env->locals[i] = builder_->Phi(local_type_vec_[i], 1, &env->locals[i], | 1776 env->locals[i] = builder_->Phi(local_type_vec_[i], 1, &env->locals[i], |
| 1754 env->control); | 1777 env->control); |
| 1755 } | 1778 } |
| 1756 SsaEnv* loop_body_env = Split(env); | 1779 SsaEnv* loop_body_env = Split(env); |
| 1757 builder_->StackCheck(position(), &(loop_body_env->effect), | 1780 builder_->StackCheck(position(), &(loop_body_env->effect), |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1820 int EnvironmentCount() { | 1843 int EnvironmentCount() { |
| 1821 if (builder_) return static_cast<int>(local_type_vec_.size()); | 1844 if (builder_) return static_cast<int>(local_type_vec_.size()); |
| 1822 return 0; // if we aren't building a graph, don't bother with SSA renaming. | 1845 return 0; // if we aren't building a graph, don't bother with SSA renaming. |
| 1823 } | 1846 } |
| 1824 | 1847 |
| 1825 virtual void onFirstError() { | 1848 virtual void onFirstError() { |
| 1826 end_ = start_; // Terminate decoding loop. | 1849 end_ = start_; // Terminate decoding loop. |
| 1827 builder_ = nullptr; // Don't build any more nodes. | 1850 builder_ = nullptr; // Don't build any more nodes. |
| 1828 TRACE(" !%s\n", error_msg_.get()); | 1851 TRACE(" !%s\n", error_msg_.get()); |
| 1829 } | 1852 } |
| 1830 BitVector* AnalyzeLoopAssignment(const byte* pc) { | |
| 1831 if (pc >= end_) return nullptr; | |
| 1832 if (*pc != kExprLoop) return nullptr; | |
| 1833 | |
| 1834 BitVector* assigned = | |
| 1835 new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_); | |
| 1836 int depth = 0; | |
| 1837 // Iteratively process all AST nodes nested inside the loop. | |
| 1838 while (pc < end_ && ok()) { | |
| 1839 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); | |
| 1840 unsigned length = 1; | |
| 1841 switch (opcode) { | |
| 1842 case kExprLoop: | |
| 1843 case kExprIf: | |
| 1844 case kExprBlock: | |
| 1845 case kExprTry: | |
| 1846 length = OpcodeLength(pc); | |
| 1847 depth++; | |
| 1848 break; | |
| 1849 case kExprSetLocal: // fallthru | |
| 1850 case kExprTeeLocal: { | |
| 1851 LocalIndexOperand operand(this, pc); | |
| 1852 if (assigned->length() > 0 && | |
| 1853 operand.index < static_cast<uint32_t>(assigned->length())) { | |
| 1854 // Unverified code might have an out-of-bounds index. | |
| 1855 assigned->Add(operand.index); | |
| 1856 } | |
| 1857 length = 1 + operand.length; | |
| 1858 break; | |
| 1859 } | |
| 1860 case kExprEnd: | |
| 1861 depth--; | |
| 1862 break; | |
| 1863 default: | |
| 1864 length = OpcodeLength(pc); | |
| 1865 break; | |
| 1866 } | |
| 1867 if (depth <= 0) break; | |
| 1868 pc += length; | |
| 1869 } | |
| 1870 return ok() ? assigned : nullptr; | |
| 1871 } | |
| 1872 | 1853 |
| 1873 inline wasm::WasmCodePosition position() { | 1854 inline wasm::WasmCodePosition position() { |
| 1874 int offset = static_cast<int>(pc_ - start_); | 1855 int offset = static_cast<int>(pc_ - start_); |
| 1875 DCHECK_EQ(pc_ - start_, offset); // overflows cannot happen | 1856 DCHECK_EQ(pc_ - start_, offset); // overflows cannot happen |
| 1876 return offset; | 1857 return offset; |
| 1877 } | 1858 } |
| 1878 | 1859 |
| 1879 inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) { | 1860 inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) { |
| 1880 TFNode* node; | 1861 TFNode* node; |
| 1881 switch (sig->parameter_count()) { | 1862 switch (sig->parameter_count()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1892 } | 1873 } |
| 1893 default: | 1874 default: |
| 1894 UNREACHABLE(); | 1875 UNREACHABLE(); |
| 1895 node = nullptr; | 1876 node = nullptr; |
| 1896 break; | 1877 break; |
| 1897 } | 1878 } |
| 1898 Push(GetReturnType(sig), node); | 1879 Push(GetReturnType(sig), node); |
| 1899 } | 1880 } |
| 1900 }; | 1881 }; |
| 1901 | 1882 |
| 1902 bool DecodeLocalDecls(BodyLocalDecls& decls, const byte* start, | 1883 bool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start, |
| 1903 const byte* end) { | 1884 const byte* end) { |
| 1904 AccountingAllocator allocator; | 1885 Decoder decoder(start, end); |
| 1905 Zone tmp(&allocator, ZONE_NAME); | 1886 if (WasmDecoder::DecodeLocals(&decoder, nullptr, &decls->type_list)) { |
| 1906 FunctionBody body = {nullptr, nullptr, start, end}; | 1887 DCHECK(decoder.ok()); |
| 1907 WasmFullDecoder decoder(&tmp, body); | 1888 decls->encoded_size = decoder.pc_offset(); |
| 1908 return decoder.DecodeLocalDecls(decls); | 1889 return true; |
| 1890 } |
| 1891 return false; |
| 1909 } | 1892 } |
| 1910 | 1893 |
| 1911 BytecodeIterator::BytecodeIterator(const byte* start, const byte* end, | 1894 BytecodeIterator::BytecodeIterator(const byte* start, const byte* end, |
| 1912 BodyLocalDecls* decls) | 1895 BodyLocalDecls* decls) |
| 1913 : Decoder(start, end) { | 1896 : Decoder(start, end) { |
| 1914 if (decls != nullptr) { | 1897 if (decls != nullptr) { |
| 1915 if (DecodeLocalDecls(*decls, start, end)) { | 1898 if (DecodeLocalDecls(decls, start, end)) { |
| 1916 pc_ += decls->decls_encoded_size; | 1899 pc_ += decls->encoded_size; |
| 1917 if (pc_ > end_) pc_ = end_; | 1900 if (pc_ > end_) pc_ = end_; |
| 1918 } | 1901 } |
| 1919 } | 1902 } |
| 1920 } | 1903 } |
| 1921 | 1904 |
| 1922 DecodeResult VerifyWasmCode(AccountingAllocator* allocator, | 1905 DecodeResult VerifyWasmCode(AccountingAllocator* allocator, |
| 1923 const wasm::WasmModule* module, | 1906 const wasm::WasmModule* module, |
| 1924 FunctionBody& body) { | 1907 FunctionBody& body) { |
| 1925 Zone zone(allocator, ZONE_NAME); | 1908 Zone zone(allocator, ZONE_NAME); |
| 1926 WasmFullDecoder decoder(&zone, module, body); | 1909 WasmFullDecoder decoder(&zone, module, body); |
| 1927 decoder.Decode(); | 1910 decoder.Decode(); |
| 1928 return decoder.toResult<DecodeStruct*>(nullptr); | 1911 return decoder.toResult<DecodeStruct*>(nullptr); |
| 1929 } | 1912 } |
| 1930 | 1913 |
| 1931 DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder, | 1914 DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder, |
| 1932 FunctionBody& body) { | 1915 FunctionBody& body) { |
| 1933 Zone zone(allocator, ZONE_NAME); | 1916 Zone zone(allocator, ZONE_NAME); |
| 1934 WasmFullDecoder decoder(&zone, builder, body); | 1917 WasmFullDecoder decoder(&zone, builder, body); |
| 1935 decoder.Decode(); | 1918 decoder.Decode(); |
| 1936 return decoder.toResult<DecodeStruct*>(nullptr); | 1919 return decoder.toResult<DecodeStruct*>(nullptr); |
| 1937 } | 1920 } |
| 1938 | 1921 |
| 1939 unsigned OpcodeLength(const byte* pc, const byte* end) { | 1922 unsigned OpcodeLength(const byte* pc, const byte* end) { |
| 1940 WasmDecoder decoder(nullptr, nullptr, pc, end); | 1923 Decoder decoder(pc, end); |
| 1941 return decoder.OpcodeLength(pc); | 1924 return WasmDecoder::OpcodeLength(&decoder, pc); |
| 1942 } | 1925 } |
| 1943 | 1926 |
| 1944 void PrintWasmCodeForDebugging(const byte* start, const byte* end) { | 1927 void PrintWasmCodeForDebugging(const byte* start, const byte* end) { |
| 1945 AccountingAllocator allocator; | 1928 AccountingAllocator allocator; |
| 1946 OFStream os(stdout); | 1929 OFStream os(stdout); |
| 1947 PrintWasmCode(&allocator, FunctionBodyForTesting(start, end), nullptr, os, | 1930 PrintWasmCode(&allocator, FunctionBodyForTesting(start, end), nullptr, os, |
| 1948 nullptr); | 1931 nullptr); |
| 1949 } | 1932 } |
| 1950 | 1933 |
| 1951 bool PrintWasmCode(AccountingAllocator* allocator, const FunctionBody& body, | 1934 bool PrintWasmCode(AccountingAllocator* allocator, const FunctionBody& body, |
| 1952 const wasm::WasmModule* module, std::ostream& os, | 1935 const wasm::WasmModule* module, std::ostream& os, |
| 1953 std::vector<std::tuple<uint32_t, int, int>>* offset_table) { | 1936 std::vector<std::tuple<uint32_t, int, int>>* offset_table) { |
| 1954 Zone zone(allocator, ZONE_NAME); | 1937 Zone zone(allocator, ZONE_NAME); |
| 1955 WasmFullDecoder decoder(&zone, module, body); | 1938 WasmFullDecoder decoder(&zone, module, body); |
| 1956 int line_nr = 0; | 1939 int line_nr = 0; |
| 1957 | 1940 |
| 1958 // Print the function signature. | 1941 // Print the function signature. |
| 1959 if (body.sig) { | 1942 if (body.sig) { |
| 1960 os << "// signature: " << *body.sig << std::endl; | 1943 os << "// signature: " << *body.sig << std::endl; |
| 1961 ++line_nr; | 1944 ++line_nr; |
| 1962 } | 1945 } |
| 1963 | 1946 |
| 1964 // Print the local declarations. | 1947 // Print the local declarations. |
| 1965 BodyLocalDecls decls(&zone); | 1948 BodyLocalDecls decls(&zone); |
| 1966 BytecodeIterator i(body.start, body.end, &decls); | 1949 BytecodeIterator i(body.start, body.end, &decls); |
| 1967 if (body.start != i.pc() && !FLAG_wasm_code_fuzzer_gen_test) { | 1950 if (body.start != i.pc() && !FLAG_wasm_code_fuzzer_gen_test) { |
| 1968 os << "// locals: "; | 1951 os << "// locals: "; |
| 1969 for (auto p : decls.local_types) { | 1952 if (!decls.type_list.empty()) { |
| 1970 ValueType type = p.first; | 1953 ValueType type = decls.type_list[0]; |
| 1971 uint32_t count = p.second; | 1954 uint32_t count = 0; |
| 1972 os << " " << count << " " << WasmOpcodes::TypeName(type); | 1955 for (size_t pos = 0; pos < decls.type_list.size(); ++pos) { |
| 1956 if (decls.type_list[pos] == type) { |
| 1957 ++count; |
| 1958 } else { |
| 1959 os << " " << count << " " << WasmOpcodes::TypeName(type); |
| 1960 type = decls.type_list[pos]; |
| 1961 count = 1; |
| 1962 } |
| 1963 } |
| 1973 } | 1964 } |
| 1974 os << std::endl; | 1965 os << std::endl; |
| 1975 ++line_nr; | 1966 ++line_nr; |
| 1976 | 1967 |
| 1977 for (const byte* locals = body.start; locals < i.pc(); locals++) { | 1968 for (const byte* locals = body.start; locals < i.pc(); locals++) { |
| 1978 os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ","; | 1969 os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ","; |
| 1979 } | 1970 } |
| 1980 os << std::endl; | 1971 os << std::endl; |
| 1981 ++line_nr; | 1972 ++line_nr; |
| 1982 } | 1973 } |
| 1983 | 1974 |
| 1984 os << "// body: " << std::endl; | 1975 os << "// body: " << std::endl; |
| 1985 ++line_nr; | 1976 ++line_nr; |
| 1986 unsigned control_depth = 0; | 1977 unsigned control_depth = 0; |
| 1987 for (; i.has_next(); i.next()) { | 1978 for (; i.has_next(); i.next()) { |
| 1988 unsigned length = decoder.OpcodeLength(i.pc()); | 1979 unsigned length = WasmDecoder::OpcodeLength(&decoder, i.pc()); |
| 1989 | 1980 |
| 1990 WasmOpcode opcode = i.current(); | 1981 WasmOpcode opcode = i.current(); |
| 1991 if (opcode == kExprElse) control_depth--; | 1982 if (opcode == kExprElse) control_depth--; |
| 1992 | 1983 |
| 1993 int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64; | 1984 int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64; |
| 1994 if (offset_table) { | 1985 if (offset_table) { |
| 1995 offset_table->push_back( | 1986 offset_table->push_back( |
| 1996 std::make_tuple(i.pc_offset(), line_nr, num_whitespaces)); | 1987 std::make_tuple(i.pc_offset(), line_nr, num_whitespaces)); |
| 1997 } | 1988 } |
| 1998 | 1989 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2063 } | 2054 } |
| 2064 os << std::endl; | 2055 os << std::endl; |
| 2065 ++line_nr; | 2056 ++line_nr; |
| 2066 } | 2057 } |
| 2067 | 2058 |
| 2068 return decoder.ok(); | 2059 return decoder.ok(); |
| 2069 } | 2060 } |
| 2070 | 2061 |
| 2071 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 2062 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 2072 const byte* start, const byte* end) { | 2063 const byte* start, const byte* end) { |
| 2073 FunctionBody body = {nullptr, nullptr, start, end}; | 2064 Decoder decoder(start, end); |
| 2074 WasmFullDecoder decoder(zone, body); | 2065 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, |
| 2075 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); | 2066 static_cast<int>(num_locals), zone); |
| 2076 } | 2067 } |
| 2077 | 2068 |
| 2078 } // namespace wasm | 2069 } // namespace wasm |
| 2079 } // namespace internal | 2070 } // namespace internal |
| 2080 } // namespace v8 | 2071 } // namespace v8 |
| OLD | NEW |