2015-02-23 22:40:01 +01:00
|
|
|
// 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/.
|
|
|
|
//
|
2008-07-11 10:18:43 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <limits.h>
|
2015-02-24 21:55:00 +01:00
|
|
|
#include <sp_vm_api.h>
|
|
|
|
#include "plugin-context.h"
|
2013-08-15 08:54:25 +02:00
|
|
|
#include "watchdog_timer.h"
|
2008-07-11 10:18:43 +02:00
|
|
|
#include "x86/jit_x86.h"
|
2015-02-24 03:19:33 +01:00
|
|
|
#include "environment.h"
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
#include "compiled-function.h"
|
2008-07-11 10:18:43 +02:00
|
|
|
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
using namespace sp;
|
2008-07-11 10:18:43 +02:00
|
|
|
using namespace SourcePawn;
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
#define CELLBOUNDMAX (INT_MAX/sizeof(cell_t))
|
|
|
|
#define STACKMARGIN ((cell_t)(16*sizeof(cell_t)))
|
2008-07-11 10:18:43 +02:00
|
|
|
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
static const size_t kMinHeapSize = 16384;
|
|
|
|
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::PluginContext(PluginRuntime *pRuntime)
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
: env_(Environment::get()),
|
|
|
|
m_pRuntime(pRuntime),
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
memory_(nullptr),
|
|
|
|
data_size_(m_pRuntime->data().length),
|
|
|
|
mem_size_(m_pRuntime->image()->HeapSize()),
|
|
|
|
m_pNullVec(nullptr),
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
m_pNullString(nullptr)
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
{
|
|
|
|
// Compute and align a minimum memory amount.
|
|
|
|
if (mem_size_ < data_size_)
|
|
|
|
mem_size_ = data_size_;
|
|
|
|
mem_size_ = ke::Align(mem_size_, sizeof(cell_t));
|
|
|
|
|
|
|
|
// Add a minimum heap size if needed.
|
|
|
|
if (mem_size_ < data_size_ + kMinHeapSize)
|
|
|
|
mem_size_ = data_size_ + kMinHeapSize;
|
|
|
|
assert(ke::IsAligned(mem_size_, sizeof(cell_t)));
|
|
|
|
|
|
|
|
hp_ = data_size_;
|
|
|
|
sp_ = mem_size_ - sizeof(cell_t);
|
|
|
|
frm_ = sp_;
|
|
|
|
|
|
|
|
tracker_.pBase = (ucell_t *)malloc(1024);
|
|
|
|
tracker_.pCur = tracker_.pBase;
|
|
|
|
tracker_.size = 1024 / sizeof(cell_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
PluginContext::~PluginContext()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
free(tracker_.pBase);
|
|
|
|
delete[] memory_;
|
|
|
|
}
|
2015-02-23 22:40:01 +01:00
|
|
|
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
bool
|
|
|
|
PluginContext::Initialize()
|
|
|
|
{
|
|
|
|
memory_ = new uint8_t[mem_size_];
|
|
|
|
if (!memory_)
|
|
|
|
return false;
|
|
|
|
memset(memory_ + data_size_, 0, mem_size_ - data_size_);
|
|
|
|
memcpy(memory_, m_pRuntime->data().bytes, data_size_);
|
2015-02-23 22:40:01 +01:00
|
|
|
|
|
|
|
/* Initialize the null references */
|
|
|
|
uint32_t index;
|
|
|
|
if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE) {
|
|
|
|
sp_pubvar_t *pubvar;
|
|
|
|
GetPubvarByIndex(index, &pubvar);
|
|
|
|
m_pNullVec = pubvar->offs;
|
|
|
|
} else {
|
|
|
|
m_pNullVec = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE) {
|
|
|
|
sp_pubvar_t *pubvar;
|
|
|
|
GetPubvarByIndex(index, &pubvar);
|
|
|
|
m_pNullString = pubvar->offs;
|
|
|
|
} else {
|
|
|
|
m_pNullString = NULL;
|
|
|
|
}
|
|
|
|
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
return true;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
IVirtualMachine *
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetVirtualMachine()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return NULL;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
sp_context_t *
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetContext()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return reinterpret_cast<sp_context_t *>((IPluginContext * )this);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
bool
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::IsDebugging()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return true;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::SetDebugBreak(void *newpfn, void *oldpfn)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
IPluginDebugInfo *
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetDebugInfo()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return NULL;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::Execute(uint32_t code_addr, cell_t *result)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
cell_t
|
|
|
|
PluginContext::ThrowNativeErrorEx(int error, const char *msg, ...)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, msg);
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
env_->ReportErrorVA(error, msg, ap);
|
2015-02-23 22:40:01 +01:00
|
|
|
va_end(ap);
|
|
|
|
return 0;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
cell_t
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::ThrowNativeError(const char *msg, ...)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, msg);
|
|
|
|
env_->ReportErrorVA(SP_ERROR_NATIVE, msg, ap);
|
|
|
|
va_end(ap);
|
2015-02-23 22:40:01 +01:00
|
|
|
return 0;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
cell_t *addr;
|
|
|
|
ucell_t realmem;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
|
|
|
#if 0
|
2015-02-23 22:40:01 +01:00
|
|
|
if (cells > CELLBOUNDMAX)
|
|
|
|
{
|
|
|
|
return SP_ERROR_ARAM;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
#else
|
2015-02-23 22:40:01 +01:00
|
|
|
assert(cells < CELLBOUNDMAX);
|
2008-07-11 10:18:43 +02:00
|
|
|
#endif
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
realmem = cells * sizeof(cell_t);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
/**
|
|
|
|
* Check if the space between the heap and stack is sufficient.
|
|
|
|
*/
|
2015-02-25 06:18:34 +01:00
|
|
|
if ((cell_t)(sp_ - hp_ - realmem) < STACKMARGIN)
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_HEAPLOW;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
addr = (cell_t *)(memory_ + hp_);
|
2015-02-23 22:40:01 +01:00
|
|
|
/* store size of allocation in cells */
|
|
|
|
*addr = (cell_t)cells;
|
|
|
|
addr++;
|
2015-02-25 06:18:34 +01:00
|
|
|
hp_ += sizeof(cell_t);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-25 06:18:34 +01:00
|
|
|
*local_addr = hp_;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
if (phys_addr)
|
|
|
|
*phys_addr = addr;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-25 06:18:34 +01:00
|
|
|
hp_ += realmem;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::HeapPop(cell_t local_addr)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
cell_t cellcount;
|
|
|
|
cell_t *addr;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
/* check the bounds of this address */
|
|
|
|
local_addr -= sizeof(cell_t);
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
if (local_addr < (cell_t)data_size_ || local_addr >= sp_)
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_INVALID_ADDRESS;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
addr = (cell_t *)(memory_ + local_addr);
|
2015-02-23 22:40:01 +01:00
|
|
|
cellcount = (*addr) * sizeof(cell_t);
|
|
|
|
/* check if this memory count looks valid */
|
2015-02-25 06:18:34 +01:00
|
|
|
if ((signed)(hp_ - cellcount - sizeof(cell_t)) != local_addr)
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_INVALID_ADDRESS;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-25 06:18:34 +01:00
|
|
|
hp_ = local_addr;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::HeapRelease(cell_t local_addr)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
if (local_addr < (cell_t)data_size_)
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_INVALID_ADDRESS;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-25 06:18:34 +01:00
|
|
|
hp_ = local_addr - sizeof(cell_t);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::FindNativeByName(const char *name, uint32_t *index)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->FindNativeByName(name, index);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetNativeByIndex(uint32_t index, sp_native_t **native)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->GetNativeByIndex(index, native);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
uint32_t
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetNativesNum()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->GetNativesNum();
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::FindPublicByName(const char *name, uint32_t *index)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->FindPublicByName(name, index);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->GetPublicByIndex(index, pblic);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
uint32_t
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetPublicsNum()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->GetPublicsNum();
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->GetPubvarByIndex(index, pubvar);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::FindPubvarByName(const char *name, uint32_t *index)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->FindPubvarByName(name, index);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->GetPubvarAddrs(index, local_addr, phys_addr);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
uint32_t
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetPubVarsNum()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->GetPubVarsNum();
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::BindNative(const sp_nativeinfo_t *native)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC func)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::BindNativeToAny(SPVM_NATIVE_FUNC native)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-25 06:18:34 +01:00
|
|
|
if (((local_addr >= hp_) && (local_addr < sp_)) ||
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
(local_addr < 0) || ((ucell_t)local_addr >= mem_size_))
|
2015-02-23 22:40:01 +01:00
|
|
|
{
|
|
|
|
return SP_ERROR_INVALID_ADDRESS;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
if (phys_addr)
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
*phys_addr = (cell_t *)(memory_ + local_addr);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::PushCell(cell_t value)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::PushCellsFromArray(cell_t array[], unsigned int numcells)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::LocalToString(cell_t local_addr, char **addr)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-25 06:18:34 +01:00
|
|
|
if (((local_addr >= hp_) && (local_addr < sp_)) ||
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
(local_addr < 0) || ((ucell_t)local_addr >= mem_size_))
|
2015-02-23 22:40:01 +01:00
|
|
|
{
|
|
|
|
return SP_ERROR_INVALID_ADDRESS;
|
|
|
|
}
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
*addr = (char *)(memory_ + local_addr);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::PushString(cell_t *local_addr, char **phys_addr, const char *string)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_ABORTED;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
char *dest;
|
|
|
|
size_t len;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-25 06:18:34 +01:00
|
|
|
if (((local_addr >= hp_) && (local_addr < sp_)) ||
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
(local_addr < 0) || ((ucell_t)local_addr >= mem_size_))
|
2015-02-23 22:40:01 +01:00
|
|
|
{
|
|
|
|
return SP_ERROR_INVALID_ADDRESS;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
if (bytes == 0)
|
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
len = strlen(source);
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
dest = (char *)(memory_ + local_addr);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
if (len >= bytes)
|
|
|
|
len = bytes - 1;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
memmove(dest, source, len);
|
|
|
|
dest[len] = '\0';
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
static inline int
|
|
|
|
__CheckValidChar(char *c)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
int count;
|
|
|
|
int bytecount = 0;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
for (count=1; (*c & 0xC0) == 0x80; count++)
|
|
|
|
c--;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
switch (*c & 0xF0)
|
|
|
|
{
|
|
|
|
case 0xC0:
|
|
|
|
case 0xD0:
|
|
|
|
{
|
|
|
|
bytecount = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0xE0:
|
|
|
|
{
|
|
|
|
bytecount = 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0xF0:
|
|
|
|
{
|
|
|
|
bytecount = 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
if (bytecount != count)
|
|
|
|
return count;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return 0;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
char *dest;
|
|
|
|
size_t len;
|
|
|
|
bool needtocheck = false;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-25 06:18:34 +01:00
|
|
|
if (((local_addr >= hp_) && (local_addr < sp_)) ||
|
2015-02-23 22:40:01 +01:00
|
|
|
(local_addr < 0) ||
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
((ucell_t)local_addr >= mem_size_))
|
2015-02-23 22:40:01 +01:00
|
|
|
{
|
|
|
|
return SP_ERROR_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxbytes == 0)
|
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
len = strlen(source);
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
dest = (char *)(memory_ + local_addr);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
if ((size_t)len >= maxbytes) {
|
|
|
|
len = maxbytes - 1;
|
|
|
|
needtocheck = true;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
memmove(dest, source, len);
|
|
|
|
if ((dest[len-1] & 1<<7) && needtocheck)
|
|
|
|
len -= __CheckValidChar(dest+len-1);
|
|
|
|
dest[len] = '\0';
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
if (wrtnbytes)
|
|
|
|
*wrtnbytes = len;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
IPluginFunction *
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetFunctionById(funcid_t func_id)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->GetFunctionById(func_id);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
IPluginFunction *
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetFunctionByName(const char *public_name)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
return m_pRuntime->GetFunctionByName(public_name);
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::LocalToStringNULL(cell_t local_addr, char **addr)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
int err;
|
|
|
|
if ((err = LocalToString(local_addr, addr)) != SP_ERROR_NONE)
|
|
|
|
return err;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
if ((cell_t *)*addr == m_pNullString)
|
|
|
|
*addr = NULL;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return SP_ERROR_NONE;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
SourceMod::IdentityToken_t *
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetIdentity()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
SourceMod::IdentityToken_t *tok;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
if (GetKey(1, (void **)&tok))
|
|
|
|
return tok;
|
|
|
|
return NULL;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
cell_t *
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetNullRef(SP_NULL_TYPE type)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
if (type == SP_NULL_VECTOR)
|
|
|
|
return m_pNullVec;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
return NULL;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
bool
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::IsInExec()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
for (InvokeFrame *ivk = env_->top(); ivk; ivk = ivk->prev()) {
|
|
|
|
if (ivk->cx() == this)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
ReportErrorNumber(SP_ERROR_ABORTED);
|
|
|
|
return SP_ERROR_ABORTED;
|
|
|
|
}
|
2015-02-23 22:40:01 +01:00
|
|
|
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
bool
|
|
|
|
PluginContext::Invoke(funcid_t fnid, const cell_t *params, unsigned int num_params, cell_t *result)
|
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
EnterProfileScope profileScope("SourcePawn", "EnterJIT");
|
|
|
|
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
if (!env_->watchdog()->HandleInterrupt()) {
|
|
|
|
ReportErrorNumber(SP_ERROR_TIMEOUT);
|
|
|
|
return false;
|
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
assert((fnid & 1) != 0);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
unsigned public_id = fnid >> 1;
|
2015-02-24 00:47:47 +01:00
|
|
|
ScriptedInvoker *cfun = m_pRuntime->GetPublicFunction(public_id);
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
if (!cfun) {
|
|
|
|
ReportErrorNumber(SP_ERROR_NOT_FOUND);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_pRuntime->IsPaused()) {
|
|
|
|
ReportErrorNumber(SP_ERROR_NOT_RUNNABLE);
|
|
|
|
return false;
|
|
|
|
}
|
2013-08-15 08:54:25 +02:00
|
|
|
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
if ((cell_t)(hp_ + 16*sizeof(cell_t)) > (cell_t)(sp_ - (sizeof(cell_t) * (num_params + 1)))) {
|
|
|
|
ReportErrorNumber(SP_ERROR_STACKLOW);
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-24 10:04:13 +02:00
|
|
|
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
// Yuck. We have to do this for compatibility, otherwise something like
|
|
|
|
// ForwardSys or any sort of multi-callback-fire code would die. Later,
|
|
|
|
// we'll expose an Invoke() or something that doesn't do this.
|
|
|
|
env_->clearPendingException();
|
2008-07-11 10:18:43 +02:00
|
|
|
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
cell_t ignore_result;
|
2015-02-23 22:40:01 +01:00
|
|
|
if (result == NULL)
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
result = &ignore_result;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
/* We got this far. It's time to start profiling. */
|
|
|
|
EnterProfileScope scriptScope("SourcePawn", cfun->FullName());
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
/* See if we have to compile the callee. */
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
CompiledFunction *fn = nullptr;
|
|
|
|
if (env_->IsJitEnabled()) {
|
2015-02-23 22:40:01 +01:00
|
|
|
/* We might not have to - check pcode offset. */
|
2015-02-25 08:37:23 +01:00
|
|
|
if ((fn = cfun->cachedCompiledFunction()) == nullptr) {
|
|
|
|
fn = m_pRuntime->GetJittedFunctionByOffset(cfun->Public()->code_offs);
|
|
|
|
if (!fn) {
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
int err = SP_ERROR_NONE;
|
|
|
|
if ((fn = CompileFunction(m_pRuntime, cfun->Public()->code_offs, &err)) == NULL) {
|
|
|
|
ReportErrorNumber(err);
|
|
|
|
return false;
|
|
|
|
}
|
2015-02-25 08:37:23 +01:00
|
|
|
}
|
|
|
|
cfun->setCachedCompiledFunction(fn);
|
2015-02-23 22:40:01 +01:00
|
|
|
}
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
} else {
|
|
|
|
ReportError("JIT is not enabled!");
|
|
|
|
return false;
|
2015-02-23 22:40:01 +01:00
|
|
|
}
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
/* Save our previous state. */
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
cell_t save_sp = sp_;
|
|
|
|
cell_t save_hp = hp_;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
/* Push parameters */
|
2015-02-25 06:06:06 +01:00
|
|
|
sp_ -= sizeof(cell_t) * (num_params + 1);
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
cell_t *sp = (cell_t *)(memory_ + sp_);
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
sp[0] = num_params;
|
|
|
|
for (unsigned int i = 0; i < num_params; i++)
|
|
|
|
sp[i + 1] = params[i];
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-24 10:12:23 +01:00
|
|
|
// Enter the execution engine.
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
int ir;
|
|
|
|
{
|
|
|
|
InvokeFrame ivkframe(this, fn->GetCodeOffset());
|
|
|
|
Environment *env = env_;
|
|
|
|
ir = env->Invoke(m_pRuntime, fn, result);
|
|
|
|
}
|
2015-02-23 22:40:01 +01:00
|
|
|
|
|
|
|
if (ir == SP_ERROR_NONE) {
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
// Verify that our state is still sane.
|
2015-02-25 06:06:06 +01:00
|
|
|
if (sp_ != save_sp) {
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
env_->ReportErrorFmt(
|
|
|
|
SP_ERROR_STACKLEAK,
|
|
|
|
"Stack leak detected: sp:%d should be %d!",
|
2015-02-25 06:06:06 +01:00
|
|
|
sp_,
|
2015-02-23 22:40:01 +01:00
|
|
|
save_sp);
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
return false;
|
2015-02-23 22:40:01 +01:00
|
|
|
}
|
2015-02-25 06:18:34 +01:00
|
|
|
if (hp_ != save_hp) {
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
env_->ReportErrorFmt(
|
|
|
|
SP_ERROR_HEAPLEAK,
|
|
|
|
"Heap leak detected: hp:%d should be %d!",
|
2015-02-25 06:18:34 +01:00
|
|
|
hp_,
|
2015-02-23 22:40:01 +01:00
|
|
|
save_hp);
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
return false;
|
2015-02-23 22:40:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-25 06:06:06 +01:00
|
|
|
sp_ = save_sp;
|
2015-02-25 06:18:34 +01:00
|
|
|
hp_ = save_hp;
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
return ir == SP_ERROR_NONE;
|
2015-02-23 22:40:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
IPluginRuntime *
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetRuntime()
|
2015-02-23 22:40:01 +01:00
|
|
|
{
|
|
|
|
return m_pRuntime;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
int
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetLastNativeError()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
Environment *env = env_;
|
|
|
|
if (!env->hasPendingException())
|
|
|
|
return SP_ERROR_NONE;
|
|
|
|
return env->getPendingExceptionCode();
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
cell_t *
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetLocalParams()
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
return (cell_t *)(memory_ + frm_ + (2 * sizeof(cell_t)));
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
void
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::SetKey(int k, void *value)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
if (k < 1 || k > 4)
|
|
|
|
return;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
m_keys[k - 1] = value;
|
|
|
|
m_keys_set[k - 1] = true;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
bool
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::GetKey(int k, void **value)
|
2008-07-11 10:18:43 +02:00
|
|
|
{
|
2015-02-23 22:40:01 +01:00
|
|
|
if (k < 1 || k > 4 || m_keys_set[k - 1] == false)
|
|
|
|
return false;
|
2008-07-11 10:18:43 +02:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
*value = m_keys[k - 1];
|
|
|
|
return true;
|
2008-07-11 10:18:43 +02:00
|
|
|
}
|
2009-02-01 08:03:03 +01:00
|
|
|
|
2015-02-23 22:40:01 +01:00
|
|
|
void
|
2015-02-24 21:50:09 +01:00
|
|
|
PluginContext::ClearLastNativeError()
|
2009-02-01 08:03:03 +01:00
|
|
|
{
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
if (env_->hasPendingException())
|
|
|
|
env_->clearPendingException();
|
2009-02-01 08:03:03 +01:00
|
|
|
}
|
2015-02-25 00:43:41 +01:00
|
|
|
|
|
|
|
int
|
|
|
|
PluginContext::popTrackerAndSetHeap()
|
|
|
|
{
|
|
|
|
assert(tracker_.pCur > tracker_.pBase);
|
|
|
|
|
|
|
|
tracker_.pCur--;
|
|
|
|
if (tracker_.pCur < tracker_.pBase)
|
|
|
|
return SP_ERROR_TRACKER_BOUNDS;
|
|
|
|
|
|
|
|
ucell_t amt = *tracker_.pCur;
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
if (amt > (hp_ - data_size_))
|
2015-02-25 00:43:41 +01:00
|
|
|
return SP_ERROR_HEAPMIN;
|
|
|
|
|
2015-02-25 06:18:34 +01:00
|
|
|
hp_ -= amt;
|
2015-02-25 00:43:41 +01:00
|
|
|
return SP_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
PluginContext::pushTracker(uint32_t amount)
|
|
|
|
{
|
|
|
|
if ((size_t)(tracker_.pCur - tracker_.pBase) >= tracker_.size)
|
|
|
|
return SP_ERROR_TRACKER_BOUNDS;
|
|
|
|
|
|
|
|
if (tracker_.pCur + 1 - (tracker_.pBase + tracker_.size) == 0) {
|
|
|
|
size_t disp = tracker_.size - 1;
|
|
|
|
tracker_.size *= 2;
|
|
|
|
tracker_.pBase = (ucell_t *)realloc(tracker_.pBase, tracker_.size * sizeof(cell_t));
|
|
|
|
|
|
|
|
if (!tracker_.pBase)
|
|
|
|
return SP_ERROR_TRACKER_BOUNDS;
|
|
|
|
|
|
|
|
tracker_.pCur = tracker_.pBase + disp;
|
|
|
|
}
|
|
|
|
|
|
|
|
*tracker_.pCur++ = amount;
|
|
|
|
return SP_ERROR_NONE;
|
|
|
|
}
|
2015-02-25 04:59:45 +01:00
|
|
|
|
|
|
|
cell_t
|
|
|
|
PluginContext::invokeNative(ucell_t native_idx, cell_t *params)
|
|
|
|
{
|
2015-02-25 06:06:06 +01:00
|
|
|
cell_t save_sp = sp_;
|
2015-02-25 06:18:34 +01:00
|
|
|
cell_t save_hp = hp_;
|
2015-02-25 04:59:45 +01:00
|
|
|
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
const sp_native_t *native = m_pRuntime->GetNative(native_idx);
|
2015-02-25 04:59:45 +01:00
|
|
|
|
|
|
|
if (native->status == SP_NATIVE_UNBOUND) {
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
ReportErrorNumber(SP_ERROR_INVALID_NATIVE);
|
2015-02-25 04:59:45 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-02-25 06:19:29 +01:00
|
|
|
cell_t result = native->pfn(this, params);
|
2015-02-25 04:59:45 +01:00
|
|
|
|
2015-02-25 06:06:06 +01:00
|
|
|
if (save_sp != sp_) {
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
if (!env_->hasPendingException())
|
|
|
|
ReportErrorNumber(SP_ERROR_STACKLEAK);
|
|
|
|
return 0;
|
2015-02-25 04:59:45 +01:00
|
|
|
}
|
2015-02-25 06:18:34 +01:00
|
|
|
if (save_hp != hp_) {
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
if (!env_->hasPendingException())
|
|
|
|
ReportErrorNumber(SP_ERROR_HEAPLEAK);
|
|
|
|
return 0;
|
2015-02-25 04:59:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
cell_t
|
|
|
|
PluginContext::invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params)
|
|
|
|
{
|
2015-02-25 06:06:06 +01:00
|
|
|
cell_t save_sp = sp_;
|
2015-02-25 06:18:34 +01:00
|
|
|
cell_t save_hp = hp_;
|
2015-02-25 04:59:45 +01:00
|
|
|
|
|
|
|
cell_t result = pfn(this, params);
|
|
|
|
|
2015-02-25 06:06:06 +01:00
|
|
|
if (save_sp != sp_) {
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
if (!env_->hasPendingException())
|
|
|
|
ReportErrorNumber(SP_ERROR_STACKLEAK);
|
2015-02-25 04:59:45 +01:00
|
|
|
return result;
|
|
|
|
}
|
2015-02-25 06:18:34 +01:00
|
|
|
if (save_hp != hp_) {
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
if (!env_->hasPendingException())
|
|
|
|
ReportErrorNumber(SP_ERROR_HEAPLEAK);
|
2015-02-25 04:59:45 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2015-02-25 06:18:34 +01:00
|
|
|
|
|
|
|
struct array_creation_t
|
|
|
|
{
|
|
|
|
const cell_t *dim_list; /* Dimension sizes */
|
|
|
|
cell_t dim_count; /* Number of dimensions */
|
|
|
|
cell_t *data_offs; /* Current offset AFTER the indirection vectors (data) */
|
|
|
|
cell_t *base; /* array base */
|
|
|
|
};
|
|
|
|
|
|
|
|
static cell_t
|
|
|
|
GenerateInnerArrayIndirectionVectors(array_creation_t *ar, int dim, cell_t cur_offs)
|
|
|
|
{
|
|
|
|
cell_t write_offs = cur_offs;
|
|
|
|
cell_t *data_offs = ar->data_offs;
|
|
|
|
|
|
|
|
cur_offs += ar->dim_list[dim];
|
|
|
|
|
|
|
|
// Dimension n-x where x > 2 will have sub-vectors.
|
|
|
|
// Otherwise, we just need to reference the data section.
|
|
|
|
if (ar->dim_count > 2 && dim < ar->dim_count - 2) {
|
|
|
|
// For each index at this dimension, write offstes to our sub-vectors.
|
|
|
|
// After we write one sub-vector, we generate its sub-vectors recursively.
|
|
|
|
// At the end, we're given the next offset we can use.
|
|
|
|
for (int i = 0; i < ar->dim_list[dim]; i++) {
|
|
|
|
ar->base[write_offs] = (cur_offs - write_offs) * sizeof(cell_t);
|
|
|
|
write_offs++;
|
|
|
|
cur_offs = GenerateInnerArrayIndirectionVectors(ar, dim + 1, cur_offs);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// In this section, there are no sub-vectors, we need to write offsets
|
|
|
|
// to the data. This is separate so the data stays in one big chunk.
|
|
|
|
// The data offset will increment by the size of the last dimension,
|
|
|
|
// because that is where the data is finally computed as.
|
|
|
|
for (int i = 0; i < ar->dim_list[dim]; i++) {
|
|
|
|
ar->base[write_offs] = (*data_offs - write_offs) * sizeof(cell_t);
|
|
|
|
write_offs++;
|
|
|
|
*data_offs = *data_offs + ar->dim_list[dim + 1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cur_offs;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t
|
|
|
|
calc_indirection(const array_creation_t *ar, cell_t dim)
|
|
|
|
{
|
|
|
|
cell_t size = ar->dim_list[dim];
|
|
|
|
if (dim < ar->dim_count - 2)
|
|
|
|
size += ar->dim_list[dim] * calc_indirection(ar, dim + 1);
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t
|
|
|
|
GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _dimcount, bool autozero)
|
|
|
|
{
|
|
|
|
array_creation_t ar;
|
|
|
|
cell_t data_offs;
|
|
|
|
|
|
|
|
/* Reverse the dimensions */
|
|
|
|
cell_t dim_list[sDIMEN_MAX];
|
|
|
|
int cur_dim = 0;
|
|
|
|
for (int i = _dimcount - 1; i >= 0; i--)
|
|
|
|
dim_list[cur_dim++] = dims[i];
|
|
|
|
|
|
|
|
ar.base = arraybase;
|
|
|
|
ar.dim_list = dim_list;
|
|
|
|
ar.dim_count = _dimcount;
|
|
|
|
ar.data_offs = &data_offs;
|
|
|
|
|
|
|
|
data_offs = calc_indirection(&ar, 0);
|
|
|
|
GenerateInnerArrayIndirectionVectors(&ar, 0, 0);
|
|
|
|
return data_offs;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
PluginContext::generateFullArray(uint32_t argc, cell_t *argv, int autozero)
|
|
|
|
{
|
|
|
|
// Calculate how many cells are needed.
|
|
|
|
if (argv[0] <= 0)
|
|
|
|
return SP_ERROR_ARRAY_TOO_BIG;
|
|
|
|
|
|
|
|
uint32_t cells = argv[0];
|
|
|
|
|
|
|
|
for (uint32_t dim = 1; dim < argc; dim++) {
|
|
|
|
cell_t dimsize = argv[dim];
|
|
|
|
if (dimsize <= 0)
|
|
|
|
return SP_ERROR_ARRAY_TOO_BIG;
|
|
|
|
if (!ke::IsUint32MultiplySafe(cells, dimsize))
|
|
|
|
return SP_ERROR_ARRAY_TOO_BIG;
|
|
|
|
cells *= uint32_t(dimsize);
|
|
|
|
if (!ke::IsUint32AddSafe(cells, dimsize))
|
|
|
|
return SP_ERROR_ARRAY_TOO_BIG;
|
|
|
|
cells += uint32_t(dimsize);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ke::IsUint32MultiplySafe(cells, 4))
|
|
|
|
return SP_ERROR_ARRAY_TOO_BIG;
|
|
|
|
|
|
|
|
uint32_t bytes = cells * 4;
|
|
|
|
if (!ke::IsUint32AddSafe(hp_, bytes))
|
|
|
|
return SP_ERROR_ARRAY_TOO_BIG;
|
|
|
|
|
|
|
|
uint32_t new_hp = hp_ + bytes;
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
cell_t *dat_hp = reinterpret_cast<cell_t *>(memory_ + new_hp);
|
2015-02-25 06:18:34 +01:00
|
|
|
|
|
|
|
// argv, coincidentally, is STK.
|
|
|
|
if (dat_hp >= argv - STACK_MARGIN)
|
|
|
|
return SP_ERROR_HEAPLOW;
|
|
|
|
|
|
|
|
if (int err = pushTracker(bytes))
|
|
|
|
return err;
|
|
|
|
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
cell_t *base = reinterpret_cast<cell_t *>(memory_ + hp_);
|
2015-02-25 06:18:34 +01:00
|
|
|
cell_t offs = GenerateArrayIndirectionVectors(base, argv, argc, !!autozero);
|
|
|
|
assert(size_t(offs) == cells);
|
|
|
|
|
|
|
|
argv[argc - 1] = hp_;
|
|
|
|
hp_ = new_hp;
|
|
|
|
return SP_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
PluginContext::generateArray(cell_t dims, cell_t *stk, bool autozero)
|
|
|
|
{
|
|
|
|
if (dims == 1) {
|
|
|
|
uint32_t size = *stk;
|
|
|
|
if (size == 0 || !ke::IsUint32MultiplySafe(size, 4))
|
|
|
|
return SP_ERROR_ARRAY_TOO_BIG;
|
|
|
|
*stk = hp_;
|
|
|
|
|
|
|
|
uint32_t bytes = size * 4;
|
|
|
|
|
|
|
|
hp_ += bytes;
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
if (uintptr_t(memory_ + hp_) >= uintptr_t(stk))
|
2015-02-25 06:18:34 +01:00
|
|
|
return SP_ERROR_HEAPLOW;
|
|
|
|
|
|
|
|
if (int err = pushTracker(bytes))
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (autozero)
|
Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.
The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.
Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.
PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.
Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 11:19:38 +01:00
|
|
|
memset(memory_ + hp_, 0, bytes);
|
2015-02-25 06:18:34 +01:00
|
|
|
|
|
|
|
return SP_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (int err = generateFullArray(dims, stk, autozero))
|
|
|
|
return err;
|
|
|
|
|
|
|
|
return SP_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.
The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.
Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.
Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.
These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-02-27 09:32:44 +01:00
|
|
|
ISourcePawnEngine2 *
|
|
|
|
PluginContext::APIv2()
|
|
|
|
{
|
|
|
|
return env_->APIv2();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginContext::ReportError(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
env_->ReportErrorVA(fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginContext::ReportErrorVA(const char *fmt, va_list ap)
|
|
|
|
{
|
|
|
|
env_->ReportErrorVA(fmt, ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginContext::ReportFatalError(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
env_->ReportErrorVA(SP_ERROR_FATAL, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginContext::ReportFatalErrorVA(const char *fmt, va_list ap)
|
|
|
|
{
|
|
|
|
env_->ReportErrorVA(SP_ERROR_FATAL, fmt, ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PluginContext::ReportErrorNumber(int error)
|
|
|
|
{
|
|
|
|
env_->ReportError(error);
|
|
|
|
}
|