Refactor the JIT to use a newer, simpler macro assembler. (bug 5827, r=ann)
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/* vim: set ts=2 sw=2 tw=99 et:
|
||||
*
|
||||
* Copyright (C) 2012 David Anderson
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
#ifndef _include_sourcepawn_allocatorpolicies_h_
|
||||
#define _include_sourcepawn_allocatorpolicies_h_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace ke {
|
||||
|
||||
class SystemAllocatorPolicy
|
||||
{
|
||||
protected:
|
||||
void reportOutOfMemory() {
|
||||
fprintf(stderr, "OUT OF MEMORY\n");
|
||||
abort();
|
||||
}
|
||||
void reportAllocationOverflow() {
|
||||
fprintf(stderr, "OUT OF MEMORY\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
public:
|
||||
void free(void *memory) {
|
||||
::free(memory);
|
||||
}
|
||||
void *malloc(size_t bytes) {
|
||||
void *ptr = ::malloc(bytes);
|
||||
if (!ptr)
|
||||
reportOutOfMemory();
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _include_sourcepawn_allocatorpolicies_h_
|
||||
@@ -0,0 +1,318 @@
|
||||
/* vim: set ts=4 sw=4 tw=99 et:
|
||||
*
|
||||
* Copyright (C) 2012-2013 David Anderson
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
#ifndef _include_jitcraft_utility_h_
|
||||
#define _include_jitcraft_utility_h_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(_MSC_VER)
|
||||
# include <intrin.h>
|
||||
#endif
|
||||
|
||||
#define KE_32BIT
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
namespace ke {
|
||||
|
||||
static const size_t kMallocAlignment = sizeof(void *) * 2;
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef int32_t int32;
|
||||
typedef uint32_t uint32;
|
||||
typedef int64_t int64;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
typedef uint8 * Address;
|
||||
|
||||
static const size_t kKB = 1024;
|
||||
static const size_t kMB = 1024 * kKB;
|
||||
static const size_t kGB = 1024 * kMB;
|
||||
|
||||
template <typename T>
|
||||
class AutoFree
|
||||
{
|
||||
T *t_;
|
||||
|
||||
public:
|
||||
AutoFree()
|
||||
: t_(NULL)
|
||||
{
|
||||
}
|
||||
AutoFree(T *t)
|
||||
: t_(t)
|
||||
{
|
||||
}
|
||||
~AutoFree() {
|
||||
free(t_);
|
||||
}
|
||||
T *take() {
|
||||
T *t = t_;
|
||||
t_ = NULL;
|
||||
return t;
|
||||
}
|
||||
T *operator *() const {
|
||||
return t_;
|
||||
}
|
||||
void operator =(T *t) {
|
||||
if (t_)
|
||||
free(t_);
|
||||
t_ = t;
|
||||
}
|
||||
};
|
||||
|
||||
// Bob Jenkin's one-at-a-time hash function[1].
|
||||
//
|
||||
// [1] http://burtleburtle.net/bob/hash/doobs.html
|
||||
class CharacterStreamHasher
|
||||
{
|
||||
uint32 hash;
|
||||
|
||||
public:
|
||||
CharacterStreamHasher()
|
||||
: hash(0)
|
||||
{ }
|
||||
|
||||
void add(char c) {
|
||||
hash += c;
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
}
|
||||
|
||||
void add(const char *s, size_t length) {
|
||||
for (size_t i = 0; i < length; i++)
|
||||
add(s[i]);
|
||||
}
|
||||
|
||||
uint32 result() {
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 11);
|
||||
hash += (hash << 15);
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
static inline uint32
|
||||
HashCharSequence(const char *s, size_t length)
|
||||
{
|
||||
CharacterStreamHasher hasher;
|
||||
hasher.add(s, length);
|
||||
return hasher.result();
|
||||
}
|
||||
|
||||
// From http://burtleburtle.net/bob/hash/integer.html
|
||||
static inline uint32
|
||||
HashInt32(int32 a)
|
||||
{
|
||||
a = (a ^ 61) ^ (a >> 16);
|
||||
a = a + (a << 3);
|
||||
a = a ^ (a >> 4);
|
||||
a = a * 0x27d4eb2d;
|
||||
a = a ^ (a >> 15);
|
||||
return a;
|
||||
}
|
||||
|
||||
// From http://www.cris.com/~Ttwang/tech/inthash.htm
|
||||
static inline uint32
|
||||
HashInt64(int64 key)
|
||||
{
|
||||
key = (~key) + (key << 18); // key = (key << 18) - key - 1;
|
||||
key = key ^ (uint64(key) >> 31);
|
||||
key = key * 21; // key = (key + (key << 2)) + (key << 4);
|
||||
key = key ^ (uint64(key) >> 11);
|
||||
key = key + (key << 6);
|
||||
key = key ^ (uint64(key) >> 22);
|
||||
return uint32(key);
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
HashPointer(void *p)
|
||||
{
|
||||
#if defined(KE_32BIT)
|
||||
return HashInt32(reinterpret_cast<int32>(p));
|
||||
#elif defined(KE_64BIT)
|
||||
return HashInt64(reinterpret_cast<int64>(p));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
Log2(size_t number)
|
||||
{
|
||||
assert(number != 0);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
unsigned long rval;
|
||||
# ifdef _M_IX86
|
||||
_BitScanReverse(&rval, number);
|
||||
# elif _M_X64
|
||||
_BitScanReverse64(&rval, number);
|
||||
# endif
|
||||
return rval;
|
||||
#else
|
||||
size_t bit;
|
||||
asm("bsr %1, %0\n"
|
||||
: "=r" (bit)
|
||||
: "rm" (number));
|
||||
return bit;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
FindRightmostBit(size_t number)
|
||||
{
|
||||
assert(number != 0);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
unsigned long rval;
|
||||
# ifdef _M_IX86
|
||||
_BitScanForward(&rval, number);
|
||||
# elif _M_X64
|
||||
_BitScanForward64(&rval, number);
|
||||
# endif
|
||||
return rval;
|
||||
#else
|
||||
size_t bit;
|
||||
asm("bsf %1, %0\n"
|
||||
: "=r" (bit)
|
||||
: "rm" (number));
|
||||
return bit;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsPowerOfTwo(size_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
return false;
|
||||
return !(value & (value - 1));
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
Align(size_t count, size_t alignment)
|
||||
{
|
||||
assert(IsPowerOfTwo(alignment));
|
||||
return count + (alignment - (count % alignment)) % alignment;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsUint32AddSafe(unsigned a, unsigned b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return true;
|
||||
size_t log2_a = Log2(a);
|
||||
size_t log2_b = Log2(b);
|
||||
return (log2_a < sizeof(unsigned) * 8) &&
|
||||
(log2_b < sizeof(unsigned) * 8);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsUintPtrAddSafe(size_t a, size_t b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return true;
|
||||
size_t log2_a = Log2(a);
|
||||
size_t log2_b = Log2(b);
|
||||
return (log2_a < sizeof(size_t) * 8) &&
|
||||
(log2_b < sizeof(size_t) * 8);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsUint32MultiplySafe(unsigned a, unsigned b)
|
||||
{
|
||||
if (a <= 1 || b <= 1)
|
||||
return true;
|
||||
|
||||
size_t log2_a = Log2(a);
|
||||
size_t log2_b = Log2(b);
|
||||
return log2_a + log2_b <= sizeof(unsigned) * 8;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsUintPtrMultiplySafe(size_t a, size_t b)
|
||||
{
|
||||
if (a <= 1 || b <= 1)
|
||||
return true;
|
||||
|
||||
size_t log2_a = Log2(a);
|
||||
size_t log2_b = Log2(b);
|
||||
return log2_a + log2_b <= sizeof(size_t) * 8;
|
||||
}
|
||||
|
||||
#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
|
||||
#define STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1])
|
||||
|
||||
#define IS_ALIGNED(addr, alignment) (!(uintptr_t(addr) & ((alignment) - 1)))
|
||||
|
||||
template <typename T>
|
||||
static inline bool
|
||||
IsAligned(T addr, size_t alignment)
|
||||
{
|
||||
assert(IsPowerOfTwo(alignment));
|
||||
return !(uintptr_t(addr) & (alignment - 1));
|
||||
}
|
||||
|
||||
static inline Address
|
||||
AlignedBase(Address addr, size_t alignment)
|
||||
{
|
||||
assert(IsPowerOfTwo(alignment));
|
||||
return Address(uintptr_t(addr) & ~(alignment - 1));
|
||||
}
|
||||
|
||||
template <typename T> static inline T
|
||||
Min(const T &t1, const T &t2)
|
||||
{
|
||||
return t1 < t2 ? t1 : t2;
|
||||
}
|
||||
|
||||
template <typename T> static inline T
|
||||
Max(const T &t1, const T &t2)
|
||||
{
|
||||
return t1 > t2 ? t1 : t2;
|
||||
}
|
||||
|
||||
template <typename T> T
|
||||
ReturnAndVoid(T &t)
|
||||
{
|
||||
T saved = t;
|
||||
t = T();
|
||||
return saved;
|
||||
}
|
||||
|
||||
#define OFFSETOF(Class, Member) reinterpret_cast<size_t>(&((Class *)NULL)->Member)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define KE_SIZET_FMT "%Iu"
|
||||
#elif defined(__GNUC__)
|
||||
# define KE_SIZET_FMT "%zu"
|
||||
#else
|
||||
# error "Implement format specifier string"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define KE_CRITICAL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#else
|
||||
# define KE_CRITICAL_LIKELY(x) x
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // _include_jitcraft_utility_h_
|
||||
@@ -0,0 +1,166 @@
|
||||
/* vim: set ts=2 sw=2 tw=99 et:
|
||||
*
|
||||
* Copyright (C) 2012 David Anderson
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
#ifndef _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
|
||||
#define _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
|
||||
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
#include <ke_allocator_policies.h>
|
||||
#include <ke_utility.h>
|
||||
|
||||
namespace ke {
|
||||
|
||||
template <typename T, typename AllocPolicy = SystemAllocatorPolicy>
|
||||
class Vector : public AllocPolicy
|
||||
{
|
||||
public:
|
||||
Vector(AllocPolicy = AllocPolicy())
|
||||
: data(NULL),
|
||||
nitems(0),
|
||||
maxsize(0)
|
||||
{
|
||||
}
|
||||
|
||||
~Vector()
|
||||
{
|
||||
zap();
|
||||
}
|
||||
|
||||
void steal(Vector &other) {
|
||||
zap();
|
||||
data = other.data;
|
||||
nitems = other.nitems;
|
||||
maxsize = other.maxsize;
|
||||
other.reset();
|
||||
}
|
||||
|
||||
bool append(const T& item) {
|
||||
if (!growIfNeeded(1))
|
||||
return false;
|
||||
new (&data[nitems]) T(item);
|
||||
nitems++;
|
||||
return true;
|
||||
}
|
||||
void infallibleAppend(const T &item) {
|
||||
assert(growIfNeeded(1));
|
||||
new (&data[nitems]) T(item);
|
||||
nitems++;
|
||||
}
|
||||
T popCopy() {
|
||||
T t = at(length() - 1);
|
||||
pop();
|
||||
return t;
|
||||
}
|
||||
void pop() {
|
||||
assert(nitems);
|
||||
data[nitems - 1].~T();
|
||||
nitems--;
|
||||
}
|
||||
bool empty() const {
|
||||
return length() == 0;
|
||||
}
|
||||
size_t length() const {
|
||||
return nitems;
|
||||
}
|
||||
T& at(size_t i) {
|
||||
assert(i < length());
|
||||
return data[i];
|
||||
}
|
||||
const T& at(size_t i) const {
|
||||
assert(i < length());
|
||||
return data[i];
|
||||
}
|
||||
T& operator [](size_t i) {
|
||||
return at(i);
|
||||
}
|
||||
const T& operator [](size_t i) const {
|
||||
return at(i);
|
||||
}
|
||||
void clear() {
|
||||
nitems = 0;
|
||||
}
|
||||
const T &back() const {
|
||||
return at(length() - 1);
|
||||
}
|
||||
T &back() {
|
||||
return at(length() - 1);
|
||||
}
|
||||
|
||||
T *buffer() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
bool ensure(size_t desired) {
|
||||
if (desired <= length())
|
||||
return true;
|
||||
|
||||
return growIfNeeded(desired - length());
|
||||
}
|
||||
|
||||
private:
|
||||
void zap() {
|
||||
for (size_t i = 0; i < nitems; i++)
|
||||
data[i].~T();
|
||||
this->free(data);
|
||||
}
|
||||
void reset() {
|
||||
data = NULL;
|
||||
nitems = 0;
|
||||
maxsize = 0;
|
||||
}
|
||||
|
||||
bool growIfNeeded(size_t needed)
|
||||
{
|
||||
if (!IsUintPtrAddSafe(nitems, needed)) {
|
||||
this->reportAllocationOverflow();
|
||||
return false;
|
||||
}
|
||||
if (nitems + needed < maxsize)
|
||||
return true;
|
||||
if (maxsize == 0)
|
||||
maxsize = 8;
|
||||
while (nitems + needed > maxsize) {
|
||||
if (!IsUintPtrMultiplySafe(maxsize, 2)) {
|
||||
this->reportAllocationOverflow();
|
||||
return false;
|
||||
}
|
||||
maxsize *= 2;
|
||||
}
|
||||
T* newdata = (T*)this->malloc(sizeof(T) * maxsize);
|
||||
if (newdata == NULL)
|
||||
return false;
|
||||
for (size_t i = 0; i < nitems; i++) {
|
||||
new (&newdata[i]) T(data[i]);
|
||||
data[i].~T();
|
||||
}
|
||||
this->free(data);
|
||||
data = newdata;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
T* data;
|
||||
size_t nitems;
|
||||
size_t maxsize;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_ */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourcePawn
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -85,6 +85,8 @@ typedef uint32_t funcid_t; /**< Function index code */
|
||||
#define SP_ERROR_ABORTED 25 /**< Function call was aborted */
|
||||
#define SP_ERROR_CODE_TOO_OLD 26 /**< Code is too old for this VM */
|
||||
#define SP_ERROR_CODE_TOO_NEW 27 /**< Code is too new for this VM */
|
||||
#define SP_ERROR_OUT_OF_MEMORY 28 /**< Out of memory */
|
||||
#define SP_ERROR_INTEGER_OVERFLOW 29 /**< Integer overflow (-INT_MIN / -1) */
|
||||
//Hey you! Update the string table if you add to the end of me! */
|
||||
|
||||
/**********************************************
|
||||
|
||||
Reference in New Issue
Block a user