136 lines
3.1 KiB
C++
136 lines
3.1 KiB
C++
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
|
//
|
|
// Copyright (C) 2006-2015 AlliedModders LLC
|
|
//
|
|
// This file is part of SourcePawn. SourcePawn is free software: you can
|
|
// redistribute it and/or modify it under the terms of the GNU General Public
|
|
// License as published by the Free Software Foundation, either version 3 of
|
|
// the License, or (at your option) any later version.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along with
|
|
// SourcePawn. If not, see http://www.gnu.org/licenses/.
|
|
//
|
|
#ifndef _include_sourcepawn_vm_stack_frames_h_
|
|
#define _include_sourcepawn_vm_stack_frames_h_
|
|
|
|
#include <sp_vm_api.h>
|
|
#include <assert.h>
|
|
|
|
namespace sp {
|
|
|
|
using namespace SourcePawn;
|
|
|
|
class PluginContext;
|
|
class PluginRuntime;
|
|
|
|
// An ExitFrame represents the state of the most recent exit from VM state to
|
|
// the outside world. Because this transition is on a critical path, we declare
|
|
// exactly one ExitFrame and save/restore it in InvokeFrame(). Anytime we're in
|
|
// the VM, we are guaranteed to have an ExitFrame for each InvokeFrame().
|
|
class ExitFrame
|
|
{
|
|
public:
|
|
ExitFrame()
|
|
: exit_sp_(nullptr),
|
|
exit_native_(-1)
|
|
{}
|
|
|
|
public:
|
|
const intptr_t *exit_sp() const {
|
|
return exit_sp_;
|
|
}
|
|
bool has_exit_native() const {
|
|
return exit_native_ != -1;
|
|
}
|
|
uint32_t exit_native() const {
|
|
assert(has_exit_native());
|
|
return exit_native_;
|
|
}
|
|
|
|
public:
|
|
static inline size_t offsetOfExitSp() {
|
|
return offsetof(ExitFrame, exit_sp_);
|
|
}
|
|
static inline size_t offsetOfExitNative() {
|
|
return offsetof(ExitFrame, exit_native_);
|
|
}
|
|
|
|
private:
|
|
const intptr_t *exit_sp_;
|
|
int exit_native_;
|
|
};
|
|
|
|
// An InvokeFrame represents one activation of Execute2().
|
|
class InvokeFrame
|
|
{
|
|
public:
|
|
InvokeFrame(PluginContext *cx, ucell_t cip);
|
|
~InvokeFrame();
|
|
|
|
InvokeFrame *prev() const {
|
|
return prev_;
|
|
}
|
|
PluginContext *cx() const {
|
|
return cx_;
|
|
}
|
|
|
|
const ExitFrame &prev_exit_frame() const {
|
|
return prev_exit_frame_;
|
|
}
|
|
const intptr_t *entry_sp() const {
|
|
return entry_sp_;
|
|
}
|
|
ucell_t entry_cip() const {
|
|
return entry_cip_;
|
|
}
|
|
|
|
public:
|
|
static inline size_t offsetOfEntrySp() {
|
|
return offsetof(InvokeFrame, entry_sp_);
|
|
}
|
|
|
|
private:
|
|
InvokeFrame *prev_;
|
|
PluginContext *cx_;
|
|
ExitFrame prev_exit_frame_;
|
|
ucell_t entry_cip_;
|
|
const intptr_t *entry_sp_;
|
|
};
|
|
|
|
class FrameIterator : public SourcePawn::IFrameIterator
|
|
{
|
|
public:
|
|
FrameIterator();
|
|
|
|
bool Done() const KE_OVERRIDE {
|
|
return !ivk_;
|
|
}
|
|
void Next() KE_OVERRIDE;
|
|
void Reset() KE_OVERRIDE;
|
|
|
|
bool IsNativeFrame() const KE_OVERRIDE;
|
|
bool IsScriptedFrame() const KE_OVERRIDE;
|
|
const char *FunctionName() const KE_OVERRIDE;
|
|
const char *FilePath() const KE_OVERRIDE;
|
|
unsigned LineNumber() const KE_OVERRIDE;
|
|
IPluginContext *Context() const KE_OVERRIDE;
|
|
|
|
private:
|
|
void nextInvokeFrame();
|
|
cell_t findCip() const;
|
|
|
|
private:
|
|
InvokeFrame *ivk_;
|
|
ExitFrame exit_frame_;
|
|
PluginRuntime *runtime_;
|
|
const intptr_t *sp_iter_;
|
|
const intptr_t *sp_stop_;
|
|
ucell_t function_cip_;
|
|
mutable ucell_t cip_;
|
|
void *pc_;
|
|
};
|
|
|
|
} // namespace sp
|
|
|
|
#endif // _include_sourcepawn_vm_stack_frames_h_
|