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 |