| 502 | //=========================================================================== |
| 503 | |
| 504 | VMFrame *VMFrameStack::PopFrame() |
| 505 | { |
| 506 | if (Blocks == NULL) |
| 507 | { |
| 508 | return NULL; |
| 509 | } |
| 510 | VMFrame *frame = Blocks->LastFrame; |
| 511 | if (frame == NULL) |
| 512 | { |
| 513 | return NULL; |
| 514 | } |
| 515 | auto Func = static_cast<VMScriptFunction *>(frame->Func); |
| 516 | if (Func->SpecialInits.Size()) |
| 517 | { |
| 518 | Func->DestroyExtra(frame->GetExtra()); |
| 519 | } |
| 520 | // Free any string registers this frame had. |
| 521 | FString *regs = frame->GetRegS(); |
| 522 | for (int i = frame->NumRegS; i != 0; --i) |
| 523 | { |
| 524 | (regs++)->~FString(); |
| 525 | } |
| 526 | VMFrame *parent = frame->ParentFrame; |
| 527 | if (parent == NULL) |
| 528 | { |
| 529 | // Popping the last frame off the stack. |
| 530 | if (Blocks != NULL) |
| 531 | { |
| 532 | assert(Blocks->NextBlock == NULL); |
| 533 | Blocks->LastFrame = NULL; |
| 534 | Blocks->InitFreeSpace(); |
| 535 | } |
| 536 | return NULL; |
| 537 | } |
| 538 | if ((VM_UBYTE *)parent < (VM_UBYTE *)Blocks || (VM_UBYTE *)parent >= (VM_UBYTE *)Blocks + Blocks->BlockSize) |
| 539 | { // Parent frame is in a different block, so move this one to the unused list. |
| 540 | BlockHeader *next = Blocks->NextBlock; |
| 541 | assert(next != NULL); |
| 542 | assert((VM_UBYTE *)parent >= (VM_UBYTE *)next && (VM_UBYTE *)parent < (VM_UBYTE *)next + next->BlockSize); |
| 543 | Blocks->NextBlock = UnusedBlocks; |
| 544 | UnusedBlocks = Blocks; |
| 545 | Blocks = next; |
| 546 | } |
| 547 | else |
| 548 | { |
| 549 | Blocks->LastFrame = parent; |
| 550 | Blocks->FreeSpace = (VM_UBYTE *)frame; |
| 551 | } |
| 552 | return parent; |
| 553 | } |
| 554 | |
| 555 | //=========================================================================== |
| 556 | // |
no test coverage detected