mirror of
https://github.com/corda/corda.git
synced 2025-06-19 15:43:52 +00:00
bulk, global reformat
This commit is contained in:
@ -20,40 +20,41 @@
|
|||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
|
||||||
# define UNICODE
|
#define UNICODE
|
||||||
|
|
||||||
# include <windows.h>
|
#include <windows.h>
|
||||||
# include <io.h>
|
#include <io.h>
|
||||||
# include <direct.h>
|
#include <direct.h>
|
||||||
# include <share.h>
|
#include <share.h>
|
||||||
|
|
||||||
# define ACCESS _waccess
|
#define ACCESS _waccess
|
||||||
# define CLOSE _close
|
#define CLOSE _close
|
||||||
# define READ _read
|
#define READ _read
|
||||||
# define WRITE _write
|
#define WRITE _write
|
||||||
# define STAT _wstat
|
#define STAT _wstat
|
||||||
# define STRUCT_STAT struct _stat
|
#define STRUCT_STAT struct _stat
|
||||||
# define MKDIR(path, mode) _wmkdir(path)
|
#define MKDIR(path, mode) _wmkdir(path)
|
||||||
# define CHMOD(path, mode) _wchmod(path, mode)
|
#define CHMOD(path, mode) _wchmod(path, mode)
|
||||||
# define REMOVE _wremove
|
#define REMOVE _wremove
|
||||||
# define RENAME _wrename
|
#define RENAME _wrename
|
||||||
# define OPEN_MASK O_BINARY
|
#define OPEN_MASK O_BINARY
|
||||||
|
|
||||||
# define CHECK_X_OK R_OK
|
#define CHECK_X_OK R_OK
|
||||||
|
|
||||||
# ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# define S_ISREG(x) ((x) & _S_IFREG)
|
#define S_ISREG(x) ((x)&_S_IFREG)
|
||||||
# define S_ISDIR(x) ((x) & _S_IFDIR)
|
#define S_ISDIR(x) ((x)&_S_IFDIR)
|
||||||
# define S_IRUSR _S_IREAD
|
#define S_IRUSR _S_IREAD
|
||||||
# define S_IWUSR _S_IWRITE
|
#define S_IWUSR _S_IWRITE
|
||||||
# define W_OK 2
|
#define W_OK 2
|
||||||
# define R_OK 4
|
#define R_OK 4
|
||||||
# else
|
#else
|
||||||
# define OPEN _wopen
|
#define OPEN _wopen
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
# define GET_CHARS GetStringChars
|
#define GET_CHARS GetStringChars
|
||||||
# define RELEASE_CHARS(path, chars) ReleaseStringChars(path, reinterpret_cast<const jchar*>(chars))
|
#define RELEASE_CHARS(path, chars) \
|
||||||
|
ReleaseStringChars(path, reinterpret_cast<const jchar*>(chars))
|
||||||
|
|
||||||
typedef wchar_t char_t;
|
typedef wchar_t char_t;
|
||||||
|
|
||||||
@ -68,44 +69,47 @@ typedef wchar_t char_t;
|
|||||||
|
|
||||||
#else // not PLATFORM_WINDOWS
|
#else // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
# include <dirent.h>
|
#include <dirent.h>
|
||||||
# include <unistd.h>
|
#include <unistd.h>
|
||||||
# include "sys/mman.h"
|
#include "sys/mman.h"
|
||||||
|
|
||||||
# define ACCESS access
|
#define ACCESS access
|
||||||
# define OPEN open
|
#define OPEN open
|
||||||
# define CLOSE close
|
#define CLOSE close
|
||||||
# define READ read
|
#define READ read
|
||||||
# define WRITE write
|
#define WRITE write
|
||||||
# define STAT stat
|
#define STAT stat
|
||||||
# define STRUCT_STAT struct stat
|
#define STRUCT_STAT struct stat
|
||||||
# define MKDIR mkdir
|
#define MKDIR mkdir
|
||||||
# define CHMOD chmod
|
#define CHMOD chmod
|
||||||
# define REMOVE remove
|
#define REMOVE remove
|
||||||
# define RENAME rename
|
#define RENAME rename
|
||||||
# define OPEN_MASK 0
|
#define OPEN_MASK 0
|
||||||
|
|
||||||
# define CHECK_X_OK X_OK
|
#define CHECK_X_OK X_OK
|
||||||
|
|
||||||
# define GET_CHARS GetStringUTFChars
|
#define GET_CHARS GetStringUTFChars
|
||||||
# define RELEASE_CHARS ReleaseStringUTFChars
|
#define RELEASE_CHARS ReleaseStringUTFChars
|
||||||
|
|
||||||
typedef char char_t;
|
typedef char char_t;
|
||||||
|
|
||||||
#endif // not PLATFORM_WINDOWS
|
#endif // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
#ifndef WINAPI_FAMILY
|
#ifndef WINAPI_FAMILY
|
||||||
# ifndef WINAPI_PARTITION_DESKTOP
|
#ifndef WINAPI_PARTITION_DESKTOP
|
||||||
# define WINAPI_PARTITION_DESKTOP 1
|
#define WINAPI_PARTITION_DESKTOP 1
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
# ifndef WINAPI_FAMILY_PARTITION
|
#ifndef WINAPI_FAMILY_PARTITION
|
||||||
# define WINAPI_FAMILY_PARTITION(x) (x)
|
#define WINAPI_FAMILY_PARTITION(x) (x)
|
||||||
# endif
|
#endif
|
||||||
#endif // WINAPI_FAMILY
|
#endif // WINAPI_FAMILY
|
||||||
|
|
||||||
#if !defined(SKIP_OPERATOR_NEW)
|
#if !defined(SKIP_OPERATOR_NEW)
|
||||||
inline void* operator new(size_t, void* p) throw() { return p; }
|
inline void* operator new(size_t, void* p) throw()
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef const char_t* string_t;
|
typedef const char_t* string_t;
|
||||||
@ -113,8 +117,7 @@ typedef const char_t* string_t;
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
inline int
|
inline int OPEN(string_t path, int mask, int mode)
|
||||||
OPEN(string_t path, int mask, int mode)
|
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
if (_wsopen_s(&fd, path, mask, _SH_DENYNO, mode) == 0) {
|
if (_wsopen_s(&fd, path, mask, _SH_DENYNO, mode) == 0) {
|
||||||
@ -125,8 +128,7 @@ OPEN(string_t path, int mask, int mode)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline bool
|
inline bool exists(string_t path)
|
||||||
exists(string_t path)
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
return GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES;
|
return GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES;
|
||||||
@ -136,8 +138,7 @@ exists(string_t path)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
inline int doOpen(JNIEnv* e, string_t path, int mask)
|
||||||
doOpen(JNIEnv* e, string_t path, int mask)
|
|
||||||
{
|
{
|
||||||
int fd = OPEN(path, mask | OPEN_MASK, S_IRUSR | S_IWUSR);
|
int fd = OPEN(path, mask | OPEN_MASK, S_IRUSR | S_IWUSR);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@ -150,8 +151,7 @@ doOpen(JNIEnv* e, string_t path, int mask)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void doClose(JNIEnv* e, jint fd)
|
||||||
doClose(JNIEnv* e, jint fd)
|
|
||||||
{
|
{
|
||||||
int r = CLOSE(fd);
|
int r = CLOSE(fd);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
@ -159,8 +159,7 @@ doClose(JNIEnv* e, jint fd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
inline int doRead(JNIEnv* e, jint fd, jbyte* data, jint length)
|
||||||
doRead(JNIEnv* e, jint fd, jbyte* data, jint length)
|
|
||||||
{
|
{
|
||||||
int r = READ(fd, data, length);
|
int r = READ(fd, data, length);
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
@ -173,8 +172,7 @@ doRead(JNIEnv* e, jint fd, jbyte* data, jint length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
|
||||||
doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
|
|
||||||
{
|
{
|
||||||
int r = WRITE(fd, data, length);
|
int r = WRITE(fd, data, length);
|
||||||
if (r != length) {
|
if (r != length) {
|
||||||
@ -182,14 +180,16 @@ doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
|
||||||
class Directory {
|
class Directory {
|
||||||
public:
|
public:
|
||||||
Directory(): handle(0), findNext(false) { }
|
Directory() : handle(0), findNext(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual string_t next() {
|
virtual string_t next()
|
||||||
|
{
|
||||||
if (handle and handle != INVALID_HANDLE_VALUE) {
|
if (handle and handle != INVALID_HANDLE_VALUE) {
|
||||||
if (findNext) {
|
if (findNext) {
|
||||||
if (FindNextFileW(handle, &data)) {
|
if (FindNextFileW(handle, &data)) {
|
||||||
@ -203,7 +203,8 @@ class Directory {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose()
|
||||||
|
{
|
||||||
if (handle and handle != INVALID_HANDLE_VALUE) {
|
if (handle and handle != INVALID_HANDLE_VALUE) {
|
||||||
FindClose(handle);
|
FindClose(handle);
|
||||||
}
|
}
|
||||||
@ -219,29 +220,30 @@ class Directory {
|
|||||||
|
|
||||||
#endif // not PLATFORM_WINDOWS
|
#endif // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
static inline string_t getChars(JNIEnv* e, jstring path) {
|
static inline string_t getChars(JNIEnv* e, jstring path)
|
||||||
|
{
|
||||||
return reinterpret_cast<string_t>(e->GET_CHARS(path, 0));
|
return reinterpret_cast<string_t>(e->GET_CHARS(path, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void releaseChars(JNIEnv* e, jstring path, string_t chars) {
|
static inline void releaseChars(JNIEnv* e, jstring path, string_t chars)
|
||||||
|
{
|
||||||
e->RELEASE_CHARS(path, chars);
|
e->RELEASE_CHARS(path, chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
Java_java_io_File_toCanonicalPath(JNIEnv* /*e*/, jclass, jstring path)
|
Java_java_io_File_toCanonicalPath(JNIEnv* /*e*/, jclass, jstring path)
|
||||||
{
|
{
|
||||||
// todo
|
// todo
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
|
Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
const unsigned BufferSize = MAX_PATH;
|
const unsigned BufferSize = MAX_PATH;
|
||||||
@ -250,25 +252,25 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
|
|||||||
releaseChars(e, path, chars);
|
releaseChars(e, path, chars);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
return e->NewString
|
return e->NewString(reinterpret_cast<const jchar*>(buffer),
|
||||||
(reinterpret_cast<const jchar*>(buffer), wcslen(buffer));
|
wcslen(buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
# else
|
#else
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if(chars) {
|
if (chars) {
|
||||||
std::wstring partialPath = chars;
|
std::wstring partialPath = chars;
|
||||||
releaseChars(e, path, chars);
|
releaseChars(e, path, chars);
|
||||||
|
|
||||||
std::wstring fullPath = AvianInterop::GetFullPath(partialPath);
|
std::wstring fullPath = AvianInterop::GetFullPath(partialPath);
|
||||||
|
|
||||||
return e->NewString
|
return e->NewString(reinterpret_cast<const jchar*>(fullPath.c_str()),
|
||||||
(reinterpret_cast<const jchar*>(fullPath.c_str()), fullPath.length());
|
fullPath.length());
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
# endif
|
#endif
|
||||||
#else
|
#else
|
||||||
jstring result = path;
|
jstring result = path;
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
@ -290,44 +292,43 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
// Option: without opening file
|
// Option: without opening file
|
||||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if(chars) {
|
if (chars) {
|
||||||
LARGE_INTEGER fileSize;
|
LARGE_INTEGER fileSize;
|
||||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
HANDLE file = CreateFileW
|
HANDLE file = CreateFileW(
|
||||||
(chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||||
#else
|
#else
|
||||||
HANDLE file = CreateFile2
|
HANDLE file = CreateFile2(
|
||||||
(chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
|
chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
|
||||||
#endif
|
#endif
|
||||||
releaseChars(e, path, chars);
|
releaseChars(e, path, chars);
|
||||||
if (file == INVALID_HANDLE_VALUE)
|
if (file == INVALID_HANDLE_VALUE)
|
||||||
return 0;
|
return 0;
|
||||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
if(!GetFileSizeEx(file, &fileSize))
|
if (!GetFileSizeEx(file, &fileSize)) {
|
||||||
{
|
|
||||||
CloseHandle(file);
|
CloseHandle(file);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
FILE_STANDARD_INFO info;
|
FILE_STANDARD_INFO info;
|
||||||
if(!GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info)))
|
if (!GetFileInformationByHandleEx(
|
||||||
{
|
file, FileStandardInfo, &info, sizeof(info))) {
|
||||||
CloseHandle(file);
|
CloseHandle(file);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fileSize = info.EndOfFile;
|
fileSize = info.EndOfFile;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CloseHandle(file);
|
CloseHandle(file);
|
||||||
return static_cast<jlong>(fileSize.QuadPart);
|
return static_cast<jlong>(fileSize.QuadPart);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -339,13 +340,13 @@ Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -360,7 +361,7 @@ Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
@ -382,7 +383,7 @@ Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_File_delete(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_delete(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -395,7 +396,7 @@ Java_java_io_File_delete(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_canRead(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_canRead(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -407,7 +408,7 @@ Java_java_io_File_canRead(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_canWrite(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_canWrite(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -419,7 +420,7 @@ Java_java_io_File_canWrite(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_canExecute(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_canExecute(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -432,13 +433,17 @@ Java_java_io_File_canExecute(JNIEnv* e, jclass, jstring path)
|
|||||||
|
|
||||||
#ifndef PLATFORM_WINDOWS
|
#ifndef PLATFORM_WINDOWS
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_setExecutable(JNIEnv* e, jclass, jstring path, jboolean executable, jboolean ownerOnly)
|
Java_java_io_File_setExecutable(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
|
jstring path,
|
||||||
|
jboolean executable,
|
||||||
|
jboolean ownerOnly)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if(chars) {
|
if (chars) {
|
||||||
jboolean v;
|
jboolean v;
|
||||||
int mask;
|
int mask;
|
||||||
if(ownerOnly) {
|
if (ownerOnly) {
|
||||||
mask = S_IXUSR;
|
mask = S_IXUSR;
|
||||||
} else {
|
} else {
|
||||||
mask = S_IXUSR | S_IXGRP | S_IXOTH;
|
mask = S_IXUSR | S_IXGRP | S_IXOTH;
|
||||||
@ -446,14 +451,14 @@ Java_java_io_File_setExecutable(JNIEnv* e, jclass, jstring path, jboolean execut
|
|||||||
|
|
||||||
STRUCT_STAT s;
|
STRUCT_STAT s;
|
||||||
int r = STAT(chars, &s);
|
int r = STAT(chars, &s);
|
||||||
if(r == 0) {
|
if (r == 0) {
|
||||||
int mode = s.st_mode;
|
int mode = s.st_mode;
|
||||||
if(executable) {
|
if (executable) {
|
||||||
mode |= mask;
|
mode |= mask;
|
||||||
} else {
|
} else {
|
||||||
mode &= ~mask;
|
mode &= ~mask;
|
||||||
}
|
}
|
||||||
if(CHMOD(chars, mode) != 0) {
|
if (CHMOD(chars, mode) != 0) {
|
||||||
v = false;
|
v = false;
|
||||||
} else {
|
} else {
|
||||||
v = true;
|
v = true;
|
||||||
@ -470,7 +475,11 @@ Java_java_io_File_setExecutable(JNIEnv* e, jclass, jstring path, jboolean execut
|
|||||||
#else // ifndef PLATFORM_WINDOWS
|
#else // ifndef PLATFORM_WINDOWS
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_setExecutable(JNIEnv*, jclass, jstring, jboolean executable, jboolean)
|
Java_java_io_File_setExecutable(JNIEnv*,
|
||||||
|
jclass,
|
||||||
|
jstring,
|
||||||
|
jboolean executable,
|
||||||
|
jboolean)
|
||||||
{
|
{
|
||||||
return executable;
|
return executable;
|
||||||
}
|
}
|
||||||
@ -478,7 +487,7 @@ Java_java_io_File_setExecutable(JNIEnv*, jclass, jstring, jboolean executable, j
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_rename(JNIEnv* e, jclass, jstring old, jstring new_)
|
Java_java_io_File_rename(JNIEnv* e, jclass, jstring old, jstring new_)
|
||||||
{
|
{
|
||||||
string_t oldChars = getChars(e, old);
|
string_t oldChars = getChars(e, old);
|
||||||
string_t newChars = getChars(e, new_);
|
string_t newChars = getChars(e, new_);
|
||||||
@ -499,7 +508,7 @@ Java_java_io_File_rename(JNIEnv* e, jclass, jstring old, jstring new_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_isDirectory(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_isDirectory(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -514,7 +523,7 @@ Java_java_io_File_isDirectory(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_isFile(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_isFile(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -529,7 +538,7 @@ Java_java_io_File_isFile(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_exists(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_exists(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -542,43 +551,42 @@ Java_java_io_File_exists(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
// Option: without opening file
|
// Option: without opening file
|
||||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx
|
||||||
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
HANDLE hFile = CreateFileW
|
HANDLE hFile = CreateFileW(
|
||||||
(chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||||
# else
|
#else
|
||||||
HANDLE hFile = CreateFile2
|
HANDLE hFile = CreateFile2(
|
||||||
(chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
|
chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
|
||||||
# endif
|
#endif
|
||||||
releaseChars(e, path, chars);
|
releaseChars(e, path, chars);
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
return 0;
|
return 0;
|
||||||
LARGE_INTEGER fileDate, filetimeToUnixEpochAdjustment;
|
LARGE_INTEGER fileDate, filetimeToUnixEpochAdjustment;
|
||||||
filetimeToUnixEpochAdjustment.QuadPart = 11644473600000L * 10000L;
|
filetimeToUnixEpochAdjustment.QuadPart = 11644473600000L * 10000L;
|
||||||
# if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
FILETIME fileLastWriteTime;
|
FILETIME fileLastWriteTime;
|
||||||
if (!GetFileTime(hFile, 0, 0, &fileLastWriteTime))
|
if (!GetFileTime(hFile, 0, 0, &fileLastWriteTime)) {
|
||||||
{
|
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fileDate.HighPart = fileLastWriteTime.dwHighDateTime;
|
fileDate.HighPart = fileLastWriteTime.dwHighDateTime;
|
||||||
fileDate.LowPart = fileLastWriteTime.dwLowDateTime;
|
fileDate.LowPart = fileLastWriteTime.dwLowDateTime;
|
||||||
# else
|
#else
|
||||||
FILE_BASIC_INFO fileInfo;
|
FILE_BASIC_INFO fileInfo;
|
||||||
if (!GetFileInformationByHandleEx(hFile, FileBasicInfo, &fileInfo, sizeof(fileInfo)))
|
if (!GetFileInformationByHandleEx(
|
||||||
{
|
hFile, FileBasicInfo, &fileInfo, sizeof(fileInfo))) {
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fileDate = fileInfo.ChangeTime;
|
fileDate = fileInfo.ChangeTime;
|
||||||
# endif
|
#endif
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
fileDate.QuadPart -= filetimeToUnixEpochAdjustment.QuadPart;
|
fileDate.QuadPart -= filetimeToUnixEpochAdjustment.QuadPart;
|
||||||
return fileDate.QuadPart / 10000000L;
|
return fileDate.QuadPart / 10000000L;
|
||||||
@ -590,13 +598,13 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
|
|||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
# ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#define MTIME st_mtimespec
|
#define MTIME st_mtimespec
|
||||||
# else
|
#else
|
||||||
#define MTIME st_mtim
|
#define MTIME st_mtim
|
||||||
# endif
|
#endif
|
||||||
return (static_cast<jlong>(fileStat.MTIME.tv_sec) * 1000) +
|
return (static_cast<jlong>(fileStat.MTIME.tv_sec) * 1000)
|
||||||
(static_cast<jlong>(fileStat.MTIME.tv_nsec) / (1000*1000));
|
+ (static_cast<jlong>(fileStat.MTIME.tv_nsec) / (1000 * 1000));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +614,7 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
|
|||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -620,11 +628,16 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
|||||||
releaseChars(e, path, chars);
|
releaseChars(e, path, chars);
|
||||||
|
|
||||||
Directory* d = new (malloc(sizeof(Directory))) Directory;
|
Directory* d = new (malloc(sizeof(Directory))) Directory;
|
||||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data));
|
d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data));
|
||||||
#else
|
#else
|
||||||
d->handle = FindFirstFileExW(RUNTIME_ARRAY_BODY(buffer), FindExInfoStandard, &(d->data), FindExSearchNameMatch, NULL, 0);
|
d->handle = FindFirstFileExW(RUNTIME_ARRAY_BODY(buffer),
|
||||||
#endif
|
FindExInfoStandard,
|
||||||
|
&(d->data),
|
||||||
|
FindExSearchNameMatch,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
#endif
|
||||||
if (d->handle == INVALID_HANDLE_VALUE) {
|
if (d->handle == INVALID_HANDLE_VALUE) {
|
||||||
d->dispose();
|
d->dispose();
|
||||||
d = 0;
|
d = 0;
|
||||||
@ -637,7 +650,7 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
|
Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
|
||||||
{
|
{
|
||||||
Directory* d = reinterpret_cast<Directory*>(handle);
|
Directory* d = reinterpret_cast<Directory*>(handle);
|
||||||
|
|
||||||
@ -656,7 +669,7 @@ Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_File_closeDir(JNIEnv* , jclass, jlong handle)
|
Java_java_io_File_closeDir(JNIEnv*, jclass, jlong handle)
|
||||||
{
|
{
|
||||||
reinterpret_cast<Directory*>(handle)->dispose();
|
reinterpret_cast<Directory*>(handle)->dispose();
|
||||||
}
|
}
|
||||||
@ -664,7 +677,7 @@ Java_java_io_File_closeDir(JNIEnv* , jclass, jlong handle)
|
|||||||
#else // not PLATFORM_WINDOWS
|
#else // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -677,18 +690,17 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
|
Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
|
||||||
{
|
{
|
||||||
struct dirent * directoryEntry;
|
struct dirent* directoryEntry;
|
||||||
|
|
||||||
if (handle!=0) {
|
if (handle != 0) {
|
||||||
while (true) {
|
while (true) {
|
||||||
directoryEntry = readdir(reinterpret_cast<DIR*>(handle));
|
directoryEntry = readdir(reinterpret_cast<DIR*>(handle));
|
||||||
if (directoryEntry == NULL) {
|
if (directoryEntry == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (strcmp(directoryEntry->d_name, ".") == 0
|
} else if (strcmp(directoryEntry->d_name, ".") == 0
|
||||||
|| strcmp(directoryEntry->d_name, "..") == 0)
|
|| strcmp(directoryEntry->d_name, "..") == 0) {
|
||||||
{
|
|
||||||
// skip . or .. and try again
|
// skip . or .. and try again
|
||||||
} else {
|
} else {
|
||||||
return e->NewStringUTF(directoryEntry->d_name);
|
return e->NewStringUTF(directoryEntry->d_name);
|
||||||
@ -699,9 +711,9 @@ Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_File_closeDir(JNIEnv* , jclass, jlong handle)
|
Java_java_io_File_closeDir(JNIEnv*, jclass, jlong handle)
|
||||||
{
|
{
|
||||||
if (handle!=0) {
|
if (handle != 0) {
|
||||||
closedir(reinterpret_cast<DIR*>(handle));
|
closedir(reinterpret_cast<DIR*>(handle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -709,7 +721,7 @@ Java_java_io_File_closeDir(JNIEnv* , jclass, jlong handle)
|
|||||||
#endif // not PLATFORM_WINDOWS
|
#endif // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_io_FileInputStream_open(JNIEnv* e, jclass, jstring path)
|
Java_java_io_FileInputStream_open(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
@ -722,7 +734,7 @@ Java_java_io_FileInputStream_open(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_io_FileInputStream_read__I(JNIEnv* e, jclass, jint fd)
|
Java_java_io_FileInputStream_read__I(JNIEnv* e, jclass, jint fd)
|
||||||
{
|
{
|
||||||
jbyte data;
|
jbyte data;
|
||||||
int r = doRead(e, fd, &data, 1);
|
int r = doRead(e, fd, &data, 1);
|
||||||
@ -734,8 +746,12 @@ Java_java_io_FileInputStream_read__I(JNIEnv* e, jclass, jint fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_io_FileInputStream_read__I_3BII
|
Java_java_io_FileInputStream_read__I_3BII(JNIEnv* e,
|
||||||
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
|
jclass,
|
||||||
|
jint fd,
|
||||||
|
jbyteArray b,
|
||||||
|
jint offset,
|
||||||
|
jint length)
|
||||||
{
|
{
|
||||||
jbyte* data = static_cast<jbyte*>(malloc(length));
|
jbyte* data = static_cast<jbyte*>(malloc(length));
|
||||||
if (data == 0) {
|
if (data == 0) {
|
||||||
@ -753,18 +769,22 @@ Java_java_io_FileInputStream_read__I_3BII
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_FileInputStream_close(JNIEnv* e, jclass, jint fd)
|
Java_java_io_FileInputStream_close(JNIEnv* e, jclass, jint fd)
|
||||||
{
|
{
|
||||||
doClose(e, fd);
|
doClose(e, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_io_FileOutputStream_open(JNIEnv* e, jclass, jstring path, jboolean append)
|
Java_java_io_FileOutputStream_open(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
|
jstring path,
|
||||||
|
jboolean append)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
int fd = doOpen(e, chars, append
|
int fd = doOpen(e,
|
||||||
? (O_WRONLY | O_CREAT | O_APPEND)
|
chars,
|
||||||
|
append ? (O_WRONLY | O_CREAT | O_APPEND)
|
||||||
: (O_WRONLY | O_CREAT | O_TRUNC));
|
: (O_WRONLY | O_CREAT | O_TRUNC));
|
||||||
releaseChars(e, path, chars);
|
releaseChars(e, path, chars);
|
||||||
return fd;
|
return fd;
|
||||||
@ -774,15 +794,19 @@ Java_java_io_FileOutputStream_open(JNIEnv* e, jclass, jstring path, jboolean app
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c)
|
Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c)
|
||||||
{
|
{
|
||||||
jbyte data = c;
|
jbyte data = c;
|
||||||
doWrite(e, fd, &data, 1);
|
doWrite(e, fd, &data, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_FileOutputStream_write__I_3BII
|
Java_java_io_FileOutputStream_write__I_3BII(JNIEnv* e,
|
||||||
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
|
jclass,
|
||||||
|
jint fd,
|
||||||
|
jbyteArray b,
|
||||||
|
jint offset,
|
||||||
|
jint length)
|
||||||
{
|
{
|
||||||
jbyte* data = static_cast<jbyte*>(malloc(length));
|
jbyte* data = static_cast<jbyte*>(malloc(length));
|
||||||
|
|
||||||
@ -800,49 +824,53 @@ Java_java_io_FileOutputStream_write__I_3BII
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint fd)
|
Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint fd)
|
||||||
{
|
{
|
||||||
doClose(e, fd);
|
doClose(e, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
|
Java_java_io_RandomAccessFile_open(JNIEnv* e,
|
||||||
jboolean allowWrite, jlongArray result)
|
jclass,
|
||||||
|
jstring path,
|
||||||
|
jboolean allowWrite,
|
||||||
|
jlongArray result)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
jlong peer = 0;
|
jlong peer = 0;
|
||||||
jlong length = 0;
|
jlong length = 0;
|
||||||
int flags = (allowWrite ? O_RDWR | O_CREAT : O_RDONLY) | OPEN_MASK;
|
int flags = (allowWrite ? O_RDWR | O_CREAT : O_RDONLY) | OPEN_MASK;
|
||||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
#if defined(PLATFORM_WINDOWS)
|
#if defined(PLATFORM_WINDOWS)
|
||||||
int fd = ::_wopen(chars, flags);
|
int fd = ::_wopen(chars, flags);
|
||||||
#else
|
#else
|
||||||
int fd = ::open((const char*)chars, flags, 0666);
|
int fd = ::open((const char*)chars, flags, 0666);
|
||||||
#endif
|
#endif
|
||||||
releaseChars(e, path, chars);
|
releaseChars(e, path, chars);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct ::stat fileStats;
|
struct ::stat fileStats;
|
||||||
if(::fstat(fd, &fileStats) == -1) {
|
if (::fstat(fd, &fileStats) == -1) {
|
||||||
::close(fd);
|
::close(fd);
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
peer = fd;
|
peer = fd;
|
||||||
length = fileStats.st_size;
|
length = fileStats.st_size;
|
||||||
#else
|
#else
|
||||||
HANDLE hFile = CreateFile2
|
HANDLE hFile = CreateFile2(
|
||||||
(chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
|
chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
|
||||||
if (hFile == INVALID_HANDLE_VALUE) {
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_STANDARD_INFO info;
|
FILE_STANDARD_INFO info;
|
||||||
if(!GetFileInformationByHandleEx(hFile, FileStandardInfo, &info, sizeof(info))) {
|
if (!GetFileInformationByHandleEx(
|
||||||
|
hFile, FileStandardInfo, &info, sizeof(info))) {
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return;
|
return;
|
||||||
@ -850,7 +878,7 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
|
|||||||
|
|
||||||
peer = (jlong)hFile;
|
peer = (jlong)hFile;
|
||||||
length = info.EndOfFile.QuadPart;
|
length = info.EndOfFile.QuadPart;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
e->SetLongArrayRegion(result, 0, 1, &peer);
|
e->SetLongArrayRegion(result, 0, 1, &peer);
|
||||||
e->SetLongArrayRegion(result, 1, 1, &length);
|
e->SetLongArrayRegion(result, 1, 1, &length);
|
||||||
@ -858,24 +886,28 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
Java_java_io_RandomAccessFile_readBytes(JNIEnv* e,
|
||||||
jlong position, jbyteArray buffer,
|
jclass,
|
||||||
int offset, int length)
|
jlong peer,
|
||||||
|
jlong position,
|
||||||
|
jbyteArray buffer,
|
||||||
|
int offset,
|
||||||
|
int length)
|
||||||
{
|
{
|
||||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
int fd = (int)peer;
|
int fd = (int)peer;
|
||||||
if(::lseek(fd, position, SEEK_SET) == -1) {
|
if (::lseek(fd, position, SEEK_SET) == -1) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
uint8_t* dst
|
||||||
(e->GetPrimitiveArrayCritical(buffer, 0));
|
= reinterpret_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, 0));
|
||||||
|
|
||||||
int64_t bytesRead = ::read(fd, dst + offset, length);
|
int64_t bytesRead = ::read(fd, dst + offset, length);
|
||||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||||
|
|
||||||
if(bytesRead == -1) {
|
if (bytesRead == -1) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -883,16 +915,16 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
|||||||
HANDLE hFile = (HANDLE)peer;
|
HANDLE hFile = (HANDLE)peer;
|
||||||
LARGE_INTEGER lPos;
|
LARGE_INTEGER lPos;
|
||||||
lPos.QuadPart = position;
|
lPos.QuadPart = position;
|
||||||
if(!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) {
|
if (!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
uint8_t* dst
|
||||||
(e->GetPrimitiveArrayCritical(buffer, 0));
|
= reinterpret_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, 0));
|
||||||
|
|
||||||
DWORD bytesRead = 0;
|
DWORD bytesRead = 0;
|
||||||
if(!ReadFile(hFile, dst + offset, length, &bytesRead, nullptr)) {
|
if (!ReadFile(hFile, dst + offset, length, &bytesRead, nullptr)) {
|
||||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
@ -904,24 +936,28 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, jclass, jlong peer,
|
Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e,
|
||||||
jlong position, jbyteArray buffer,
|
jclass,
|
||||||
int offset, int length)
|
jlong peer,
|
||||||
|
jlong position,
|
||||||
|
jbyteArray buffer,
|
||||||
|
int offset,
|
||||||
|
int length)
|
||||||
{
|
{
|
||||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
int fd = (int)peer;
|
int fd = (int)peer;
|
||||||
if(::lseek(fd, position, SEEK_SET) == -1) {
|
if (::lseek(fd, position, SEEK_SET) == -1) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
uint8_t* dst
|
||||||
(e->GetPrimitiveArrayCritical(buffer, 0));
|
= reinterpret_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, 0));
|
||||||
|
|
||||||
int64_t bytesWritten = ::write(fd, dst + offset, length);
|
int64_t bytesWritten = ::write(fd, dst + offset, length);
|
||||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||||
|
|
||||||
if(bytesWritten == -1) {
|
if (bytesWritten == -1) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -929,16 +965,16 @@ Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, jclass, jlong peer,
|
|||||||
HANDLE hFile = (HANDLE)peer;
|
HANDLE hFile = (HANDLE)peer;
|
||||||
LARGE_INTEGER lPos;
|
LARGE_INTEGER lPos;
|
||||||
lPos.QuadPart = position;
|
lPos.QuadPart = position;
|
||||||
if(!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) {
|
if (!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
uint8_t* dst
|
||||||
(e->GetPrimitiveArrayCritical(buffer, 0));
|
= reinterpret_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, 0));
|
||||||
|
|
||||||
DWORD bytesWritten = 0;
|
DWORD bytesWritten = 0;
|
||||||
if(!WriteFile(hFile, dst + offset, length, &bytesWritten, nullptr)) {
|
if (!WriteFile(hFile, dst + offset, length, &bytesWritten, nullptr)) {
|
||||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
@ -950,7 +986,7 @@ Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, jclass, jlong peer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer)
|
Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer)
|
||||||
{
|
{
|
||||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
int fd = (int)peer;
|
int fd = (int)peer;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -15,48 +15,62 @@
|
|||||||
|
|
||||||
using namespace avian::classpath::sockets;
|
using namespace avian::classpath::sockets;
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_init(JNIEnv* e, jclass)
|
||||||
Java_java_net_Socket_init(JNIEnv* e, jclass) {
|
{
|
||||||
init(e);
|
init(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT SOCKET JNICALL
|
extern "C" JNIEXPORT SOCKET JNICALL
|
||||||
Java_java_net_Socket_create(JNIEnv* e, jclass) {
|
Java_java_net_Socket_create(JNIEnv* e, jclass)
|
||||||
|
{
|
||||||
return create(e);
|
return create(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_connect(JNIEnv* e,
|
||||||
Java_java_net_Socket_connect(JNIEnv* e, jclass, SOCKET sock, long addr, short port) {
|
jclass,
|
||||||
|
SOCKET sock,
|
||||||
|
long addr,
|
||||||
|
short port)
|
||||||
|
{
|
||||||
connect(e, sock, addr, port);
|
connect(e, sock, addr, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_bind(JNIEnv* e,
|
||||||
Java_java_net_Socket_bind(JNIEnv* e, jclass, SOCKET sock, long addr, short port) {
|
jclass,
|
||||||
|
SOCKET sock,
|
||||||
|
long addr,
|
||||||
|
short port)
|
||||||
|
{
|
||||||
bind(e, sock, addr, port);
|
bind(e, sock, addr, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_net_Socket_abort(JNIEnv* e, jclass, SOCKET sock) {
|
Java_java_net_Socket_abort(JNIEnv* e, jclass, SOCKET sock)
|
||||||
|
{
|
||||||
abort(e, sock);
|
abort(e, sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_net_Socket_close(JNIEnv* e, jclass, SOCKET sock) {
|
Java_java_net_Socket_close(JNIEnv* e, jclass, SOCKET sock)
|
||||||
|
{
|
||||||
close(e, sock);
|
close(e, sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_net_Socket_closeOutput(JNIEnv* e, jclass, SOCKET sock) {
|
Java_java_net_Socket_closeOutput(JNIEnv* e, jclass, SOCKET sock)
|
||||||
|
{
|
||||||
close_output(e, sock);
|
close_output(e, sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_net_Socket_closeInput(JNIEnv* e, jclass, SOCKET sock) {
|
Java_java_net_Socket_closeInput(JNIEnv* e, jclass, SOCKET sock)
|
||||||
|
{
|
||||||
close_input(e, sock);
|
close_input(e, sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments)
|
||||||
|
{ /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||||
t, reinterpret_cast<vm::object>(arguments[2]));
|
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||||
@ -67,7 +81,8 @@ Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments) { /
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments)
|
||||||
|
{ /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||||
t, reinterpret_cast<vm::object>(arguments[2]));
|
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||||
@ -78,7 +93,7 @@ Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments) { /
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jstring name)
|
jstring name)
|
||||||
{
|
{
|
||||||
@ -107,8 +122,8 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
|||||||
throwNew(e, "java/net/UnknownHostException", 0);
|
throwNew(e, "java/net/UnknownHostException", 0);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
int address = ntohl
|
int address = ntohl(
|
||||||
(reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
|
reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
|
||||||
|
|
||||||
freeaddrinfo(result);
|
freeaddrinfo(result);
|
||||||
return address;
|
return address;
|
||||||
@ -119,4 +134,3 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,25 +17,25 @@
|
|||||||
#include "jni-util.h"
|
#include "jni-util.h"
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
# include <winsock2.h>
|
#include <winsock2.h>
|
||||||
# include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
# include <errno.h>
|
#include <errno.h>
|
||||||
# ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# define snprintf sprintf_s
|
#define snprintf sprintf_s
|
||||||
# else
|
|
||||||
# include <unistd.h>
|
|
||||||
# endif
|
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
#include <unistd.h>
|
||||||
# include <fcntl.h>
|
#endif
|
||||||
# include <errno.h>
|
#else
|
||||||
# include <netdb.h>
|
#include <unistd.h>
|
||||||
# include <sys/select.h>
|
#include <fcntl.h>
|
||||||
# include <arpa/inet.h>
|
#include <errno.h>
|
||||||
# include <netinet/in.h>
|
#include <netdb.h>
|
||||||
# include <netinet/ip.h>
|
#include <sys/select.h>
|
||||||
# include <netinet/tcp.h>
|
#include <arpa/inet.h>
|
||||||
# include <sys/socket.h>
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define java_nio_channels_SelectionKey_OP_READ 1L
|
#define java_nio_channels_SelectionKey_OP_READ 1L
|
||||||
@ -47,12 +47,14 @@
|
|||||||
typedef int socklen_t;
|
typedef int socklen_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void* operator new(size_t, void* p) throw() { return p; }
|
inline void* operator new(size_t, void* p) throw()
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
inline jbyteArray
|
inline jbyteArray charsToArray(JNIEnv* e, const char* s)
|
||||||
charsToArray(JNIEnv* e, const char* s)
|
|
||||||
{
|
{
|
||||||
unsigned length = strlen(s);
|
unsigned length = strlen(s);
|
||||||
jbyteArray a = e->NewByteArray(length + 1);
|
jbyteArray a = e->NewByteArray(length + 1);
|
||||||
@ -60,8 +62,7 @@ charsToArray(JNIEnv* e, const char* s)
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void doClose(int socket)
|
||||||
doClose(int socket)
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
closesocket(socket);
|
closesocket(socket);
|
||||||
@ -70,8 +71,7 @@ doClose(int socket)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jbyteArray
|
inline jbyteArray errorString(JNIEnv* e, int n)
|
||||||
errorString(JNIEnv* e, int n)
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
const unsigned size = 128;
|
const unsigned size = 128;
|
||||||
@ -83,8 +83,7 @@ errorString(JNIEnv* e, int n)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jbyteArray
|
inline jbyteArray socketErrorString(JNIEnv* e, int n)
|
||||||
socketErrorString(JNIEnv* e, int n)
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
const unsigned size = 64;
|
const unsigned size = 64;
|
||||||
@ -96,8 +95,7 @@ socketErrorString(JNIEnv* e, int n)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jbyteArray
|
inline jbyteArray errorString(JNIEnv* e)
|
||||||
errorString(JNIEnv* e)
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
const unsigned size = 64;
|
const unsigned size = 64;
|
||||||
@ -109,8 +107,7 @@ errorString(JNIEnv* e)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void throwIOException(JNIEnv* e, const char* s)
|
||||||
throwIOException(JNIEnv* e, const char* s)
|
|
||||||
{
|
{
|
||||||
throwNew(e, "java/io/IOException", s);
|
throwNew(e, "java/io/IOException", s);
|
||||||
}
|
}
|
||||||
@ -128,20 +125,17 @@ void throwIOException(JNIEnv* e, jbyteArray a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void throwIOException(JNIEnv* e)
|
||||||
throwIOException(JNIEnv* e)
|
|
||||||
{
|
{
|
||||||
throwIOException(e, errorString(e));
|
throwIOException(e, errorString(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void throwSocketException(JNIEnv* e, const char* s)
|
||||||
throwSocketException(JNIEnv* e, const char* s)
|
|
||||||
{
|
{
|
||||||
throwNew(e, "java/net/SocketException", s);
|
throwNew(e, "java/net/SocketException", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void throwSocketException(JNIEnv* e, jbyteArray a)
|
||||||
throwSocketException(JNIEnv* e, jbyteArray a)
|
|
||||||
{
|
{
|
||||||
size_t length = e->GetArrayLength(a);
|
size_t length = e->GetArrayLength(a);
|
||||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||||
@ -154,8 +148,7 @@ throwSocketException(JNIEnv* e, jbyteArray a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void throwSocketException(JNIEnv* e)
|
||||||
throwSocketException(JNIEnv* e)
|
|
||||||
{
|
{
|
||||||
throwSocketException(e, errorString(e));
|
throwSocketException(e, errorString(e));
|
||||||
}
|
}
|
||||||
@ -168,19 +161,16 @@ void init(sockaddr_in* address, jint host, jint port)
|
|||||||
address->sin_addr.s_addr = htonl(host);
|
address->sin_addr.s_addr = htonl(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool einProgress(int error)
|
||||||
einProgress(int error)
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
return error == WSAEINPROGRESS
|
return error == WSAEINPROGRESS or error == WSAEWOULDBLOCK;
|
||||||
or error == WSAEWOULDBLOCK;
|
|
||||||
#else
|
#else
|
||||||
return error == EINPROGRESS;
|
return error == EINPROGRESS;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool einProgress()
|
||||||
einProgress()
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
return WSAGetLastError() == WSAEINPROGRESS
|
return WSAGetLastError() == WSAEINPROGRESS
|
||||||
@ -190,8 +180,7 @@ einProgress()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool eagain()
|
||||||
eagain()
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
return WSAGetLastError() == WSAEINPROGRESS
|
return WSAGetLastError() == WSAEINPROGRESS
|
||||||
@ -201,8 +190,7 @@ eagain()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool setBlocking(JNIEnv* e, int d, bool blocking)
|
||||||
setBlocking(JNIEnv* e, int d, bool blocking)
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
u_long a = (blocking ? 0 : 1);
|
u_long a = (blocking ? 0 : 1);
|
||||||
@ -212,8 +200,9 @@ setBlocking(JNIEnv* e, int d, bool blocking)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int r = fcntl(d, F_SETFL, (blocking
|
int r = fcntl(d,
|
||||||
? (fcntl(d, F_GETFL) & (~O_NONBLOCK))
|
F_SETFL,
|
||||||
|
(blocking ? (fcntl(d, F_GETFL) & (~O_NONBLOCK))
|
||||||
: (fcntl(d, F_GETFL) | O_NONBLOCK)));
|
: (fcntl(d, F_GETFL) | O_NONBLOCK)));
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
@ -223,12 +212,11 @@ setBlocking(JNIEnv* e, int d, bool blocking)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool setTcpNoDelay(JNIEnv* e, int d, bool on)
|
||||||
setTcpNoDelay(JNIEnv* e, int d, bool on)
|
|
||||||
{
|
{
|
||||||
int flag = on;
|
int flag = on;
|
||||||
int r = setsockopt
|
int r = setsockopt(
|
||||||
(d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&flag), sizeof(int));
|
d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&flag), sizeof(int));
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
throwSocketException(e);
|
throwSocketException(e);
|
||||||
return false;
|
return false;
|
||||||
@ -236,12 +224,15 @@ setTcpNoDelay(JNIEnv* e, int d, bool on)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void doBind(JNIEnv* e, int s, sockaddr_in* address)
|
||||||
doBind(JNIEnv* e, int s, sockaddr_in* address)
|
|
||||||
{
|
{
|
||||||
{ int opt = 1;
|
{
|
||||||
int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
int opt = 1;
|
||||||
reinterpret_cast<char*>(&opt), sizeof(int));
|
int r = ::setsockopt(s,
|
||||||
|
SOL_SOCKET,
|
||||||
|
SO_REUSEADDR,
|
||||||
|
reinterpret_cast<char*>(&opt),
|
||||||
|
sizeof(int));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
return;
|
return;
|
||||||
@ -249,9 +240,13 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SO_NOSIGPIPE
|
#ifdef SO_NOSIGPIPE
|
||||||
{ int opt = 1;
|
{
|
||||||
int r = ::setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE,
|
int opt = 1;
|
||||||
reinterpret_cast<char*>(&opt), sizeof(int));
|
int r = ::setsockopt(s,
|
||||||
|
SOL_SOCKET,
|
||||||
|
SO_NOSIGPIPE,
|
||||||
|
reinterpret_cast<char*>(&opt),
|
||||||
|
sizeof(int));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
return;
|
return;
|
||||||
@ -259,8 +254,9 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ int r = ::bind
|
{
|
||||||
(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
int r
|
||||||
|
= ::bind(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
return;
|
return;
|
||||||
@ -268,8 +264,7 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void doListen(JNIEnv* e, int s)
|
||||||
doListen(JNIEnv* e, int s)
|
|
||||||
{
|
{
|
||||||
int r = ::listen(s, 100);
|
int r = ::listen(s, 100);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
@ -277,13 +272,12 @@ doListen(JNIEnv* e, int s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void doFinishConnect(JNIEnv* e, int socket)
|
||||||
doFinishConnect(JNIEnv* e, int socket)
|
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
socklen_t size = sizeof(int);
|
socklen_t size = sizeof(int);
|
||||||
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR,
|
int r = getsockopt(
|
||||||
reinterpret_cast<char*>(&error), &size);
|
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
|
||||||
|
|
||||||
if (r != 0 or size != sizeof(int)) {
|
if (r != 0 or size != sizeof(int)) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
@ -292,11 +286,10 @@ doFinishConnect(JNIEnv* e, int socket)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool doConnect(JNIEnv* e, int s, sockaddr_in* address)
|
||||||
doConnect(JNIEnv* e, int s, sockaddr_in* address)
|
|
||||||
{
|
{
|
||||||
int r = ::connect(s, reinterpret_cast<sockaddr*>(address),
|
int r
|
||||||
sizeof(sockaddr_in));
|
= ::connect(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
return true;
|
return true;
|
||||||
} else if (not einProgress()) {
|
} else if (not einProgress()) {
|
||||||
@ -307,8 +300,7 @@ doConnect(JNIEnv* e, int s, sockaddr_in* address)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int doAccept(JNIEnv* e, int s)
|
||||||
doAccept(JNIEnv* e, int s)
|
|
||||||
{
|
{
|
||||||
sockaddr address;
|
sockaddr address;
|
||||||
socklen_t length = sizeof(address);
|
socklen_t length = sizeof(address);
|
||||||
@ -321,8 +313,7 @@ doAccept(JNIEnv* e, int s)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int doRead(int fd, void* buffer, size_t count)
|
||||||
doRead(int fd, void* buffer, size_t count)
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
return recv(fd, static_cast<char*>(buffer), count, 0);
|
return recv(fd, static_cast<char*>(buffer), count, 0);
|
||||||
@ -331,16 +322,15 @@ doRead(int fd, void* buffer, size_t count)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
|
||||||
doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
|
|
||||||
{
|
{
|
||||||
sockaddr address;
|
sockaddr address;
|
||||||
socklen_t length = sizeof(address);
|
socklen_t length = sizeof(address);
|
||||||
int r = recvfrom
|
int r = recvfrom(fd, static_cast<char*>(buffer), count, 0, &address, &length);
|
||||||
(fd, static_cast<char*>(buffer), count, 0, &address, &length);
|
|
||||||
|
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
sockaddr_in a; memcpy(&a, &address, length);
|
sockaddr_in a;
|
||||||
|
memcpy(&a, &address, length);
|
||||||
*host = ntohl(a.sin_addr.s_addr);
|
*host = ntohl(a.sin_addr.s_addr);
|
||||||
*port = ntohs(a.sin_port);
|
*port = ntohs(a.sin_port);
|
||||||
} else {
|
} else {
|
||||||
@ -351,8 +341,7 @@ doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int doWrite(int fd, const void* buffer, size_t count)
|
||||||
doWrite(int fd, const void* buffer, size_t count)
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
return send(fd, static_cast<const char*>(buffer), count, 0);
|
return send(fd, static_cast<const char*>(buffer), count, 0);
|
||||||
@ -384,9 +373,10 @@ int makeSocket(JNIEnv* e, int type = SOCK_STREAM, int protocol = IPPROTO_TCP)
|
|||||||
|
|
||||||
} // namespace <anonymous>
|
} // namespace <anonymous>
|
||||||
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_nio_channels_ServerSocketChannel_natDoAccept(JNIEnv *e, jclass, jint socket)
|
Java_java_nio_channels_ServerSocketChannel_natDoAccept(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
|
jint socket)
|
||||||
{
|
{
|
||||||
return ::doAccept(e, socket);
|
return ::doAccept(e, socket);
|
||||||
}
|
}
|
||||||
@ -432,7 +422,7 @@ extern "C" JNIEXPORT void JNICALL
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jint socket,
|
jint socket,
|
||||||
jboolean blocking)
|
jboolean blocking)
|
||||||
@ -441,17 +431,17 @@ Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv *e,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e,
|
Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e,
|
||||||
jclass c,
|
jclass c,
|
||||||
jint socket,
|
jint socket,
|
||||||
jboolean blocking)
|
jboolean blocking)
|
||||||
{
|
{
|
||||||
return Java_java_nio_channels_SocketChannel_configureBlocking
|
return Java_java_nio_channels_SocketChannel_configureBlocking(
|
||||||
(e, c, socket, blocking);
|
e, c, socket, blocking);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jint socket,
|
jint socket,
|
||||||
jboolean on)
|
jboolean on)
|
||||||
@ -498,7 +488,7 @@ extern "C" JNIEXPORT jboolean JNICALL
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jint socket)
|
jint socket)
|
||||||
{
|
{
|
||||||
@ -506,7 +496,7 @@ Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv *e,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_natRead(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jint socket,
|
jint socket,
|
||||||
jbyteArray buffer,
|
jbyteArray buffer,
|
||||||
@ -520,8 +510,7 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
|
|||||||
if (buf) {
|
if (buf) {
|
||||||
r = ::doRead(socket, buf, length);
|
r = ::doRead(socket, buf, length);
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
e->SetByteArrayRegion
|
e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
||||||
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
} else {
|
} else {
|
||||||
@ -529,8 +518,8 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
jboolean isCopy;
|
jboolean isCopy;
|
||||||
uint8_t* buf = static_cast<uint8_t*>
|
uint8_t* buf
|
||||||
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||||
|
|
||||||
r = ::doRead(socket, buf + offset, length);
|
r = ::doRead(socket, buf + offset, length);
|
||||||
|
|
||||||
@ -550,7 +539,7 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jint socket,
|
jint socket,
|
||||||
jbyteArray buffer,
|
jbyteArray buffer,
|
||||||
@ -567,8 +556,7 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
|||||||
if (buf) {
|
if (buf) {
|
||||||
r = ::doRecv(socket, buf, length, &host, &port);
|
r = ::doRecv(socket, buf, length, &host, &port);
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
e->SetByteArrayRegion
|
e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
||||||
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
} else {
|
} else {
|
||||||
@ -576,8 +564,8 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
jboolean isCopy;
|
jboolean isCopy;
|
||||||
uint8_t* buf = static_cast<uint8_t*>
|
uint8_t* buf
|
||||||
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||||
|
|
||||||
r = ::doRecv(socket, buf + offset, length, &host, &port);
|
r = ::doRecv(socket, buf + offset, length, &host, &port);
|
||||||
|
|
||||||
@ -593,15 +581,17 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
|||||||
} else if (r == 0) {
|
} else if (r == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
jint jhost = host; e->SetIntArrayRegion(address, 0, 1, &jhost);
|
jint jhost = host;
|
||||||
jint jport = port; e->SetIntArrayRegion(address, 1, 1, &jport);
|
e->SetIntArrayRegion(address, 0, 1, &jhost);
|
||||||
|
jint jport = port;
|
||||||
|
e->SetIntArrayRegion(address, 1, 1, &jport);
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_natWrite(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jint socket,
|
jint socket,
|
||||||
jbyteArray buffer,
|
jbyteArray buffer,
|
||||||
@ -613,8 +603,8 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
|
|||||||
if (blocking) {
|
if (blocking) {
|
||||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||||
if (buf) {
|
if (buf) {
|
||||||
e->GetByteArrayRegion
|
e->GetByteArrayRegion(
|
||||||
(buffer, offset, length, reinterpret_cast<jbyte*>(buf));
|
buffer, offset, length, reinterpret_cast<jbyte*>(buf));
|
||||||
r = ::doWrite(socket, buf, length);
|
r = ::doWrite(socket, buf, length);
|
||||||
free(buf);
|
free(buf);
|
||||||
} else {
|
} else {
|
||||||
@ -622,8 +612,8 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
jboolean isCopy;
|
jboolean isCopy;
|
||||||
uint8_t* buf = static_cast<uint8_t*>
|
uint8_t* buf
|
||||||
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||||
|
|
||||||
r = ::doWrite(socket, buf + offset, length);
|
r = ::doWrite(socket, buf + offset, length);
|
||||||
|
|
||||||
@ -641,7 +631,7 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_nio_channels_DatagramChannel_write(JNIEnv* e,
|
Java_java_nio_channels_DatagramChannel_write(JNIEnv* e,
|
||||||
jclass c,
|
jclass c,
|
||||||
jint socket,
|
jint socket,
|
||||||
jbyteArray buffer,
|
jbyteArray buffer,
|
||||||
@ -649,8 +639,8 @@ Java_java_nio_channels_DatagramChannel_write(JNIEnv* e,
|
|||||||
jint length,
|
jint length,
|
||||||
jboolean blocking)
|
jboolean blocking)
|
||||||
{
|
{
|
||||||
return Java_java_nio_channels_SocketChannel_natWrite
|
return Java_java_nio_channels_SocketChannel_natWrite(
|
||||||
(e, c, socket, buffer, offset, length, blocking);
|
e, c, socket, buffer, offset, length, blocking);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
@ -699,14 +689,14 @@ extern "C" JNIEXPORT jint JNICALL
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jint socket)
|
jint socket)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
socklen_t size = sizeof(int);
|
socklen_t size = sizeof(int);
|
||||||
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR,
|
int r = getsockopt(
|
||||||
reinterpret_cast<char*>(&error), &size);
|
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
|
||||||
if (r != 0 or size != sizeof(int)) {
|
if (r != 0 or size != sizeof(int)) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
} else if (error != 0) {
|
} else if (error != 0) {
|
||||||
@ -715,7 +705,7 @@ Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv *,
|
Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv*,
|
||||||
jclass,
|
jclass,
|
||||||
jint socket)
|
jint socket)
|
||||||
{
|
{
|
||||||
@ -723,9 +713,7 @@ Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv *,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_DatagramChannel_close(JNIEnv *,
|
Java_java_nio_channels_DatagramChannel_close(JNIEnv*, jclass, jint socket)
|
||||||
jclass,
|
|
||||||
jint socket)
|
|
||||||
{
|
{
|
||||||
doClose(socket);
|
doClose(socket);
|
||||||
}
|
}
|
||||||
@ -739,69 +727,85 @@ class Pipe {
|
|||||||
// pipe descriptors or others. Thus, to implement
|
// pipe descriptors or others. Thus, to implement
|
||||||
// Selector.wakeup(), we make a socket connection via the loopback
|
// Selector.wakeup(), we make a socket connection via the loopback
|
||||||
// interface and use it as a pipe.
|
// interface and use it as a pipe.
|
||||||
Pipe(JNIEnv* e): connected_(false), listener_(-1), reader_(-1), writer_(-1) {
|
Pipe(JNIEnv* e) : connected_(false), listener_(-1), reader_(-1), writer_(-1)
|
||||||
|
{
|
||||||
sockaddr_in address;
|
sockaddr_in address;
|
||||||
address.sin_family = AF_INET;
|
address.sin_family = AF_INET;
|
||||||
address.sin_port = 0;
|
address.sin_port = 0;
|
||||||
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //INADDR_LOOPBACK;
|
address.sin_addr.s_addr = inet_addr("127.0.0.1"); // INADDR_LOOPBACK;
|
||||||
|
|
||||||
listener_ = makeSocket(e);
|
listener_ = makeSocket(e);
|
||||||
if (e->ExceptionCheck()) return;
|
if (e->ExceptionCheck())
|
||||||
|
return;
|
||||||
|
|
||||||
setBlocking(e, listener_, false);
|
setBlocking(e, listener_, false);
|
||||||
|
|
||||||
::doBind(e, listener_, &address);
|
::doBind(e, listener_, &address);
|
||||||
if (e->ExceptionCheck()) return;
|
if (e->ExceptionCheck())
|
||||||
|
return;
|
||||||
|
|
||||||
::doListen(e, listener_);
|
::doListen(e, listener_);
|
||||||
if (e->ExceptionCheck()) return;
|
if (e->ExceptionCheck())
|
||||||
|
return;
|
||||||
|
|
||||||
socklen_t length = sizeof(sockaddr_in);
|
socklen_t length = sizeof(sockaddr_in);
|
||||||
int r = getsockname(listener_, reinterpret_cast<sockaddr*>(&address),
|
int r = getsockname(
|
||||||
&length);
|
listener_, reinterpret_cast<sockaddr*>(&address), &length);
|
||||||
if (r) {
|
if (r) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writer_ = makeSocket(e);
|
writer_ = makeSocket(e);
|
||||||
if (e->ExceptionCheck()) return;
|
if (e->ExceptionCheck())
|
||||||
|
return;
|
||||||
|
|
||||||
setBlocking(e, writer_, true);
|
setBlocking(e, writer_, true);
|
||||||
connected_ = ::doConnect(e, writer_, &address);
|
connected_ = ::doConnect(e, writer_, &address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose()
|
||||||
if (listener_ >= 0) ::doClose(listener_);
|
{
|
||||||
if (reader_ >= 0) ::doClose(reader_);
|
if (listener_ >= 0)
|
||||||
if (writer_ >= 0) ::doClose(writer_);
|
::doClose(listener_);
|
||||||
|
if (reader_ >= 0)
|
||||||
|
::doClose(reader_);
|
||||||
|
if (writer_ >= 0)
|
||||||
|
::doClose(writer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool connected() {
|
bool connected()
|
||||||
|
{
|
||||||
return connected_;
|
return connected_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setConnected(bool v) {
|
void setConnected(bool v)
|
||||||
|
{
|
||||||
connected_ = v;
|
connected_ = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int listener() {
|
int listener()
|
||||||
|
{
|
||||||
return listener_;
|
return listener_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setListener(int v) {
|
void setListener(int v)
|
||||||
|
{
|
||||||
listener_ = v;
|
listener_ = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int reader() {
|
int reader()
|
||||||
|
{
|
||||||
return reader_;
|
return reader_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setReader(int v) {
|
void setReader(int v)
|
||||||
|
{
|
||||||
reader_ = v;
|
reader_ = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int writer() {
|
int writer()
|
||||||
|
{
|
||||||
return writer_;
|
return writer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,7 +815,8 @@ class Pipe {
|
|||||||
int reader_;
|
int reader_;
|
||||||
int writer_;
|
int writer_;
|
||||||
#else
|
#else
|
||||||
Pipe(JNIEnv* e) {
|
Pipe(JNIEnv* e)
|
||||||
|
{
|
||||||
if (::pipe(pipe) != 0) {
|
if (::pipe(pipe) != 0) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
return;
|
return;
|
||||||
@ -824,21 +829,25 @@ class Pipe {
|
|||||||
open_ = true;
|
open_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose()
|
||||||
|
{
|
||||||
::doClose(pipe[0]);
|
::doClose(pipe[0]);
|
||||||
::doClose(pipe[1]);
|
::doClose(pipe[1]);
|
||||||
open_ = false;
|
open_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool connected() {
|
bool connected()
|
||||||
|
{
|
||||||
return open_;
|
return open_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int reader() {
|
int reader()
|
||||||
|
{
|
||||||
return pipe[0];
|
return pipe[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
int writer() {
|
int writer()
|
||||||
|
{
|
||||||
return pipe[1];
|
return pipe[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -853,18 +862,21 @@ struct SelectorState {
|
|||||||
fd_set write;
|
fd_set write;
|
||||||
fd_set except;
|
fd_set except;
|
||||||
Pipe control;
|
Pipe control;
|
||||||
SelectorState(JNIEnv* e) : control(e) { }
|
SelectorState(JNIEnv* e) : control(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass)
|
Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass)
|
||||||
{
|
{
|
||||||
void *mem = malloc(sizeof(SelectorState));
|
void* mem = malloc(sizeof(SelectorState));
|
||||||
if (mem) {
|
if (mem) {
|
||||||
SelectorState *s = new (mem) SelectorState(e);
|
SelectorState* s = new (mem) SelectorState(e);
|
||||||
if (e->ExceptionCheck()) return 0;
|
if (e->ExceptionCheck())
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (s) {
|
if (s) {
|
||||||
FD_ZERO(&(s->read));
|
FD_ZERO(&(s->read));
|
||||||
@ -878,7 +890,9 @@ Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv *e, jclass, jlong state)
|
Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
|
jlong state)
|
||||||
{
|
{
|
||||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||||
if (s->control.connected()) {
|
if (s->control.connected()) {
|
||||||
@ -891,7 +905,7 @@ Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv *e, jclass, jlong state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketSelector_natClose(JNIEnv *, jclass, jlong state)
|
Java_java_nio_channels_SocketSelector_natClose(JNIEnv*, jclass, jlong state)
|
||||||
{
|
{
|
||||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||||
s->control.dispose();
|
s->control.dispose();
|
||||||
@ -899,7 +913,8 @@ Java_java_nio_channels_SocketSelector_natClose(JNIEnv *, jclass, jlong state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv *, jclass,
|
Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv*,
|
||||||
|
jclass,
|
||||||
jint socket,
|
jint socket,
|
||||||
jlong state)
|
jlong state)
|
||||||
{
|
{
|
||||||
@ -910,7 +925,8 @@ Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv *, jclass,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *,
|
Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(
|
||||||
|
JNIEnv*,
|
||||||
jclass,
|
jclass,
|
||||||
jint socket,
|
jint socket,
|
||||||
jint interest,
|
jint interest,
|
||||||
@ -918,19 +934,21 @@ Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *,
|
|||||||
jint max)
|
jint max)
|
||||||
{
|
{
|
||||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||||
if (interest & (java_nio_channels_SelectionKey_OP_READ |
|
if (interest & (java_nio_channels_SelectionKey_OP_READ
|
||||||
java_nio_channels_SelectionKey_OP_ACCEPT)) {
|
| java_nio_channels_SelectionKey_OP_ACCEPT)) {
|
||||||
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
||||||
if (max < socket) max = socket;
|
if (max < socket)
|
||||||
|
max = socket;
|
||||||
} else {
|
} else {
|
||||||
FD_CLR(static_cast<unsigned>(socket), &(s->read));
|
FD_CLR(static_cast<unsigned>(socket), &(s->read));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interest & (java_nio_channels_SelectionKey_OP_WRITE |
|
if (interest & (java_nio_channels_SelectionKey_OP_WRITE
|
||||||
java_nio_channels_SelectionKey_OP_CONNECT)) {
|
| java_nio_channels_SelectionKey_OP_CONNECT)) {
|
||||||
FD_SET(static_cast<unsigned>(socket), &(s->write));
|
FD_SET(static_cast<unsigned>(socket), &(s->write));
|
||||||
FD_SET(static_cast<unsigned>(socket), &(s->except));
|
FD_SET(static_cast<unsigned>(socket), &(s->except));
|
||||||
if (max < socket) max = socket;
|
if (max < socket)
|
||||||
|
max = socket;
|
||||||
} else {
|
} else {
|
||||||
FD_CLR(static_cast<unsigned>(socket), &(s->write));
|
FD_CLR(static_cast<unsigned>(socket), &(s->write));
|
||||||
}
|
}
|
||||||
@ -938,7 +956,8 @@ Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
jlong state,
|
jlong state,
|
||||||
jint max,
|
jint max,
|
||||||
jlong interval)
|
jlong interval)
|
||||||
@ -947,21 +966,24 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
|||||||
if (s->control.reader() >= 0) {
|
if (s->control.reader() >= 0) {
|
||||||
int socket = s->control.reader();
|
int socket = s->control.reader();
|
||||||
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
||||||
if (max < socket) max = socket;
|
if (max < socket)
|
||||||
|
max = socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
if (s->control.listener() >= 0) {
|
if (s->control.listener() >= 0) {
|
||||||
int socket = s->control.listener();
|
int socket = s->control.listener();
|
||||||
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
||||||
if (max < socket) max = socket;
|
if (max < socket)
|
||||||
|
max = socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not s->control.connected()) {
|
if (not s->control.connected()) {
|
||||||
int socket = s->control.writer();
|
int socket = s->control.writer();
|
||||||
FD_SET(static_cast<unsigned>(socket), &(s->write));
|
FD_SET(static_cast<unsigned>(socket), &(s->write));
|
||||||
FD_SET(static_cast<unsigned>(socket), &(s->except));
|
FD_SET(static_cast<unsigned>(socket), &(s->except));
|
||||||
if (max < socket) max = socket;
|
if (max < socket)
|
||||||
|
max = socket;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -986,17 +1008,16 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
if (FD_ISSET(s->control.writer(), &(s->write)) or
|
if (FD_ISSET(s->control.writer(), &(s->write))
|
||||||
FD_ISSET(s->control.writer(), &(s->except)))
|
or FD_ISSET(s->control.writer(), &(s->except))) {
|
||||||
{
|
|
||||||
int socket = s->control.writer();
|
int socket = s->control.writer();
|
||||||
FD_CLR(static_cast<unsigned>(socket), &(s->write));
|
FD_CLR(static_cast<unsigned>(socket), &(s->write));
|
||||||
FD_CLR(static_cast<unsigned>(socket), &(s->except));
|
FD_CLR(static_cast<unsigned>(socket), &(s->except));
|
||||||
|
|
||||||
int error;
|
int error;
|
||||||
socklen_t size = sizeof(int);
|
socklen_t size = sizeof(int);
|
||||||
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR,
|
int r = getsockopt(
|
||||||
reinterpret_cast<char*>(&error), &size);
|
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
|
||||||
if (r != 0 or size != sizeof(int)) {
|
if (r != 0 or size != sizeof(int)) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
} else if (error != 0) {
|
} else if (error != 0) {
|
||||||
@ -1005,9 +1026,8 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
|||||||
s->control.setConnected(true);
|
s->control.setConnected(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->control.listener() >= 0 and
|
if (s->control.listener() >= 0
|
||||||
FD_ISSET(s->control.listener(), &(s->read)))
|
and FD_ISSET(s->control.listener(), &(s->read))) {
|
||||||
{
|
|
||||||
FD_CLR(static_cast<unsigned>(s->control.listener()), &(s->read));
|
FD_CLR(static_cast<unsigned>(s->control.listener()), &(s->read));
|
||||||
|
|
||||||
s->control.setReader(::doAccept(e, s->control.listener()));
|
s->control.setReader(::doAccept(e, s->control.listener()));
|
||||||
@ -1015,9 +1035,7 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (s->control.reader() >= 0 and
|
if (s->control.reader() >= 0 and FD_ISSET(s->control.reader(), &(s->read))) {
|
||||||
FD_ISSET(s->control.reader(), &(s->read)))
|
|
||||||
{
|
|
||||||
FD_CLR(static_cast<unsigned>(s->control.reader()), &(s->read));
|
FD_CLR(static_cast<unsigned>(s->control.reader()), &(s->read));
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
@ -1034,7 +1052,8 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass,
|
Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv*,
|
||||||
|
jclass,
|
||||||
jint socket,
|
jint socket,
|
||||||
jint interest,
|
jint interest,
|
||||||
jlong state)
|
jlong state)
|
||||||
@ -1065,9 +1084,8 @@ Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass,
|
|||||||
return ready;
|
return ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv *, jclass)
|
Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv*, jclass)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
@ -16,8 +16,7 @@
|
|||||||
#include "jni-util.h"
|
#include "jni-util.h"
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
Java_java_util_zip_Inflater_make
|
Java_java_util_zip_Inflater_make(JNIEnv* e, jclass, jboolean nowrap)
|
||||||
(JNIEnv* e, jclass, jboolean nowrap)
|
|
||||||
{
|
{
|
||||||
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
||||||
if (s == 0) {
|
if (s == 0) {
|
||||||
@ -38,7 +37,7 @@ Java_java_util_zip_Inflater_make
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_util_zip_Inflater_dispose(JNIEnv*, jclass, jlong peer)
|
Java_java_util_zip_Inflater_dispose(JNIEnv*, jclass, jlong peer)
|
||||||
{
|
{
|
||||||
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||||
inflateEnd(s);
|
inflateEnd(s);
|
||||||
@ -46,10 +45,15 @@ Java_java_util_zip_Inflater_dispose(JNIEnv*, jclass, jlong peer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_util_zip_Inflater_inflate
|
Java_java_util_zip_Inflater_inflate(JNIEnv* e,
|
||||||
(JNIEnv* e, jclass, jlong peer,
|
jclass,
|
||||||
jbyteArray input, jint inputOffset, jint inputLength,
|
jlong peer,
|
||||||
jbyteArray output, jint outputOffset, jint outputLength,
|
jbyteArray input,
|
||||||
|
jint inputOffset,
|
||||||
|
jint inputLength,
|
||||||
|
jbyteArray output,
|
||||||
|
jint outputOffset,
|
||||||
|
jint outputLength,
|
||||||
jintArray results)
|
jintArray results)
|
||||||
{
|
{
|
||||||
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||||
@ -75,10 +79,9 @@ Java_java_util_zip_Inflater_inflate
|
|||||||
s->avail_out = outputLength;
|
s->avail_out = outputLength;
|
||||||
|
|
||||||
int r = inflate(s, Z_SYNC_FLUSH);
|
int r = inflate(s, Z_SYNC_FLUSH);
|
||||||
jint resultArray[3]
|
jint resultArray[3] = {r,
|
||||||
= { r,
|
|
||||||
static_cast<jint>(inputLength - s->avail_in),
|
static_cast<jint>(inputLength - s->avail_in),
|
||||||
static_cast<jint>(outputLength - s->avail_out) };
|
static_cast<jint>(outputLength - s->avail_out)};
|
||||||
|
|
||||||
free(in);
|
free(in);
|
||||||
|
|
||||||
@ -89,8 +92,10 @@ Java_java_util_zip_Inflater_inflate
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
Java_java_util_zip_Deflater_make
|
Java_java_util_zip_Deflater_make(JNIEnv* e,
|
||||||
(JNIEnv* e, jclass, jboolean nowrap, jint level)
|
jclass,
|
||||||
|
jboolean nowrap,
|
||||||
|
jint level)
|
||||||
{
|
{
|
||||||
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
||||||
if (s == 0) {
|
if (s == 0) {
|
||||||
@ -111,7 +116,7 @@ Java_java_util_zip_Deflater_make
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_util_zip_Deflater_dispose(JNIEnv*, jclass, jlong peer)
|
Java_java_util_zip_Deflater_dispose(JNIEnv*, jclass, jlong peer)
|
||||||
{
|
{
|
||||||
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||||
deflateEnd(s);
|
deflateEnd(s);
|
||||||
@ -119,11 +124,17 @@ Java_java_util_zip_Deflater_dispose(JNIEnv*, jclass, jlong peer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_util_zip_Deflater_deflate
|
Java_java_util_zip_Deflater_deflate(JNIEnv* e,
|
||||||
(JNIEnv* e, jclass, jlong peer,
|
jclass,
|
||||||
jbyteArray input, jint inputOffset, jint inputLength,
|
jlong peer,
|
||||||
jbyteArray output, jint outputOffset, jint outputLength,
|
jbyteArray input,
|
||||||
jboolean finish, jintArray results)
|
jint inputOffset,
|
||||||
|
jint inputLength,
|
||||||
|
jbyteArray output,
|
||||||
|
jint outputOffset,
|
||||||
|
jint outputLength,
|
||||||
|
jboolean finish,
|
||||||
|
jintArray results)
|
||||||
{
|
{
|
||||||
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||||
|
|
||||||
@ -148,10 +159,9 @@ Java_java_util_zip_Deflater_deflate
|
|||||||
s->avail_out = outputLength;
|
s->avail_out = outputLength;
|
||||||
|
|
||||||
int r = deflate(s, finish ? Z_FINISH : Z_NO_FLUSH);
|
int r = deflate(s, finish ? Z_FINISH : Z_NO_FLUSH);
|
||||||
jint resultArray[3]
|
jint resultArray[3] = {r,
|
||||||
= { r,
|
|
||||||
static_cast<jint>(inputLength - s->avail_in),
|
static_cast<jint>(inputLength - s->avail_in),
|
||||||
static_cast<jint>(outputLength - s->avail_out) };
|
static_cast<jint>(outputLength - s->avail_out)};
|
||||||
|
|
||||||
free(in);
|
free(in);
|
||||||
|
|
||||||
|
@ -16,8 +16,7 @@ namespace {
|
|||||||
|
|
||||||
#if (!defined PLATFORM_WINDOWS) || (defined _MSC_VER)
|
#if (!defined PLATFORM_WINDOWS) || (defined _MSC_VER)
|
||||||
|
|
||||||
void
|
void removeNewline(char* s)
|
||||||
removeNewline(char* s)
|
|
||||||
{
|
{
|
||||||
for (; s; ++s) {
|
for (; s; ++s) {
|
||||||
if (*s == '\n') {
|
if (*s == '\n') {
|
||||||
@ -32,7 +31,7 @@ removeNewline(char* s)
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
Java_java_util_Date_toString(JNIEnv* e, jclass c UNUSED, jlong when)
|
Java_java_util_Date_toString(JNIEnv* e, jclass c UNUSED, jlong when)
|
||||||
{
|
{
|
||||||
const unsigned BufferSize UNUSED = 27;
|
const unsigned BufferSize UNUSED = 27;
|
||||||
|
|
||||||
@ -40,13 +39,13 @@ Java_java_util_Date_toString(JNIEnv* e, jclass c UNUSED, jlong when)
|
|||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
e->MonitorEnter(c);
|
e->MonitorEnter(c);
|
||||||
# ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
char buffer[BufferSize];
|
char buffer[BufferSize];
|
||||||
ctime_s(buffer, BufferSize, &time);
|
ctime_s(buffer, BufferSize, &time);
|
||||||
removeNewline(buffer);
|
removeNewline(buffer);
|
||||||
# else
|
#else
|
||||||
char* buffer = ctime(&time);
|
char* buffer = ctime(&time);
|
||||||
# endif
|
#endif
|
||||||
jstring r = e->NewStringUTF(buffer);
|
jstring r = e->NewStringUTF(buffer);
|
||||||
e->MonitorExit(c);
|
e->MonitorExit(c);
|
||||||
return r;
|
return r;
|
||||||
|
@ -20,19 +20,18 @@
|
|||||||
#undef JNIEXPORT
|
#undef JNIEXPORT
|
||||||
|
|
||||||
#if (defined __MINGW32__) || (defined _MSC_VER)
|
#if (defined __MINGW32__) || (defined _MSC_VER)
|
||||||
# define PLATFORM_WINDOWS
|
#define PLATFORM_WINDOWS
|
||||||
# define PATH_SEPARATOR ';'
|
#define PATH_SEPARATOR ';'
|
||||||
# define JNIEXPORT __declspec(dllexport)
|
#define JNIEXPORT __declspec(dllexport)
|
||||||
#else // not (defined __MINGW32__) || (defined _MSC_VER)
|
#else // not (defined __MINGW32__) || (defined _MSC_VER)
|
||||||
# define PLATFORM_POSIX
|
#define PLATFORM_POSIX
|
||||||
# define PATH_SEPARATOR ':'
|
#define PATH_SEPARATOR ':'
|
||||||
# define JNIEXPORT __attribute__ ((visibility("default"))) \
|
#define JNIEXPORT __attribute__((visibility("default"))) __attribute__((used))
|
||||||
__attribute__ ((used))
|
|
||||||
#endif // not (defined __MINGW32__) || (defined _MSC_VER)
|
#endif // not (defined __MINGW32__) || (defined _MSC_VER)
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
# define UNUSED
|
#define UNUSED
|
||||||
|
|
||||||
typedef char int8_t;
|
typedef char int8_t;
|
||||||
typedef unsigned char uint8_t;
|
typedef unsigned char uint8_t;
|
||||||
@ -43,38 +42,37 @@ typedef unsigned int uint32_t;
|
|||||||
typedef __int64 int64_t;
|
typedef __int64 int64_t;
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
|
|
||||||
# define INT32_MAX 2147483647
|
#define INT32_MAX 2147483647
|
||||||
|
|
||||||
# define not !
|
#define not!
|
||||||
# define or ||
|
#define or ||
|
||||||
# define and &&
|
#define and &&
|
||||||
# define xor ^
|
#define xor ^
|
||||||
|
|
||||||
# ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
# define ARCH_x86_32
|
#define ARCH_x86_32
|
||||||
# elif defined _M_X64
|
#elif defined _M_X64
|
||||||
# define ARCH_x86_64
|
#define ARCH_x86_64
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
#else // not _MSC_VER
|
#else // not _MSC_VER
|
||||||
|
|
||||||
# define UNUSED __attribute__((unused))
|
#define UNUSED __attribute__((unused))
|
||||||
|
|
||||||
# include "stdint.h"
|
#include "stdint.h"
|
||||||
# include "errno.h"
|
#include "errno.h"
|
||||||
|
|
||||||
# ifdef __i386__
|
#ifdef __i386__
|
||||||
# define ARCH_x86_32
|
#define ARCH_x86_32
|
||||||
# elif defined __x86_64__
|
#elif defined __x86_64__
|
||||||
# define ARCH_x86_64
|
#define ARCH_x86_64
|
||||||
# elif defined __arm__
|
#elif defined __arm__
|
||||||
# define ARCH_arm
|
#define ARCH_arm
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
#endif // not _MSC_VER
|
#endif // not _MSC_VER
|
||||||
|
|
||||||
inline void
|
inline void throwNew(JNIEnv* e, const char* class_, const char* message, ...)
|
||||||
throwNew(JNIEnv* e, const char* class_, const char* message, ...)
|
|
||||||
{
|
{
|
||||||
jclass c = e->FindClass(class_);
|
jclass c = e->FindClass(class_);
|
||||||
if (c) {
|
if (c) {
|
||||||
@ -99,8 +97,7 @@ throwNew(JNIEnv* e, const char* class_, const char* message, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void throwNewErrno(JNIEnv* e, const char* class_)
|
||||||
throwNewErrno(JNIEnv* e, const char* class_)
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
const unsigned size = 128;
|
const unsigned size = 128;
|
||||||
@ -112,8 +109,7 @@ throwNewErrno(JNIEnv* e, const char* class_)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void*
|
inline void* allocate(JNIEnv* e, unsigned size)
|
||||||
allocate(JNIEnv* e, unsigned size)
|
|
||||||
{
|
{
|
||||||
void* p = malloc(size);
|
void* p = malloc(size);
|
||||||
if (p == 0) {
|
if (p == 0) {
|
||||||
@ -122,4 +118,4 @@ allocate(JNIEnv* e, unsigned size)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif//JNI_UTIL
|
#endif // JNI_UTIL
|
||||||
|
@ -19,7 +19,8 @@ namespace avian {
|
|||||||
namespace classpath {
|
namespace classpath {
|
||||||
namespace sockets {
|
namespace sockets {
|
||||||
|
|
||||||
int last_socket_error() {
|
int last_socket_error()
|
||||||
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
int error = WSAGetLastError();
|
int error = WSAGetLastError();
|
||||||
#else
|
#else
|
||||||
@ -28,8 +29,8 @@ int last_socket_error() {
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init(JNIEnv* ONLY_ON_WINDOWS(e))
|
||||||
void init(JNIEnv* ONLY_ON_WINDOWS(e)) {
|
{
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
static bool wsaInitialized = false;
|
static bool wsaInitialized = false;
|
||||||
if (not wsaInitialized) {
|
if (not wsaInitialized) {
|
||||||
@ -44,18 +45,21 @@ void init(JNIEnv* ONLY_ON_WINDOWS(e)) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET create(JNIEnv* e) {
|
SOCKET create(JNIEnv* e)
|
||||||
|
{
|
||||||
SOCKET sock;
|
SOCKET sock;
|
||||||
if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
|
if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
|
||||||
char buf[255];
|
char buf[255];
|
||||||
sprintf(buf, "Can't create a socket. System error: %d", last_socket_error());
|
sprintf(
|
||||||
|
buf, "Can't create a socket. System error: %d", last_socket_error());
|
||||||
throwNew(e, "java/io/IOException", buf);
|
throwNew(e, "java/io/IOException", buf);
|
||||||
return 0; // This doesn't matter cause we have risen an exception
|
return 0; // This doesn't matter cause we have risen an exception
|
||||||
}
|
}
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect(JNIEnv* e, SOCKET sock, long addr, short port) {
|
void connect(JNIEnv* e, SOCKET sock, long addr, short port)
|
||||||
|
{
|
||||||
sockaddr_in adr;
|
sockaddr_in adr;
|
||||||
adr.sin_family = AF_INET;
|
adr.sin_family = AF_INET;
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
@ -63,18 +67,19 @@ void connect(JNIEnv* e, SOCKET sock, long addr, short port) {
|
|||||||
#else
|
#else
|
||||||
adr.sin_addr.s_addr = htonl(addr);
|
adr.sin_addr.s_addr = htonl(addr);
|
||||||
#endif
|
#endif
|
||||||
adr.sin_port = htons (port);
|
adr.sin_port = htons(port);
|
||||||
|
|
||||||
if (SOCKET_ERROR == ::connect(sock, (sockaddr* )&adr, sizeof(adr)))
|
if (SOCKET_ERROR == ::connect(sock, (sockaddr*)&adr, sizeof(adr))) {
|
||||||
{
|
|
||||||
char buf[255];
|
char buf[255];
|
||||||
sprintf(buf, "Can't connect a socket. System error: %d", last_socket_error());
|
sprintf(
|
||||||
|
buf, "Can't connect a socket. System error: %d", last_socket_error());
|
||||||
throwNew(e, "java/io/IOException", buf);
|
throwNew(e, "java/io/IOException", buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(JNIEnv* e, SOCKET sock, long addr, short port) {
|
void bind(JNIEnv* e, SOCKET sock, long addr, short port)
|
||||||
|
{
|
||||||
sockaddr_in adr;
|
sockaddr_in adr;
|
||||||
adr.sin_family = AF_INET;
|
adr.sin_family = AF_INET;
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
@ -82,10 +87,9 @@ void bind(JNIEnv* e, SOCKET sock, long addr, short port) {
|
|||||||
#else
|
#else
|
||||||
adr.sin_addr.s_addr = htonl(addr);
|
adr.sin_addr.s_addr = htonl(addr);
|
||||||
#endif
|
#endif
|
||||||
adr.sin_port = htons (port);
|
adr.sin_port = htons(port);
|
||||||
|
|
||||||
if (SOCKET_ERROR == ::bind(sock, (sockaddr* )&adr, sizeof(adr)))
|
if (SOCKET_ERROR == ::bind(sock, (sockaddr*)&adr, sizeof(adr))) {
|
||||||
{
|
|
||||||
char buf[255];
|
char buf[255];
|
||||||
sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error());
|
sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error());
|
||||||
throwNew(e, "java/io/IOException", buf);
|
throwNew(e, "java/io/IOException", buf);
|
||||||
@ -93,60 +97,72 @@ void bind(JNIEnv* e, SOCKET sock, long addr, short port) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port) {
|
SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port)
|
||||||
|
{
|
||||||
sockaddr_in adr;
|
sockaddr_in adr;
|
||||||
SOCKET client_socket = ::accept(sock, (sockaddr* )&adr, NULL);
|
SOCKET client_socket = ::accept(sock, (sockaddr*)&adr, NULL);
|
||||||
if (INVALID_SOCKET == client_socket) {
|
if (INVALID_SOCKET == client_socket) {
|
||||||
char buf[255];
|
char buf[255];
|
||||||
sprintf(buf, "Can't accept the incoming connection. System error: %d", last_socket_error());
|
sprintf(buf,
|
||||||
|
"Can't accept the incoming connection. System error: %d",
|
||||||
|
last_socket_error());
|
||||||
throwNew(e, "java/io/IOException", buf);
|
throwNew(e, "java/io/IOException", buf);
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_addr != NULL) {
|
if (client_addr != NULL) {
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
*client_addr = ntohl(adr.sin_addr.S_un.S_addr);
|
*client_addr = ntohl(adr.sin_addr.S_un.S_addr);
|
||||||
#else
|
#else
|
||||||
*client_addr = ntohl(adr.sin_addr.s_addr);
|
*client_addr = ntohl(adr.sin_addr.s_addr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_port != NULL) {
|
if (client_port != NULL) {
|
||||||
*client_port = ntohs (adr.sin_port);
|
*client_port = ntohs(adr.sin_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
return client_socket;
|
return client_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size) {
|
void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size)
|
||||||
|
{
|
||||||
if (SOCKET_ERROR == ::send(sock, buff_ptr, buff_size, 0)) {
|
if (SOCKET_ERROR == ::send(sock, buff_ptr, buff_size, 0)) {
|
||||||
char buf[255];
|
char buf[255];
|
||||||
sprintf(buf, "Can't send data through the socket. System error: %d", last_socket_error());
|
sprintf(buf,
|
||||||
|
"Can't send data through the socket. System error: %d",
|
||||||
|
last_socket_error());
|
||||||
throwNew(e, "java/io/IOException", buf);
|
throwNew(e, "java/io/IOException", buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size) {
|
int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size)
|
||||||
|
{
|
||||||
int length = ::recv(sock, buff_ptr, buff_size, 0);
|
int length = ::recv(sock, buff_ptr, buff_size, 0);
|
||||||
if (SOCKET_ERROR == length) {
|
if (SOCKET_ERROR == length) {
|
||||||
char buf[255];
|
char buf[255];
|
||||||
sprintf(buf, "Can't receive data through the socket. System error: %d", last_socket_error());
|
sprintf(buf,
|
||||||
|
"Can't receive data through the socket. System error: %d",
|
||||||
|
last_socket_error());
|
||||||
throwNew(e, "java/io/IOException", buf);
|
throwNew(e, "java/io/IOException", buf);
|
||||||
return 0; // This doesn't matter cause we have risen an exception
|
return 0; // This doesn't matter cause we have risen an exception
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void abort(JNIEnv* e, SOCKET sock) {
|
void abort(JNIEnv* e, SOCKET sock)
|
||||||
|
{
|
||||||
if (SOCKET_ERROR == ::closesocket(sock)) {
|
if (SOCKET_ERROR == ::closesocket(sock)) {
|
||||||
char buf[255];
|
char buf[255];
|
||||||
sprintf(buf, "Can't close the socket. System error: %d", last_socket_error());
|
sprintf(
|
||||||
|
buf, "Can't close the socket. System error: %d", last_socket_error());
|
||||||
throwNew(e, "java/io/IOException", buf);
|
throwNew(e, "java/io/IOException", buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void close(JNIEnv* e, SOCKET sock) {
|
void close(JNIEnv* e, SOCKET sock)
|
||||||
|
{
|
||||||
if (SOCKET_ERROR == ::shutdown(sock, SD_BOTH)) {
|
if (SOCKET_ERROR == ::shutdown(sock, SD_BOTH)) {
|
||||||
int errcode = last_socket_error();
|
int errcode = last_socket_error();
|
||||||
if (errcode != ENOTCONN) {
|
if (errcode != ENOTCONN) {
|
||||||
@ -157,7 +173,8 @@ void close(JNIEnv* e, SOCKET sock) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_input(JNIEnv* e, SOCKET sock) {
|
void close_input(JNIEnv* e, SOCKET sock)
|
||||||
|
{
|
||||||
if (SOCKET_ERROR == ::shutdown(sock, SD_RECEIVE)) {
|
if (SOCKET_ERROR == ::shutdown(sock, SD_RECEIVE)) {
|
||||||
int errcode = last_socket_error();
|
int errcode = last_socket_error();
|
||||||
if (errcode != ENOTCONN) {
|
if (errcode != ENOTCONN) {
|
||||||
@ -168,7 +185,8 @@ void close_input(JNIEnv* e, SOCKET sock) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_output(JNIEnv* e, SOCKET sock) {
|
void close_output(JNIEnv* e, SOCKET sock)
|
||||||
|
{
|
||||||
if (SOCKET_ERROR == ::shutdown(sock, SD_SEND)) {
|
if (SOCKET_ERROR == ::shutdown(sock, SD_SEND)) {
|
||||||
int errcode = last_socket_error();
|
int errcode = last_socket_error();
|
||||||
if (errcode != ENOTCONN) {
|
if (errcode != ENOTCONN) {
|
||||||
@ -178,7 +196,6 @@ void close_output(JNIEnv* e, SOCKET sock) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
There is NO WARRANTY for this software. See license.txt for
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file represents a simple cross-platform JNI sockets API
|
* This file represents a simple cross-platform JNI sockets API
|
||||||
* It is used from different classes of the default Avian classpath
|
* It is used from different classes of the default Avian classpath
|
||||||
@ -22,28 +21,28 @@
|
|||||||
#include "jni-util.h"
|
#include "jni-util.h"
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
# include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
|
||||||
# define ONLY_ON_WINDOWS(x) x
|
#define ONLY_ON_WINDOWS(x) x
|
||||||
|
|
||||||
# ifndef ENOTCONN
|
#ifndef ENOTCONN
|
||||||
# define ENOTCONN WSAENOTCONN
|
#define ENOTCONN WSAENOTCONN
|
||||||
# endif
|
#endif
|
||||||
#else
|
#else
|
||||||
# include <netdb.h>
|
#include <netdb.h>
|
||||||
# include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
# include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
# include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
# define ONLY_ON_WINDOWS(x)
|
#define ONLY_ON_WINDOWS(x)
|
||||||
# define SOCKET int
|
#define SOCKET int
|
||||||
# define INVALID_SOCKET -1
|
#define INVALID_SOCKET -1
|
||||||
# define SOCKET_ERROR -1
|
#define SOCKET_ERROR -1
|
||||||
# define closesocket(x) close(x)
|
#define closesocket(x) close(x)
|
||||||
|
|
||||||
# define SD_RECEIVE SHUT_RD
|
#define SD_RECEIVE SHUT_RD
|
||||||
# define SD_SEND SHUT_WR
|
#define SD_SEND SHUT_WR
|
||||||
# define SD_BOTH SHUT_RDWR
|
#define SD_BOTH SHUT_RDWR
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -69,7 +68,6 @@ void abort(JNIEnv* e, SOCKET sock);
|
|||||||
void close(JNIEnv* e, SOCKET sock);
|
void close(JNIEnv* e, SOCKET sock);
|
||||||
void close_input(JNIEnv* e, SOCKET sock);
|
void close_input(JNIEnv* e, SOCKET sock);
|
||||||
void close_output(JNIEnv* e, SOCKET sock);
|
void close_output(JNIEnv* e, SOCKET sock);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,113 +30,123 @@ class Assembler;
|
|||||||
class RegisterFile;
|
class RegisterFile;
|
||||||
|
|
||||||
class OperandMask {
|
class OperandMask {
|
||||||
public:
|
public:
|
||||||
uint8_t typeMask;
|
uint8_t typeMask;
|
||||||
uint64_t registerMask;
|
uint64_t registerMask;
|
||||||
|
|
||||||
OperandMask(uint8_t typeMask, uint64_t registerMask):
|
OperandMask(uint8_t typeMask, uint64_t registerMask)
|
||||||
typeMask(typeMask),
|
: typeMask(typeMask), registerMask(registerMask)
|
||||||
registerMask(registerMask)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
OperandMask():
|
OperandMask() : typeMask(~0), registerMask(~static_cast<uint64_t>(0))
|
||||||
typeMask(~0),
|
{
|
||||||
registerMask(~static_cast<uint64_t>(0))
|
}
|
||||||
{ }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Architecture {
|
class Architecture {
|
||||||
public:
|
public:
|
||||||
virtual unsigned floatRegisterSize() = 0;
|
virtual unsigned floatRegisterSize() = 0;
|
||||||
|
|
||||||
virtual const RegisterFile* registerFile() = 0;
|
virtual const RegisterFile* registerFile() = 0;
|
||||||
|
|
||||||
virtual int scratch() = 0;
|
virtual int scratch() = 0;
|
||||||
virtual int stack() = 0;
|
virtual int stack() = 0;
|
||||||
virtual int thread() = 0;
|
virtual int thread() = 0;
|
||||||
virtual int returnLow() = 0;
|
virtual int returnLow() = 0;
|
||||||
virtual int returnHigh() = 0;
|
virtual int returnHigh() = 0;
|
||||||
virtual int virtualCallTarget() = 0;
|
virtual int virtualCallTarget() = 0;
|
||||||
virtual int virtualCallIndex() = 0;
|
virtual int virtualCallIndex() = 0;
|
||||||
|
|
||||||
virtual ir::TargetInfo targetInfo() = 0;
|
virtual ir::TargetInfo targetInfo() = 0;
|
||||||
|
|
||||||
virtual bool bigEndian() = 0;
|
virtual bool bigEndian() = 0;
|
||||||
|
|
||||||
virtual uintptr_t maximumImmediateJump() = 0;
|
virtual uintptr_t maximumImmediateJump() = 0;
|
||||||
|
|
||||||
virtual bool alwaysCondensed(lir::BinaryOperation op) = 0;
|
virtual bool alwaysCondensed(lir::BinaryOperation op) = 0;
|
||||||
virtual bool alwaysCondensed(lir::TernaryOperation op) = 0;
|
virtual bool alwaysCondensed(lir::TernaryOperation op) = 0;
|
||||||
|
|
||||||
virtual bool reserved(int register_) = 0;
|
virtual bool reserved(int register_) = 0;
|
||||||
|
|
||||||
virtual unsigned frameFootprint(unsigned footprint) = 0;
|
virtual unsigned frameFootprint(unsigned footprint) = 0;
|
||||||
virtual unsigned argumentFootprint(unsigned footprint) = 0;
|
virtual unsigned argumentFootprint(unsigned footprint) = 0;
|
||||||
virtual bool argumentAlignment() = 0;
|
virtual bool argumentAlignment() = 0;
|
||||||
virtual bool argumentRegisterAlignment() = 0;
|
virtual bool argumentRegisterAlignment() = 0;
|
||||||
virtual unsigned argumentRegisterCount() = 0;
|
virtual unsigned argumentRegisterCount() = 0;
|
||||||
virtual int argumentRegister(unsigned index) = 0;
|
virtual int argumentRegister(unsigned index) = 0;
|
||||||
|
|
||||||
virtual bool hasLinkRegister() = 0;
|
virtual bool hasLinkRegister() = 0;
|
||||||
|
|
||||||
virtual unsigned stackAlignmentInWords() = 0;
|
virtual unsigned stackAlignmentInWords() = 0;
|
||||||
|
|
||||||
virtual bool matchCall(void* returnAddress, void* target) = 0;
|
virtual bool matchCall(void* returnAddress, void* target) = 0;
|
||||||
|
|
||||||
virtual void updateCall(lir::UnaryOperation op, void* returnAddress,
|
virtual void updateCall(lir::UnaryOperation op,
|
||||||
|
void* returnAddress,
|
||||||
void* newTarget) = 0;
|
void* newTarget) = 0;
|
||||||
|
|
||||||
virtual void setConstant(void* dst, uint64_t constant) = 0;
|
virtual void setConstant(void* dst, uint64_t constant) = 0;
|
||||||
|
|
||||||
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
|
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
|
||||||
|
|
||||||
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
virtual void nextFrame(void* start,
|
||||||
void* link, bool mostRecent,
|
unsigned size,
|
||||||
int targetParameterFootprint, void** ip,
|
unsigned footprint,
|
||||||
|
void* link,
|
||||||
|
bool mostRecent,
|
||||||
|
int targetParameterFootprint,
|
||||||
|
void** ip,
|
||||||
void** stack) = 0;
|
void** stack) = 0;
|
||||||
virtual void* frameIp(void* stack) = 0;
|
virtual void* frameIp(void* stack) = 0;
|
||||||
virtual unsigned frameHeaderSize() = 0;
|
virtual unsigned frameHeaderSize() = 0;
|
||||||
virtual unsigned frameReturnAddressSize() = 0;
|
virtual unsigned frameReturnAddressSize() = 0;
|
||||||
virtual unsigned frameFooterSize() = 0;
|
virtual unsigned frameFooterSize() = 0;
|
||||||
virtual int returnAddressOffset() = 0;
|
virtual int returnAddressOffset() = 0;
|
||||||
virtual int framePointerOffset() = 0;
|
virtual int framePointerOffset() = 0;
|
||||||
|
|
||||||
virtual void plan
|
virtual void plan(lir::UnaryOperation op,
|
||||||
(lir::UnaryOperation op,
|
unsigned aSize,
|
||||||
unsigned aSize, OperandMask& aMask,
|
OperandMask& aMask,
|
||||||
bool* thunk) = 0;
|
bool* thunk) = 0;
|
||||||
|
|
||||||
virtual void planSource
|
virtual void planSource(lir::BinaryOperation op,
|
||||||
(lir::BinaryOperation op,
|
unsigned aSize,
|
||||||
unsigned aSize, OperandMask& aMask,
|
OperandMask& aMask,
|
||||||
unsigned bSize, bool* thunk) = 0;
|
unsigned bSize,
|
||||||
|
bool* thunk) = 0;
|
||||||
|
|
||||||
virtual void planDestination
|
virtual void planDestination(lir::BinaryOperation op,
|
||||||
(lir::BinaryOperation op,
|
unsigned aSize,
|
||||||
unsigned aSize, const OperandMask& aMask,
|
const OperandMask& aMask,
|
||||||
unsigned bSize, OperandMask& bMask) = 0;
|
unsigned bSize,
|
||||||
|
OperandMask& bMask) = 0;
|
||||||
|
|
||||||
virtual void planMove
|
virtual void planMove(unsigned size,
|
||||||
(unsigned size, OperandMask& src,
|
OperandMask& src,
|
||||||
OperandMask& tmp,
|
OperandMask& tmp,
|
||||||
const OperandMask& dst) = 0;
|
const OperandMask& dst) = 0;
|
||||||
|
|
||||||
virtual void planSource
|
virtual void planSource(lir::TernaryOperation op,
|
||||||
(lir::TernaryOperation op,
|
unsigned aSize,
|
||||||
unsigned aSize, OperandMask& aMask,
|
OperandMask& aMask,
|
||||||
unsigned bSize, OperandMask& bMask,
|
unsigned bSize,
|
||||||
unsigned cSize, bool* thunk) = 0;
|
OperandMask& bMask,
|
||||||
|
unsigned cSize,
|
||||||
|
bool* thunk) = 0;
|
||||||
|
|
||||||
virtual void planDestination
|
virtual void planDestination(lir::TernaryOperation op,
|
||||||
(lir::TernaryOperation op,
|
unsigned aSize,
|
||||||
unsigned aSize, const OperandMask& aMask,
|
const OperandMask& aMask,
|
||||||
unsigned bSize, const OperandMask& bMask,
|
unsigned bSize,
|
||||||
unsigned cSize, OperandMask& cMask) = 0;
|
const OperandMask& bMask,
|
||||||
|
unsigned cSize,
|
||||||
|
OperandMask& cMask) = 0;
|
||||||
|
|
||||||
virtual Assembler* makeAssembler(util::Allocator*, vm::Zone*) = 0;
|
virtual Assembler* makeAssembler(util::Allocator*, vm::Zone*) = 0;
|
||||||
|
|
||||||
virtual void acquire() = 0;
|
virtual void acquire() = 0;
|
||||||
virtual void release() = 0;
|
virtual void release() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
|
@ -23,16 +23,17 @@ namespace codegen {
|
|||||||
class Architecture;
|
class Architecture;
|
||||||
|
|
||||||
class OperandInfo {
|
class OperandInfo {
|
||||||
public:
|
public:
|
||||||
const unsigned size;
|
const unsigned size;
|
||||||
const lir::OperandType type;
|
const lir::OperandType type;
|
||||||
lir::Operand* const operand;
|
lir::Operand* const operand;
|
||||||
|
|
||||||
inline OperandInfo(unsigned size, lir::OperandType type, lir::Operand* operand):
|
inline OperandInfo(unsigned size,
|
||||||
size(size),
|
lir::OperandType type,
|
||||||
type(type),
|
lir::Operand* operand)
|
||||||
operand(operand)
|
: size(size), type(type), operand(operand)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef AVIAN_TAILS
|
#ifdef AVIAN_TAILS
|
||||||
@ -49,11 +50,9 @@ const bool UseFramePointer = false;
|
|||||||
|
|
||||||
class Assembler {
|
class Assembler {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
public:
|
public:
|
||||||
virtual int acquireTemporary
|
virtual int acquireTemporary(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
|
||||||
(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
|
|
||||||
virtual void releaseTemporary(int r) = 0;
|
virtual void releaseTemporary(int r) = 0;
|
||||||
|
|
||||||
virtual void save(int r) = 0;
|
virtual void save(int r) = 0;
|
||||||
@ -75,12 +74,12 @@ class Assembler {
|
|||||||
virtual void allocateFrame(unsigned footprint) = 0;
|
virtual void allocateFrame(unsigned footprint) = 0;
|
||||||
virtual void adjustFrame(unsigned difference) = 0;
|
virtual void adjustFrame(unsigned difference) = 0;
|
||||||
virtual void popFrame(unsigned footprint) = 0;
|
virtual void popFrame(unsigned footprint) = 0;
|
||||||
virtual void popFrameForTailCall(unsigned footprint, int offset,
|
virtual void popFrameForTailCall(unsigned footprint,
|
||||||
|
int offset,
|
||||||
int returnAddressSurrogate,
|
int returnAddressSurrogate,
|
||||||
int framePointerSurrogate) = 0;
|
int framePointerSurrogate) = 0;
|
||||||
virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint,
|
virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint,
|
||||||
unsigned argumentFootprint)
|
unsigned argumentFootprint) = 0;
|
||||||
= 0;
|
|
||||||
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
|
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
|
||||||
unsigned stackOffsetFromThread)
|
unsigned stackOffsetFromThread)
|
||||||
= 0;
|
= 0;
|
||||||
@ -88,7 +87,10 @@ class Assembler {
|
|||||||
virtual void apply(lir::Operation op) = 0;
|
virtual void apply(lir::Operation op) = 0;
|
||||||
virtual void apply(lir::UnaryOperation op, OperandInfo a) = 0;
|
virtual void apply(lir::UnaryOperation op, OperandInfo a) = 0;
|
||||||
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) = 0;
|
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) = 0;
|
||||||
virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c) = 0;
|
virtual void apply(lir::TernaryOperation op,
|
||||||
|
OperandInfo a,
|
||||||
|
OperandInfo b,
|
||||||
|
OperandInfo c) = 0;
|
||||||
|
|
||||||
virtual void setDestination(uint8_t* dst) = 0;
|
virtual void setDestination(uint8_t* dst) = 0;
|
||||||
|
|
||||||
|
@ -30,10 +30,13 @@ class Compiler {
|
|||||||
class Client {
|
class Client {
|
||||||
public:
|
public:
|
||||||
virtual intptr_t getThunk(lir::UnaryOperation op, unsigned size) = 0;
|
virtual intptr_t getThunk(lir::UnaryOperation op, unsigned size) = 0;
|
||||||
virtual intptr_t getThunk(lir::BinaryOperation op, unsigned size,
|
virtual intptr_t getThunk(lir::BinaryOperation op,
|
||||||
|
unsigned size,
|
||||||
unsigned resultSize) = 0;
|
unsigned resultSize) = 0;
|
||||||
virtual intptr_t getThunk(lir::TernaryOperation op, unsigned size,
|
virtual intptr_t getThunk(lir::TernaryOperation op,
|
||||||
unsigned resultSize, bool* threadParameter) = 0;
|
unsigned size,
|
||||||
|
unsigned resultSize,
|
||||||
|
bool* threadParameter) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned Aligned = 1 << 0;
|
static const unsigned Aligned = 1 << 0;
|
||||||
@ -41,13 +44,16 @@ class Compiler {
|
|||||||
static const unsigned TailJump = 1 << 2;
|
static const unsigned TailJump = 1 << 2;
|
||||||
static const unsigned LongJumpOrCall = 1 << 3;
|
static const unsigned LongJumpOrCall = 1 << 3;
|
||||||
|
|
||||||
class State { };
|
class State {
|
||||||
|
};
|
||||||
|
|
||||||
virtual State* saveState() = 0;
|
virtual State* saveState() = 0;
|
||||||
virtual void restoreState(State* state) = 0;
|
virtual void restoreState(State* state) = 0;
|
||||||
|
|
||||||
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
|
virtual void init(unsigned logicalCodeSize,
|
||||||
unsigned localFootprint, unsigned alignedFrameSize) = 0;
|
unsigned parameterFootprint,
|
||||||
|
unsigned localFootprint,
|
||||||
|
unsigned alignedFrameSize) = 0;
|
||||||
|
|
||||||
virtual void extendLogicalCode(unsigned more) = 0;
|
virtual void extendLogicalCode(unsigned more) = 0;
|
||||||
|
|
||||||
@ -128,8 +134,7 @@ class Compiler {
|
|||||||
ir::Type type,
|
ir::Type type,
|
||||||
ir::Value* a,
|
ir::Value* a,
|
||||||
ir::Value* b) = 0;
|
ir::Value* b) = 0;
|
||||||
virtual ir::Value* unaryOp(lir::BinaryOperation op,
|
virtual ir::Value* unaryOp(lir::BinaryOperation op, ir::Value* a) = 0;
|
||||||
ir::Value* a) = 0;
|
|
||||||
virtual void nullaryOp(lir::Operation op) = 0;
|
virtual void nullaryOp(lir::Operation op) = 0;
|
||||||
|
|
||||||
virtual ir::Value* f2f(ir::Type resType, ir::Value* a) = 0;
|
virtual ir::Value* f2f(ir::Type resType, ir::Value* a) = 0;
|
||||||
@ -145,8 +150,9 @@ class Compiler {
|
|||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Compiler*
|
Compiler* makeCompiler(vm::System* system,
|
||||||
makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone,
|
Assembler* assembler,
|
||||||
|
vm::Zone* zone,
|
||||||
Compiler::Client* client);
|
Compiler::Client* client);
|
||||||
|
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
|
@ -17,71 +17,67 @@ class Promise;
|
|||||||
|
|
||||||
namespace lir {
|
namespace lir {
|
||||||
enum Operation {
|
enum Operation {
|
||||||
#define LIR_OP_0(x) x,
|
#define LIR_OP_0(x) x,
|
||||||
#define LIR_OP_1(x)
|
#define LIR_OP_1(x)
|
||||||
#define LIR_OP_2(x)
|
#define LIR_OP_2(x)
|
||||||
#define LIR_OP_3(x)
|
#define LIR_OP_3(x)
|
||||||
#include "lir-ops.inc.cpp"
|
#include "lir-ops.inc.cpp"
|
||||||
#undef LIR_OP_0
|
#undef LIR_OP_0
|
||||||
#undef LIR_OP_1
|
#undef LIR_OP_1
|
||||||
#undef LIR_OP_2
|
#undef LIR_OP_2
|
||||||
#undef LIR_OP_3
|
#undef LIR_OP_3
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned OperationCount = Trap + 1;
|
const unsigned OperationCount = Trap + 1;
|
||||||
|
|
||||||
enum UnaryOperation {
|
enum UnaryOperation {
|
||||||
#define LIR_OP_0(x)
|
#define LIR_OP_0(x)
|
||||||
#define LIR_OP_1(x) x,
|
#define LIR_OP_1(x) x,
|
||||||
#define LIR_OP_2(x)
|
#define LIR_OP_2(x)
|
||||||
#define LIR_OP_3(x)
|
#define LIR_OP_3(x)
|
||||||
#include "lir-ops.inc.cpp"
|
#include "lir-ops.inc.cpp"
|
||||||
#undef LIR_OP_0
|
#undef LIR_OP_0
|
||||||
#undef LIR_OP_1
|
#undef LIR_OP_1
|
||||||
#undef LIR_OP_2
|
#undef LIR_OP_2
|
||||||
#undef LIR_OP_3
|
#undef LIR_OP_3
|
||||||
|
|
||||||
NoUnaryOperation = -1
|
NoUnaryOperation = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned UnaryOperationCount = AlignedJump + 1;
|
const unsigned UnaryOperationCount = AlignedJump + 1;
|
||||||
|
|
||||||
enum BinaryOperation {
|
enum BinaryOperation {
|
||||||
#define LIR_OP_0(x)
|
#define LIR_OP_0(x)
|
||||||
#define LIR_OP_1(x)
|
#define LIR_OP_1(x)
|
||||||
#define LIR_OP_2(x) x,
|
#define LIR_OP_2(x) x,
|
||||||
#define LIR_OP_3(x)
|
#define LIR_OP_3(x)
|
||||||
#include "lir-ops.inc.cpp"
|
#include "lir-ops.inc.cpp"
|
||||||
#undef LIR_OP_0
|
#undef LIR_OP_0
|
||||||
#undef LIR_OP_1
|
#undef LIR_OP_1
|
||||||
#undef LIR_OP_2
|
#undef LIR_OP_2
|
||||||
#undef LIR_OP_3
|
#undef LIR_OP_3
|
||||||
|
|
||||||
NoBinaryOperation = -1
|
NoBinaryOperation = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned BinaryOperationCount = Absolute + 1;
|
const unsigned BinaryOperationCount = Absolute + 1;
|
||||||
|
|
||||||
enum TernaryOperation {
|
enum TernaryOperation {
|
||||||
#define LIR_OP_0(x)
|
#define LIR_OP_0(x)
|
||||||
#define LIR_OP_1(x)
|
#define LIR_OP_1(x)
|
||||||
#define LIR_OP_2(x)
|
#define LIR_OP_2(x)
|
||||||
#define LIR_OP_3(x) x,
|
#define LIR_OP_3(x) x,
|
||||||
#include "lir-ops.inc.cpp"
|
#include "lir-ops.inc.cpp"
|
||||||
#undef LIR_OP_0
|
#undef LIR_OP_0
|
||||||
#undef LIR_OP_1
|
#undef LIR_OP_1
|
||||||
#undef LIR_OP_2
|
#undef LIR_OP_2
|
||||||
#undef LIR_OP_3
|
#undef LIR_OP_3
|
||||||
|
|
||||||
NoTernaryOperation = -1
|
NoTernaryOperation = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned TernaryOperationCount
|
const unsigned TernaryOperationCount = JumpIfFloatGreaterOrEqualOrUnordered + 1;
|
||||||
= JumpIfFloatGreaterOrEqualOrUnordered + 1;
|
|
||||||
|
|
||||||
const unsigned NonBranchTernaryOperationCount = FloatMin + 1;
|
const unsigned NonBranchTernaryOperationCount = FloatMin + 1;
|
||||||
const unsigned BranchOperationCount
|
const unsigned BranchOperationCount = JumpIfFloatGreaterOrEqualOrUnordered
|
||||||
= JumpIfFloatGreaterOrEqualOrUnordered - FloatMin;
|
- FloatMin;
|
||||||
|
|
||||||
enum OperandType {
|
enum OperandType {
|
||||||
ConstantOperand,
|
ConstantOperand,
|
||||||
@ -90,72 +86,84 @@ enum OperandType {
|
|||||||
MemoryOperand
|
MemoryOperand
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ValueType {
|
enum ValueType { ValueGeneral, ValueFloat };
|
||||||
ValueGeneral,
|
|
||||||
ValueFloat
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned OperandTypeCount = MemoryOperand + 1;
|
const unsigned OperandTypeCount = MemoryOperand + 1;
|
||||||
|
|
||||||
const int NoRegister = -1;
|
const int NoRegister = -1;
|
||||||
|
|
||||||
inline bool isBranch(lir::TernaryOperation op) {
|
inline bool isBranch(lir::TernaryOperation op)
|
||||||
|
{
|
||||||
return op > FloatMin;
|
return op > FloatMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isFloatBranch(lir::TernaryOperation op) {
|
inline bool isFloatBranch(lir::TernaryOperation op)
|
||||||
|
{
|
||||||
return op > JumpIfNotEqual;
|
return op > JumpIfNotEqual;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isGeneralBranch(lir::TernaryOperation op) {
|
inline bool isGeneralBranch(lir::TernaryOperation op)
|
||||||
|
{
|
||||||
return isBranch(op) && !isFloatBranch(op);
|
return isBranch(op) && !isFloatBranch(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isGeneralBinaryOp(lir::TernaryOperation op) {
|
inline bool isGeneralBinaryOp(lir::TernaryOperation op)
|
||||||
|
{
|
||||||
return op < FloatAdd;
|
return op < FloatAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isFloatBinaryOp(lir::TernaryOperation op) {
|
inline bool isFloatBinaryOp(lir::TernaryOperation op)
|
||||||
|
{
|
||||||
return op >= FloatAdd && op <= FloatMin;
|
return op >= FloatAdd && op <= FloatMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isGeneralUnaryOp(lir::BinaryOperation op) {
|
inline bool isGeneralUnaryOp(lir::BinaryOperation op)
|
||||||
|
{
|
||||||
return op == Negate || op == Absolute;
|
return op == Negate || op == Absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isFloatUnaryOp(lir::BinaryOperation op) {
|
inline bool isFloatUnaryOp(lir::BinaryOperation op)
|
||||||
|
{
|
||||||
return op == FloatNegate || op == FloatSquareRoot || op == FloatAbsolute;
|
return op == FloatNegate || op == FloatSquareRoot || op == FloatAbsolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Operand { };
|
class Operand {
|
||||||
|
};
|
||||||
|
|
||||||
class Constant: public Operand {
|
class Constant : public Operand {
|
||||||
public:
|
public:
|
||||||
Constant(Promise* value): value(value) { }
|
Constant(Promise* value) : value(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Promise* value;
|
Promise* value;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Address: public Operand {
|
class Address : public Operand {
|
||||||
public:
|
public:
|
||||||
Address(Promise* address): address(address) { }
|
Address(Promise* address) : address(address)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Promise* address;
|
Promise* address;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Register: public Operand {
|
class Register : public Operand {
|
||||||
public:
|
public:
|
||||||
Register(int low, int high = NoRegister): low(low), high(high) { }
|
Register(int low, int high = NoRegister) : low(low), high(high)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int low;
|
int low;
|
||||||
int high;
|
int high;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Memory: public Operand {
|
class Memory : public Operand {
|
||||||
public:
|
public:
|
||||||
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1):
|
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1)
|
||||||
base(base), offset(offset), index(index), scale(scale)
|
: base(base), offset(offset), index(index), scale(scale)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int base;
|
int base;
|
||||||
int offset;
|
int offset;
|
||||||
|
@ -29,35 +29,45 @@ class Promise {
|
|||||||
|
|
||||||
virtual int64_t value() = 0;
|
virtual int64_t value() = 0;
|
||||||
virtual bool resolved() = 0;
|
virtual bool resolved() = 0;
|
||||||
virtual Listener* listen(unsigned) { return 0; }
|
virtual Listener* listen(unsigned)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResolvedPromise: public Promise {
|
class ResolvedPromise : public Promise {
|
||||||
public:
|
public:
|
||||||
ResolvedPromise(int64_t value): value_(value) { }
|
ResolvedPromise(int64_t value) : value_(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value()
|
||||||
|
{
|
||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved()
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t value_;
|
int64_t value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShiftMaskPromise: public Promise {
|
class ShiftMaskPromise : public Promise {
|
||||||
public:
|
public:
|
||||||
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
|
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask)
|
||||||
base(base), shift(shift), mask(mask)
|
: base(base), shift(shift), mask(mask)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value()
|
||||||
|
{
|
||||||
return (base->value() >> shift) & mask;
|
return (base->value() >> shift) & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved()
|
||||||
|
{
|
||||||
return base->resolved();
|
return base->resolved();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,17 +76,19 @@ class ShiftMaskPromise: public Promise {
|
|||||||
int64_t mask;
|
int64_t mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CombinedPromise: public Promise {
|
class CombinedPromise : public Promise {
|
||||||
public:
|
public:
|
||||||
CombinedPromise(Promise* low, Promise* high):
|
CombinedPromise(Promise* low, Promise* high) : low(low), high(high)
|
||||||
low(low), high(high)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value()
|
||||||
|
{
|
||||||
return low->value() | (high->value() << 32);
|
return low->value() | (high->value() << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved()
|
||||||
|
{
|
||||||
return low->resolved() and high->resolved();
|
return low->resolved() and high->resolved();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,17 +96,19 @@ class CombinedPromise: public Promise {
|
|||||||
Promise* high;
|
Promise* high;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OffsetPromise: public Promise {
|
class OffsetPromise : public Promise {
|
||||||
public:
|
public:
|
||||||
OffsetPromise(Promise* base, int64_t offset):
|
OffsetPromise(Promise* base, int64_t offset) : base(base), offset(offset)
|
||||||
base(base), offset(offset)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value()
|
||||||
|
{
|
||||||
return base->value() + offset;
|
return base->value() + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved()
|
||||||
|
{
|
||||||
return base->resolved();
|
return base->resolved();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,21 +116,25 @@ class OffsetPromise: public Promise {
|
|||||||
int64_t offset;
|
int64_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ListenPromise: public Promise {
|
class ListenPromise : public Promise {
|
||||||
public:
|
public:
|
||||||
ListenPromise(vm::System* s, util::Allocator* allocator)
|
ListenPromise(vm::System* s, util::Allocator* allocator)
|
||||||
: s(s), allocator(allocator), listener(0)
|
: s(s), allocator(allocator), listener(0)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value()
|
||||||
|
{
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Listener* listen(unsigned sizeInBytes) {
|
virtual Listener* listen(unsigned sizeInBytes)
|
||||||
|
{
|
||||||
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
|
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
|
||||||
l->next = listener;
|
l->next = listener;
|
||||||
listener = l;
|
listener = l;
|
||||||
@ -129,24 +147,28 @@ class ListenPromise: public Promise {
|
|||||||
Promise* promise;
|
Promise* promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DelayedPromise: public ListenPromise {
|
class DelayedPromise : public ListenPromise {
|
||||||
public:
|
public:
|
||||||
DelayedPromise(vm::System* s,
|
DelayedPromise(vm::System* s,
|
||||||
util::Allocator* allocator,
|
util::Allocator* allocator,
|
||||||
Promise* basis,
|
Promise* basis,
|
||||||
DelayedPromise* next)
|
DelayedPromise* next)
|
||||||
: ListenPromise(s, allocator), basis(basis), next(next)
|
: ListenPromise(s, allocator), basis(basis), next(next)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value()
|
||||||
|
{
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Listener* listen(unsigned sizeInBytes) {
|
virtual Listener* listen(unsigned sizeInBytes)
|
||||||
|
{
|
||||||
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
|
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
|
||||||
l->next = listener;
|
l->next = listener;
|
||||||
listener = l;
|
listener = l;
|
||||||
|
@ -17,7 +17,7 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
|
|
||||||
class RegisterMask {
|
class RegisterMask {
|
||||||
public:
|
public:
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
uint8_t start;
|
uint8_t start;
|
||||||
uint8_t limit;
|
uint8_t limit;
|
||||||
@ -25,44 +25,47 @@ public:
|
|||||||
static unsigned maskStart(uint32_t mask);
|
static unsigned maskStart(uint32_t mask);
|
||||||
static unsigned maskLimit(uint32_t mask);
|
static unsigned maskLimit(uint32_t mask);
|
||||||
|
|
||||||
inline RegisterMask(uint32_t mask):
|
inline RegisterMask(uint32_t mask)
|
||||||
mask(mask),
|
: mask(mask), start(maskStart(mask)), limit(maskLimit(mask))
|
||||||
start(maskStart(mask)),
|
{
|
||||||
limit(maskLimit(mask))
|
}
|
||||||
{ }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegisterFile {
|
class RegisterFile {
|
||||||
public:
|
public:
|
||||||
RegisterMask allRegisters;
|
RegisterMask allRegisters;
|
||||||
RegisterMask generalRegisters;
|
RegisterMask generalRegisters;
|
||||||
RegisterMask floatRegisters;
|
RegisterMask floatRegisters;
|
||||||
|
|
||||||
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask):
|
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask)
|
||||||
allRegisters(generalRegisterMask | floatRegisterMask),
|
: allRegisters(generalRegisterMask | floatRegisterMask),
|
||||||
generalRegisters(generalRegisterMask),
|
generalRegisters(generalRegisterMask),
|
||||||
floatRegisters(floatRegisterMask)
|
floatRegisters(floatRegisterMask)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegisterIterator {
|
class RegisterIterator {
|
||||||
public:
|
public:
|
||||||
int index;
|
int index;
|
||||||
const RegisterMask& mask;
|
const RegisterMask& mask;
|
||||||
|
|
||||||
inline RegisterIterator(const RegisterMask& mask):
|
inline RegisterIterator(const RegisterMask& mask)
|
||||||
index(mask.start),
|
: index(mask.start), mask(mask)
|
||||||
mask(mask) {}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
inline bool hasNext() {
|
inline bool hasNext()
|
||||||
|
{
|
||||||
return index < mask.limit;
|
return index < mask.limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int next() {
|
inline int next()
|
||||||
|
{
|
||||||
int r = index;
|
int r = index;
|
||||||
do {
|
do {
|
||||||
index++;
|
index++;
|
||||||
} while(index < mask.limit && !(mask.mask & (1 << index)));
|
} while (index < mask.limit && !(mask.mask & (1 << index)));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,8 @@ namespace codegen {
|
|||||||
|
|
||||||
class Architecture;
|
class Architecture;
|
||||||
|
|
||||||
Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures);
|
Architecture* makeArchitectureNative(vm::System* system,
|
||||||
|
bool useNativeFeatures);
|
||||||
|
|
||||||
Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures);
|
Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures);
|
||||||
Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures);
|
Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures);
|
||||||
|
@ -24,17 +24,9 @@ const unsigned FixieTenureThreshold = TenureThreshold + 2;
|
|||||||
|
|
||||||
class Heap : public avian::util::Allocator {
|
class Heap : public avian::util::Allocator {
|
||||||
public:
|
public:
|
||||||
enum CollectionType {
|
enum CollectionType { MinorCollection, MajorCollection };
|
||||||
MinorCollection,
|
|
||||||
MajorCollection
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Status {
|
enum Status { Null, Reachable, Unreachable, Tenured };
|
||||||
Null,
|
|
||||||
Reachable,
|
|
||||||
Unreachable,
|
|
||||||
Tenured
|
|
||||||
};
|
|
||||||
|
|
||||||
class Visitor {
|
class Visitor {
|
||||||
public:
|
public:
|
||||||
@ -62,7 +54,8 @@ class Heap : public avian::util::Allocator {
|
|||||||
virtual unsigned remaining() = 0;
|
virtual unsigned remaining() = 0;
|
||||||
virtual unsigned limit() = 0;
|
virtual unsigned limit() = 0;
|
||||||
virtual bool limitExceeded(int pendingAllocation = 0) = 0;
|
virtual bool limitExceeded(int pendingAllocation = 0) = 0;
|
||||||
virtual void collect(CollectionType type, unsigned footprint,
|
virtual void collect(CollectionType type,
|
||||||
|
unsigned footprint,
|
||||||
int pendingAllocation) = 0;
|
int pendingAllocation) = 0;
|
||||||
virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) = 0;
|
virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) = 0;
|
||||||
virtual void* allocateFixed(avian::util::Allocator* allocator,
|
virtual void* allocateFixed(avian::util::Allocator* allocator,
|
||||||
@ -92,4 +85,4 @@ Heap* makeHeap(System* system, unsigned limit);
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//HEAP_H
|
#endif // HEAP_H
|
||||||
|
@ -21,7 +21,8 @@ namespace system {
|
|||||||
// order to trigger the crash dump logic.
|
// order to trigger the crash dump logic.
|
||||||
NO_RETURN void crash();
|
NO_RETURN void crash();
|
||||||
|
|
||||||
// Registrar for unix-like "signals" (implemented with structured exceptions on windows).
|
// Registrar for unix-like "signals" (implemented with structured exceptions on
|
||||||
|
// windows).
|
||||||
// TODO: remove dependence on generated code having a well-known "thread"
|
// TODO: remove dependence on generated code having a well-known "thread"
|
||||||
// register. Use a thread-local variable instead.
|
// register. Use a thread-local variable instead.
|
||||||
class SignalRegistrar {
|
class SignalRegistrar {
|
||||||
@ -40,7 +41,6 @@ class SignalRegistrar {
|
|||||||
// "Segmentation fault" exceptions (mostly null pointer dereference, but
|
// "Segmentation fault" exceptions (mostly null pointer dereference, but
|
||||||
// generally access to any non-mapped memory)
|
// generally access to any non-mapped memory)
|
||||||
SegFault,
|
SegFault,
|
||||||
|
|
||||||
DivideByZero,
|
DivideByZero,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,7 +72,6 @@ class SignalRegistrar {
|
|||||||
struct Data;
|
struct Data;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Data* data;
|
Data* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,12 +21,7 @@ class System : public avian::util::Aborter {
|
|||||||
public:
|
public:
|
||||||
typedef intptr_t Status;
|
typedef intptr_t Status;
|
||||||
|
|
||||||
enum FileType {
|
enum FileType { TypeUnknown, TypeDoesNotExist, TypeFile, TypeDirectory };
|
||||||
TypeUnknown,
|
|
||||||
TypeDoesNotExist,
|
|
||||||
TypeFile,
|
|
||||||
TypeDirectory
|
|
||||||
};
|
|
||||||
|
|
||||||
class Thread {
|
class Thread {
|
||||||
public:
|
public:
|
||||||
@ -100,11 +95,13 @@ class System : public avian::util::Aborter {
|
|||||||
|
|
||||||
class MonitorResource {
|
class MonitorResource {
|
||||||
public:
|
public:
|
||||||
MonitorResource(System::Thread* t, System::Monitor* m): t(t), m(m) {
|
MonitorResource(System::Thread* t, System::Monitor* m) : t(t), m(m)
|
||||||
|
{
|
||||||
m->acquire(t);
|
m->acquire(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
~MonitorResource() {
|
~MonitorResource()
|
||||||
|
{
|
||||||
m->release(t);
|
m->release(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,8 +123,8 @@ class System : public avian::util::Aborter {
|
|||||||
virtual Status make(Monitor**) = 0;
|
virtual Status make(Monitor**) = 0;
|
||||||
virtual Status make(Local**) = 0;
|
virtual Status make(Local**) = 0;
|
||||||
|
|
||||||
virtual Status visit(Thread* thread, Thread* target,
|
virtual Status visit(Thread* thread, Thread* target, ThreadVisitor* visitor)
|
||||||
ThreadVisitor* visitor) = 0;
|
= 0;
|
||||||
|
|
||||||
virtual Status map(Region**, const char* name) = 0;
|
virtual Status map(Region**, const char* name) = 0;
|
||||||
virtual FileType stat(const char* name, unsigned* length) = 0;
|
virtual FileType stat(const char* name, unsigned* length) = 0;
|
||||||
@ -145,23 +142,23 @@ class System : public avian::util::Aborter {
|
|||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void*
|
inline void* allocate(System* s, unsigned size)
|
||||||
allocate(System* s, unsigned size)
|
|
||||||
{
|
{
|
||||||
void* p = s->tryAllocate(size);
|
void* p = s->tryAllocate(size);
|
||||||
if (p == 0) s->abort();
|
if (p == 0)
|
||||||
|
s->abort();
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ACQUIRE_MONITOR(t, m) \
|
#define ACQUIRE_MONITOR(t, m) \
|
||||||
System::MonitorResource MAKE_NAME(monitorResource_) (t, m)
|
System::MonitorResource MAKE_NAME(monitorResource_)(t, m)
|
||||||
|
|
||||||
inline avian::util::Aborter* getAborter(System* s) {
|
inline avian::util::Aborter* getAborter(System* s)
|
||||||
|
{
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void NO_RETURN
|
inline void NO_RETURN sysAbort(System* s)
|
||||||
sysAbort(System* s)
|
|
||||||
{
|
{
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
@ -183,9 +180,8 @@ sysAbort(System* s)
|
|||||||
|
|
||||||
// #endif // not NDEBUG
|
// #endif // not NDEBUG
|
||||||
|
|
||||||
AVIAN_EXPORT System*
|
AVIAN_EXPORT System* makeSystem();
|
||||||
makeSystem();
|
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//SYSTEM_H
|
#endif // SYSTEM_H
|
||||||
|
@ -23,16 +23,17 @@ namespace avian {
|
|||||||
namespace tools {
|
namespace tools {
|
||||||
|
|
||||||
class OutputStream {
|
class OutputStream {
|
||||||
public:
|
public:
|
||||||
virtual void writeChunk(const void* data, size_t size) = 0;
|
virtual void writeChunk(const void* data, size_t size) = 0;
|
||||||
virtual void write(uint8_t byte);
|
virtual void write(uint8_t byte);
|
||||||
virtual void writeRepeat(uint8_t byte, size_t size);
|
virtual void writeRepeat(uint8_t byte, size_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileOutputStream : public OutputStream {
|
class FileOutputStream : public OutputStream {
|
||||||
private:
|
private:
|
||||||
FILE* file;
|
FILE* file;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
FileOutputStream(const char* name);
|
FileOutputStream(const char* name);
|
||||||
~FileOutputStream();
|
~FileOutputStream();
|
||||||
|
|
||||||
@ -43,20 +44,22 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class SymbolInfo {
|
class SymbolInfo {
|
||||||
public:
|
public:
|
||||||
unsigned addr;
|
unsigned addr;
|
||||||
util::String name;
|
util::String name;
|
||||||
|
|
||||||
inline SymbolInfo(uint64_t addr, const util::String& name):
|
inline SymbolInfo(uint64_t addr, const util::String& name)
|
||||||
addr(addr),
|
: addr(addr), name(name)
|
||||||
name(name) {}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
inline SymbolInfo():
|
inline SymbolInfo() : name("")
|
||||||
name("") {}
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Buffer {
|
class Buffer {
|
||||||
public:
|
public:
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
size_t length;
|
size_t length;
|
||||||
uint8_t* data;
|
uint8_t* data;
|
||||||
@ -69,7 +72,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class StringTable : public Buffer {
|
class StringTable : public Buffer {
|
||||||
public:
|
public:
|
||||||
unsigned add(util::String str);
|
unsigned add(util::String str);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,7 +106,7 @@ class DynamicArray : public util::Slice<T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class PlatformInfo {
|
class PlatformInfo {
|
||||||
public:
|
public:
|
||||||
enum Format {
|
enum Format {
|
||||||
Elf = AVIAN_FORMAT_ELF,
|
Elf = AVIAN_FORMAT_ELF,
|
||||||
Pe = AVIAN_FORMAT_PE,
|
Pe = AVIAN_FORMAT_PE,
|
||||||
@ -124,33 +127,31 @@ public:
|
|||||||
static Format formatFromString(const char* format);
|
static Format formatFromString(const char* format);
|
||||||
static Architecture archFromString(const char* arch);
|
static Architecture archFromString(const char* arch);
|
||||||
|
|
||||||
inline PlatformInfo(Format format, Architecture arch):
|
inline PlatformInfo(Format format, Architecture arch)
|
||||||
format(format),
|
: format(format), arch(arch)
|
||||||
arch(arch) {}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
inline bool operator == (const PlatformInfo& other) {
|
inline bool operator==(const PlatformInfo& other)
|
||||||
|
{
|
||||||
return format == other.format && arch == other.arch;
|
return format == other.format && arch == other.arch;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Platform {
|
class Platform {
|
||||||
private:
|
private:
|
||||||
Platform* next;
|
Platform* next;
|
||||||
static Platform* first;
|
static Platform* first;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
PlatformInfo info;
|
PlatformInfo info;
|
||||||
|
|
||||||
inline Platform(PlatformInfo info):
|
inline Platform(PlatformInfo info) : next(first), info(info)
|
||||||
next(first),
|
|
||||||
info(info)
|
|
||||||
{
|
{
|
||||||
first = this;
|
first = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AccessFlags {
|
enum AccessFlags { Writable = 1 << 0, Executable = 1 << 1 };
|
||||||
Writable = 1 << 0,
|
|
||||||
Executable = 1 << 1
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual bool writeObject(OutputStream* out,
|
virtual bool writeObject(OutputStream* out,
|
||||||
util::Slice<SymbolInfo> symbols,
|
util::Slice<SymbolInfo> symbols,
|
||||||
@ -166,4 +167,3 @@ public:
|
|||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ namespace avian {
|
|||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
class Aborter {
|
class Aborter {
|
||||||
public:
|
public:
|
||||||
virtual void NO_RETURN abort() = 0;
|
virtual void NO_RETURN abort() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,15 +28,17 @@ inline Aborter* getAborter(Aborter* a)
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
inline void NO_RETURN abort(T t) {
|
inline void NO_RETURN abort(T t)
|
||||||
|
{
|
||||||
getAborter(t)->abort();
|
getAborter(t)->abort();
|
||||||
::abort();
|
::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
inline void expect(T t, bool v) {
|
inline void expect(T t, bool v)
|
||||||
if(UNLIKELY(!v)) {
|
{
|
||||||
|
if (UNLIKELY(!v)) {
|
||||||
abort(t);
|
abort(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ class ArgParser {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Arg {
|
class Arg {
|
||||||
public:
|
public:
|
||||||
Arg* next;
|
Arg* next;
|
||||||
bool required;
|
bool required;
|
||||||
const char* name;
|
const char* name;
|
||||||
@ -42,7 +42,6 @@ public:
|
|||||||
Arg(ArgParser& parser, bool required, const char* name, const char* desc);
|
Arg(ArgParser& parser, bool required, const char* name, const char* desc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
||||||
|
@ -18,16 +18,17 @@ namespace util {
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class List {
|
class List {
|
||||||
public:
|
public:
|
||||||
List(const T& item, List<T>* next):
|
List(const T& item, List<T>* next) : item(item), next(next)
|
||||||
item(item),
|
{
|
||||||
next(next) {}
|
}
|
||||||
|
|
||||||
unsigned count() {
|
unsigned count()
|
||||||
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
List<T>* c = this;
|
List<T>* c = this;
|
||||||
while (c) {
|
while (c) {
|
||||||
++ count;
|
++count;
|
||||||
c = c->next;
|
c = c->next;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
@ -17,36 +17,47 @@
|
|||||||
namespace avian {
|
namespace avian {
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
inline unsigned max(unsigned a, unsigned b) {
|
inline unsigned max(unsigned a, unsigned b)
|
||||||
|
{
|
||||||
return (a > b ? a : b);
|
return (a > b ? a : b);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned min(unsigned a, unsigned b) {
|
inline unsigned min(unsigned a, unsigned b)
|
||||||
|
{
|
||||||
return (a < b ? a : b);
|
return (a < b ? a : b);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned avg(unsigned a, unsigned b) {
|
inline unsigned avg(unsigned a, unsigned b)
|
||||||
|
{
|
||||||
return (a + b) / 2;
|
return (a + b) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned ceilingDivide(unsigned n, unsigned d) {
|
inline unsigned ceilingDivide(unsigned n, unsigned d)
|
||||||
|
{
|
||||||
return (n + d - 1) / d;
|
return (n + d - 1) / d;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool powerOfTwo(unsigned n) {
|
inline bool powerOfTwo(unsigned n)
|
||||||
for (; n > 2; n >>= 1) if (n & 1) return false;
|
{
|
||||||
|
for (; n > 2; n >>= 1)
|
||||||
|
if (n & 1)
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned nextPowerOfTwo(unsigned n) {
|
inline unsigned nextPowerOfTwo(unsigned n)
|
||||||
|
{
|
||||||
unsigned r = 1;
|
unsigned r = 1;
|
||||||
while (r < n) r <<= 1;
|
while (r < n)
|
||||||
|
r <<= 1;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned log(unsigned n) {
|
inline unsigned log(unsigned n)
|
||||||
|
{
|
||||||
unsigned r = 0;
|
unsigned r = 0;
|
||||||
for (unsigned i = 1; i < n; ++r) i <<= 1;
|
for (unsigned i = 1; i < n; ++r)
|
||||||
|
i <<= 1;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,24 +16,25 @@
|
|||||||
template <class T>
|
template <class T>
|
||||||
class RuntimeArray {
|
class RuntimeArray {
|
||||||
public:
|
public:
|
||||||
RuntimeArray(unsigned size):
|
RuntimeArray(unsigned size) : body(static_cast<T*>(malloc(size * sizeof(T))))
|
||||||
body(static_cast<T*>(malloc(size * sizeof(T))))
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
~RuntimeArray() {
|
~RuntimeArray()
|
||||||
|
{
|
||||||
free(body);
|
free(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
T* body;
|
T* body;
|
||||||
};
|
};
|
||||||
|
|
||||||
# define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size);
|
#define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size);
|
||||||
# define RUNTIME_ARRAY_BODY(name) name.body
|
#define RUNTIME_ARRAY_BODY(name) name.body
|
||||||
|
|
||||||
#else // not _MSC_VER
|
#else // not _MSC_VER
|
||||||
|
|
||||||
# define RUNTIME_ARRAY(type, name, size) type name##_body[size];
|
#define RUNTIME_ARRAY(type, name, size) type name##_body[size];
|
||||||
# define RUNTIME_ARRAY_BODY(name) name##_body
|
#define RUNTIME_ARRAY_BODY(name) name##_body
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -22,19 +22,23 @@ class AbstractStream {
|
|||||||
virtual void handleError() = 0;
|
virtual void handleError() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractStream(Client* client, unsigned size):
|
AbstractStream(Client* client, unsigned size)
|
||||||
client(client), size(size), position_(0)
|
: client(client), size(size), position_(0)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsigned position() {
|
unsigned position()
|
||||||
|
{
|
||||||
return position_;
|
return position_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPosition(unsigned p) {
|
void setPosition(unsigned p)
|
||||||
|
{
|
||||||
position_ = p;
|
position_ = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skip(unsigned size) {
|
void skip(unsigned size)
|
||||||
|
{
|
||||||
if (size > this->size - position_) {
|
if (size > this->size - position_) {
|
||||||
client->handleError();
|
client->handleError();
|
||||||
} else {
|
} else {
|
||||||
@ -42,7 +46,8 @@ class AbstractStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void read(uint8_t* dst, unsigned size) {
|
void read(uint8_t* dst, unsigned size)
|
||||||
|
{
|
||||||
if (size > this->size - position_) {
|
if (size > this->size - position_) {
|
||||||
memset(dst, 0, size);
|
memset(dst, 0, size);
|
||||||
|
|
||||||
@ -53,35 +58,41 @@ class AbstractStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t read1() {
|
uint8_t read1()
|
||||||
|
{
|
||||||
uint8_t v;
|
uint8_t v;
|
||||||
read(&v, 1);
|
read(&v, 1);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t read2() {
|
uint16_t read2()
|
||||||
|
{
|
||||||
uint16_t a = read1();
|
uint16_t a = read1();
|
||||||
uint16_t b = read1();
|
uint16_t b = read1();
|
||||||
return (a << 8) | b;
|
return (a << 8) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t read4() {
|
uint32_t read4()
|
||||||
|
{
|
||||||
uint32_t a = read2();
|
uint32_t a = read2();
|
||||||
uint32_t b = read2();
|
uint32_t b = read2();
|
||||||
return (a << 16) | b;
|
return (a << 16) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t read8() {
|
uint64_t read8()
|
||||||
|
{
|
||||||
uint64_t a = read4();
|
uint64_t a = read4();
|
||||||
uint64_t b = read4();
|
uint64_t b = read4();
|
||||||
return (a << 32) | b;
|
return (a << 32) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t readFloat() {
|
uint32_t readFloat()
|
||||||
|
{
|
||||||
return read4();
|
return read4();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t readDouble() {
|
uint64_t readDouble()
|
||||||
|
{
|
||||||
return read8();
|
return read8();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,14 +105,16 @@ class AbstractStream {
|
|||||||
unsigned position_;
|
unsigned position_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Stream: public AbstractStream {
|
class Stream : public AbstractStream {
|
||||||
public:
|
public:
|
||||||
Stream(Client* client, const uint8_t* data, unsigned size):
|
Stream(Client* client, const uint8_t* data, unsigned size)
|
||||||
AbstractStream(client, size), data(data)
|
: AbstractStream(client, size), data(data)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void copy(uint8_t* dst, unsigned offset, unsigned size) {
|
virtual void copy(uint8_t* dst, unsigned offset, unsigned size)
|
||||||
|
{
|
||||||
memcpy(dst, data + offset, size);
|
memcpy(dst, data + offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,4 +123,4 @@ class Stream: public AbstractStream {
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//STREAM_H
|
#endif // STREAM_H
|
||||||
|
@ -17,38 +17,43 @@ namespace avian {
|
|||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
class String {
|
class String {
|
||||||
public:
|
public:
|
||||||
const char* text;
|
const char* text;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
String(const char* text):
|
String(const char* text) : text(text), length(strlen(text))
|
||||||
text(text),
|
{
|
||||||
length(strlen(text)) {}
|
}
|
||||||
|
|
||||||
inline String(const char* text, size_t length):
|
inline String(const char* text, size_t length) : text(text), length(length)
|
||||||
text(text),
|
{
|
||||||
length(length) {}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Tokenizer {
|
class Tokenizer {
|
||||||
public:
|
public:
|
||||||
|
Tokenizer(const char* s, char delimiter)
|
||||||
|
: s(s), limit(0), delimiter(delimiter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Tokenizer(const char* s, char delimiter):
|
Tokenizer(String str, char delimiter)
|
||||||
s(s), limit(0), delimiter(delimiter)
|
: s(str.text), limit(str.text + str.length), delimiter(delimiter)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Tokenizer(String str, char delimiter):
|
bool hasMore()
|
||||||
s(str.text), limit(str.text + str.length), delimiter(delimiter)
|
{
|
||||||
{ }
|
while (s != limit and *s == delimiter)
|
||||||
|
++s;
|
||||||
bool hasMore() {
|
|
||||||
while (s != limit and *s == delimiter) ++s;
|
|
||||||
return s != limit and *s != 0;
|
return s != limit and *s != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String next() {
|
String next()
|
||||||
|
{
|
||||||
const char* p = s;
|
const char* p = s;
|
||||||
while (s != limit and *s and *s != delimiter) ++s;
|
while (s != limit and *s and *s != delimiter)
|
||||||
|
++s;
|
||||||
return String(p, s - p);
|
return String(p, s - p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,4 +65,4 @@ class Tokenizer {
|
|||||||
} // namespace util
|
} // namespace util
|
||||||
} // namespace avain
|
} // namespace avain
|
||||||
|
|
||||||
#endif//AVIAN_UTIL_STRING_H
|
#endif // AVIAN_UTIL_STRING_H
|
||||||
|
@ -11,8 +11,7 @@ struct JniConstants {
|
|||||||
static void init(_JNIEnv* env);
|
static void init(_JNIEnv* env);
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void JniConstants::init(_JNIEnv*)
|
||||||
JniConstants::init(_JNIEnv*)
|
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,16 @@ class Vector {
|
|||||||
data(0, 0),
|
data(0, 0),
|
||||||
position(0),
|
position(0),
|
||||||
minimumCapacity(minimumCapacity)
|
minimumCapacity(minimumCapacity)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~Vector() {
|
~Vector()
|
||||||
|
{
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose()
|
||||||
|
{
|
||||||
if (data.items and minimumCapacity > 0) {
|
if (data.items and minimumCapacity > 0) {
|
||||||
allocator->free(data.items, data.count);
|
allocator->free(data.items, data.count);
|
||||||
data.items = 0;
|
data.items = 0;
|
||||||
@ -95,27 +98,33 @@ class Vector {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(uint8_t v) {
|
void append(uint8_t v)
|
||||||
|
{
|
||||||
append(&v, 1);
|
append(&v, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append2(uint16_t v) {
|
void append2(uint16_t v)
|
||||||
|
{
|
||||||
append(&v, 2);
|
append(&v, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append4(uint32_t v) {
|
void append4(uint32_t v)
|
||||||
|
{
|
||||||
append(&v, 4);
|
append(&v, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendTargetAddress(target_uintptr_t v) {
|
void appendTargetAddress(target_uintptr_t v)
|
||||||
|
{
|
||||||
append(&v, TargetBytesPerWord);
|
append(&v, TargetBytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendAddress(uintptr_t v) {
|
void appendAddress(uintptr_t v)
|
||||||
|
{
|
||||||
append(&v, BytesPerWord);
|
append(&v, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendAddress(void* v) {
|
void appendAddress(void* v)
|
||||||
|
{
|
||||||
append(&v, BytesPerWord);
|
append(&v, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,25 +136,29 @@ class Vector {
|
|||||||
|
|
||||||
size_t get(size_t offset)
|
size_t get(size_t offset)
|
||||||
{
|
{
|
||||||
uint8_t v; get(offset, &v, 1);
|
uint8_t v;
|
||||||
|
get(offset, &v, 1);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t get2(size_t offset)
|
size_t get2(size_t offset)
|
||||||
{
|
{
|
||||||
uint16_t v; get(offset, &v, 2);
|
uint16_t v;
|
||||||
|
get(offset, &v, 2);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t get4(size_t offset)
|
size_t get4(size_t offset)
|
||||||
{
|
{
|
||||||
uint32_t v; get(offset, &v, 4);
|
uint32_t v;
|
||||||
|
get(offset, &v, 4);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t getAddress(size_t offset)
|
uintptr_t getAddress(size_t offset)
|
||||||
{
|
{
|
||||||
uintptr_t v; get(offset, &v, BytesPerWord);
|
uintptr_t v;
|
||||||
|
get(offset, &v, BytesPerWord);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,4 +183,4 @@ class Vector {
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//VECTOR_H
|
#endif // VECTOR_H
|
||||||
|
@ -12,39 +12,41 @@
|
|||||||
#define ARCH_H
|
#define ARCH_H
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# include "windows.h"
|
#include "windows.h"
|
||||||
# pragma push_macro("assert")
|
#pragma push_macro("assert")
|
||||||
# include "intrin.h"
|
#include "intrin.h"
|
||||||
# pragma pop_macro("assert")
|
#pragma pop_macro("assert")
|
||||||
# undef interface
|
#undef interface
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "avian/common.h"
|
#include "avian/common.h"
|
||||||
|
|
||||||
extern "C" void NO_RETURN
|
extern "C" void NO_RETURN vmJump(void* address,
|
||||||
vmJump(void* address, void* frame, void* stack, void* thread,
|
void* frame,
|
||||||
uintptr_t returnLow, uintptr_t returnHigh);
|
void* stack,
|
||||||
|
void* thread,
|
||||||
|
uintptr_t returnLow,
|
||||||
|
uintptr_t returnHigh);
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
inline void
|
inline void compileTimeMemoryBarrier()
|
||||||
compileTimeMemoryBarrier()
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
_ReadWriteBarrier();
|
_ReadWriteBarrier();
|
||||||
#else
|
#else
|
||||||
__asm__ __volatile__("": : :"memory");
|
__asm__ __volatile__("" : : : "memory");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#if (defined ARCH_x86_32) || (defined ARCH_x86_64)
|
#if (defined ARCH_x86_32) || (defined ARCH_x86_64)
|
||||||
# include "x86.h"
|
#include "x86.h"
|
||||||
#elif defined ARCH_arm
|
#elif defined ARCH_arm
|
||||||
# include "arm.h"
|
#include "arm.h"
|
||||||
#else
|
#else
|
||||||
# error unsupported architecture
|
#error unsupported architecture
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif//ARCH_H
|
#endif // ARCH_H
|
||||||
|
183
src/avian/arm.h
183
src/avian/arm.h
@ -16,61 +16,62 @@
|
|||||||
#include <avian/util/runtime-array.h>
|
#include <avian/util/runtime-array.h>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# include "libkern/OSAtomic.h"
|
#include "libkern/OSAtomic.h"
|
||||||
# include "libkern/OSCacheControl.h"
|
#include "libkern/OSCacheControl.h"
|
||||||
# include "mach/mach_types.h"
|
#include "mach/mach_types.h"
|
||||||
# include "mach/thread_act.h"
|
#include "mach/thread_act.h"
|
||||||
# include "mach/thread_status.h"
|
#include "mach/thread_status.h"
|
||||||
|
|
||||||
# define THREAD_STATE ARM_THREAD_STATE
|
#define THREAD_STATE ARM_THREAD_STATE
|
||||||
# define THREAD_STATE_TYPE arm_thread_state_t
|
#define THREAD_STATE_TYPE arm_thread_state_t
|
||||||
# define THREAD_STATE_COUNT ARM_THREAD_STATE_COUNT
|
#define THREAD_STATE_COUNT ARM_THREAD_STATE_COUNT
|
||||||
|
|
||||||
# if __DARWIN_UNIX03 && defined(_STRUCT_ARM_EXCEPTION_STATE)
|
#if __DARWIN_UNIX03 && defined(_STRUCT_ARM_EXCEPTION_STATE)
|
||||||
# define FIELD(x) __##x
|
#define FIELD(x) __##x
|
||||||
# else
|
|
||||||
# define FIELD(x) x
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# define THREAD_STATE_IP(state) ((state).FIELD(pc))
|
|
||||||
# define THREAD_STATE_STACK(state) ((state).FIELD(sp))
|
|
||||||
# define THREAD_STATE_THREAD(state) ((state).FIELD(r[8]))
|
|
||||||
# define THREAD_STATE_LINK(state) ((state).FIELD(lr))
|
|
||||||
|
|
||||||
# define IP_REGISTER(context) \
|
|
||||||
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
|
||||||
# define STACK_REGISTER(context) \
|
|
||||||
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
|
|
||||||
# define THREAD_REGISTER(context) \
|
|
||||||
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
|
||||||
# define LINK_REGISTER(context) \
|
|
||||||
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
|
||||||
#elif (defined __QNX__)
|
|
||||||
# include "arm/smpxchg.h"
|
|
||||||
# include "sys/mman.h"
|
|
||||||
|
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_PC])
|
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_SP])
|
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_IP])
|
|
||||||
# define LINK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_LR])
|
|
||||||
#else
|
#else
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext.arm_pc)
|
#define FIELD(x) x
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext.arm_sp)
|
#endif
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.arm_ip)
|
|
||||||
# define LINK_REGISTER(context) (context->uc_mcontext.arm_lr)
|
#define THREAD_STATE_IP(state) ((state).FIELD(pc))
|
||||||
|
#define THREAD_STATE_STACK(state) ((state).FIELD(sp))
|
||||||
|
#define THREAD_STATE_THREAD(state) ((state).FIELD(r[8]))
|
||||||
|
#define THREAD_STATE_LINK(state) ((state).FIELD(lr))
|
||||||
|
|
||||||
|
#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
||||||
|
#define STACK_REGISTER(context) \
|
||||||
|
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
|
||||||
|
#define THREAD_REGISTER(context) \
|
||||||
|
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
||||||
|
#define LINK_REGISTER(context) \
|
||||||
|
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
||||||
|
#elif(defined __QNX__)
|
||||||
|
#include "arm/smpxchg.h"
|
||||||
|
#include "sys/mman.h"
|
||||||
|
|
||||||
|
#define IP_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_PC])
|
||||||
|
#define STACK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_SP])
|
||||||
|
#define THREAD_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_IP])
|
||||||
|
#define LINK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_LR])
|
||||||
|
#else
|
||||||
|
#define IP_REGISTER(context) (context->uc_mcontext.arm_pc)
|
||||||
|
#define STACK_REGISTER(context) (context->uc_mcontext.arm_sp)
|
||||||
|
#define THREAD_REGISTER(context) (context->uc_mcontext.arm_ip)
|
||||||
|
#define LINK_REGISTER(context) (context->uc_mcontext.arm_lr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define VA_LIST(x) (&(x))
|
#define VA_LIST(x) (&(x))
|
||||||
|
|
||||||
extern "C" uint64_t
|
extern "C" uint64_t vmNativeCall(void* function,
|
||||||
vmNativeCall(void* function, unsigned stackTotal, void* memoryTable,
|
unsigned stackTotal,
|
||||||
unsigned memoryCount, void* gprTable, void* vfpTable,
|
void* memoryTable,
|
||||||
|
unsigned memoryCount,
|
||||||
|
void* gprTable,
|
||||||
|
void* vfpTable,
|
||||||
unsigned returnType);
|
unsigned returnType);
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
inline void
|
inline void trap()
|
||||||
trap()
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
@ -86,23 +87,21 @@ trap()
|
|||||||
// performant choice.
|
// performant choice.
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
inline void
|
inline void memoryBarrier()
|
||||||
memoryBarrier()
|
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
OSMemoryBarrier();
|
OSMemoryBarrier();
|
||||||
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
||||||
return __sync_synchronize();
|
return __sync_synchronize();
|
||||||
#elif (! defined AVIAN_ASSUME_ARMV6)
|
#elif(!defined AVIAN_ASSUME_ARMV6)
|
||||||
__asm__ __volatile__ ("dmb" : : : "memory");
|
__asm__ __volatile__("dmb" : : : "memory");
|
||||||
#else
|
#else
|
||||||
__asm__ __volatile__ ("" : : : "memory");
|
__asm__ __volatile__("" : : : "memory");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void
|
inline void storeStoreMemoryBarrier()
|
||||||
storeStoreMemoryBarrier()
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
_ReadWriteBarrier();
|
_ReadWriteBarrier();
|
||||||
@ -111,8 +110,7 @@ storeStoreMemoryBarrier()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void storeLoadMemoryBarrier()
|
||||||
storeLoadMemoryBarrier()
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
MemoryBarrier();
|
MemoryBarrier();
|
||||||
@ -121,8 +119,7 @@ storeLoadMemoryBarrier()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void loadMemoryBarrier()
|
||||||
loadMemoryBarrier()
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
_ReadWriteBarrier();
|
_ReadWriteBarrier();
|
||||||
@ -135,18 +132,18 @@ loadMemoryBarrier()
|
|||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
// http://code.google.com/p/android/issues/detail?id=1803
|
// http://code.google.com/p/android/issues/detail?id=1803
|
||||||
extern "C" void __clear_cache (void *beg __attribute__((__unused__)), void *end __attribute__((__unused__)));
|
extern "C" void __clear_cache(void* beg __attribute__((__unused__)),
|
||||||
|
void* end __attribute__((__unused__)));
|
||||||
#endif
|
#endif
|
||||||
inline void
|
inline void syncInstructionCache(const void* start, unsigned size)
|
||||||
syncInstructionCache(const void* start, unsigned size)
|
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
sys_icache_invalidate(const_cast<void*>(start), size);
|
sys_icache_invalidate(const_cast<void*>(start), size);
|
||||||
#elif (defined __QNX__)
|
#elif(defined __QNX__)
|
||||||
msync(const_cast<void*>(start), size, MS_INVALIDATE_ICACHE);
|
msync(const_cast<void*>(start), size, MS_INVALIDATE_ICACHE);
|
||||||
#else
|
#else
|
||||||
__clear_cache
|
__clear_cache(
|
||||||
(const_cast<void*>(start),
|
const_cast<void*>(start),
|
||||||
const_cast<uint8_t*>(static_cast<const uint8_t*>(start) + size));
|
const_cast<uint8_t*>(static_cast<const uint8_t*>(start) + size));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -154,32 +151,34 @@ syncInstructionCache(const void* start, unsigned size)
|
|||||||
#endif // AVIAN_AOT_ONLY
|
#endif // AVIAN_AOT_ONLY
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
|
typedef int(__kernel_cmpxchg_t)(int oldval, int newval, int* ptr);
|
||||||
# define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
|
#define __kernel_cmpxchg (*(__kernel_cmpxchg_t*)0xffff0fc0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline bool
|
inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
||||||
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
return OSAtomicCompareAndSwap32Barrier(old, new_, reinterpret_cast<int32_t*>(p));
|
return OSAtomicCompareAndSwap32Barrier(
|
||||||
#elif (defined __QNX__)
|
old, new_, reinterpret_cast<int32_t*>(p));
|
||||||
|
#elif(defined __QNX__)
|
||||||
return old == _smp_cmpxchg(p, old, new_);
|
return old == _smp_cmpxchg(p, old, new_);
|
||||||
#else
|
#else
|
||||||
int r = __kernel_cmpxchg(static_cast<int>(old), static_cast<int>(new_), reinterpret_cast<int*>(p));
|
int r = __kernel_cmpxchg(
|
||||||
|
static_cast<int>(old), static_cast<int>(new_), reinterpret_cast<int*>(p));
|
||||||
return (!r ? true : false);
|
return (!r ? true : false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
||||||
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
|
||||||
{
|
{
|
||||||
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
|
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint64_t
|
inline uint64_t dynamicCall(void* function,
|
||||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
uintptr_t* arguments,
|
||||||
unsigned argumentCount, unsigned argumentsSize UNUSED,
|
uint8_t* argumentTypes,
|
||||||
|
unsigned argumentCount,
|
||||||
|
unsigned argumentsSize UNUSED,
|
||||||
unsigned returnType)
|
unsigned returnType)
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@ -197,11 +196,14 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
unsigned vfpIndex = 0;
|
unsigned vfpIndex = 0;
|
||||||
unsigned vfpBackfillIndex UNUSED = 0;
|
unsigned vfpBackfillIndex UNUSED = 0;
|
||||||
|
|
||||||
RUNTIME_ARRAY(uintptr_t, stack, (argumentCount * 8) / BytesPerWord); // is > argumentSize to account for padding
|
RUNTIME_ARRAY(uintptr_t,
|
||||||
|
stack,
|
||||||
|
(argumentCount * 8)
|
||||||
|
/ BytesPerWord); // is > argumentSize to account for padding
|
||||||
unsigned stackIndex = 0;
|
unsigned stackIndex = 0;
|
||||||
|
|
||||||
unsigned ai = 0;
|
unsigned ai = 0;
|
||||||
for (unsigned ati = 0; ati < argumentCount; ++ ati) {
|
for (unsigned ati = 0; ati < argumentCount; ++ati) {
|
||||||
switch (argumentTypes[ati]) {
|
switch (argumentTypes[ati]) {
|
||||||
case DOUBLE_TYPE:
|
case DOUBLE_TYPE:
|
||||||
#if defined(__ARM_PCS_VFP)
|
#if defined(__ARM_PCS_VFP)
|
||||||
@ -209,7 +211,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
if (vfpIndex + Alignment <= VfpCount) {
|
if (vfpIndex + Alignment <= VfpCount) {
|
||||||
if (vfpIndex % Alignment) {
|
if (vfpIndex % Alignment) {
|
||||||
vfpBackfillIndex = vfpIndex;
|
vfpBackfillIndex = vfpIndex;
|
||||||
++ vfpIndex;
|
++vfpIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(vfpTable + vfpIndex, arguments + ai, 8);
|
memcpy(vfpTable + vfpIndex, arguments + ai, 8);
|
||||||
@ -217,7 +219,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
} else {
|
} else {
|
||||||
vfpIndex = VfpCount;
|
vfpIndex = VfpCount;
|
||||||
if (stackIndex % Alignment) {
|
if (stackIndex % Alignment) {
|
||||||
++ stackIndex;
|
++stackIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8);
|
memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8);
|
||||||
@ -235,15 +237,13 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
} else {
|
} else {
|
||||||
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
||||||
}
|
}
|
||||||
++ ai;
|
++ai;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case INT64_TYPE: {
|
case INT64_TYPE: {
|
||||||
if (gprIndex + Alignment <= GprCount) { // pass argument in register(s)
|
if (gprIndex + Alignment <= GprCount) { // pass argument in register(s)
|
||||||
if (Alignment == 1
|
if (Alignment == 1 and BytesPerWord < 8
|
||||||
and BytesPerWord < 8
|
and gprIndex + Alignment == GprCount) {
|
||||||
and gprIndex + Alignment == GprCount)
|
|
||||||
{
|
|
||||||
gprTable[gprIndex++] = arguments[ai];
|
gprTable[gprIndex++] = arguments[ai];
|
||||||
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1];
|
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1];
|
||||||
} else {
|
} else {
|
||||||
@ -272,25 +272,28 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
} else {
|
} else {
|
||||||
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
||||||
}
|
}
|
||||||
++ ai;
|
++ai;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gprIndex < GprCount) { // pad since assembly loads all GPRs
|
if (gprIndex < GprCount) { // pad since assembly loads all GPRs
|
||||||
memset(gprTable + gprIndex, 0, (GprCount-gprIndex)*4);
|
memset(gprTable + gprIndex, 0, (GprCount - gprIndex) * 4);
|
||||||
gprIndex = GprCount;
|
gprIndex = GprCount;
|
||||||
}
|
}
|
||||||
if (vfpIndex < VfpCount) {
|
if (vfpIndex < VfpCount) {
|
||||||
memset(vfpTable + vfpIndex, 0, (VfpCount-vfpIndex)*4);
|
memset(vfpTable + vfpIndex, 0, (VfpCount - vfpIndex) * 4);
|
||||||
vfpIndex = VfpCount;
|
vfpIndex = VfpCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2);
|
unsigned stackSize = stackIndex * BytesPerWord + ((stackIndex & 1) << 2);
|
||||||
return vmNativeCall
|
return vmNativeCall(function,
|
||||||
(function, stackSize, RUNTIME_ARRAY_BODY(stack), stackIndex * BytesPerWord,
|
stackSize,
|
||||||
|
RUNTIME_ARRAY_BODY(stack),
|
||||||
|
stackIndex * BytesPerWord,
|
||||||
(gprIndex ? gprTable : 0),
|
(gprIndex ? gprTable : 0),
|
||||||
(vfpIndex ? vfpTable : 0), returnType);
|
(vfpIndex ? vfpTable : 0),
|
||||||
|
returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
@ -24,13 +24,14 @@ class BootImage {
|
|||||||
public:
|
public:
|
||||||
class Thunk {
|
class Thunk {
|
||||||
public:
|
public:
|
||||||
Thunk():
|
Thunk() : start(0), frameSavedOffset(0), length(0)
|
||||||
start(0), frameSavedOffset(0), length(0)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
Thunk(uint32_t start, uint32_t frameSavedOffset, uint32_t length):
|
Thunk(uint32_t start, uint32_t frameSavedOffset, uint32_t length)
|
||||||
start(start), frameSavedOffset(frameSavedOffset), length(length)
|
: start(start), frameSavedOffset(frameSavedOffset), length(length)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t start;
|
uint32_t start;
|
||||||
uint32_t frameSavedOffset;
|
uint32_t frameSavedOffset;
|
||||||
@ -74,4 +75,4 @@ class OffsetResolver {
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//BOOTIMAGE_H
|
#endif // BOOTIMAGE_H
|
||||||
|
@ -18,16 +18,16 @@ using namespace avian::util;
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
object
|
object getTrace(Thread* t, unsigned skipCount)
|
||||||
getTrace(Thread* t, unsigned skipCount)
|
|
||||||
{
|
{
|
||||||
class Visitor: public Processor::StackVisitor {
|
class Visitor : public Processor::StackVisitor {
|
||||||
public:
|
public:
|
||||||
Visitor(Thread* t, int skipCount):
|
Visitor(Thread* t, int skipCount) : t(t), trace(0), skipCount(skipCount)
|
||||||
t(t), trace(0), skipCount(skipCount)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
virtual bool visit(Processor::StackWalker* walker) {
|
virtual bool visit(Processor::StackWalker* walker)
|
||||||
|
{
|
||||||
if (skipCount == 0) {
|
if (skipCount == 0) {
|
||||||
GcMethod* method = walker->method();
|
GcMethod* method = walker->method();
|
||||||
if (isAssignableFrom(t, type(t, GcThrowable::Type), method->class_())
|
if (isAssignableFrom(t, type(t, GcThrowable::Type), method->class_())
|
||||||
@ -39,7 +39,7 @@ getTrace(Thread* t, unsigned skipCount)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
-- skipCount;
|
--skipCount;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,7 +51,8 @@ getTrace(Thread* t, unsigned skipCount)
|
|||||||
|
|
||||||
t->m->processor->walkStack(t, &v);
|
t->m->processor->walkStack(t, &v);
|
||||||
|
|
||||||
if (v.trace == 0) v.trace = makeObjectArray(t, 0);
|
if (v.trace == 0)
|
||||||
|
v.trace = makeObjectArray(t, 0);
|
||||||
|
|
||||||
return v.trace;
|
return v.trace;
|
||||||
}
|
}
|
||||||
@ -63,23 +64,24 @@ bool compatibleArrayTypes(Thread* t UNUSED, GcClass* a, GcClass* b)
|
|||||||
or (b->vmFlags() & PrimitiveFlag))));
|
or (b->vmFlags() & PrimitiveFlag))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void arrayCopy(Thread* t,
|
||||||
arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
|
object src,
|
||||||
int32_t dstOffset, int32_t length)
|
int32_t srcOffset,
|
||||||
|
object dst,
|
||||||
|
int32_t dstOffset,
|
||||||
|
int32_t length)
|
||||||
{
|
{
|
||||||
if (LIKELY(src and dst)) {
|
if (LIKELY(src and dst)) {
|
||||||
if (LIKELY(compatibleArrayTypes
|
if (LIKELY(compatibleArrayTypes(
|
||||||
(t, objectClass(t, src), objectClass(t, dst))))
|
t, objectClass(t, src), objectClass(t, dst)))) {
|
||||||
{
|
|
||||||
unsigned elementSize = objectClass(t, src)->arrayElementSize();
|
unsigned elementSize = objectClass(t, src)->arrayElementSize();
|
||||||
|
|
||||||
if (LIKELY(elementSize)) {
|
if (LIKELY(elementSize)) {
|
||||||
intptr_t sl = fieldAtOffset<uintptr_t>(src, BytesPerWord);
|
intptr_t sl = fieldAtOffset<uintptr_t>(src, BytesPerWord);
|
||||||
intptr_t dl = fieldAtOffset<uintptr_t>(dst, BytesPerWord);
|
intptr_t dl = fieldAtOffset<uintptr_t>(dst, BytesPerWord);
|
||||||
if (LIKELY(length > 0)) {
|
if (LIKELY(length > 0)) {
|
||||||
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
|
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl
|
||||||
dstOffset >= 0 and dstOffset + length <= dl))
|
and dstOffset >= 0 and dstOffset + length <= dl)) {
|
||||||
{
|
|
||||||
uint8_t* sbody = &fieldAtOffset<uint8_t>(src, ArrayBody);
|
uint8_t* sbody = &fieldAtOffset<uint8_t>(src, ArrayBody);
|
||||||
uint8_t* dbody = &fieldAtOffset<uint8_t>(dst, ArrayBody);
|
uint8_t* dbody = &fieldAtOffset<uint8_t>(dst, ArrayBody);
|
||||||
if (src == dst) {
|
if (src == dst) {
|
||||||
@ -113,8 +115,7 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
|
|||||||
throwNew(t, GcArrayStoreException::Type);
|
throwNew(t, GcArrayStoreException::Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void runOnLoadIfFound(Thread* t, System::Library* library)
|
||||||
runOnLoadIfFound(Thread* t, System::Library* library)
|
|
||||||
{
|
{
|
||||||
void* p = library->resolve("JNI_OnLoad");
|
void* p = library->resolve("JNI_OnLoad");
|
||||||
|
|
||||||
@ -128,14 +129,13 @@ runOnLoadIfFound(Thread* t, System::Library* library)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
jint (JNICALL * JNI_OnLoad)(Machine*, void*);
|
jint(JNICALL * JNI_OnLoad)(Machine*, void*);
|
||||||
memcpy(&JNI_OnLoad, &p, sizeof(void*));
|
memcpy(&JNI_OnLoad, &p, sizeof(void*));
|
||||||
JNI_OnLoad(t->m, 0);
|
JNI_OnLoad(t->m, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Library*
|
System::Library* loadLibrary(Thread* t, const char* name)
|
||||||
loadLibrary(Thread* t, const char* name)
|
|
||||||
{
|
{
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
@ -157,9 +157,12 @@ loadLibrary(Thread* t, const char* name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Library*
|
System::Library* loadLibrary(Thread* t,
|
||||||
loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
const char* path,
|
||||||
bool runOnLoad, bool throw_ = true)
|
const char* name,
|
||||||
|
bool mapName,
|
||||||
|
bool runOnLoad,
|
||||||
|
bool throw_ = true)
|
||||||
{
|
{
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
@ -171,8 +174,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
|||||||
const char* s = builtins;
|
const char* s = builtins;
|
||||||
while (*s) {
|
while (*s) {
|
||||||
if (::strncmp(s, name, nameLength) == 0
|
if (::strncmp(s, name, nameLength) == 0
|
||||||
and (s[nameLength] == ',' or s[nameLength] == 0))
|
and (s[nameLength] == ',' or s[nameLength] == 0)) {
|
||||||
{
|
|
||||||
// library is built in to this executable
|
// library is built in to this executable
|
||||||
if (runOnLoad and not t->m->triedBuiltinOnLoad) {
|
if (runOnLoad and not t->m->triedBuiltinOnLoad) {
|
||||||
t->m->triedBuiltinOnLoad = true;
|
t->m->triedBuiltinOnLoad = true;
|
||||||
@ -182,8 +184,10 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
|||||||
}
|
}
|
||||||
return t->m->libraries;
|
return t->m->libraries;
|
||||||
} else {
|
} else {
|
||||||
while (*s and *s != ',') ++ s;
|
while (*s and *s != ',')
|
||||||
if (*s) ++ s;
|
++s;
|
||||||
|
if (*s)
|
||||||
|
++s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,8 +196,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
|||||||
const char* suffix = t->m->system->librarySuffix();
|
const char* suffix = t->m->system->librarySuffix();
|
||||||
unsigned mappedNameLength = nameLength + strlen(prefix) + strlen(suffix);
|
unsigned mappedNameLength = nameLength + strlen(prefix) + strlen(suffix);
|
||||||
|
|
||||||
mappedName = static_cast<char*>
|
mappedName = static_cast<char*>(t->m->heap->allocate(mappedNameLength + 1));
|
||||||
(t->m->heap->allocate(mappedNameLength + 1));
|
|
||||||
|
|
||||||
snprintf(mappedName, mappedNameLength + 1, "%s%s%s", prefix, name, suffix);
|
snprintf(mappedName, mappedNameLength + 1, "%s%s%s", prefix, name, suffix);
|
||||||
|
|
||||||
@ -203,25 +206,28 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
|||||||
mappedName = 0;
|
mappedName = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
THREAD_RESOURCE2
|
THREAD_RESOURCE2(t, char*, mappedName, unsigned, nameLength, if (mappedName) {
|
||||||
(t, char*, mappedName, unsigned, nameLength, if (mappedName) {
|
|
||||||
t->m->heap->free(mappedName, nameLength + 1);
|
t->m->heap->free(mappedName, nameLength + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
System::Library* lib = 0;
|
System::Library* lib = 0;
|
||||||
for (Tokenizer tokenizer(path, t->m->system->pathSeparator());
|
for (Tokenizer tokenizer(path, t->m->system->pathSeparator());
|
||||||
tokenizer.hasMore();)
|
tokenizer.hasMore();) {
|
||||||
{
|
|
||||||
String token(tokenizer.next());
|
String token(tokenizer.next());
|
||||||
|
|
||||||
unsigned fullNameLength = token.length + 1 + nameLength;
|
unsigned fullNameLength = token.length + 1 + nameLength;
|
||||||
THREAD_RUNTIME_ARRAY(t, char, fullName, fullNameLength + 1);
|
THREAD_RUNTIME_ARRAY(t, char, fullName, fullNameLength + 1);
|
||||||
|
|
||||||
snprintf(RUNTIME_ARRAY_BODY(fullName), fullNameLength + 1,
|
snprintf(RUNTIME_ARRAY_BODY(fullName),
|
||||||
"%.*s/%s", token.length, token.text, name);
|
fullNameLength + 1,
|
||||||
|
"%.*s/%s",
|
||||||
|
token.length,
|
||||||
|
token.text,
|
||||||
|
name);
|
||||||
|
|
||||||
lib = loadLibrary(t, RUNTIME_ARRAY_BODY(fullName));
|
lib = loadLibrary(t, RUNTIME_ARRAY_BODY(fullName));
|
||||||
if (lib) break;
|
if (lib)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lib == 0) {
|
if (lib == 0) {
|
||||||
@ -243,8 +249,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
|||||||
return lib;
|
return lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object clone(Thread* t, object o)
|
||||||
clone(Thread* t, object o)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, o);
|
PROTECT(t, o);
|
||||||
|
|
||||||
@ -396,10 +401,10 @@ GcPair* resolveParameterTypes(Thread* t,
|
|||||||
switch (spec->body()[offset]) {
|
switch (spec->body()[offset]) {
|
||||||
case 'L': {
|
case 'L': {
|
||||||
unsigned start = offset;
|
unsigned start = offset;
|
||||||
++ offset;
|
++offset;
|
||||||
while (spec->body()[offset] != ';')
|
while (spec->body()[offset] != ';')
|
||||||
++offset;
|
++offset;
|
||||||
++ offset;
|
++offset;
|
||||||
|
|
||||||
GcClass* type
|
GcClass* type
|
||||||
= resolveClassBySpec(t,
|
= resolveClassBySpec(t,
|
||||||
@ -409,7 +414,7 @@ GcPair* resolveParameterTypes(Thread* t,
|
|||||||
|
|
||||||
list = makePair(t, type, list);
|
list = makePair(t, type, list);
|
||||||
|
|
||||||
++ count;
|
++count;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case '[': {
|
case '[': {
|
||||||
@ -418,14 +423,14 @@ GcPair* resolveParameterTypes(Thread* t,
|
|||||||
++offset;
|
++offset;
|
||||||
switch (spec->body()[offset]) {
|
switch (spec->body()[offset]) {
|
||||||
case 'L':
|
case 'L':
|
||||||
++ offset;
|
++offset;
|
||||||
while (spec->body()[offset] != ';')
|
while (spec->body()[offset] != ';')
|
||||||
++offset;
|
++offset;
|
||||||
++ offset;
|
++offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
++ offset;
|
++offset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,13 +441,13 @@ GcPair* resolveParameterTypes(Thread* t,
|
|||||||
offset - start);
|
offset - start);
|
||||||
|
|
||||||
list = makePair(t, type, list);
|
list = makePair(t, type, list);
|
||||||
++ count;
|
++count;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
list = makePair(t, primitiveClass(t, spec->body()[offset]), list);
|
list = makePair(t, primitiveClass(t, spec->body()[offset]), list);
|
||||||
++ offset;
|
++offset;
|
||||||
++ count;
|
++count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -570,7 +575,7 @@ object invoke(Thread* t, GcMethod* method, object instance, object args)
|
|||||||
objectType = true;
|
objectType = true;
|
||||||
unsigned nameLength;
|
unsigned nameLength;
|
||||||
if (*p == 'L') {
|
if (*p == 'L') {
|
||||||
++ p;
|
++p;
|
||||||
nameLength = it.s - p;
|
nameLength = it.s - p;
|
||||||
} else {
|
} else {
|
||||||
nameLength = (it.s - p) + 1;
|
nameLength = (it.s - p) + 1;
|
||||||
@ -588,9 +593,10 @@ object invoke(Thread* t, GcMethod* method, object instance, object args)
|
|||||||
|
|
||||||
object arg = objectArrayBody(t, args, i++);
|
object arg = objectArrayBody(t, args, i++);
|
||||||
if ((arg == 0 and (not objectType))
|
if ((arg == 0 and (not objectType))
|
||||||
or (arg and (not instanceOf(t, type, arg))))
|
or (arg and (not instanceOf(t, type, arg)))) {
|
||||||
{
|
// fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t,
|
||||||
// fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast<const int8_t*>("<null>"), &byteArrayBody(t, className(t, type), 0));
|
// className(t, objectClass(t, arg)), 0) : reinterpret_cast<const
|
||||||
|
// int8_t*>("<null>"), &byteArrayBody(t, className(t, type), 0));
|
||||||
|
|
||||||
throwNew(t, GcIllegalArgumentException::Type);
|
throwNew(t, GcIllegalArgumentException::Type);
|
||||||
}
|
}
|
||||||
@ -664,8 +670,7 @@ void intercept(Thread* t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Finder*
|
Finder* getFinder(Thread* t, const char* name, unsigned nameLength)
|
||||||
getFinder(Thread* t, const char* name, unsigned nameLength)
|
|
||||||
{
|
{
|
||||||
ACQUIRE(t, t->m->referenceLock);
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
@ -718,7 +723,7 @@ object getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
|||||||
GcByteArray* outer = reference->outer();
|
GcByteArray* outer = reference->outer();
|
||||||
if (outer and byteArrayEqual(t, outer, c->name())
|
if (outer and byteArrayEqual(t, outer, c->name())
|
||||||
and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) {
|
and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) {
|
||||||
++ count;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,7 +739,7 @@ object getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
|||||||
object inner
|
object inner
|
||||||
= getJClass(t, resolveClass(t, c->loader(), reference->inner()));
|
= getJClass(t, resolveClass(t, c->loader(), reference->inner()));
|
||||||
|
|
||||||
-- count;
|
--count;
|
||||||
reinterpret_cast<GcArray*>(result)->setBodyElement(t, count, inner);
|
reinterpret_cast<GcArray*>(result)->setBodyElement(t, count, inner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -789,4 +794,4 @@ unsigned classModifiers(Thread* t, GcClass* c)
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//CLASSPATH_COMMON_H
|
#endif // CLASSPATH_COMMON_H
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#define AVIAN_COMMON_H
|
#define AVIAN_COMMON_H
|
||||||
|
|
||||||
#ifndef __STDC_CONSTANT_MACROS
|
#ifndef __STDC_CONSTANT_MACROS
|
||||||
# define __STDC_CONSTANT_MACROS
|
#define __STDC_CONSTANT_MACROS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
@ -31,11 +31,11 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef linux
|
#ifdef linux
|
||||||
# undef linux
|
#undef linux
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// don't complain about using 'this' in member initializers:
|
// don't complain about using 'this' in member initializers:
|
||||||
# pragma warning(disable:4355)
|
#pragma warning(disable : 4355)
|
||||||
|
|
||||||
#define strncasecmp _strnicmp
|
#define strncasecmp _strnicmp
|
||||||
|
|
||||||
@ -43,9 +43,9 @@
|
|||||||
#define FP_INFINITE 1
|
#define FP_INFINITE 1
|
||||||
#define FP_UNDEF 2
|
#define FP_UNDEF 2
|
||||||
|
|
||||||
inline int fpclassify(double d) {
|
inline int fpclassify(double d)
|
||||||
|
{
|
||||||
switch(_fpclass(d)) {
|
switch (_fpclass(d)) {
|
||||||
case _FPCLASS_SNAN:
|
case _FPCLASS_SNAN:
|
||||||
case _FPCLASS_QNAN:
|
case _FPCLASS_QNAN:
|
||||||
return FP_NAN;
|
return FP_NAN;
|
||||||
@ -56,44 +56,45 @@ inline int fpclassify(double d) {
|
|||||||
return FP_UNDEF;
|
return FP_UNDEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int signbit(double d) {
|
inline int signbit(double d)
|
||||||
|
{
|
||||||
return _copysign(1.0, d) < 0;
|
return _copysign(1.0, d) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# define not !
|
#define not!
|
||||||
# define or ||
|
#define or ||
|
||||||
# define and &&
|
#define and &&
|
||||||
# define xor ^
|
#define xor ^
|
||||||
|
|
||||||
# define LIKELY(v) v
|
#define LIKELY(v) v
|
||||||
# define UNLIKELY(v) v
|
#define UNLIKELY(v) v
|
||||||
|
|
||||||
# define UNUSED
|
#define UNUSED
|
||||||
|
|
||||||
# define NO_RETURN __declspec(noreturn)
|
#define NO_RETURN __declspec(noreturn)
|
||||||
|
|
||||||
# define PACKED
|
#define PACKED
|
||||||
|
|
||||||
# define PLATFORM_WINDOWS
|
#define PLATFORM_WINDOWS
|
||||||
|
|
||||||
# ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
typedef int32_t intptr_t;
|
typedef int32_t intptr_t;
|
||||||
typedef uint32_t uintptr_t;
|
typedef uint32_t uintptr_t;
|
||||||
# define ARCH_x86_32
|
#define ARCH_x86_32
|
||||||
# define BYTES_PER_WORD 4
|
#define BYTES_PER_WORD 4
|
||||||
# elif defined _M_X64
|
#elif defined _M_X64
|
||||||
typedef int64_t intptr_t;
|
typedef int64_t intptr_t;
|
||||||
typedef uint64_t uintptr_t;
|
typedef uint64_t uintptr_t;
|
||||||
# define ARCH_x86_64
|
#define ARCH_x86_64
|
||||||
# define BYTES_PER_WORD 8
|
#define BYTES_PER_WORD 8
|
||||||
# elif defined _M_ARM_FP
|
#elif defined _M_ARM_FP
|
||||||
typedef int32_t intptr_t;
|
typedef int32_t intptr_t;
|
||||||
typedef uint32_t uintptr_t;
|
typedef uint32_t uintptr_t;
|
||||||
# define ARCH_arm
|
#define ARCH_arm
|
||||||
# define BYTES_PER_WORD 4
|
#define BYTES_PER_WORD 4
|
||||||
# else
|
#else
|
||||||
# error "unsupported architecture"
|
#error "unsupported architecture"
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
@ -103,32 +104,32 @@ typedef intptr_t intptr_alias_t;
|
|||||||
|
|
||||||
#else // not _MSC_VER
|
#else // not _MSC_VER
|
||||||
|
|
||||||
# include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
# define BYTES_PER_WORD __SIZEOF_POINTER__
|
#define BYTES_PER_WORD __SIZEOF_POINTER__
|
||||||
|
|
||||||
# define LIKELY(v) __builtin_expect((v) != 0, true)
|
#define LIKELY(v) __builtin_expect((v) != 0, true)
|
||||||
# define UNLIKELY(v) __builtin_expect((v) != 0, false)
|
#define UNLIKELY(v) __builtin_expect((v) != 0, false)
|
||||||
|
|
||||||
# define UNUSED __attribute__((unused))
|
#define UNUSED __attribute__((unused))
|
||||||
|
|
||||||
# define NO_RETURN __attribute__((noreturn))
|
#define NO_RETURN __attribute__((noreturn))
|
||||||
|
|
||||||
# define PACKED __attribute__((packed))
|
#define PACKED __attribute__((packed))
|
||||||
|
|
||||||
# ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
# define PLATFORM_WINDOWS
|
#define PLATFORM_WINDOWS
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
# ifdef __i386__
|
#ifdef __i386__
|
||||||
# define ARCH_x86_32
|
#define ARCH_x86_32
|
||||||
# elif defined __x86_64__
|
#elif defined __x86_64__
|
||||||
# define ARCH_x86_64
|
#define ARCH_x86_64
|
||||||
# elif defined __arm__
|
#elif defined __arm__
|
||||||
# define ARCH_arm
|
#define ARCH_arm
|
||||||
# else
|
#else
|
||||||
# error "unsupported architecture"
|
#error "unsupported architecture"
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
@ -139,58 +140,58 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
|
|||||||
#endif // not _MSC_VER
|
#endif // not _MSC_VER
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
# define AVIAN_EXPORT __declspec(dllexport)
|
#define AVIAN_EXPORT __declspec(dllexport)
|
||||||
# define PATH_SEPARATOR ';'
|
#define PATH_SEPARATOR ';'
|
||||||
#else // not PLATFORM_WINDOWS
|
#else // not PLATFORM_WINDOWS
|
||||||
# define AVIAN_EXPORT __attribute__ ((visibility("default"))) \
|
#define AVIAN_EXPORT \
|
||||||
__attribute__ ((used))
|
__attribute__((visibility("default"))) __attribute__((used))
|
||||||
# define PATH_SEPARATOR ':'
|
#define PATH_SEPARATOR ':'
|
||||||
#endif // not PLATFORM_WINDOWS
|
#endif // not PLATFORM_WINDOWS
|
||||||
|
|
||||||
#if (defined ARCH_x86_32) || (defined ARCH_arm)
|
#if (defined ARCH_x86_32) || (defined ARCH_arm)
|
||||||
# define LD "ld"
|
#define LD "ld"
|
||||||
# if (defined _MSC_VER) || ((defined __MINGW32__) && __GNUC__ >= 4)
|
#if (defined _MSC_VER) || ((defined __MINGW32__) && __GNUC__ >= 4)
|
||||||
# define LLD "I64d"
|
#define LLD "I64d"
|
||||||
# else
|
|
||||||
# define LLD "lld"
|
|
||||||
# endif
|
|
||||||
# ifdef __APPLE__
|
|
||||||
# define ULD "lu"
|
|
||||||
# define LX "lx"
|
|
||||||
# else
|
|
||||||
# define LX "x"
|
|
||||||
# define ULD "u"
|
|
||||||
# endif
|
|
||||||
#elif defined ARCH_x86_64
|
|
||||||
# define LD "ld"
|
|
||||||
# define LX "lx"
|
|
||||||
# if (defined _MSC_VER) || (defined __MINGW32__)
|
|
||||||
# define LLD "I64d"
|
|
||||||
# define ULD "I64x"
|
|
||||||
# else
|
|
||||||
# ifdef __APPLE__
|
|
||||||
# define LLD "lld"
|
|
||||||
# else
|
|
||||||
# define LLD "ld"
|
|
||||||
# endif
|
|
||||||
# define ULD "lu"
|
|
||||||
# endif
|
|
||||||
#else
|
#else
|
||||||
# error "Unsupported architecture"
|
#define LLD "lld"
|
||||||
|
#endif
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define ULD "lu"
|
||||||
|
#define LX "lx"
|
||||||
|
#else
|
||||||
|
#define LX "x"
|
||||||
|
#define ULD "u"
|
||||||
|
#endif
|
||||||
|
#elif defined ARCH_x86_64
|
||||||
|
#define LD "ld"
|
||||||
|
#define LX "lx"
|
||||||
|
#if (defined _MSC_VER) || (defined __MINGW32__)
|
||||||
|
#define LLD "I64d"
|
||||||
|
#define ULD "I64x"
|
||||||
|
#else
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define LLD "lld"
|
||||||
|
#else
|
||||||
|
#define LLD "ld"
|
||||||
|
#endif
|
||||||
|
#define ULD "lu"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
# define SO_PREFIX ""
|
#define SO_PREFIX ""
|
||||||
#else
|
#else
|
||||||
# define SO_PREFIX "lib"
|
#define SO_PREFIX "lib"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# define SO_SUFFIX ".dylib"
|
#define SO_SUFFIX ".dylib"
|
||||||
#elif defined PLATFORM_WINDOWS
|
#elif defined PLATFORM_WINDOWS
|
||||||
# define SO_SUFFIX ".dll"
|
#define SO_SUFFIX ".dll"
|
||||||
#else
|
#else
|
||||||
# define SO_SUFFIX ".so"
|
#define SO_SUFFIX ".so"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MACRO_XY(X, Y) X##Y
|
#define MACRO_XY(X, Y) X##Y
|
||||||
@ -200,35 +201,37 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
|
|||||||
#define RESOURCE(type, name, release) \
|
#define RESOURCE(type, name, release) \
|
||||||
class MAKE_NAME(Resource_) { \
|
class MAKE_NAME(Resource_) { \
|
||||||
public: \
|
public: \
|
||||||
MAKE_NAME(Resource_)(type name): name(name) { } \
|
MAKE_NAME(Resource_)(type name) : name(name) \
|
||||||
~MAKE_NAME(Resource_)() { release; } \
|
{ \
|
||||||
|
} \
|
||||||
|
~MAKE_NAME(Resource_)() \
|
||||||
|
{ \
|
||||||
|
release; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
private: \
|
private: \
|
||||||
type name; \
|
type name; \
|
||||||
} MAKE_NAME(resource_)(name);
|
} MAKE_NAME(resource_)(name);
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# pragma warning( disable : 4291 )
|
#pragma warning(disable : 4291)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
inline intptr_alias_t&
|
inline intptr_alias_t& alias(void* p, unsigned offset)
|
||||||
alias(void* p, unsigned offset)
|
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<intptr_alias_t*>(static_cast<uint8_t*>(p) + offset);
|
return *reinterpret_cast<intptr_alias_t*>(static_cast<uint8_t*>(p) + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
inline int
|
inline int vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
||||||
vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
|
||||||
{
|
{
|
||||||
return vsnprintf_s(dst, size, _TRUNCATE, format, a);
|
return vsnprintf_s(dst, size, _TRUNCATE, format, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
inline int snprintf(char* dst, size_t size, const char* format, ...)
|
||||||
snprintf(char* dst, size_t size, const char* format, ...)
|
|
||||||
{
|
{
|
||||||
va_list a;
|
va_list a;
|
||||||
va_start(a, format);
|
va_start(a, format);
|
||||||
@ -237,8 +240,7 @@ snprintf(char* dst, size_t size, const char* format, ...)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline FILE*
|
inline FILE* fopen(const char* name, const char* mode)
|
||||||
fopen(const char* name, const char* mode)
|
|
||||||
{
|
{
|
||||||
FILE* file;
|
FILE* file;
|
||||||
if (fopen_s(&file, name, mode) == 0) {
|
if (fopen_s(&file, name, mode) == 0) {
|
||||||
@ -250,14 +252,12 @@ fopen(const char* name, const char* mode)
|
|||||||
|
|
||||||
#else // not _MSC_VER
|
#else // not _MSC_VER
|
||||||
|
|
||||||
inline int
|
inline int vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
||||||
vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
|
||||||
{
|
{
|
||||||
return ::vsnprintf(dst, size, format, a);
|
return ::vsnprintf(dst, size, format, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
inline int snprintf(char* dst, size_t size, const char* format, ...)
|
||||||
snprintf(char* dst, size_t size, const char* format, ...)
|
|
||||||
{
|
{
|
||||||
va_list a;
|
va_list a;
|
||||||
va_start(a, format);
|
va_start(a, format);
|
||||||
@ -266,8 +266,7 @@ snprintf(char* dst, size_t size, const char* format, ...)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline FILE*
|
inline FILE* fopen(const char* name, const char* mode)
|
||||||
fopen(const char* name, const char* mode)
|
|
||||||
{
|
{
|
||||||
return ::fopen(name, mode);
|
return ::fopen(name, mode);
|
||||||
}
|
}
|
||||||
@ -277,102 +276,92 @@ fopen(const char* name, const char* mode)
|
|||||||
const unsigned BytesPerWord = sizeof(uintptr_t);
|
const unsigned BytesPerWord = sizeof(uintptr_t);
|
||||||
const unsigned BitsPerWord = BytesPerWord * 8;
|
const unsigned BitsPerWord = BytesPerWord * 8;
|
||||||
|
|
||||||
const uintptr_t PointerMask
|
const uintptr_t PointerMask = ((~static_cast<uintptr_t>(0)) / BytesPerWord)
|
||||||
= ((~static_cast<uintptr_t>(0)) / BytesPerWord) * BytesPerWord;
|
* BytesPerWord;
|
||||||
|
|
||||||
const unsigned LikelyPageSizeInBytes = 4 * 1024;
|
const unsigned LikelyPageSizeInBytes = 4 * 1024;
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned pad(unsigned n, unsigned alignment)
|
||||||
pad(unsigned n, unsigned alignment)
|
|
||||||
{
|
{
|
||||||
return (n + (alignment - 1)) & ~(alignment - 1);
|
return (n + (alignment - 1)) & ~(alignment - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned pad(unsigned n)
|
||||||
pad(unsigned n)
|
|
||||||
{
|
{
|
||||||
return pad(n, BytesPerWord);
|
return pad(n, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uintptr_t
|
inline uintptr_t padWord(uintptr_t n, uintptr_t alignment)
|
||||||
padWord(uintptr_t n, uintptr_t alignment)
|
|
||||||
{
|
{
|
||||||
return (n + (alignment - 1)) & ~(alignment - 1);
|
return (n + (alignment - 1)) & ~(alignment - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uintptr_t
|
inline uintptr_t padWord(uintptr_t n)
|
||||||
padWord(uintptr_t n)
|
|
||||||
{
|
{
|
||||||
return padWord(n, BytesPerWord);
|
return padWord(n, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool fitsInInt8(int64_t v) {
|
inline bool fitsInInt8(int64_t v)
|
||||||
|
{
|
||||||
return v == static_cast<int8_t>(v);
|
return v == static_cast<int8_t>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool fitsInInt16(int64_t v) {
|
inline bool fitsInInt16(int64_t v)
|
||||||
|
{
|
||||||
return v == static_cast<int16_t>(v);
|
return v == static_cast<int16_t>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool fitsInInt32(int64_t v) {
|
inline bool fitsInInt32(int64_t v)
|
||||||
|
{
|
||||||
return v == static_cast<int32_t>(v);
|
return v == static_cast<int32_t>(v);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
inline unsigned
|
inline unsigned wordOf(unsigned i)
|
||||||
wordOf(unsigned i)
|
|
||||||
{
|
{
|
||||||
return i / (sizeof(T) * 8);
|
return i / (sizeof(T) * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned wordOf(unsigned i)
|
||||||
wordOf(unsigned i)
|
|
||||||
{
|
{
|
||||||
return wordOf<uintptr_t>(i);
|
return wordOf<uintptr_t>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline unsigned
|
inline unsigned bitOf(unsigned i)
|
||||||
bitOf(unsigned i)
|
|
||||||
{
|
{
|
||||||
return i % (sizeof(T) * 8);
|
return i % (sizeof(T) * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned bitOf(unsigned i)
|
||||||
bitOf(unsigned i)
|
|
||||||
{
|
{
|
||||||
return bitOf<uintptr_t>(i);
|
return bitOf<uintptr_t>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline unsigned
|
inline unsigned indexOf(unsigned word, unsigned bit)
|
||||||
indexOf(unsigned word, unsigned bit)
|
|
||||||
{
|
{
|
||||||
return (word * (sizeof(T) * 8)) + bit;
|
return (word * (sizeof(T) * 8)) + bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned indexOf(unsigned word, unsigned bit)
|
||||||
indexOf(unsigned word, unsigned bit)
|
|
||||||
{
|
{
|
||||||
return indexOf<uintptr_t>(word, bit);
|
return indexOf<uintptr_t>(word, bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void
|
inline void markBit(T* map, unsigned i)
|
||||||
markBit(T* map, unsigned i)
|
|
||||||
{
|
{
|
||||||
map[wordOf<T>(i)] |= static_cast<T>(1) << bitOf<T>(i);
|
map[wordOf<T>(i)] |= static_cast<T>(1) << bitOf<T>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void
|
inline void clearBit(T* map, unsigned i)
|
||||||
clearBit(T* map, unsigned i)
|
|
||||||
{
|
{
|
||||||
map[wordOf<T>(i)] &= ~(static_cast<T>(1) << bitOf<T>(i));
|
map[wordOf<T>(i)] &= ~(static_cast<T>(1) << bitOf<T>(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline unsigned
|
inline unsigned getBit(T* map, unsigned i)
|
||||||
getBit(T* map, unsigned i)
|
|
||||||
{
|
{
|
||||||
return (map[wordOf<T>(i)] & (static_cast<T>(1) << bitOf<T>(i)))
|
return (map[wordOf<T>(i)] & (static_cast<T>(1) << bitOf<T>(i)))
|
||||||
>> bitOf<T>(i);
|
>> bitOf<T>(i);
|
||||||
@ -383,8 +372,7 @@ getBit(T* map, unsigned i)
|
|||||||
// a time:
|
// a time:
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void
|
inline void clearBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||||
clearBits(T* map, unsigned bitsPerRecord, unsigned index)
|
|
||||||
{
|
{
|
||||||
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
||||||
clearBit<T>(map, i);
|
clearBit<T>(map, i);
|
||||||
@ -392,18 +380,19 @@ clearBits(T* map, unsigned bitsPerRecord, unsigned index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void
|
inline void setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
|
||||||
setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
|
|
||||||
{
|
{
|
||||||
for (int i = index + bitsPerRecord - 1; i >= index; --i) {
|
for (int i = index + bitsPerRecord - 1; i >= index; --i) {
|
||||||
if (v & 1) markBit<T>(map, i); else clearBit<T>(map, i);
|
if (v & 1)
|
||||||
|
markBit<T>(map, i);
|
||||||
|
else
|
||||||
|
clearBit<T>(map, i);
|
||||||
v >>= 1;
|
v >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline unsigned
|
inline unsigned getBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||||
getBits(T* map, unsigned bitsPerRecord, unsigned index)
|
|
||||||
{
|
{
|
||||||
unsigned v = 0;
|
unsigned v = 0;
|
||||||
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
||||||
@ -414,86 +403,80 @@ getBits(T* map, unsigned bitsPerRecord, unsigned index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T&
|
inline T& fieldAtOffset(void* p, unsigned offset)
|
||||||
fieldAtOffset(void* p, unsigned offset)
|
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T*
|
inline T* maskAlignedPointer(T* p)
|
||||||
maskAlignedPointer(T* p)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
|
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void write4(uint8_t* dst, uint32_t v)
|
||||||
write4(uint8_t* dst, uint32_t v)
|
|
||||||
{
|
{
|
||||||
memcpy(dst, &v, 4);
|
memcpy(dst, &v, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t
|
inline uint32_t floatToBits(float f)
|
||||||
floatToBits(float f)
|
|
||||||
{
|
{
|
||||||
uint32_t bits; memcpy(&bits, &f, 4);
|
uint32_t bits;
|
||||||
|
memcpy(&bits, &f, 4);
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint64_t
|
inline uint64_t doubleToBits(double d)
|
||||||
doubleToBits(double d)
|
|
||||||
{
|
{
|
||||||
uint64_t bits; memcpy(&bits, &d, 8);
|
uint64_t bits;
|
||||||
|
memcpy(&bits, &d, 8);
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double
|
inline double bitsToDouble(uint64_t bits)
|
||||||
bitsToDouble(uint64_t bits)
|
|
||||||
{
|
{
|
||||||
double d; memcpy(&d, &bits, 8);
|
double d;
|
||||||
|
memcpy(&d, &bits, 8);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float
|
inline float bitsToFloat(uint32_t bits)
|
||||||
bitsToFloat(uint32_t bits)
|
|
||||||
{
|
{
|
||||||
float f; memcpy(&f, &bits, 4);
|
float f;
|
||||||
|
memcpy(&f, &bits, 4);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
inline int difference(void* a, void* b)
|
||||||
difference(void* a, void* b)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
|
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void*
|
inline void* voidPointer(T function)
|
||||||
voidPointer(T function)
|
|
||||||
{
|
{
|
||||||
void* p;
|
void* p;
|
||||||
memcpy(&p, &function, sizeof(void*));
|
memcpy(&p, &function, sizeof(void*));
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void replace(char a, char b, char* c)
|
||||||
replace(char a, char b, char* c)
|
|
||||||
{
|
{
|
||||||
for (; *c; ++c) if (*c == a) *c = b;
|
for (; *c; ++c)
|
||||||
|
if (*c == a)
|
||||||
|
*c = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void replace(char a, char b, char* dst, const char* src)
|
||||||
replace(char a, char b, char* dst, const char* src)
|
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (; src[i]; ++ i) {
|
for (; src[i]; ++i) {
|
||||||
dst[i] = src[i] == a ? b : src[i];
|
dst[i] = src[i] == a ? b : src[i];
|
||||||
}
|
}
|
||||||
dst[i] = 0;
|
dst[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool equal(const void* a, unsigned al, const void* b, unsigned bl)
|
||||||
equal(const void* a, unsigned al, const void* b, unsigned bl)
|
|
||||||
{
|
{
|
||||||
if (al == bl) {
|
if (al == bl) {
|
||||||
return memcmp(a, b, al) == 0;
|
return memcmp(a, b, al) == 0;
|
||||||
|
@ -279,4 +279,4 @@ const int AVIAN_JNI_VERSION_1_4 = 0x00010004;
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//CONSTANTS_H
|
#endif // CONSTANTS_H
|
||||||
|
@ -30,4 +30,3 @@
|
|||||||
#define AVIAN_ARCH_ARM (3 << 8)
|
#define AVIAN_ARCH_ARM (3 << 8)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -30,96 +30,113 @@ const unsigned EntrySignature = 0x02014b50;
|
|||||||
|
|
||||||
const unsigned CentralDirectorySearchStart = 22;
|
const unsigned CentralDirectorySearchStart = 22;
|
||||||
|
|
||||||
inline uint16_t get2(const uint8_t* p) {
|
inline uint16_t get2(const uint8_t* p)
|
||||||
return
|
{
|
||||||
(static_cast<uint16_t>(p[1]) << 8) |
|
return (static_cast<uint16_t>(p[1]) << 8) | (static_cast<uint16_t>(p[0]));
|
||||||
(static_cast<uint16_t>(p[0]) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t get4(const uint8_t* p) {
|
inline uint32_t get4(const uint8_t* p)
|
||||||
return
|
{
|
||||||
(static_cast<uint32_t>(p[3]) << 24) |
|
return (static_cast<uint32_t>(p[3]) << 24)
|
||||||
(static_cast<uint32_t>(p[2]) << 16) |
|
| (static_cast<uint32_t>(p[2]) << 16)
|
||||||
(static_cast<uint32_t>(p[1]) << 8) |
|
| (static_cast<uint32_t>(p[1]) << 8) | (static_cast<uint32_t>(p[0]));
|
||||||
(static_cast<uint32_t>(p[0]) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t signature(const uint8_t* p) {
|
inline uint32_t signature(const uint8_t* p)
|
||||||
|
{
|
||||||
return get4(p);
|
return get4(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t compressionMethod(const uint8_t* centralHeader) {
|
inline uint16_t compressionMethod(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get2(centralHeader + 10);
|
return get2(centralHeader + 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t fileTime(const uint8_t* centralHeader) {
|
inline uint32_t fileTime(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get4(centralHeader + 12);
|
return get4(centralHeader + 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t fileCRC(const uint8_t* centralHeader) {
|
inline uint32_t fileCRC(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get4(centralHeader + 16);
|
return get4(centralHeader + 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t compressedSize(const uint8_t* centralHeader) {
|
inline uint32_t compressedSize(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get4(centralHeader + 20);
|
return get4(centralHeader + 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t uncompressedSize(const uint8_t* centralHeader) {
|
inline uint32_t uncompressedSize(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get4(centralHeader + 24);
|
return get4(centralHeader + 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t fileNameLength(const uint8_t* centralHeader) {
|
inline uint16_t fileNameLength(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get2(centralHeader + 28);
|
return get2(centralHeader + 28);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t extraFieldLength(const uint8_t* centralHeader) {
|
inline uint16_t extraFieldLength(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get2(centralHeader + 30);
|
return get2(centralHeader + 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t commentFieldLength(const uint8_t* centralHeader) {
|
inline uint16_t commentFieldLength(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get2(centralHeader + 32);
|
return get2(centralHeader + 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t localHeaderOffset(const uint8_t* centralHeader) {
|
inline uint32_t localHeaderOffset(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get4(centralHeader + 42);
|
return get4(centralHeader + 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t localFileNameLength(const uint8_t* localHeader) {
|
inline uint16_t localFileNameLength(const uint8_t* localHeader)
|
||||||
|
{
|
||||||
return get2(localHeader + 26);
|
return get2(localHeader + 26);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t localExtraFieldLength(const uint8_t* localHeader) {
|
inline uint16_t localExtraFieldLength(const uint8_t* localHeader)
|
||||||
|
{
|
||||||
return get2(localHeader + 28);
|
return get2(localHeader + 28);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader) {
|
inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return get4(centralHeader + 16);
|
return get4(centralHeader + 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const uint8_t* fileName(const uint8_t* centralHeader) {
|
inline const uint8_t* fileName(const uint8_t* centralHeader)
|
||||||
|
{
|
||||||
return centralHeader + 46;
|
return centralHeader + 46;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const uint8_t* fileData(const uint8_t* localHeader) {
|
inline const uint8_t* fileData(const uint8_t* localHeader)
|
||||||
return localHeader + LocalHeaderSize + localFileNameLength(localHeader) +
|
{
|
||||||
localExtraFieldLength(localHeader);
|
return localHeader + LocalHeaderSize + localFileNameLength(localHeader)
|
||||||
|
+ localExtraFieldLength(localHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const uint8_t* endOfEntry(const uint8_t* p) {
|
inline const uint8_t* endOfEntry(const uint8_t* p)
|
||||||
return p + HeaderSize + fileNameLength(p) + extraFieldLength(p) +
|
{
|
||||||
commentFieldLength(p);
|
return p + HeaderSize + fileNameLength(p) + extraFieldLength(p)
|
||||||
|
+ commentFieldLength(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool readLine(const uint8_t* base,
|
||||||
readLine(const uint8_t* base, unsigned total, unsigned* start,
|
unsigned total,
|
||||||
|
unsigned* start,
|
||||||
unsigned* length)
|
unsigned* length)
|
||||||
{
|
{
|
||||||
const uint8_t* p = base + *start;
|
const uint8_t* p = base + *start;
|
||||||
const uint8_t* end = base + total;
|
const uint8_t* end = base + total;
|
||||||
while (p != end and (*p == '\n' or *p == '\r')) ++ p;
|
while (p != end and (*p == '\n' or *p == '\r'))
|
||||||
|
++p;
|
||||||
|
|
||||||
*start = p - base;
|
*start = p - base;
|
||||||
while (p != end and not (*p == '\n' or *p == '\r')) ++ p;
|
while (p != end and not(*p == '\n' or *p == '\r'))
|
||||||
|
++p;
|
||||||
|
|
||||||
*length = (p - base) - *start;
|
*length = (p - base) - *start;
|
||||||
|
|
||||||
@ -136,22 +153,26 @@ class Finder {
|
|||||||
|
|
||||||
class Iterator {
|
class Iterator {
|
||||||
public:
|
public:
|
||||||
Iterator(Finder* finder):
|
Iterator(Finder* finder)
|
||||||
it(finder->iterator()),
|
: it(finder->iterator()), current(it->next(¤tSize))
|
||||||
current(it->next(¤tSize))
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
~Iterator() {
|
~Iterator()
|
||||||
|
{
|
||||||
it->dispose();
|
it->dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasMore() {
|
bool hasMore()
|
||||||
if (current) return true;
|
{
|
||||||
|
if (current)
|
||||||
|
return true;
|
||||||
current = it->next(¤tSize);
|
current = it->next(¤tSize);
|
||||||
return current != 0;
|
return current != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* next(unsigned* size) {
|
const char* next(unsigned* size)
|
||||||
|
{
|
||||||
if (hasMore()) {
|
if (hasMore()) {
|
||||||
*size = currentSize;
|
*size = currentSize;
|
||||||
const char* v = current;
|
const char* v = current;
|
||||||
@ -173,7 +194,8 @@ class Finder {
|
|||||||
unsigned* length,
|
unsigned* length,
|
||||||
bool tryDirectory = false) = 0;
|
bool tryDirectory = false) = 0;
|
||||||
virtual const char* urlPrefix(const char* name) = 0;
|
virtual const char* urlPrefix(const char* name) = 0;
|
||||||
virtual const char* nextUrlPrefix(const char* name, void *&finderElementPtr) = 0;
|
virtual const char* nextUrlPrefix(const char* name, void*& finderElementPtr)
|
||||||
|
= 0;
|
||||||
virtual const char* sourceUrl(const char* name) = 0;
|
virtual const char* sourceUrl(const char* name) = 0;
|
||||||
virtual const char* path() = 0;
|
virtual const char* path() = 0;
|
||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
@ -191,4 +213,4 @@ Finder* makeFinder(System* s,
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//FINDER_H
|
#endif // FINDER_H
|
||||||
|
@ -29,8 +29,8 @@ class HeapVisitor {
|
|||||||
virtual void root() = 0;
|
virtual void root() = 0;
|
||||||
virtual unsigned visitNew(object value) = 0;
|
virtual unsigned visitNew(object value) = 0;
|
||||||
virtual void visitOld(object value, unsigned number) = 0;
|
virtual void visitOld(object value, unsigned number) = 0;
|
||||||
virtual void push(object parent, unsigned parentNumber,
|
virtual void push(object parent, unsigned parentNumber, unsigned childOffset)
|
||||||
unsigned childOffset) = 0;
|
= 0;
|
||||||
virtual void pop() = 0;
|
virtual void pop() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -42,9 +42,8 @@ class HeapWalker {
|
|||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
HeapWalker*
|
HeapWalker* makeHeapWalker(Thread* t, HeapVisitor* v);
|
||||||
makeHeapWalker(Thread* t, HeapVisitor* v);
|
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//HEAPWALK_H
|
#endif // HEAPWALK_H
|
||||||
|
@ -27,9 +27,8 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
void
|
void populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
|
||||||
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
|
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//JNIENV_H
|
#endif // JNIENV_H
|
||||||
|
@ -22,7 +22,8 @@ const unsigned Padding = 16;
|
|||||||
|
|
||||||
class LzmaAllocator {
|
class LzmaAllocator {
|
||||||
public:
|
public:
|
||||||
LzmaAllocator(avian::util::Allocator* a): a(a) {
|
LzmaAllocator(avian::util::Allocator* a) : a(a)
|
||||||
|
{
|
||||||
allocator.Alloc = allocate;
|
allocator.Alloc = allocate;
|
||||||
allocator.Free = free;
|
allocator.Free = free;
|
||||||
}
|
}
|
||||||
@ -30,15 +31,17 @@ class LzmaAllocator {
|
|||||||
ISzAlloc allocator;
|
ISzAlloc allocator;
|
||||||
avian::util::Allocator* a;
|
avian::util::Allocator* a;
|
||||||
|
|
||||||
static void* allocate(void* allocator, size_t size) {
|
static void* allocate(void* allocator, size_t size)
|
||||||
uint8_t* p = static_cast<uint8_t*>
|
{
|
||||||
(static_cast<LzmaAllocator*>(allocator)->a->allocate(size + Padding));
|
uint8_t* p = static_cast<uint8_t*>(
|
||||||
|
static_cast<LzmaAllocator*>(allocator)->a->allocate(size + Padding));
|
||||||
int32_t size32 = size;
|
int32_t size32 = size;
|
||||||
memcpy(p, &size32, 4);
|
memcpy(p, &size32, 4);
|
||||||
return p + Padding;
|
return p + Padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free(void* allocator, void* address) {
|
static void free(void* allocator, void* address)
|
||||||
|
{
|
||||||
if (address) {
|
if (address) {
|
||||||
void* p = static_cast<uint8_t*>(address) - Padding;
|
void* p = static_cast<uint8_t*>(address) - Padding;
|
||||||
int32_t size32;
|
int32_t size32;
|
||||||
|
2053
src/avian/machine.h
2053
src/avian/machine.h
File diff suppressed because it is too large
Load Diff
@ -58,4 +58,4 @@ int findLineNumber(Thread* t, GcMethod* method, unsigned ip);
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//PROCESS_H
|
#endif // PROCESS_H
|
||||||
|
@ -69,7 +69,10 @@ class Processor {
|
|||||||
|
|
||||||
class CompilationHandler {
|
class CompilationHandler {
|
||||||
public:
|
public:
|
||||||
virtual void compiled(const void* code, unsigned size, unsigned frameSize, const char* name) = 0;
|
virtual void compiled(const void* code,
|
||||||
|
unsigned size,
|
||||||
|
unsigned frameSize,
|
||||||
|
const char* name) = 0;
|
||||||
|
|
||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
@ -112,25 +115,19 @@ class Processor {
|
|||||||
|
|
||||||
virtual void initVtable(Thread* t, GcClass* c) = 0;
|
virtual void initVtable(Thread* t, GcClass* c) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void walkStack(Thread* t, StackVisitor* v) = 0;
|
||||||
walkStack(Thread* t, StackVisitor* v) = 0;
|
|
||||||
|
|
||||||
virtual int lineNumber(Thread* t, GcMethod* method, int ip) = 0;
|
virtual int lineNumber(Thread* t, GcMethod* method, int ip) = 0;
|
||||||
|
|
||||||
virtual object*
|
virtual object* makeLocalReference(Thread* t, object o) = 0;
|
||||||
makeLocalReference(Thread* t, object o) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void disposeLocalReference(Thread* t, object* r) = 0;
|
||||||
disposeLocalReference(Thread* t, object* r) = 0;
|
|
||||||
|
|
||||||
virtual bool
|
virtual bool pushLocalFrame(Thread* t, unsigned capacity) = 0;
|
||||||
pushLocalFrame(Thread* t, unsigned capacity) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void popLocalFrame(Thread* t) = 0;
|
||||||
popLocalFrame(Thread* t) = 0;
|
|
||||||
|
|
||||||
virtual object invokeArray(Thread* t,
|
virtual object invokeArray(Thread* t,
|
||||||
GcMethod* method,
|
GcMethod* method,
|
||||||
@ -156,20 +153,16 @@ class Processor {
|
|||||||
object this_,
|
object this_,
|
||||||
va_list arguments) = 0;
|
va_list arguments) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void dispose(Thread* t) = 0;
|
||||||
dispose(Thread* t) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void dispose() = 0;
|
||||||
dispose() = 0;
|
|
||||||
|
|
||||||
virtual object
|
virtual object getStackTrace(Thread* t, Thread* target) = 0;
|
||||||
getStackTrace(Thread* t, Thread* target) = 0;
|
|
||||||
|
|
||||||
virtual void initialize(BootImage* image, avian::util::Slice<uint8_t> code)
|
virtual void initialize(BootImage* image, avian::util::Slice<uint8_t> code)
|
||||||
= 0;
|
= 0;
|
||||||
|
|
||||||
virtual void
|
virtual void addCompilationHandler(CompilationHandler* handler) = 0;
|
||||||
addCompilationHandler(CompilationHandler* handler) = 0;
|
|
||||||
|
|
||||||
virtual void compileMethod(Thread* t,
|
virtual void compileMethod(Thread* t,
|
||||||
Zone* zone,
|
Zone* zone,
|
||||||
@ -179,23 +172,18 @@ class Processor {
|
|||||||
GcMethod* method,
|
GcMethod* method,
|
||||||
OffsetResolver* resolver) = 0;
|
OffsetResolver* resolver) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void visitRoots(Thread* t, HeapWalker* w) = 0;
|
||||||
visitRoots(Thread* t, HeapWalker* w) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void normalizeVirtualThunks(Thread* t) = 0;
|
||||||
normalizeVirtualThunks(Thread* t) = 0;
|
|
||||||
|
|
||||||
virtual unsigned*
|
virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) = 0;
|
||||||
makeCallTable(Thread* t, HeapWalker* w) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void boot(Thread* t, BootImage* image, uint8_t* code) = 0;
|
||||||
boot(Thread* t, BootImage* image, uint8_t* code) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void callWithCurrentContinuation(Thread* t, object receiver) = 0;
|
||||||
callWithCurrentContinuation(Thread* t, object receiver) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void dynamicWind(Thread* t, object before, object thunk, object after)
|
||||||
dynamicWind(Thread* t, object before, object thunk, object after) = 0;
|
= 0;
|
||||||
|
|
||||||
virtual void feedResultToContinuation(Thread* t,
|
virtual void feedResultToContinuation(Thread* t,
|
||||||
GcContinuation* continuation,
|
GcContinuation* continuation,
|
||||||
@ -205,9 +193,10 @@ class Processor {
|
|||||||
GcContinuation* continuation,
|
GcContinuation* continuation,
|
||||||
GcThrowable* exception) = 0;
|
GcThrowable* exception) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void walkContinuationBody(Thread* t,
|
||||||
walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start)
|
Heap::Walker* w,
|
||||||
= 0;
|
object o,
|
||||||
|
unsigned start) = 0;
|
||||||
|
|
||||||
object invoke(Thread* t, GcMethod* method, object this_, ...)
|
object invoke(Thread* t, GcMethod* method, object this_, ...)
|
||||||
{
|
{
|
||||||
@ -232,8 +221,8 @@ class Processor {
|
|||||||
va_list a;
|
va_list a;
|
||||||
va_start(a, this_);
|
va_start(a, this_);
|
||||||
|
|
||||||
object r = invokeList
|
object r
|
||||||
(t, loader, className, methodName, methodSpec, this_, a);
|
= invokeList(t, loader, className, methodName, methodSpec, this_, a);
|
||||||
|
|
||||||
va_end(a);
|
va_end(a);
|
||||||
|
|
||||||
@ -248,4 +237,4 @@ Processor* makeProcessor(System* system,
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//PROCESSOR_H
|
#endif // PROCESSOR_H
|
||||||
|
@ -11,9 +11,8 @@
|
|||||||
#ifndef AVIAN_TARGET_FIELDS_H
|
#ifndef AVIAN_TARGET_FIELDS_H
|
||||||
#define AVIAN_TARGET_FIELDS_H
|
#define AVIAN_TARGET_FIELDS_H
|
||||||
|
|
||||||
|
|
||||||
#ifdef TARGET_BYTES_PER_WORD
|
#ifdef TARGET_BYTES_PER_WORD
|
||||||
# if (TARGET_BYTES_PER_WORD == 8)
|
#if (TARGET_BYTES_PER_WORD == 8)
|
||||||
|
|
||||||
#define TARGET_THREAD_EXCEPTION 80
|
#define TARGET_THREAD_EXCEPTION 80
|
||||||
#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2264
|
#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2264
|
||||||
@ -33,7 +32,7 @@
|
|||||||
#define TARGET_THREAD_THUNKTABLE 2328
|
#define TARGET_THREAD_THUNKTABLE 2328
|
||||||
#define TARGET_THREAD_STACKLIMIT 2376
|
#define TARGET_THREAD_STACKLIMIT 2376
|
||||||
|
|
||||||
# elif (TARGET_BYTES_PER_WORD == 4)
|
#elif(TARGET_BYTES_PER_WORD == 4)
|
||||||
|
|
||||||
#define TARGET_THREAD_EXCEPTION 44
|
#define TARGET_THREAD_EXCEPTION 44
|
||||||
#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2168
|
#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2168
|
||||||
@ -53,12 +52,11 @@
|
|||||||
#define TARGET_THREAD_THUNKTABLE 2200
|
#define TARGET_THREAD_THUNKTABLE 2200
|
||||||
#define TARGET_THREAD_STACKLIMIT 2224
|
#define TARGET_THREAD_STACKLIMIT 2224
|
||||||
|
|
||||||
# else
|
|
||||||
# error
|
|
||||||
# endif
|
|
||||||
#else
|
#else
|
||||||
# error
|
#error
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#error
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -17,96 +17,82 @@
|
|||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T targetV1(T v)
|
||||||
targetV1(T v)
|
|
||||||
{
|
{
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T swapV2(T v)
|
||||||
swapV2(T v)
|
|
||||||
{
|
{
|
||||||
return (((v >> 8) & 0xFF) |
|
return (((v >> 8) & 0xFF) | ((v << 8)));
|
||||||
((v << 8)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T swapV4(T v)
|
||||||
swapV4(T v)
|
|
||||||
{
|
{
|
||||||
return (((v >> 24) & 0x000000FF) |
|
return (((v >> 24) & 0x000000FF) | ((v >> 8) & 0x0000FF00)
|
||||||
((v >> 8) & 0x0000FF00) |
|
| ((v << 8) & 0x00FF0000) | ((v << 24)));
|
||||||
((v << 8) & 0x00FF0000) |
|
|
||||||
((v << 24)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T swapV8(T v)
|
||||||
swapV8(T v)
|
|
||||||
{
|
{
|
||||||
return (((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) |
|
return (((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF))
|
||||||
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) |
|
| ((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00))
|
||||||
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) |
|
| ((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000))
|
||||||
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) |
|
| ((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000))
|
||||||
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) |
|
| ((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000))
|
||||||
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) |
|
| ((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000))
|
||||||
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) |
|
| ((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000))
|
||||||
((static_cast<uint64_t>(v) << 56)));
|
| ((static_cast<uint64_t>(v) << 56)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_OPPOSITE_ENDIAN
|
#ifdef TARGET_OPPOSITE_ENDIAN
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T targetV2(T v)
|
||||||
targetV2(T v)
|
|
||||||
{
|
{
|
||||||
return swapV2(v);
|
return swapV2(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T targetV4(T v)
|
||||||
targetV4(T v)
|
|
||||||
{
|
{
|
||||||
return swapV4(v);
|
return swapV4(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T targetV8(T v)
|
||||||
targetV8(T v)
|
|
||||||
{
|
{
|
||||||
return swapV8(v);
|
return swapV8(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T targetV2(T v)
|
||||||
targetV2(T v)
|
|
||||||
{
|
{
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T targetV4(T v)
|
||||||
targetV4(T v)
|
|
||||||
{
|
{
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T targetV8(T v)
|
||||||
targetV8(T v)
|
|
||||||
{
|
{
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TARGET_BYTES_PER_WORD
|
#ifdef TARGET_BYTES_PER_WORD
|
||||||
# if (TARGET_BYTES_PER_WORD == 8)
|
#if (TARGET_BYTES_PER_WORD == 8)
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T targetVW(T v)
|
||||||
targetVW(T v)
|
|
||||||
{
|
{
|
||||||
return targetV8(v);
|
return targetV8(v);
|
||||||
}
|
}
|
||||||
@ -120,11 +106,10 @@ const unsigned TargetClassVtable = 136;
|
|||||||
|
|
||||||
const unsigned TargetFieldOffset = 12;
|
const unsigned TargetFieldOffset = 12;
|
||||||
|
|
||||||
# elif (TARGET_BYTES_PER_WORD == 4)
|
#elif(TARGET_BYTES_PER_WORD == 4)
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T
|
inline T targetVW(T v)
|
||||||
targetVW(T v)
|
|
||||||
{
|
{
|
||||||
return targetV4(v);
|
return targetV4(v);
|
||||||
}
|
}
|
||||||
@ -138,11 +123,11 @@ const unsigned TargetClassVtable = 72;
|
|||||||
|
|
||||||
const unsigned TargetFieldOffset = 8;
|
const unsigned TargetFieldOffset = 8;
|
||||||
|
|
||||||
# else
|
|
||||||
# error
|
|
||||||
# endif
|
|
||||||
#else
|
#else
|
||||||
# error
|
#error
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#error
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const unsigned TargetBytesPerWord = TARGET_BYTES_PER_WORD;
|
const unsigned TargetBytesPerWord = TARGET_BYTES_PER_WORD;
|
||||||
@ -150,19 +135,18 @@ const unsigned TargetBytesPerWord = TARGET_BYTES_PER_WORD;
|
|||||||
const unsigned TargetBitsPerWord = TargetBytesPerWord * 8;
|
const unsigned TargetBitsPerWord = TargetBytesPerWord * 8;
|
||||||
|
|
||||||
const target_uintptr_t TargetPointerMask
|
const target_uintptr_t TargetPointerMask
|
||||||
= ((~static_cast<target_uintptr_t>(0)) / TargetBytesPerWord)
|
= ((~static_cast<target_uintptr_t>(0)) / TargetBytesPerWord)
|
||||||
* TargetBytesPerWord;
|
* TargetBytesPerWord;
|
||||||
|
|
||||||
const unsigned TargetArrayLength = TargetBytesPerWord;
|
const unsigned TargetArrayLength = TargetBytesPerWord;
|
||||||
const unsigned TargetArrayBody = TargetBytesPerWord * 2;
|
const unsigned TargetArrayBody = TargetBytesPerWord * 2;
|
||||||
|
|
||||||
inline void
|
inline void targetMarkBit(target_uintptr_t* map, unsigned i)
|
||||||
targetMarkBit(target_uintptr_t* map, unsigned i)
|
|
||||||
{
|
{
|
||||||
map[wordOf<target_uintptr_t>(i)] |=
|
map[wordOf<target_uintptr_t>(i)] |= targetVW(static_cast<target_uintptr_t>(1)
|
||||||
targetVW(static_cast<target_uintptr_t>(1) << bitOf<target_uintptr_t>(i));
|
<< bitOf<target_uintptr_t>(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//TARGET_H
|
#endif // TARGET_H
|
||||||
|
@ -20,4 +20,4 @@
|
|||||||
#define DOUBLE_TYPE 6
|
#define DOUBLE_TYPE 6
|
||||||
#define POINTER_TYPE 7
|
#define POINTER_TYPE 7
|
||||||
|
|
||||||
#endif//TYPES_H
|
#endif // TYPES_H
|
||||||
|
@ -84,15 +84,13 @@ object hashMapRemove(Thread* t,
|
|||||||
|
|
||||||
object hashMapIterator(Thread* t, GcHashMap* map);
|
object hashMapIterator(Thread* t, GcHashMap* map);
|
||||||
|
|
||||||
object
|
object hashMapIteratorNext(Thread* t, object it);
|
||||||
hashMapIteratorNext(Thread* t, object it);
|
|
||||||
|
|
||||||
void listAppend(Thread* t, GcList* list, object value);
|
void listAppend(Thread* t, GcList* list, object value);
|
||||||
|
|
||||||
GcVector* vectorAppend(Thread* t, GcVector* vector, object value);
|
GcVector* vectorAppend(Thread* t, GcVector* vector, object value);
|
||||||
|
|
||||||
object
|
object growArray(Thread* t, object array);
|
||||||
growArray(Thread* t, object array);
|
|
||||||
|
|
||||||
object treeQuery(Thread* t,
|
object treeQuery(Thread* t,
|
||||||
GcTreeNode* tree,
|
GcTreeNode* tree,
|
||||||
@ -115,7 +113,7 @@ void treeUpdate(Thread* t,
|
|||||||
GcTreeNode* sentinal,
|
GcTreeNode* sentinal,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||||
|
|
||||||
class HashMapIterator: public Thread::Protector {
|
class HashMapIterator : public Thread::Protector {
|
||||||
public:
|
public:
|
||||||
HashMapIterator(Thread* t, GcHashMap* map)
|
HashMapIterator(Thread* t, GcHashMap* map)
|
||||||
: Protector(t), map(map), node(0), index(0)
|
: Protector(t), map(map), node(0), index(0)
|
||||||
@ -123,7 +121,8 @@ class HashMapIterator: public Thread::Protector {
|
|||||||
find();
|
find();
|
||||||
}
|
}
|
||||||
|
|
||||||
void find() {
|
void find()
|
||||||
|
{
|
||||||
GcArray* array = map->array();
|
GcArray* array = map->array();
|
||||||
if (array) {
|
if (array) {
|
||||||
for (unsigned i = index; i < array->length(); ++i) {
|
for (unsigned i = index; i < array->length(); ++i) {
|
||||||
@ -137,7 +136,8 @@ class HashMapIterator: public Thread::Protector {
|
|||||||
node = 0;
|
node = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasMore() {
|
bool hasMore()
|
||||||
|
{
|
||||||
return node != 0;
|
return node != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +156,8 @@ class HashMapIterator: public Thread::Protector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(Heap::Visitor* v) {
|
virtual void visit(Heap::Visitor* v)
|
||||||
|
{
|
||||||
v->visit(&map);
|
v->visit(&map);
|
||||||
v->visit(&node);
|
v->visit(&node);
|
||||||
}
|
}
|
||||||
@ -168,4 +169,4 @@ class HashMapIterator: public Thread::Protector {
|
|||||||
|
|
||||||
} // vm
|
} // vm
|
||||||
|
|
||||||
#endif//UTIL_H
|
#endif // UTIL_H
|
||||||
|
260
src/avian/x86.h
260
src/avian/x86.h
@ -15,84 +15,87 @@
|
|||||||
#include "avian/common.h"
|
#include "avian/common.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# include "windows.h"
|
#include "windows.h"
|
||||||
# pragma push_macro("assert")
|
#pragma push_macro("assert")
|
||||||
# include "intrin.h"
|
#include "intrin.h"
|
||||||
# pragma pop_macro("assert")
|
#pragma pop_macro("assert")
|
||||||
# undef interface
|
#undef interface
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined ARCH_x86_32) || (defined PLATFORM_WINDOWS)
|
#if (defined ARCH_x86_32) || (defined PLATFORM_WINDOWS)
|
||||||
# define VA_LIST(x) (&(x))
|
#define VA_LIST(x) (&(x))
|
||||||
#else
|
#else
|
||||||
# define VA_LIST(x) (x)
|
#define VA_LIST(x) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# include "mach/mach_types.h"
|
#include "mach/mach_types.h"
|
||||||
# include "mach/thread_act.h"
|
#include "mach/thread_act.h"
|
||||||
# include "mach/thread_status.h"
|
#include "mach/thread_status.h"
|
||||||
|
|
||||||
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
#if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
||||||
# define FIELD(x) __##x
|
#define FIELD(x) __##x
|
||||||
# else
|
#else
|
||||||
# define FIELD(x) x
|
#define FIELD(x) x
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_x86_32
|
#ifdef ARCH_x86_32
|
||||||
|
|
||||||
# ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# define THREAD_STATE x86_THREAD_STATE32
|
#define THREAD_STATE x86_THREAD_STATE32
|
||||||
# define THREAD_STATE_TYPE x86_thread_state32_t
|
#define THREAD_STATE_TYPE x86_thread_state32_t
|
||||||
# define THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
|
#define THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
|
||||||
|
|
||||||
# define THREAD_STATE_IP(state) ((state).FIELD(eip))
|
#define THREAD_STATE_IP(state) ((state).FIELD(eip))
|
||||||
# define THREAD_STATE_STACK(state) ((state).FIELD(esp))
|
#define THREAD_STATE_STACK(state) ((state).FIELD(esp))
|
||||||
# define THREAD_STATE_THREAD(state) ((state).FIELD(ebx))
|
#define THREAD_STATE_THREAD(state) ((state).FIELD(ebx))
|
||||||
# define THREAD_STATE_LINK(state) ((state).FIELD(ecx))
|
#define THREAD_STATE_LINK(state) ((state).FIELD(ecx))
|
||||||
# define THREAD_STATE_FRAME(state) ((state).FIELD(ebp))
|
#define THREAD_STATE_FRAME(state) ((state).FIELD(ebp))
|
||||||
|
|
||||||
# define IP_REGISTER(context) \
|
#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
||||||
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
#define STACK_REGISTER(context) \
|
||||||
# define STACK_REGISTER(context) \
|
|
||||||
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
|
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
|
||||||
# define THREAD_REGISTER(context) \
|
#define THREAD_REGISTER(context) \
|
||||||
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
||||||
# define LINK_REGISTER(context) \
|
#define LINK_REGISTER(context) \
|
||||||
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
||||||
# define FRAME_REGISTER(context) \
|
#define FRAME_REGISTER(context) \
|
||||||
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
|
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
|
||||||
|
|
||||||
# elif (defined __QNX__)
|
#elif(defined __QNX__)
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext.cpu.eip)
|
#define IP_REGISTER(context) (context->uc_mcontext.cpu.eip)
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext.cpu.esp)
|
#define STACK_REGISTER(context) (context->uc_mcontext.cpu.esp)
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.cpu.ebx)
|
#define THREAD_REGISTER(context) (context->uc_mcontext.cpu.ebx)
|
||||||
# define LINK_REGISTER(context) (context->uc_mcontext.cpu.ecx)
|
#define LINK_REGISTER(context) (context->uc_mcontext.cpu.ecx)
|
||||||
# define FRAME_REGISTER(context) (context->uc_mcontext.cpu.ebp)
|
#define FRAME_REGISTER(context) (context->uc_mcontext.cpu.ebp)
|
||||||
# elif (defined __FreeBSD__)
|
#elif(defined __FreeBSD__)
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext.mc_eip)
|
#define IP_REGISTER(context) (context->uc_mcontext.mc_eip)
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext.mc_esp)
|
#define STACK_REGISTER(context) (context->uc_mcontext.mc_esp)
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.mc_ebx)
|
#define THREAD_REGISTER(context) (context->uc_mcontext.mc_ebx)
|
||||||
# define LINK_REGISTER(context) (context->uc_mcontext.mc_ecx)
|
#define LINK_REGISTER(context) (context->uc_mcontext.mc_ecx)
|
||||||
# define FRAME_REGISTER(context) (context->uc_mcontext.mc_ebp)
|
#define FRAME_REGISTER(context) (context->uc_mcontext.mc_ebp)
|
||||||
# else
|
#else
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
|
#define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
|
#define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX])
|
#define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX])
|
||||||
# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_ECX])
|
#define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_ECX])
|
||||||
# define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
|
#define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
extern "C" uint64_t
|
extern "C" uint64_t vmNativeCall(void* function,
|
||||||
vmNativeCall(void* function, void* stack, unsigned stackSize,
|
void* stack,
|
||||||
|
unsigned stackSize,
|
||||||
unsigned returnType);
|
unsigned returnType);
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
inline uint64_t
|
inline uint64_t dynamicCall(void* function,
|
||||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
uintptr_t* arguments,
|
||||||
unsigned, unsigned argumentsSize, unsigned returnType)
|
uint8_t*,
|
||||||
|
unsigned,
|
||||||
|
unsigned argumentsSize,
|
||||||
|
unsigned returnType)
|
||||||
{
|
{
|
||||||
return vmNativeCall(function, arguments, argumentsSize, returnType);
|
return vmNativeCall(function, arguments, argumentsSize, returnType);
|
||||||
}
|
}
|
||||||
@ -101,64 +104,75 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
|||||||
|
|
||||||
#elif defined ARCH_x86_64
|
#elif defined ARCH_x86_64
|
||||||
|
|
||||||
# ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# define THREAD_STATE x86_THREAD_STATE64
|
#define THREAD_STATE x86_THREAD_STATE64
|
||||||
# define THREAD_STATE_TYPE x86_thread_state64_t
|
#define THREAD_STATE_TYPE x86_thread_state64_t
|
||||||
# define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
|
#define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
|
||||||
|
|
||||||
# define THREAD_STATE_IP(state) ((state).FIELD(rip))
|
#define THREAD_STATE_IP(state) ((state).FIELD(rip))
|
||||||
# define THREAD_STATE_STACK(state) ((state).FIELD(rsp))
|
#define THREAD_STATE_STACK(state) ((state).FIELD(rsp))
|
||||||
# define THREAD_STATE_THREAD(state) ((state).FIELD(rbx))
|
#define THREAD_STATE_THREAD(state) ((state).FIELD(rbx))
|
||||||
# define THREAD_STATE_LINK(state) ((state).FIELD(rcx))
|
#define THREAD_STATE_LINK(state) ((state).FIELD(rcx))
|
||||||
# define THREAD_STATE_FRAME(state) ((state).FIELD(rbp))
|
#define THREAD_STATE_FRAME(state) ((state).FIELD(rbp))
|
||||||
|
|
||||||
# define IP_REGISTER(context) \
|
#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
||||||
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
#define STACK_REGISTER(context) \
|
||||||
# define STACK_REGISTER(context) \
|
|
||||||
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
|
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
|
||||||
# define THREAD_REGISTER(context) \
|
#define THREAD_REGISTER(context) \
|
||||||
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
||||||
# define LINK_REGISTER(context) \
|
#define LINK_REGISTER(context) \
|
||||||
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
||||||
# define FRAME_REGISTER(context) \
|
#define FRAME_REGISTER(context) \
|
||||||
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
|
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
|
||||||
|
|
||||||
# elif (defined __FreeBSD__)
|
#elif(defined __FreeBSD__)
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext.mc_rip)
|
#define IP_REGISTER(context) (context->uc_mcontext.mc_rip)
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext.mc_rsp)
|
#define STACK_REGISTER(context) (context->uc_mcontext.mc_rsp)
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.mc_rbx)
|
#define THREAD_REGISTER(context) (context->uc_mcontext.mc_rbx)
|
||||||
# define LINK_REGISTER(context) (context->uc_mcontext.mc_rcx)
|
#define LINK_REGISTER(context) (context->uc_mcontext.mc_rcx)
|
||||||
# define FRAME_REGISTER(context) (context->uc_mcontext.mc_rbp)
|
#define FRAME_REGISTER(context) (context->uc_mcontext.mc_rbp)
|
||||||
# else
|
#else
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
|
#define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
|
#define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
|
#define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
|
||||||
# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_RCX])
|
#define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_RCX])
|
||||||
# define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP])
|
#define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP])
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
extern "C" uint64_t
|
extern "C" uint64_t
|
||||||
# ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
vmNativeCall(void* function, void* stack, unsigned stackSize,
|
vmNativeCall(void* function,
|
||||||
|
void* stack,
|
||||||
|
unsigned stackSize,
|
||||||
unsigned returnType);
|
unsigned returnType);
|
||||||
# else
|
#else
|
||||||
vmNativeCall(void* function, void* stack, unsigned stackSize,
|
vmNativeCall(void* function,
|
||||||
void* gprTable, void* sseTable, unsigned returnType);
|
void* stack,
|
||||||
# endif
|
unsigned stackSize,
|
||||||
|
void* gprTable,
|
||||||
|
void* sseTable,
|
||||||
|
unsigned returnType);
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
# ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
inline uint64_t
|
inline uint64_t dynamicCall(void* function,
|
||||||
dynamicCall(void* function, uint64_t* arguments, UNUSED uint8_t* argumentTypes,
|
uint64_t* arguments,
|
||||||
unsigned argumentCount, unsigned, unsigned returnType)
|
UNUSED uint8_t* argumentTypes,
|
||||||
|
unsigned argumentCount,
|
||||||
|
unsigned,
|
||||||
|
unsigned returnType)
|
||||||
{
|
{
|
||||||
return vmNativeCall(function, arguments, argumentCount, returnType);
|
return vmNativeCall(function, arguments, argumentCount, returnType);
|
||||||
}
|
}
|
||||||
# else
|
#else
|
||||||
inline uint64_t
|
inline uint64_t dynamicCall(void* function,
|
||||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
uintptr_t* arguments,
|
||||||
unsigned argumentCount, unsigned, unsigned returnType)
|
uint8_t* argumentTypes,
|
||||||
|
unsigned argumentCount,
|
||||||
|
unsigned,
|
||||||
|
unsigned returnType)
|
||||||
{
|
{
|
||||||
const unsigned GprCount = 6;
|
const unsigned GprCount = 6;
|
||||||
uint64_t gprTable[GprCount];
|
uint64_t gprTable[GprCount];
|
||||||
@ -192,22 +206,24 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vmNativeCall(function, stack, stackIndex * BytesPerWord,
|
return vmNativeCall(function,
|
||||||
|
stack,
|
||||||
|
stackIndex * BytesPerWord,
|
||||||
(gprIndex ? gprTable : 0),
|
(gprIndex ? gprTable : 0),
|
||||||
(sseIndex ? sseTable : 0), returnType);
|
(sseIndex ? sseTable : 0),
|
||||||
|
returnType);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error unsupported architecture
|
#error unsupported architecture
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
inline void
|
inline void trap()
|
||||||
trap()
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
__asm int 3
|
__asm int 3
|
||||||
@ -216,50 +232,44 @@ trap()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void programOrderMemoryBarrier()
|
||||||
programOrderMemoryBarrier()
|
|
||||||
{
|
{
|
||||||
compileTimeMemoryBarrier();
|
compileTimeMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void storeStoreMemoryBarrier()
|
||||||
storeStoreMemoryBarrier()
|
|
||||||
{
|
{
|
||||||
programOrderMemoryBarrier();
|
programOrderMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void storeLoadMemoryBarrier()
|
||||||
storeLoadMemoryBarrier()
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
MemoryBarrier();
|
MemoryBarrier();
|
||||||
#elif defined ARCH_x86_32
|
#elif defined ARCH_x86_32
|
||||||
__asm__ __volatile__("lock; addl $0,0(%%esp)": : :"memory");
|
__asm__ __volatile__("lock; addl $0,0(%%esp)" : : : "memory");
|
||||||
#elif defined ARCH_x86_64
|
#elif defined ARCH_x86_64
|
||||||
__asm__ __volatile__("mfence": : :"memory");
|
__asm__ __volatile__("mfence" : : : "memory");
|
||||||
#endif // ARCH_x86_64
|
#endif // ARCH_x86_64
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void loadMemoryBarrier()
|
||||||
loadMemoryBarrier()
|
|
||||||
{
|
{
|
||||||
programOrderMemoryBarrier();
|
programOrderMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void syncInstructionCache(const void*, unsigned)
|
||||||
syncInstructionCache(const void*, unsigned)
|
|
||||||
{
|
{
|
||||||
programOrderMemoryBarrier();
|
programOrderMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_ATOMIC_OPERATIONS
|
#ifdef USE_ATOMIC_OPERATIONS
|
||||||
inline bool
|
inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
||||||
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return old == InterlockedCompareExchange
|
return old
|
||||||
(reinterpret_cast<LONG*>(p), new_, old);
|
== InterlockedCompareExchange(reinterpret_cast<LONG*>(p), new_, old);
|
||||||
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
||||||
return __sync_bool_compare_and_swap(p, old, new_);
|
return __sync_bool_compare_and_swap(p, old, new_);
|
||||||
#else
|
#else
|
||||||
uint8_t result;
|
uint8_t result;
|
||||||
@ -275,13 +285,12 @@ atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
|||||||
|
|
||||||
#define AVIAN_HAS_CAS64
|
#define AVIAN_HAS_CAS64
|
||||||
|
|
||||||
inline bool
|
inline bool atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
|
||||||
atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
|
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return old == InterlockedCompareExchange64
|
return old == InterlockedCompareExchange64(
|
||||||
(reinterpret_cast<LONGLONG*>(p), new_, old);
|
reinterpret_cast<LONGLONG*>(p), new_, old);
|
||||||
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
||||||
return __sync_bool_compare_and_swap(p, old, new_);
|
return __sync_bool_compare_and_swap(p, old, new_);
|
||||||
#elif defined ARCH_x86_32
|
#elif defined ARCH_x86_32
|
||||||
uint8_t result;
|
uint8_t result;
|
||||||
@ -308,8 +317,7 @@ atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
||||||
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
|
||||||
{
|
{
|
||||||
#ifdef ARCH_x86_32
|
#ifdef ARCH_x86_32
|
||||||
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
|
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
|
||||||
@ -321,4 +329,4 @@ atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//X86_H
|
#endif // X86_H
|
||||||
|
@ -13,11 +13,19 @@
|
|||||||
#ifdef inflateInit2
|
#ifdef inflateInit2
|
||||||
#undef inflateInit2
|
#undef inflateInit2
|
||||||
#define inflateInit2(strm, windowBits) \
|
#define inflateInit2(strm, windowBits) \
|
||||||
inflateInit2_((strm), (windowBits), ZLIB_VERSION, static_cast<int>(sizeof(z_stream)))
|
inflateInit2_( \
|
||||||
|
(strm), (windowBits), ZLIB_VERSION, static_cast<int>(sizeof(z_stream)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef deflateInit2
|
#ifdef deflateInit2
|
||||||
#undef deflateInit2
|
#undef deflateInit2
|
||||||
#define deflateInit2(strm, level, windowBits) \
|
#define deflateInit2(strm, level, windowBits) \
|
||||||
deflateInit2_((strm), (level), Z_DEFLATED, (windowBits), 8, Z_DEFAULT_STRATEGY, ZLIB_VERSION, static_cast<int>(sizeof(z_stream)))
|
deflateInit2_((strm), \
|
||||||
|
(level), \
|
||||||
|
Z_DEFLATED, \
|
||||||
|
(windowBits), \
|
||||||
|
8, \
|
||||||
|
Z_DEFAULT_STRATEGY, \
|
||||||
|
ZLIB_VERSION, \
|
||||||
|
static_cast<int>(sizeof(z_stream)))
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,9 +21,9 @@ class Zone : public avian::util::Allocator {
|
|||||||
public:
|
public:
|
||||||
class Segment {
|
class Segment {
|
||||||
public:
|
public:
|
||||||
Segment(Segment* next, unsigned size):
|
Segment(Segment* next, unsigned size) : next(next), size(size), position(0)
|
||||||
next(next), size(size), position(0)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
Segment* next;
|
Segment* next;
|
||||||
uintptr_t size;
|
uintptr_t size;
|
||||||
@ -31,19 +31,23 @@ class Zone : public avian::util::Allocator {
|
|||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
Zone(System* s, Allocator* allocator, unsigned minimumFootprint):
|
Zone(System* s, Allocator* allocator, unsigned minimumFootprint)
|
||||||
s(s),
|
: s(s),
|
||||||
allocator(allocator),
|
allocator(allocator),
|
||||||
segment(0),
|
segment(0),
|
||||||
minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 :
|
minimumFootprint(minimumFootprint < sizeof(Segment)
|
||||||
minimumFootprint - sizeof(Segment))
|
? 0
|
||||||
{ }
|
: minimumFootprint - sizeof(Segment))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~Zone() {
|
~Zone()
|
||||||
|
{
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose()
|
||||||
|
{
|
||||||
for (Segment* seg = segment, *next; seg; seg = next) {
|
for (Segment* seg = segment, *next; seg; seg = next) {
|
||||||
next = seg->next;
|
next = seg->next;
|
||||||
allocator->free(seg, sizeof(Segment) + seg->size);
|
allocator->free(seg, sizeof(Segment) + seg->size);
|
||||||
@ -52,17 +56,19 @@ class Zone : public avian::util::Allocator {
|
|||||||
segment = 0;
|
segment = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned padToPage(unsigned size) {
|
static unsigned padToPage(unsigned size)
|
||||||
return (size + (LikelyPageSizeInBytes - 1))
|
{
|
||||||
& ~(LikelyPageSizeInBytes - 1);
|
return (size + (LikelyPageSizeInBytes - 1)) & ~(LikelyPageSizeInBytes - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tryEnsure(unsigned space) {
|
bool tryEnsure(unsigned space)
|
||||||
|
{
|
||||||
if (segment == 0 or segment->position + space > segment->size) {
|
if (segment == 0 or segment->position + space > segment->size) {
|
||||||
unsigned size = padToPage
|
unsigned size = padToPage(
|
||||||
(avian::util::max
|
avian::util::max(
|
||||||
(space, avian::util::max
|
space,
|
||||||
(minimumFootprint, segment == 0 ? 0 : segment->size * 2))
|
avian::util::max(minimumFootprint,
|
||||||
|
segment == 0 ? 0 : segment->size * 2))
|
||||||
+ sizeof(Segment));
|
+ sizeof(Segment));
|
||||||
|
|
||||||
void* p = allocator->tryAllocate(size);
|
void* p = allocator->tryAllocate(size);
|
||||||
@ -79,7 +85,8 @@ class Zone : public avian::util::Allocator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensure(unsigned space) {
|
void ensure(unsigned space)
|
||||||
|
{
|
||||||
if (segment == 0 or segment->position + space > segment->size) {
|
if (segment == 0 or segment->position + space > segment->size) {
|
||||||
unsigned size = padToPage(space + sizeof(Segment));
|
unsigned size = padToPage(space + sizeof(Segment));
|
||||||
|
|
||||||
@ -88,7 +95,8 @@ class Zone : public avian::util::Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* tryAllocate(unsigned size) {
|
virtual void* tryAllocate(unsigned size)
|
||||||
|
{
|
||||||
size = pad(size);
|
size = pad(size);
|
||||||
if (tryEnsure(size)) {
|
if (tryEnsure(size)) {
|
||||||
void* r = segment->data + segment->position;
|
void* r = segment->data + segment->position;
|
||||||
@ -99,7 +107,8 @@ class Zone : public avian::util::Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* allocate(unsigned size) {
|
virtual void* allocate(unsigned size)
|
||||||
|
{
|
||||||
size = pad(size);
|
size = pad(size);
|
||||||
void* p = tryAllocate(size);
|
void* p = tryAllocate(size);
|
||||||
if (p) {
|
if (p) {
|
||||||
@ -112,7 +121,8 @@ class Zone : public avian::util::Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* peek(unsigned size) {
|
void* peek(unsigned size)
|
||||||
|
{
|
||||||
size = pad(size);
|
size = pad(size);
|
||||||
Segment* s = segment;
|
Segment* s = segment;
|
||||||
while (s->position < size) {
|
while (s->position < size) {
|
||||||
@ -122,7 +132,8 @@ class Zone : public avian::util::Allocator {
|
|||||||
return s->data + (s->position - size);
|
return s->data + (s->position - size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop(unsigned size) {
|
void pop(unsigned size)
|
||||||
|
{
|
||||||
size = pad(size);
|
size = pad(size);
|
||||||
Segment* s = segment;
|
Segment* s = segment;
|
||||||
while (s->position < size) {
|
while (s->position < size) {
|
||||||
@ -135,7 +146,8 @@ class Zone : public avian::util::Allocator {
|
|||||||
segment = s;
|
segment = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void free(const void*, unsigned) {
|
virtual void free(const void*, unsigned)
|
||||||
|
{
|
||||||
// not supported
|
// not supported
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
@ -149,4 +161,4 @@ class Zone : public avian::util::Allocator {
|
|||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//ZONE_H
|
#endif // ZONE_H
|
||||||
|
@ -12,26 +12,23 @@
|
|||||||
|
|
||||||
#ifdef BOOT_JAVAHOME
|
#ifdef BOOT_JAVAHOME
|
||||||
|
|
||||||
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||||
# define SYMBOL(x) binary_javahome_jar_##x
|
#define SYMBOL(x) binary_javahome_jar_##x
|
||||||
#else
|
#else
|
||||||
# define SYMBOL(x) _binary_javahome_jar_##x
|
#define SYMBOL(x) _binary_javahome_jar_##x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
extern const uint8_t SYMBOL(start)[];
|
||||||
|
extern const uint8_t SYMBOL(end)[];
|
||||||
|
|
||||||
extern const uint8_t SYMBOL(start)[];
|
AVIAN_EXPORT const uint8_t* javahomeJar(unsigned* size)
|
||||||
extern const uint8_t SYMBOL(end)[];
|
{
|
||||||
|
|
||||||
AVIAN_EXPORT const uint8_t*
|
|
||||||
javahomeJar(unsigned* size)
|
|
||||||
{
|
|
||||||
*size = SYMBOL(end) - SYMBOL(start);
|
*size = SYMBOL(end) - SYMBOL(start);
|
||||||
return SYMBOL(start);
|
return SYMBOL(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef SYMBOL
|
#undef SYMBOL
|
||||||
|
|
||||||
#endif//BOOT_JAVAHOME
|
#endif // BOOT_JAVAHOME
|
||||||
|
62
src/boot.cpp
62
src/boot.cpp
@ -14,68 +14,64 @@
|
|||||||
|
|
||||||
// since we aren't linking against libstdc++, we must implement this
|
// since we aren't linking against libstdc++, we must implement this
|
||||||
// ourselves:
|
// ourselves:
|
||||||
extern "C" void __cxa_pure_virtual(void) { abort(); }
|
extern "C" void __cxa_pure_virtual(void)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BOOT_IMAGE
|
#ifdef BOOT_IMAGE
|
||||||
|
|
||||||
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||||
# define BOOTIMAGE_SYMBOL(x) binary_bootimage_bin_##x
|
#define BOOTIMAGE_SYMBOL(x) binary_bootimage_bin_##x
|
||||||
# define CODEIMAGE_SYMBOL(x) binary_codeimage_bin_##x
|
#define CODEIMAGE_SYMBOL(x) binary_codeimage_bin_##x
|
||||||
#else
|
#else
|
||||||
# define BOOTIMAGE_SYMBOL(x) _binary_bootimage_bin_##x
|
#define BOOTIMAGE_SYMBOL(x) _binary_bootimage_bin_##x
|
||||||
# define CODEIMAGE_SYMBOL(x) _binary_codeimage_bin_##x
|
#define CODEIMAGE_SYMBOL(x) _binary_codeimage_bin_##x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
extern const uint8_t BOOTIMAGE_SYMBOL(start)[];
|
||||||
|
extern const uint8_t BOOTIMAGE_SYMBOL(end)[];
|
||||||
|
|
||||||
extern const uint8_t BOOTIMAGE_SYMBOL(start)[];
|
AVIAN_EXPORT const uint8_t* bootimageBin(unsigned* size)
|
||||||
extern const uint8_t BOOTIMAGE_SYMBOL(end)[];
|
{
|
||||||
|
|
||||||
AVIAN_EXPORT const uint8_t*
|
|
||||||
bootimageBin(unsigned* size)
|
|
||||||
{
|
|
||||||
*size = BOOTIMAGE_SYMBOL(end) - BOOTIMAGE_SYMBOL(start);
|
*size = BOOTIMAGE_SYMBOL(end) - BOOTIMAGE_SYMBOL(start);
|
||||||
return BOOTIMAGE_SYMBOL(start);
|
return BOOTIMAGE_SYMBOL(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const uint8_t CODEIMAGE_SYMBOL(start)[];
|
extern const uint8_t CODEIMAGE_SYMBOL(start)[];
|
||||||
extern const uint8_t CODEIMAGE_SYMBOL(end)[];
|
extern const uint8_t CODEIMAGE_SYMBOL(end)[];
|
||||||
|
|
||||||
AVIAN_EXPORT const uint8_t*
|
AVIAN_EXPORT const uint8_t* codeimageBin(unsigned* size)
|
||||||
codeimageBin(unsigned* size)
|
{
|
||||||
{
|
|
||||||
*size = CODEIMAGE_SYMBOL(end) - CODEIMAGE_SYMBOL(start);
|
*size = CODEIMAGE_SYMBOL(end) - CODEIMAGE_SYMBOL(start);
|
||||||
return CODEIMAGE_SYMBOL(start);
|
return CODEIMAGE_SYMBOL(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef SYMBOL
|
#undef SYMBOL
|
||||||
|
|
||||||
#endif//BOOT_IMAGE
|
#endif // BOOT_IMAGE
|
||||||
|
|
||||||
#ifdef BOOT_CLASSPATH
|
#ifdef BOOT_CLASSPATH
|
||||||
|
|
||||||
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||||
# define SYMBOL(x) binary_classpath_jar_##x
|
#define SYMBOL(x) binary_classpath_jar_##x
|
||||||
#else
|
#else
|
||||||
# define SYMBOL(x) _binary_classpath_jar_##x
|
#define SYMBOL(x) _binary_classpath_jar_##x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
extern const uint8_t SYMBOL(start)[];
|
||||||
|
extern const uint8_t SYMBOL(end)[];
|
||||||
|
|
||||||
extern const uint8_t SYMBOL(start)[];
|
AVIAN_EXPORT const uint8_t* classpathJar(unsigned* size)
|
||||||
extern const uint8_t SYMBOL(end)[];
|
{
|
||||||
|
|
||||||
AVIAN_EXPORT const uint8_t*
|
|
||||||
classpathJar(unsigned* size)
|
|
||||||
{
|
|
||||||
*size = SYMBOL(end) - SYMBOL(start);
|
*size = SYMBOL(end) - SYMBOL(start);
|
||||||
return SYMBOL(start);
|
return SYMBOL(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef SYMBOL
|
#undef SYMBOL
|
||||||
|
|
||||||
#endif//BOOT_CLASSPATH
|
#endif // BOOT_CLASSPATH
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#ifndef FIELD
|
#ifndef FIELD
|
||||||
# define FIELD(name)
|
#define FIELD(name)
|
||||||
# define FIELD_DEFINED
|
#define FIELD_DEFINED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FIELD(magic)
|
FIELD(magic)
|
||||||
@ -23,13 +23,13 @@ FIELD(methodTreeSentinal)
|
|||||||
FIELD(virtualThunks)
|
FIELD(virtualThunks)
|
||||||
|
|
||||||
#ifdef FIELD_DEFINED
|
#ifdef FIELD_DEFINED
|
||||||
# undef FIELD
|
#undef FIELD
|
||||||
# undef FIELD_DEFINED
|
#undef FIELD_DEFINED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef THUNK_FIELD
|
#ifndef THUNK_FIELD
|
||||||
# define THUNK_FIELD(name)
|
#define THUNK_FIELD(name)
|
||||||
# define THUNK_FIELD_DEFINED
|
#define THUNK_FIELD_DEFINED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
THUNK_FIELD(default_);
|
THUNK_FIELD(default_);
|
||||||
@ -40,6 +40,6 @@ THUNK_FIELD(stackOverflow);
|
|||||||
THUNK_FIELD(table);
|
THUNK_FIELD(table);
|
||||||
|
|
||||||
#ifdef THUNK_FIELD_DEFINED
|
#ifdef THUNK_FIELD_DEFINED
|
||||||
# undef THUNK_FIELD
|
#undef THUNK_FIELD
|
||||||
# undef THUNK_FIELD_DEFINED
|
#undef THUNK_FIELD_DEFINED
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,21 +6,20 @@ const unsigned NAME(BootShift) = 32 - avian::util::log(NAME(BytesPerWord));
|
|||||||
const unsigned NAME(BootFlatConstant) = 1 << NAME(BootShift);
|
const unsigned NAME(BootFlatConstant) = 1 << NAME(BootShift);
|
||||||
const unsigned NAME(BootHeapOffset) = 1 << (NAME(BootShift) + 1);
|
const unsigned NAME(BootHeapOffset) = 1 << (NAME(BootShift) + 1);
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned LABEL(codeMapSize)(unsigned codeSize)
|
||||||
LABEL(codeMapSize)(unsigned codeSize)
|
|
||||||
{
|
{
|
||||||
return avian::util::ceilingDivide(codeSize, TargetBitsPerWord) * TargetBytesPerWord;
|
return avian::util::ceilingDivide(codeSize, TargetBitsPerWord)
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned
|
|
||||||
LABEL(heapMapSize)(unsigned heapSize)
|
|
||||||
{
|
|
||||||
return avian::util::ceilingDivide(heapSize, TargetBitsPerWord * TargetBytesPerWord)
|
|
||||||
* TargetBytesPerWord;
|
* TargetBytesPerWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline unsigned LABEL(heapMapSize)(unsigned heapSize)
|
||||||
LABEL(bootObject)(LABEL(uintptr_t)* heap, unsigned offset)
|
{
|
||||||
|
return avian::util::ceilingDivide(heapSize,
|
||||||
|
TargetBitsPerWord * TargetBytesPerWord)
|
||||||
|
* TargetBytesPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object LABEL(bootObject)(LABEL(uintptr_t) * heap, unsigned offset)
|
||||||
{
|
{
|
||||||
if (offset) {
|
if (offset) {
|
||||||
return reinterpret_cast<object>(heap + offset - 1);
|
return reinterpret_cast<object>(heap + offset - 1);
|
||||||
|
516
src/builtin.cpp
516
src/builtin.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -22,9 +22,9 @@ namespace local {
|
|||||||
|
|
||||||
class MyClasspath : public Classpath {
|
class MyClasspath : public Classpath {
|
||||||
public:
|
public:
|
||||||
MyClasspath(Allocator* allocator):
|
MyClasspath(Allocator* allocator) : allocator(allocator)
|
||||||
allocator(allocator)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
virtual GcJclass* makeJclass(Thread* t, GcClass* class_)
|
virtual GcJclass* makeJclass(Thread* t, GcClass* class_)
|
||||||
{
|
{
|
||||||
@ -97,14 +97,12 @@ class MyClasspath : public Classpath {
|
|||||||
return jfield->vmField();
|
return jfield->vmField();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void clearInterrupted(Thread*)
|
||||||
clearInterrupted(Thread*)
|
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void runThread(Thread* t)
|
||||||
runThread(Thread* t)
|
|
||||||
{
|
{
|
||||||
GcMethod* method = resolveMethod(t,
|
GcMethod* method = resolveMethod(t,
|
||||||
roots(t)->bootLoader(),
|
roots(t)->bootLoader(),
|
||||||
@ -120,14 +118,12 @@ class MyClasspath : public Classpath {
|
|||||||
vm::resolveNative(t, method);
|
vm::resolveNative(t, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void interceptMethods(Thread*)
|
||||||
interceptMethods(Thread*)
|
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void preBoot(Thread*)
|
||||||
preBoot(Thread*)
|
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
@ -137,20 +133,17 @@ class MyClasspath : public Classpath {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void boot(Thread*)
|
||||||
boot(Thread*)
|
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char*
|
virtual const char* bootClasspath()
|
||||||
bootClasspath()
|
|
||||||
{
|
{
|
||||||
return AVIAN_CLASSPATH;
|
return AVIAN_CLASSPATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
||||||
makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
|
||||||
{
|
{
|
||||||
GcClass* c
|
GcClass* c
|
||||||
= resolveClass(t, roots(t)->bootLoader(), "java/nio/DirectByteBuffer");
|
= resolveClass(t, roots(t)->bootLoader(), "java/nio/DirectByteBuffer");
|
||||||
@ -161,15 +154,16 @@ class MyClasspath : public Classpath {
|
|||||||
|
|
||||||
GcMethod* constructor = resolveMethod(t, c, "<init>", "(JI)V");
|
GcMethod* constructor = resolveMethod(t, c, "<init>", "(JI)V");
|
||||||
|
|
||||||
t->m->processor->invoke
|
t->m->processor->invoke(t,
|
||||||
(t, constructor, instance, reinterpret_cast<int64_t>(p),
|
constructor,
|
||||||
|
instance,
|
||||||
|
reinterpret_cast<int64_t>(p),
|
||||||
static_cast<int32_t>(capacity));
|
static_cast<int32_t>(capacity));
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void*
|
virtual void* getDirectBufferAddress(Thread* t, object b)
|
||||||
getDirectBufferAddress(Thread* t, object b)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, b);
|
PROTECT(t, b);
|
||||||
|
|
||||||
@ -178,8 +172,7 @@ class MyClasspath : public Classpath {
|
|||||||
return reinterpret_cast<void*>(fieldAtOffset<int64_t>(b, field->offset()));
|
return reinterpret_cast<void*>(fieldAtOffset<int64_t>(b, field->offset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int64_t
|
virtual int64_t getDirectBufferCapacity(Thread* t, object b)
|
||||||
getDirectBufferCapacity(Thread* t, object b)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, b);
|
PROTECT(t, b);
|
||||||
|
|
||||||
@ -219,14 +212,12 @@ class MyClasspath : public Classpath {
|
|||||||
: caller->class_()->loader();
|
: caller->class_()->loader();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void shutDown(Thread*)
|
||||||
shutDown(Thread*)
|
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void dispose()
|
||||||
dispose()
|
|
||||||
{
|
{
|
||||||
allocator->free(this, sizeof(*this));
|
allocator->free(this, sizeof(*this));
|
||||||
}
|
}
|
||||||
@ -242,11 +233,13 @@ void enumerateThreads(Thread* t,
|
|||||||
{
|
{
|
||||||
if (*index < limit) {
|
if (*index < limit) {
|
||||||
array->setBodyElement(t, *index, x->javaThread);
|
array->setBodyElement(t, *index, x->javaThread);
|
||||||
++ (*index);
|
++(*index);
|
||||||
|
|
||||||
if (x->peer) enumerateThreads(t, x->peer, array, index, limit);
|
if (x->peer)
|
||||||
|
enumerateThreads(t, x->peer, array, index, limit);
|
||||||
|
|
||||||
if (x->child) enumerateThreads(t, x->child, array, index, limit);
|
if (x->child)
|
||||||
|
enumerateThreads(t, x->child, array, index, limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,8 +249,10 @@ void enumerateThreads(Thread* t,
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
Classpath*
|
Classpath* makeClasspath(System*,
|
||||||
makeClasspath(System*, Allocator* allocator, const char*, const char*)
|
Allocator* allocator,
|
||||||
|
const char*,
|
||||||
|
const char*)
|
||||||
{
|
{
|
||||||
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
||||||
local::MyClasspath(allocator);
|
local::MyClasspath(allocator);
|
||||||
@ -266,8 +261,7 @@ makeClasspath(System*, Allocator* allocator, const char*, const char*)
|
|||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Object_toString
|
Avian_java_lang_Object_toString(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
@ -279,26 +273,24 @@ Avian_java_lang_Object_toString
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Object_getVMClass
|
Avian_java_lang_Object_getVMClass(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(
|
||||||
(objectClass(t, reinterpret_cast<object>(arguments[0])));
|
objectClass(t, reinterpret_cast<object>(arguments[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_Object_wait
|
Avian_java_lang_Object_wait(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
int64_t milliseconds; memcpy(&milliseconds, arguments + 1, 8);
|
int64_t milliseconds;
|
||||||
|
memcpy(&milliseconds, arguments + 1, 8);
|
||||||
|
|
||||||
vm::wait(t, this_, milliseconds);
|
vm::wait(t, this_, milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_Object_notify
|
Avian_java_lang_Object_notify(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
@ -306,8 +298,7 @@ Avian_java_lang_Object_notify
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_Object_notifyAll
|
Avian_java_lang_Object_notifyAll(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
@ -315,8 +306,7 @@ Avian_java_lang_Object_notifyAll
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Object_hashCode
|
Avian_java_lang_Object_hashCode(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
@ -324,16 +314,16 @@ Avian_java_lang_Object_hashCode
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Object_clone
|
Avian_java_lang_Object_clone(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(
|
||||||
(clone(t, reinterpret_cast<object>(arguments[0])));
|
clone(t, reinterpret_cast<object>(arguments[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_io_ObjectInputStream_makeInstance
|
Avian_java_io_ObjectInputStream_makeInstance(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClass* c = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
|
GcClass* c = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
|
|
||||||
@ -341,15 +331,17 @@ Avian_java_io_ObjectInputStream_makeInstance
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_LegacyObjectInputStream_makeInstance
|
Avian_avian_LegacyObjectInputStream_makeInstance(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return Avian_java_io_ObjectInputStream_makeInstance(t, NULL, arguments);
|
return Avian_java_io_ObjectInputStream_makeInstance(t, NULL, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Field_getPrimitive
|
Avian_java_lang_reflect_Field_getPrimitive(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object instance = reinterpret_cast<object>(arguments[0]);
|
object instance = reinterpret_cast<object>(arguments[0]);
|
||||||
int code = arguments[1];
|
int code = arguments[1];
|
||||||
@ -378,8 +370,9 @@ Avian_java_lang_reflect_Field_getPrimitive
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Field_getObject
|
Avian_java_lang_reflect_Field_getObject(Thread*,
|
||||||
(Thread*, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object instance = reinterpret_cast<object>(arguments[0]);
|
object instance = reinterpret_cast<object>(arguments[0]);
|
||||||
int offset = arguments[1];
|
int offset = arguments[1];
|
||||||
@ -388,13 +381,15 @@ Avian_java_lang_reflect_Field_getObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_reflect_Field_setPrimitive
|
Avian_java_lang_reflect_Field_setPrimitive(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object instance = reinterpret_cast<object>(arguments[0]);
|
object instance = reinterpret_cast<object>(arguments[0]);
|
||||||
int code = arguments[1];
|
int code = arguments[1];
|
||||||
int offset = arguments[2];
|
int offset = arguments[2];
|
||||||
int64_t value; memcpy(&value, arguments + 3, 8);
|
int64_t value;
|
||||||
|
memcpy(&value, arguments + 3, 8);
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case ByteField:
|
case ByteField:
|
||||||
@ -427,8 +422,9 @@ Avian_java_lang_reflect_Field_setPrimitive
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_reflect_Field_setObject
|
Avian_java_lang_reflect_Field_setObject(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object instance = reinterpret_cast<object>(arguments[0]);
|
object instance = reinterpret_cast<object>(arguments[0]);
|
||||||
int offset = arguments[1];
|
int offset = arguments[1];
|
||||||
@ -438,8 +434,9 @@ Avian_java_lang_reflect_Field_setObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Constructor_make
|
Avian_java_lang_reflect_Constructor_make(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClass* c = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
|
GcClass* c = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
|
|
||||||
@ -447,15 +444,15 @@ Avian_java_lang_reflect_Constructor_make
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Method_getCaller
|
Avian_java_lang_reflect_Method_getCaller(Thread* t, object, uintptr_t*)
|
||||||
(Thread* t, object, uintptr_t*)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>(getCaller(t, 2));
|
return reinterpret_cast<int64_t>(getCaller(t, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Method_invoke
|
Avian_java_lang_reflect_Method_invoke(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcMethod* method = cast<GcMethod>(t, reinterpret_cast<object>(arguments[0]));
|
GcMethod* method = cast<GcMethod>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
object instance = reinterpret_cast<object>(arguments[1]);
|
object instance = reinterpret_cast<object>(arguments[1]);
|
||||||
@ -471,14 +468,14 @@ Avian_java_lang_reflect_Method_invoke
|
|||||||
|
|
||||||
unsigned returnCode = method->returnCode();
|
unsigned returnCode = method->returnCode();
|
||||||
|
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(translateInvokeResult(
|
||||||
(translateInvokeResult
|
t, returnCode, t->m->processor->invokeArray(t, method, instance, args)));
|
||||||
(t, returnCode, t->m->processor->invokeArray(t, method, instance, args)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Array_getLength
|
Avian_java_lang_reflect_Array_getLength(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object array = reinterpret_cast<object>(arguments[0]);
|
object array = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
@ -496,8 +493,9 @@ Avian_java_lang_reflect_Array_getLength
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_reflect_Array_makeObjectArray
|
Avian_java_lang_reflect_Array_makeObjectArray(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcJclass* elementType
|
GcJclass* elementType
|
||||||
= cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]));
|
= cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
@ -508,38 +506,41 @@ Avian_java_lang_reflect_Array_makeObjectArray
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Float_floatToRawIntBits
|
Avian_java_lang_Float_floatToRawIntBits(Thread*,
|
||||||
(Thread*, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return static_cast<int32_t>(*arguments);
|
return static_cast<int32_t>(*arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Float_intBitsToFloat
|
Avian_java_lang_Float_intBitsToFloat(Thread*, object, uintptr_t* arguments)
|
||||||
(Thread*, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
return static_cast<int32_t>(*arguments);
|
return static_cast<int32_t>(*arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Double_doubleToRawLongBits
|
Avian_java_lang_Double_doubleToRawLongBits(Thread*,
|
||||||
(Thread*, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
int64_t v; memcpy(&v, arguments, 8);
|
int64_t v;
|
||||||
|
memcpy(&v, arguments, 8);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Double_longBitsToDouble
|
Avian_java_lang_Double_longBitsToDouble(Thread*,
|
||||||
(Thread*, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
int64_t v; memcpy(&v, arguments, 8);
|
int64_t v;
|
||||||
|
memcpy(&v, arguments, 8);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_String_intern
|
Avian_java_lang_String_intern(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
@ -562,10 +563,10 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_System_arraycopy
|
Avian_java_lang_System_arraycopy(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
arrayCopy(t, reinterpret_cast<object>(arguments[0]),
|
arrayCopy(t,
|
||||||
|
reinterpret_cast<object>(arguments[0]),
|
||||||
arguments[1],
|
arguments[1],
|
||||||
reinterpret_cast<object>(arguments[2]),
|
reinterpret_cast<object>(arguments[2]),
|
||||||
arguments[3],
|
arguments[3],
|
||||||
@ -573,8 +574,9 @@ Avian_java_lang_System_arraycopy
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_System_identityHashCode
|
Avian_java_lang_System_identityHashCode(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object o = reinterpret_cast<object>(arguments[0]);
|
object o = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
@ -612,15 +614,15 @@ extern "C" AVIAN_EXPORT void JNICALL
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_Runtime_gc
|
Avian_java_lang_Runtime_gc(Thread* t, object, uintptr_t*)
|
||||||
(Thread* t, object, uintptr_t*)
|
|
||||||
{
|
{
|
||||||
collect(t, Heap::MajorCollection);
|
collect(t, Heap::MajorCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_Runtime_addShutdownHook
|
Avian_java_lang_Runtime_addShutdownHook(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object hook = reinterpret_cast<object>(arguments[1]);
|
object hook = reinterpret_cast<object>(arguments[1]);
|
||||||
PROTECT(t, hook);
|
PROTECT(t, hook);
|
||||||
@ -633,15 +635,15 @@ Avian_java_lang_Runtime_addShutdownHook
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Throwable_trace
|
Avian_java_lang_Throwable_trace(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>(getTrace(t, arguments[0]));
|
return reinterpret_cast<int64_t>(getTrace(t, arguments[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Throwable_resolveTrace
|
Avian_java_lang_Throwable_resolveTrace(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object trace = reinterpret_cast<object>(*arguments);
|
object trace = reinterpret_cast<object>(*arguments);
|
||||||
PROTECT(t, trace);
|
PROTECT(t, trace);
|
||||||
@ -661,63 +663,61 @@ Avian_java_lang_Throwable_resolveTrace
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Thread_currentThread
|
Avian_java_lang_Thread_currentThread(Thread* t, object, uintptr_t*)
|
||||||
(Thread* t, object, uintptr_t*)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>(t->javaThread);
|
return reinterpret_cast<int64_t>(t->javaThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Thread_doStart
|
Avian_java_lang_Thread_doStart(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>(
|
return reinterpret_cast<int64_t>(
|
||||||
startThread(t, cast<GcThread>(t, reinterpret_cast<object>(*arguments))));
|
startThread(t, cast<GcThread>(t, reinterpret_cast<object>(*arguments))));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_Thread_interrupt
|
Avian_java_lang_Thread_interrupt(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
int64_t peer; memcpy(&peer, arguments, 8);
|
int64_t peer;
|
||||||
|
memcpy(&peer, arguments, 8);
|
||||||
|
|
||||||
threadInterrupt(t, reinterpret_cast<Thread*>(peer)->javaThread);
|
threadInterrupt(t, reinterpret_cast<Thread*>(peer)->javaThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Thread_interrupted
|
Avian_java_lang_Thread_interrupted(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
int64_t peer; memcpy(&peer, arguments, 8);
|
int64_t peer;
|
||||||
|
memcpy(&peer, arguments, 8);
|
||||||
|
|
||||||
return threadIsInterrupted
|
return threadIsInterrupted(
|
||||||
(t, reinterpret_cast<Thread*>(peer)->javaThread, true);
|
t, reinterpret_cast<Thread*>(peer)->javaThread, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Thread_getStackTrace
|
Avian_java_lang_Thread_getStackTrace(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
int64_t peer; memcpy(&peer, arguments, 8);
|
int64_t peer;
|
||||||
|
memcpy(&peer, arguments, 8);
|
||||||
|
|
||||||
if (reinterpret_cast<Thread*>(peer) == t) {
|
if (reinterpret_cast<Thread*>(peer) == t) {
|
||||||
return reinterpret_cast<int64_t>(makeTrace(t));
|
return reinterpret_cast<int64_t>(makeTrace(t));
|
||||||
} else {
|
} else {
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(
|
||||||
(t->m->processor->getStackTrace(t, reinterpret_cast<Thread*>(peer)));
|
t->m->processor->getStackTrace(t, reinterpret_cast<Thread*>(peer)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Thread_activeCount
|
Avian_java_lang_Thread_activeCount(Thread* t, object, uintptr_t*)
|
||||||
(Thread* t, object, uintptr_t*)
|
|
||||||
{
|
{
|
||||||
return t->m->liveCount;
|
return t->m->liveCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_Thread_enumerate
|
Avian_java_lang_Thread_enumerate(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
GcArray* array = cast<GcArray>(t, reinterpret_cast<object>(*arguments));
|
GcArray* array = cast<GcArray>(t, reinterpret_cast<object>(*arguments));
|
||||||
|
|
||||||
@ -731,15 +731,13 @@ Avian_java_lang_Thread_enumerate
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
Avian_java_lang_Thread_yield
|
Avian_java_lang_Thread_yield(Thread* t, object, uintptr_t*)
|
||||||
(Thread* t, object, uintptr_t*)
|
|
||||||
{
|
{
|
||||||
t->m->system->yield();
|
t->m->system->yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_Atomic_getOffset
|
Avian_avian_Atomic_getOffset(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[0]))
|
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[0]))
|
||||||
->vmField()
|
->vmField()
|
||||||
@ -747,8 +745,9 @@ Avian_avian_Atomic_getOffset
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_sun_misc_Unsafe_objectFieldOffset
|
Avian_sun_misc_Unsafe_objectFieldOffset(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[1]))
|
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[1]))
|
||||||
->vmField()
|
->vmField()
|
||||||
@ -756,16 +755,18 @@ Avian_sun_misc_Unsafe_objectFieldOffset
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_Atomic_compareAndSwapObject
|
Avian_avian_Atomic_compareAndSwapObject(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
object target = reinterpret_cast<object>(arguments[0]);
|
object target = reinterpret_cast<object>(arguments[0]);
|
||||||
int64_t offset; memcpy(&offset, arguments + 1, 8);
|
int64_t offset;
|
||||||
|
memcpy(&offset, arguments + 1, 8);
|
||||||
uintptr_t expect = arguments[3];
|
uintptr_t expect = arguments[3];
|
||||||
uintptr_t update = arguments[4];
|
uintptr_t update = arguments[4];
|
||||||
|
|
||||||
bool success = atomicCompareAndSwap
|
bool success = atomicCompareAndSwap(
|
||||||
(&fieldAtOffset<uintptr_t>(target, offset), expect, update);
|
&fieldAtOffset<uintptr_t>(target, offset), expect, update);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
mark(t, target, offset);
|
mark(t, target, offset);
|
||||||
@ -775,8 +776,9 @@ Avian_avian_Atomic_compareAndSwapObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_Classes_isAssignableFrom
|
Avian_avian_Classes_isAssignableFrom(Thread* t,
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
object,
|
||||||
|
uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClass* this_ = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
|
GcClass* this_ = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
GcClass* that = cast<GcClass>(t, reinterpret_cast<object>(arguments[1]));
|
GcClass* that = cast<GcClass>(t, reinterpret_cast<object>(arguments[1]));
|
||||||
@ -789,16 +791,14 @@ Avian_avian_Classes_isAssignableFrom
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_Classes_getVMClass
|
Avian_avian_Classes_getVMClass(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(
|
||||||
(objectClass(t, reinterpret_cast<object>(arguments[0])));
|
objectClass(t, reinterpret_cast<object>(arguments[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_Classes_makeMethod
|
Avian_avian_Classes_makeMethod(Thread* t, object, uintptr_t* arguments)
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
|
||||||
{
|
{
|
||||||
GcMethod* method = cast<GcMethod>(
|
GcMethod* method = cast<GcMethod>(
|
||||||
t,
|
t,
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -53,14 +53,18 @@ Context::Context(vm::System* system,
|
|||||||
- regFile->generalRegisters.start),
|
- regFile->generalRegisters.start),
|
||||||
targetInfo(arch->targetInfo())
|
targetInfo(arch->targetInfo())
|
||||||
{
|
{
|
||||||
for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) {
|
for (unsigned i = regFile->generalRegisters.start;
|
||||||
|
i < regFile->generalRegisters.limit;
|
||||||
|
++i) {
|
||||||
new (registerResources + i) RegisterResource(arch->reserved(i));
|
new (registerResources + i) RegisterResource(arch->reserved(i));
|
||||||
|
|
||||||
if (registerResources[i].reserved) {
|
if (registerResources[i].reserved) {
|
||||||
-- availableGeneralRegisterCount;
|
--availableGeneralRegisterCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (unsigned i = regFile->floatRegisters.start; i < regFile->floatRegisters.limit; ++i) {
|
for (unsigned i = regFile->floatRegisters.start;
|
||||||
|
i < regFile->floatRegisters.limit;
|
||||||
|
++i) {
|
||||||
new (registerResources + i) RegisterResource(arch->reserved(i));
|
new (registerResources + i) RegisterResource(arch->reserved(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,9 @@ class ConstantPoolNode;
|
|||||||
class ForkState;
|
class ForkState;
|
||||||
class Block;
|
class Block;
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
List<T>* reverseDestroy(List<T>* cell) {
|
List<T>* reverseDestroy(List<T>* cell)
|
||||||
|
{
|
||||||
List<T>* previous = 0;
|
List<T>* previous = 0;
|
||||||
while (cell) {
|
while (cell) {
|
||||||
List<T>* next = cell->next;
|
List<T>* next = cell->next;
|
||||||
@ -93,7 +94,9 @@ class LogicalCode {
|
|||||||
|
|
||||||
class Context {
|
class Context {
|
||||||
public:
|
public:
|
||||||
Context(vm::System* system, Assembler* assembler, vm::Zone* zone,
|
Context(vm::System* system,
|
||||||
|
Assembler* assembler,
|
||||||
|
vm::Zone* zone,
|
||||||
Compiler::Client* client);
|
Compiler::Client* client);
|
||||||
|
|
||||||
vm::System* system;
|
vm::System* system;
|
||||||
@ -128,12 +131,14 @@ class Context {
|
|||||||
ir::TargetInfo targetInfo;
|
ir::TargetInfo targetInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Aborter* getAborter(Context* c) {
|
inline Aborter* getAborter(Context* c)
|
||||||
|
{
|
||||||
return c->system;
|
return c->system;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
List<T>* cons(Context* c, const T& value, List<T>* next) {
|
List<T>* cons(Context* c, const T& value, List<T>* next)
|
||||||
|
{
|
||||||
return new (c->zone) List<T>(value, next);
|
return new (c->zone) List<T>(value, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -33,25 +33,41 @@ class Event {
|
|||||||
|
|
||||||
virtual void compile(Context* c) = 0;
|
virtual void compile(Context* c) = 0;
|
||||||
|
|
||||||
virtual bool isBranch() { return false; }
|
virtual bool isBranch()
|
||||||
|
{
|
||||||
virtual bool allExits() { return false; }
|
return false;
|
||||||
|
}
|
||||||
virtual Local* locals() { return localsBefore; }
|
|
||||||
|
|
||||||
|
virtual bool allExits()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Local* locals()
|
||||||
|
{
|
||||||
|
return localsBefore;
|
||||||
|
}
|
||||||
|
|
||||||
void addRead(Context* c, Value* v, Read* r);
|
void addRead(Context* c, Value* v, Read* r);
|
||||||
|
|
||||||
void addRead(Context* c, Value* v, const SiteMask& mask,
|
void addRead(Context* c,
|
||||||
|
Value* v,
|
||||||
|
const SiteMask& mask,
|
||||||
Value* successor = 0);
|
Value* successor = 0);
|
||||||
|
|
||||||
void addReads(Context* c, Value* v, unsigned size,
|
void addReads(Context* c,
|
||||||
const SiteMask& lowMask, Value* lowSuccessor,
|
Value* v,
|
||||||
const SiteMask& highMask, Value* highSuccessor);
|
unsigned size,
|
||||||
|
const SiteMask& lowMask,
|
||||||
|
Value* lowSuccessor,
|
||||||
|
const SiteMask& highMask,
|
||||||
|
Value* highSuccessor);
|
||||||
|
|
||||||
void addReads(Context* c, Value* v, unsigned size,
|
void addReads(Context* c,
|
||||||
const SiteMask& lowMask, const SiteMask& highMask);
|
Value* v,
|
||||||
|
unsigned size,
|
||||||
|
const SiteMask& lowMask,
|
||||||
|
const SiteMask& highMask);
|
||||||
|
|
||||||
CodePromise* makeCodePromise(Context* c);
|
CodePromise* makeCodePromise(Context* c);
|
||||||
|
|
||||||
@ -82,7 +98,9 @@ class StubReadPair {
|
|||||||
|
|
||||||
class JunctionState {
|
class JunctionState {
|
||||||
public:
|
public:
|
||||||
JunctionState(unsigned frameFootprint): frameFootprint(frameFootprint) { }
|
JunctionState(unsigned frameFootprint) : frameFootprint(frameFootprint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsigned frameFootprint;
|
unsigned frameFootprint;
|
||||||
StubReadPair reads[0];
|
StubReadPair reads[0];
|
||||||
@ -90,12 +108,19 @@ class JunctionState {
|
|||||||
|
|
||||||
class Link {
|
class Link {
|
||||||
public:
|
public:
|
||||||
Link(Event* predecessor, Link* nextPredecessor, Event* successor,
|
Link(Event* predecessor,
|
||||||
Link* nextSuccessor, ForkState* forkState):
|
Link* nextPredecessor,
|
||||||
predecessor(predecessor), nextPredecessor(nextPredecessor),
|
Event* successor,
|
||||||
successor(successor), nextSuccessor(nextSuccessor), forkState(forkState),
|
Link* nextSuccessor,
|
||||||
|
ForkState* forkState)
|
||||||
|
: predecessor(predecessor),
|
||||||
|
nextPredecessor(nextPredecessor),
|
||||||
|
successor(successor),
|
||||||
|
nextSuccessor(nextSuccessor),
|
||||||
|
forkState(forkState),
|
||||||
junctionState(0)
|
junctionState(0)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsigned countPredecessors();
|
unsigned countPredecessors();
|
||||||
Link* lastPredecessor();
|
Link* lastPredecessor();
|
||||||
@ -109,9 +134,12 @@ class Link {
|
|||||||
JunctionState* junctionState;
|
JunctionState* junctionState;
|
||||||
};
|
};
|
||||||
|
|
||||||
Link*
|
Link* link(Context* c,
|
||||||
link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor,
|
Event* predecessor,
|
||||||
Link* nextSuccessor, ForkState* forkState);
|
Link* nextPredecessor,
|
||||||
|
Event* successor,
|
||||||
|
Link* nextSuccessor,
|
||||||
|
ForkState* forkState);
|
||||||
|
|
||||||
void appendCall(Context* c,
|
void appendCall(Context* c,
|
||||||
Value* address,
|
Value* address,
|
||||||
@ -142,12 +170,14 @@ void appendTranslate(Context* c,
|
|||||||
Value* first,
|
Value* first,
|
||||||
Value* result);
|
Value* result);
|
||||||
|
|
||||||
void
|
void appendOperation(Context* c, lir::Operation op);
|
||||||
appendOperation(Context* c, lir::Operation op);
|
|
||||||
|
|
||||||
void
|
void appendMemory(Context* c,
|
||||||
appendMemory(Context* c, Value* base, int displacement, Value* index,
|
Value* base,
|
||||||
unsigned scale, Value* result);
|
int displacement,
|
||||||
|
Value* index,
|
||||||
|
unsigned scale,
|
||||||
|
Value* result);
|
||||||
|
|
||||||
void appendBranch(Context* c,
|
void appendBranch(Context* c,
|
||||||
lir::TernaryOperation op,
|
lir::TernaryOperation op,
|
||||||
@ -161,18 +191,17 @@ void appendJump(Context* c,
|
|||||||
bool exit = false,
|
bool exit = false,
|
||||||
bool cleanLocals = false);
|
bool cleanLocals = false);
|
||||||
|
|
||||||
void
|
void appendBoundsCheck(Context* c,
|
||||||
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
|
Value* object,
|
||||||
Value* index, intptr_t handler);
|
unsigned lengthOffset,
|
||||||
|
Value* index,
|
||||||
|
intptr_t handler);
|
||||||
|
|
||||||
void
|
void appendFrameSite(Context* c, Value* value, int index);
|
||||||
appendFrameSite(Context* c, Value* value, int index);
|
|
||||||
|
|
||||||
void
|
void appendSaveLocals(Context* c);
|
||||||
appendSaveLocals(Context* c);
|
|
||||||
|
|
||||||
void
|
void appendDummy(Context* c);
|
||||||
appendDummy(Context* c);
|
|
||||||
|
|
||||||
void appendBuddy(Context* c, Value* original, Value* buddy);
|
void appendBuddy(Context* c, Value* original, Value* buddy);
|
||||||
|
|
||||||
|
@ -19,13 +19,14 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
unsigned totalFrameSize(Context* c) {
|
unsigned totalFrameSize(Context* c)
|
||||||
return c->alignedFrameSize
|
{
|
||||||
+ c->arch->frameHeaderSize()
|
return c->alignedFrameSize + c->arch->frameHeaderSize()
|
||||||
+ c->arch->argumentFootprint(c->parameterFootprint);
|
+ c->arch->argumentFootprint(c->parameterFootprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
int frameIndex(Context* c, int localIndex) {
|
int frameIndex(Context* c, int localIndex)
|
||||||
|
{
|
||||||
assertT(c, localIndex >= 0);
|
assertT(c, localIndex >= 0);
|
||||||
|
|
||||||
int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1;
|
int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1;
|
||||||
@ -42,13 +43,15 @@ int frameIndex(Context* c, int localIndex) {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned frameIndexToOffset(Context* c, unsigned frameIndex) {
|
unsigned frameIndexToOffset(Context* c, unsigned frameIndex)
|
||||||
|
{
|
||||||
assertT(c, frameIndex < totalFrameSize(c));
|
assertT(c, frameIndex < totalFrameSize(c));
|
||||||
|
|
||||||
return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize;
|
return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned offsetToFrameIndex(Context* c, unsigned offset) {
|
unsigned offsetToFrameIndex(Context* c, unsigned offset)
|
||||||
|
{
|
||||||
assertT(c,
|
assertT(c,
|
||||||
static_cast<int>((offset / c->targetInfo.pointerSize)
|
static_cast<int>((offset / c->targetInfo.pointerSize)
|
||||||
- c->arch->frameFooterSize()) >= 0);
|
- c->arch->frameFooterSize()) >= 0);
|
||||||
@ -59,43 +62,50 @@ unsigned offsetToFrameIndex(Context* c, unsigned offset) {
|
|||||||
return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize();
|
return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned frameBase(Context* c) {
|
unsigned frameBase(Context* c)
|
||||||
return c->alignedFrameSize
|
{
|
||||||
- c->arch->frameReturnAddressSize()
|
return c->alignedFrameSize - c->arch->frameReturnAddressSize()
|
||||||
- c->arch->frameFooterSize()
|
- c->arch->frameFooterSize() + c->arch->frameHeaderSize();
|
||||||
+ c->arch->frameHeaderSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameIterator::Element::Element(Value* value, unsigned localIndex):
|
FrameIterator::Element::Element(Value* value, unsigned localIndex)
|
||||||
value(value), localIndex(localIndex)
|
: value(value), localIndex(localIndex)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int FrameIterator::Element::frameIndex(Context* c)
|
||||||
int FrameIterator::Element::frameIndex(Context* c) {
|
{
|
||||||
return compiler::frameIndex(c, this->localIndex);
|
return compiler::frameIndex(c, this->localIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameIterator::FrameIterator(Context* c, Stack* stack, Local* locals,
|
FrameIterator::FrameIterator(Context* c,
|
||||||
bool includeEmpty):
|
Stack* stack,
|
||||||
stack(stack), locals(locals), localIndex(c->localFootprint - 1),
|
Local* locals,
|
||||||
|
bool includeEmpty)
|
||||||
|
: stack(stack),
|
||||||
|
locals(locals),
|
||||||
|
localIndex(c->localFootprint - 1),
|
||||||
includeEmpty(includeEmpty)
|
includeEmpty(includeEmpty)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool FrameIterator::hasMore() {
|
bool FrameIterator::hasMore()
|
||||||
|
{
|
||||||
if (not includeEmpty) {
|
if (not includeEmpty) {
|
||||||
while (stack and stack->value == 0) {
|
while (stack and stack->value == 0) {
|
||||||
stack = stack->next;
|
stack = stack->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (localIndex >= 0 and locals[localIndex].value == 0) {
|
while (localIndex >= 0 and locals[localIndex].value == 0) {
|
||||||
-- localIndex;
|
--localIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stack != 0 or localIndex >= 0;
|
return stack != 0 or localIndex >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameIterator::Element FrameIterator::next(Context* c) {
|
FrameIterator::Element FrameIterator::next(Context* c)
|
||||||
|
{
|
||||||
Value* v;
|
Value* v;
|
||||||
unsigned li;
|
unsigned li;
|
||||||
if (stack) {
|
if (stack) {
|
||||||
@ -107,17 +117,16 @@ FrameIterator::Element FrameIterator::next(Context* c) {
|
|||||||
Local* l = locals + localIndex;
|
Local* l = locals + localIndex;
|
||||||
v = l->value;
|
v = l->value;
|
||||||
li = localIndex;
|
li = localIndex;
|
||||||
-- localIndex;
|
--localIndex;
|
||||||
}
|
}
|
||||||
return Element(v, li);
|
return Element(v, li);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack* stack(Context* c, Value* value, Stack* next) {
|
Stack* stack(Context* c, Value* value, Stack* next)
|
||||||
return new(c->zone) Stack(next ? next->index + 1 : 0, value, next);
|
{
|
||||||
|
return new (c->zone) Stack(next ? next->index + 1 : 0, value, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -37,7 +37,9 @@ class FrameIterator {
|
|||||||
const unsigned localIndex;
|
const unsigned localIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
FrameIterator(Context* c, Stack* stack, Local* locals,
|
FrameIterator(Context* c,
|
||||||
|
Stack* stack,
|
||||||
|
Local* locals,
|
||||||
bool includeEmpty = false);
|
bool includeEmpty = false);
|
||||||
|
|
||||||
bool hasMore();
|
bool hasMore();
|
||||||
@ -57,9 +59,10 @@ class Local {
|
|||||||
|
|
||||||
class Stack {
|
class Stack {
|
||||||
public:
|
public:
|
||||||
Stack(unsigned index, Value* value, Stack* next):
|
Stack(unsigned index, Value* value, Stack* next)
|
||||||
index(index), value(value), next(next)
|
: index(index), value(value), next(next)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsigned index;
|
unsigned index;
|
||||||
Value* value;
|
Value* value;
|
||||||
|
@ -23,29 +23,33 @@ LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals)
|
|||||||
locals(locals),
|
locals(locals),
|
||||||
machineOffset(0),
|
machineOffset(0),
|
||||||
/*subroutine(0), */ index(index)
|
/*subroutine(0), */ index(index)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
LogicalInstruction* LogicalInstruction::next(Context* c) {
|
LogicalInstruction* LogicalInstruction::next(Context* c)
|
||||||
|
{
|
||||||
LogicalInstruction* i = this;
|
LogicalInstruction* i = this;
|
||||||
for (size_t n = i->index + 1; n < c->logicalCode.count(); ++n) {
|
for (size_t n = i->index + 1; n < c->logicalCode.count(); ++n) {
|
||||||
i = c->logicalCode[n];
|
i = c->logicalCode[n];
|
||||||
if (i) return i;
|
if (i)
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned machineOffset(Context* c, int logicalIp)
|
||||||
machineOffset(Context* c, int logicalIp)
|
|
||||||
{
|
{
|
||||||
return c->logicalCode[logicalIp]->machineOffset->value();
|
return c->logicalCode[logicalIp]->machineOffset->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
Block::Block(Event* head):
|
Block::Block(Event* head)
|
||||||
head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
|
: head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Block* block(Context* c, Event* head) {
|
Block* block(Context* c, Event* head)
|
||||||
return new(c->zone) Block(head);
|
{
|
||||||
|
return new (c->zone) Block(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
@ -24,17 +24,21 @@ class ForkElement {
|
|||||||
bool local;
|
bool local;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ForkState: public Compiler::State {
|
class ForkState : public Compiler::State {
|
||||||
public:
|
public:
|
||||||
ForkState(Stack* stack, Local* locals, List<Value*>* saved, Event* predecessor,
|
ForkState(Stack* stack,
|
||||||
unsigned logicalIp):
|
Local* locals,
|
||||||
stack(stack),
|
List<Value*>* saved,
|
||||||
|
Event* predecessor,
|
||||||
|
unsigned logicalIp)
|
||||||
|
: stack(stack),
|
||||||
locals(locals),
|
locals(locals),
|
||||||
saved(saved),
|
saved(saved),
|
||||||
predecessor(predecessor),
|
predecessor(predecessor),
|
||||||
logicalIp(logicalIp),
|
logicalIp(logicalIp),
|
||||||
readCount(0)
|
readCount(0)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Stack* stack;
|
Stack* stack;
|
||||||
Local* locals;
|
Local* locals;
|
||||||
|
@ -18,15 +18,18 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
CodePromise::CodePromise(Context* c, CodePromise* next):
|
CodePromise::CodePromise(Context* c, CodePromise* next)
|
||||||
c(c), offset(0), next(next)
|
: c(c), offset(0), next(next)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
CodePromise::CodePromise(Context* c, Promise* offset):
|
CodePromise::CodePromise(Context* c, Promise* offset)
|
||||||
c(c), offset(offset), next(0)
|
: c(c), offset(offset), next(0)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int64_t CodePromise::value() {
|
int64_t CodePromise::value()
|
||||||
|
{
|
||||||
if (resolved()) {
|
if (resolved()) {
|
||||||
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
|
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
|
||||||
}
|
}
|
||||||
@ -34,43 +37,52 @@ int64_t CodePromise::value() {
|
|||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CodePromise::resolved() {
|
bool CodePromise::resolved()
|
||||||
|
{
|
||||||
return c->machineCode != 0 and offset and offset->resolved();
|
return c->machineCode != 0 and offset and offset->resolved();
|
||||||
}
|
}
|
||||||
|
|
||||||
CodePromise* codePromise(Context* c, Promise* offset) {
|
CodePromise* codePromise(Context* c, Promise* offset)
|
||||||
|
{
|
||||||
return new (c->zone) CodePromise(c, offset);
|
return new (c->zone) CodePromise(c, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) {
|
Promise* shiftMaskPromise(Context* c,
|
||||||
|
Promise* base,
|
||||||
|
unsigned shift,
|
||||||
|
int64_t mask)
|
||||||
|
{
|
||||||
return new (c->zone) ShiftMaskPromise(base, shift, mask);
|
return new (c->zone) ShiftMaskPromise(base, shift, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high) {
|
Promise* combinedPromise(Context* c, Promise* low, Promise* high)
|
||||||
|
{
|
||||||
return new (c->zone) CombinedPromise(low, high);
|
return new (c->zone) CombinedPromise(low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise* resolvedPromise(Context* c, int64_t value) {
|
Promise* resolvedPromise(Context* c, int64_t value)
|
||||||
|
{
|
||||||
return new (c->zone) ResolvedPromise(value);
|
return new (c->zone) ResolvedPromise(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
class IpPromise: public Promise {
|
class IpPromise : public Promise {
|
||||||
public:
|
public:
|
||||||
IpPromise(Context* c, int logicalIp):
|
IpPromise(Context* c, int logicalIp) : c(c), logicalIp(logicalIp)
|
||||||
c(c),
|
{
|
||||||
logicalIp(logicalIp)
|
}
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value()
|
||||||
|
{
|
||||||
if (resolved()) {
|
if (resolved()) {
|
||||||
return reinterpret_cast<intptr_t>
|
return reinterpret_cast<intptr_t>(c->machineCode
|
||||||
(c->machineCode + machineOffset(c, logicalIp));
|
+ machineOffset(c, logicalIp));
|
||||||
}
|
}
|
||||||
|
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved()
|
||||||
|
{
|
||||||
return c->machineCode != 0
|
return c->machineCode != 0
|
||||||
and c->logicalCode[logicalIp]->machineOffset->resolved();
|
and c->logicalCode[logicalIp]->machineOffset->resolved();
|
||||||
}
|
}
|
||||||
@ -79,16 +91,19 @@ class IpPromise: public Promise {
|
|||||||
int logicalIp;
|
int logicalIp;
|
||||||
};
|
};
|
||||||
|
|
||||||
Promise* ipPromise(Context* c, int logicalIp) {
|
Promise* ipPromise(Context* c, int logicalIp)
|
||||||
|
{
|
||||||
return new (c->zone) IpPromise(c, logicalIp);
|
return new (c->zone) IpPromise(c, logicalIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PoolPromise : public Promise {
|
||||||
class PoolPromise: public Promise {
|
|
||||||
public:
|
public:
|
||||||
PoolPromise(Context* c, int key): c(c), key(key) { }
|
PoolPromise(Context* c, int key) : c(c), key(key)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value()
|
||||||
|
{
|
||||||
if (resolved()) {
|
if (resolved()) {
|
||||||
return reinterpret_cast<int64_t>(
|
return reinterpret_cast<int64_t>(
|
||||||
c->machineCode
|
c->machineCode
|
||||||
@ -99,7 +114,8 @@ class PoolPromise: public Promise {
|
|||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved()
|
||||||
|
{
|
||||||
return c->machineCode != 0;
|
return c->machineCode != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,11 +123,11 @@ class PoolPromise: public Promise {
|
|||||||
int key;
|
int key;
|
||||||
};
|
};
|
||||||
|
|
||||||
Promise* poolPromise(Context* c, int key) {
|
Promise* poolPromise(Context* c, int key)
|
||||||
return new(c->zone) PoolPromise(c, key);
|
{
|
||||||
|
return new (c->zone) PoolPromise(c, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -15,8 +15,7 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
|
class CodePromise : public Promise {
|
||||||
class CodePromise: public Promise {
|
|
||||||
public:
|
public:
|
||||||
CodePromise(Context* c, CodePromise* next);
|
CodePromise(Context* c, CodePromise* next);
|
||||||
|
|
||||||
@ -33,7 +32,10 @@ class CodePromise: public Promise {
|
|||||||
|
|
||||||
CodePromise* codePromise(Context* c, Promise* offset);
|
CodePromise* codePromise(Context* c, Promise* offset);
|
||||||
|
|
||||||
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask);
|
Promise* shiftMaskPromise(Context* c,
|
||||||
|
Promise* base,
|
||||||
|
unsigned shift,
|
||||||
|
int64_t mask);
|
||||||
|
|
||||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high);
|
Promise* combinedPromise(Context* c, Promise* low, Promise* high);
|
||||||
|
|
||||||
|
@ -20,43 +20,51 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
|
SingleRead::SingleRead(const SiteMask& mask, Value* successor)
|
||||||
|
: next_(0), mask(mask), high_(0), successor_(successor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SingleRead::SingleRead(const SiteMask& mask, Value* successor):
|
bool SingleRead::intersect(SiteMask* mask, unsigned)
|
||||||
next_(0), mask(mask), high_(0), successor_(successor)
|
{
|
||||||
{ }
|
|
||||||
|
|
||||||
bool SingleRead::intersect(SiteMask* mask, unsigned) {
|
|
||||||
*mask = mask->intersectionWith(this->mask);
|
*mask = mask->intersectionWith(this->mask);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* SingleRead::high(Context*) {
|
Value* SingleRead::high(Context*)
|
||||||
|
{
|
||||||
return high_;
|
return high_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* SingleRead::successor() {
|
Value* SingleRead::successor()
|
||||||
|
{
|
||||||
return successor_;
|
return successor_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleRead::valid() {
|
bool SingleRead::valid()
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleRead::append(Context* c UNUSED, Read* r) {
|
void SingleRead::append(Context* c UNUSED, Read* r)
|
||||||
|
{
|
||||||
assertT(c, next_ == 0);
|
assertT(c, next_ == 0);
|
||||||
next_ = r;
|
next_ = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
Read* SingleRead::next(Context*) {
|
Read* SingleRead::next(Context*)
|
||||||
|
{
|
||||||
return next_;
|
return next_;
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiRead::MultiRead():
|
MultiRead::MultiRead()
|
||||||
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
: reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool MultiRead::intersect(SiteMask* mask, unsigned depth) {
|
bool MultiRead::intersect(SiteMask* mask, unsigned depth)
|
||||||
|
{
|
||||||
if (depth > 0) {
|
if (depth > 0) {
|
||||||
// short-circuit recursion to avoid poor performance in
|
// short-circuit recursion to avoid poor performance in
|
||||||
// deeply-nested branches
|
// deeply-nested branches
|
||||||
@ -81,11 +89,13 @@ bool MultiRead::intersect(SiteMask* mask, unsigned depth) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* MultiRead::successor() {
|
Value* MultiRead::successor()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MultiRead::valid() {
|
bool MultiRead::valid()
|
||||||
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (not visited) {
|
if (not visited) {
|
||||||
visited = true;
|
visited = true;
|
||||||
@ -103,7 +113,8 @@ bool MultiRead::valid() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiRead::append(Context* c, Read* r) {
|
void MultiRead::append(Context* c, Read* r)
|
||||||
|
{
|
||||||
List<Read*>* cell = cons<Read*>(c, r, 0);
|
List<Read*>* cell = cons<Read*>(c, r, 0);
|
||||||
if (lastRead == 0) {
|
if (lastRead == 0) {
|
||||||
reads = cell;
|
reads = cell;
|
||||||
@ -112,19 +123,21 @@ void MultiRead::append(Context* c, Read* r) {
|
|||||||
}
|
}
|
||||||
lastRead = cell;
|
lastRead = cell;
|
||||||
|
|
||||||
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
||||||
|
|
||||||
lastTarget->item = r;
|
lastTarget->item = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
Read* MultiRead::next(Context* c) {
|
Read* MultiRead::next(Context* c)
|
||||||
|
{
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiRead::allocateTarget(Context* c) {
|
void MultiRead::allocateTarget(Context* c)
|
||||||
|
{
|
||||||
List<Read*>* cell = cons<Read*>(c, 0, 0);
|
List<Read*>* cell = cons<Read*>(c, 0, 0);
|
||||||
|
|
||||||
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
||||||
|
|
||||||
if (lastTarget) {
|
if (lastTarget) {
|
||||||
lastTarget->next = cell;
|
lastTarget->next = cell;
|
||||||
@ -134,7 +147,8 @@ void MultiRead::allocateTarget(Context* c) {
|
|||||||
lastTarget = cell;
|
lastTarget = cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
Read* MultiRead::nextTarget() {
|
Read* MultiRead::nextTarget()
|
||||||
|
{
|
||||||
// fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
|
// fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
|
||||||
|
|
||||||
Read* r = firstTarget->item;
|
Read* r = firstTarget->item;
|
||||||
@ -142,12 +156,12 @@ Read* MultiRead::nextTarget() {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StubRead::StubRead() : next_(0), read(0), visited(false), valid_(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
StubRead::StubRead():
|
bool StubRead::intersect(SiteMask* mask, unsigned depth)
|
||||||
next_(0), read(0), visited(false), valid_(true)
|
{
|
||||||
{ }
|
|
||||||
|
|
||||||
bool StubRead::intersect(SiteMask* mask, unsigned depth) {
|
|
||||||
if (not visited) {
|
if (not visited) {
|
||||||
visited = true;
|
visited = true;
|
||||||
if (read) {
|
if (read) {
|
||||||
@ -161,30 +175,33 @@ bool StubRead::intersect(SiteMask* mask, unsigned depth) {
|
|||||||
return valid_;
|
return valid_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* StubRead::successor() {
|
Value* StubRead::successor()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StubRead::valid() {
|
bool StubRead::valid()
|
||||||
|
{
|
||||||
return valid_;
|
return valid_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StubRead::append(Context* c UNUSED, Read* r) {
|
void StubRead::append(Context* c UNUSED, Read* r)
|
||||||
|
{
|
||||||
assertT(c, next_ == 0);
|
assertT(c, next_ == 0);
|
||||||
next_ = r;
|
next_ = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
Read* StubRead::next(Context*) {
|
Read* StubRead::next(Context*)
|
||||||
|
{
|
||||||
return next_;
|
return next_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SingleRead* read(Context* c, const SiteMask& mask, Value* successor)
|
||||||
|
{
|
||||||
SingleRead* read(Context* c, const SiteMask& mask, Value* successor) {
|
|
||||||
assertT(c,
|
assertT(c,
|
||||||
(mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
|
(mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
|
||||||
|
|
||||||
return new(c->zone) SingleRead(mask, successor);
|
return new (c->zone) SingleRead(mask, successor);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
@ -22,13 +22,16 @@ class Event;
|
|||||||
|
|
||||||
class Read {
|
class Read {
|
||||||
public:
|
public:
|
||||||
Read():
|
Read() : value(0), event(0), eventNext(0)
|
||||||
value(0), event(0), eventNext(0)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0;
|
virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0;
|
||||||
|
|
||||||
virtual Value* high(Context* c) { abort(c); }
|
virtual Value* high(Context* c)
|
||||||
|
{
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
|
||||||
virtual Value* successor() = 0;
|
virtual Value* successor() = 0;
|
||||||
|
|
||||||
@ -43,11 +46,12 @@ class Read {
|
|||||||
Read* eventNext;
|
Read* eventNext;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool valid(Read* r) {
|
inline bool valid(Read* r)
|
||||||
|
{
|
||||||
return r and r->valid();
|
return r and r->valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SingleRead: public Read {
|
class SingleRead : public Read {
|
||||||
public:
|
public:
|
||||||
SingleRead(const SiteMask& mask, Value* successor);
|
SingleRead(const SiteMask& mask, Value* successor);
|
||||||
|
|
||||||
@ -69,8 +73,7 @@ class SingleRead: public Read {
|
|||||||
Value* successor_;
|
Value* successor_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MultiRead : public Read {
|
||||||
class MultiRead: public Read {
|
|
||||||
public:
|
public:
|
||||||
MultiRead();
|
MultiRead();
|
||||||
|
|
||||||
@ -95,7 +98,7 @@ class MultiRead: public Read {
|
|||||||
bool visited;
|
bool visited;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StubRead: public Read {
|
class StubRead : public Read {
|
||||||
public:
|
public:
|
||||||
StubRead();
|
StubRead();
|
||||||
|
|
||||||
@ -117,7 +120,6 @@ class StubRead: public Read {
|
|||||||
|
|
||||||
SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0);
|
SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0);
|
||||||
|
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -20,24 +20,25 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile):
|
RegisterAllocator::RegisterAllocator(Aborter* a,
|
||||||
a(a),
|
const RegisterFile* registerFile)
|
||||||
registerFile(registerFile)
|
: a(a), registerFile(registerFile)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsigned totalFrameSize(Context* c);
|
unsigned totalFrameSize(Context* c);
|
||||||
Read* live(Context* c UNUSED, Value* v);
|
Read* live(Context* c UNUSED, Value* v);
|
||||||
|
|
||||||
unsigned
|
unsigned resourceCost(Context* c,
|
||||||
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
|
Value* v,
|
||||||
|
Resource* r,
|
||||||
|
SiteMask mask,
|
||||||
CostCalculator* costCalculator)
|
CostCalculator* costCalculator)
|
||||||
{
|
{
|
||||||
if (r->reserved or r->freezeCount or r->referenceCount) {
|
if (r->reserved or r->freezeCount or r->referenceCount) {
|
||||||
return Target::Impossible;
|
return Target::Impossible;
|
||||||
} else {
|
} else {
|
||||||
unsigned baseCost =
|
unsigned baseCost = costCalculator ? costCalculator->cost(c, mask) : 0;
|
||||||
costCalculator ? costCalculator->cost(c, mask) : 0;
|
|
||||||
|
|
||||||
if (r->value) {
|
if (r->value) {
|
||||||
assertT(c, r->value->findSite(r->site));
|
assertT(c, r->value->findSite(r->site));
|
||||||
@ -55,15 +56,23 @@ resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool pickRegisterTarget(Context* c,
|
||||||
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
|
int i,
|
||||||
unsigned* cost, CostCalculator* costCalculator)
|
Value* v,
|
||||||
|
uint32_t mask,
|
||||||
|
int* target,
|
||||||
|
unsigned* cost,
|
||||||
|
CostCalculator* costCalculator)
|
||||||
{
|
{
|
||||||
if ((1 << i) & mask) {
|
if ((1 << i) & mask) {
|
||||||
RegisterResource* r = c->registerResources + i;
|
RegisterResource* r = c->registerResources + i;
|
||||||
unsigned myCost = resourceCost
|
unsigned myCost
|
||||||
(c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator)
|
= resourceCost(
|
||||||
+ Target::MinimumRegisterCost;
|
c,
|
||||||
|
v,
|
||||||
|
r,
|
||||||
|
SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex),
|
||||||
|
costCalculator) + Target::MinimumRegisterCost;
|
||||||
|
|
||||||
if ((static_cast<uint32_t>(1) << i) == mask) {
|
if ((static_cast<uint32_t>(1) << i) == mask) {
|
||||||
*cost = myCost;
|
*cost = myCost;
|
||||||
@ -76,8 +85,10 @@ pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int pickRegisterTarget(Context* c,
|
||||||
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
|
Value* v,
|
||||||
|
uint32_t mask,
|
||||||
|
unsigned* cost,
|
||||||
CostCalculator* costCalculator)
|
CostCalculator* costCalculator)
|
||||||
{
|
{
|
||||||
int target = lir::NoRegister;
|
int target = lir::NoRegister;
|
||||||
@ -85,8 +96,8 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
|
|||||||
|
|
||||||
if (mask & c->regFile->generalRegisters.mask) {
|
if (mask & c->regFile->generalRegisters.mask) {
|
||||||
for (int i = c->regFile->generalRegisters.limit - 1;
|
for (int i = c->regFile->generalRegisters.limit - 1;
|
||||||
i >= c->regFile->generalRegisters.start; --i)
|
i >= c->regFile->generalRegisters.start;
|
||||||
{
|
--i) {
|
||||||
if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
|
if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -95,8 +106,8 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
|
|||||||
|
|
||||||
if (mask & c->regFile->floatRegisters.mask) {
|
if (mask & c->regFile->floatRegisters.mask) {
|
||||||
for (int i = c->regFile->floatRegisters.start;
|
for (int i = c->regFile->floatRegisters.start;
|
||||||
i < static_cast<int>(c->regFile->floatRegisters.limit); ++i)
|
i < static_cast<int>(c->regFile->floatRegisters.limit);
|
||||||
{
|
++i) {
|
||||||
if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
|
if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -106,8 +117,9 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target
|
Target pickRegisterTarget(Context* c,
|
||||||
pickRegisterTarget(Context* c, Value* v, uint32_t mask,
|
Value* v,
|
||||||
|
uint32_t mask,
|
||||||
CostCalculator* costCalculator)
|
CostCalculator* costCalculator)
|
||||||
{
|
{
|
||||||
unsigned cost;
|
unsigned cost;
|
||||||
@ -115,25 +127,28 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask,
|
|||||||
return Target(number, lir::RegisterOperand, cost);
|
return Target(number, lir::RegisterOperand, cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned frameCost(Context* c,
|
||||||
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator)
|
Value* v,
|
||||||
|
int frameIndex,
|
||||||
|
CostCalculator* costCalculator)
|
||||||
{
|
{
|
||||||
return resourceCost
|
return resourceCost(c,
|
||||||
(c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex),
|
v,
|
||||||
costCalculator)
|
c->frameResources + frameIndex,
|
||||||
+ Target::MinimumFrameCost;
|
SiteMask(1 << lir::MemoryOperand, 0, frameIndex),
|
||||||
|
costCalculator) + Target::MinimumFrameCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target
|
Target pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
||||||
pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
|
||||||
{
|
{
|
||||||
Target best;
|
Target best;
|
||||||
|
|
||||||
Value* p = v;
|
Value* p = v;
|
||||||
do {
|
do {
|
||||||
if (p->home >= 0) {
|
if (p->home >= 0) {
|
||||||
Target mine
|
Target mine(p->home,
|
||||||
(p->home, lir::MemoryOperand, frameCost(c, v, p->home, costCalculator));
|
lir::MemoryOperand,
|
||||||
|
frameCost(c, v, p->home, costCalculator));
|
||||||
|
|
||||||
if (mine.cost == Target::MinimumFrameCost) {
|
if (mine.cost == Target::MinimumFrameCost) {
|
||||||
return mine;
|
return mine;
|
||||||
@ -147,8 +162,7 @@ pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
|||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target
|
Target pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
||||||
pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
|
||||||
{
|
{
|
||||||
Target best;
|
Target best;
|
||||||
|
|
||||||
@ -165,14 +179,16 @@ pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
|||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target
|
Target pickTarget(Context* c,
|
||||||
pickTarget(Context* c, Value* value, const SiteMask& mask,
|
Value* value,
|
||||||
unsigned registerPenalty, Target best,
|
const SiteMask& mask,
|
||||||
|
unsigned registerPenalty,
|
||||||
|
Target best,
|
||||||
CostCalculator* costCalculator)
|
CostCalculator* costCalculator)
|
||||||
{
|
{
|
||||||
if (mask.typeMask & (1 << lir::RegisterOperand)) {
|
if (mask.typeMask & (1 << lir::RegisterOperand)) {
|
||||||
Target mine = pickRegisterTarget
|
Target mine
|
||||||
(c, value, mask.registerMask, costCalculator);
|
= pickRegisterTarget(c, value, mask.registerMask, costCalculator);
|
||||||
|
|
||||||
mine.cost += registerPenalty;
|
mine.cost += registerPenalty;
|
||||||
if (mine.cost == Target::MinimumRegisterCost) {
|
if (mine.cost == Target::MinimumRegisterCost) {
|
||||||
@ -184,7 +200,8 @@ pickTarget(Context* c, Value* value, const SiteMask& mask,
|
|||||||
|
|
||||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||||
if (mask.frameIndex >= 0) {
|
if (mask.frameIndex >= 0) {
|
||||||
Target mine(mask.frameIndex, lir::MemoryOperand,
|
Target mine(mask.frameIndex,
|
||||||
|
lir::MemoryOperand,
|
||||||
frameCost(c, value, mask.frameIndex, costCalculator));
|
frameCost(c, value, mask.frameIndex, costCalculator));
|
||||||
if (mine.cost == Target::MinimumFrameCost) {
|
if (mine.cost == Target::MinimumFrameCost) {
|
||||||
return mine;
|
return mine;
|
||||||
@ -204,13 +221,16 @@ pickTarget(Context* c, Value* value, const SiteMask& mask,
|
|||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target
|
Target pickTarget(Context* c,
|
||||||
pickTarget(Context* c, Read* read, bool intersectRead,
|
Read* read,
|
||||||
unsigned registerReserveCount, CostCalculator* costCalculator)
|
bool intersectRead,
|
||||||
|
unsigned registerReserveCount,
|
||||||
|
CostCalculator* costCalculator)
|
||||||
{
|
{
|
||||||
unsigned registerPenalty
|
unsigned registerPenalty
|
||||||
= (c->availableGeneralRegisterCount > registerReserveCount
|
= (c->availableGeneralRegisterCount > registerReserveCount
|
||||||
? 0 : Target::LowRegisterPenalty);
|
? 0
|
||||||
|
: Target::LowRegisterPenalty);
|
||||||
|
|
||||||
Value* value = read->value;
|
Value* value = read->value;
|
||||||
|
|
||||||
@ -235,8 +255,8 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
|||||||
if (r) {
|
if (r) {
|
||||||
SiteMask intersection = mask;
|
SiteMask intersection = mask;
|
||||||
if (r->intersect(&intersection)) {
|
if (r->intersect(&intersection)) {
|
||||||
best = pickTarget
|
best = pickTarget(
|
||||||
(c, value, intersection, registerPenalty, best, costCalculator);
|
c, value, intersection, registerPenalty, best, costCalculator);
|
||||||
|
|
||||||
if (best.cost <= Target::MinimumFrameCost) {
|
if (best.cost <= Target::MinimumFrameCost) {
|
||||||
return best;
|
return best;
|
||||||
@ -252,14 +272,18 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
|||||||
|
|
||||||
if (intersectRead) {
|
if (intersectRead) {
|
||||||
if (best.cost == Target::Impossible) {
|
if (best.cost == Target::Impossible) {
|
||||||
fprintf(stderr, "mask type %d reg %d frame %d\n",
|
fprintf(stderr,
|
||||||
mask.typeMask, mask.registerMask, mask.frameIndex);
|
"mask type %d reg %d frame %d\n",
|
||||||
|
mask.typeMask,
|
||||||
|
mask.registerMask,
|
||||||
|
mask.frameIndex);
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ Target mine = pickRegisterTarget(c, value, registerMask, costCalculator);
|
{
|
||||||
|
Target mine = pickRegisterTarget(c, value, registerMask, costCalculator);
|
||||||
|
|
||||||
mine.cost += registerPenalty;
|
mine.cost += registerPenalty;
|
||||||
|
|
||||||
@ -270,7 +294,8 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ Target mine = pickFrameTarget(c, value, costCalculator);
|
{
|
||||||
|
Target mine = pickFrameTarget(c, value, costCalculator);
|
||||||
if (mine.cost == Target::MinimumFrameCost) {
|
if (mine.cost == Target::MinimumFrameCost) {
|
||||||
return mine;
|
return mine;
|
||||||
} else if (mine.cost < best.cost) {
|
} else if (mine.cost < best.cost) {
|
||||||
@ -279,8 +304,7 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (best.cost >= Target::StealUniquePenalty
|
if (best.cost >= Target::StealUniquePenalty
|
||||||
and c->availableGeneralRegisterCount == 0)
|
and c->availableGeneralRegisterCount == 0) {
|
||||||
{
|
|
||||||
// there are no free registers left, so moving from memory to
|
// there are no free registers left, so moving from memory to
|
||||||
// memory isn't an option - try harder to find an available frame
|
// memory isn't an option - try harder to find an available frame
|
||||||
// site:
|
// site:
|
||||||
|
@ -33,14 +33,12 @@ class SiteMask;
|
|||||||
class Resource;
|
class Resource;
|
||||||
class Read;
|
class Read;
|
||||||
|
|
||||||
|
|
||||||
class RegisterAllocator {
|
class RegisterAllocator {
|
||||||
public:
|
public:
|
||||||
Aborter* a;
|
Aborter* a;
|
||||||
const RegisterFile* registerFile;
|
const RegisterFile* registerFile;
|
||||||
|
|
||||||
RegisterAllocator(Aborter* a, const RegisterFile* registerFile);
|
RegisterAllocator(Aborter* a, const RegisterFile* registerFile);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Target {
|
class Target {
|
||||||
@ -53,11 +51,14 @@ class Target {
|
|||||||
static const unsigned LowRegisterPenalty = 10;
|
static const unsigned LowRegisterPenalty = 10;
|
||||||
static const unsigned Impossible = 20;
|
static const unsigned Impossible = 20;
|
||||||
|
|
||||||
Target(): cost(Impossible) { }
|
Target() : cost(Impossible)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Target(int index, lir::OperandType type, unsigned cost):
|
Target(int index, lir::OperandType type, unsigned cost)
|
||||||
index(index), type(type), cost(cost)
|
: index(index), type(type), cost(cost)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int16_t index;
|
int16_t index;
|
||||||
lir::OperandType type;
|
lir::OperandType type;
|
||||||
@ -69,40 +70,52 @@ class CostCalculator {
|
|||||||
virtual unsigned cost(Context* c, SiteMask mask) = 0;
|
virtual unsigned cost(Context* c, SiteMask mask) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned
|
unsigned resourceCost(Context* c,
|
||||||
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
|
Value* v,
|
||||||
|
Resource* r,
|
||||||
|
SiteMask mask,
|
||||||
CostCalculator* costCalculator);
|
CostCalculator* costCalculator);
|
||||||
|
|
||||||
|
bool pickRegisterTarget(Context* c,
|
||||||
bool
|
int i,
|
||||||
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
|
Value* v,
|
||||||
unsigned* cost, CostCalculator* costCalculator = 0);
|
uint32_t mask,
|
||||||
|
int* target,
|
||||||
int
|
unsigned* cost,
|
||||||
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
|
|
||||||
CostCalculator* costCalculator = 0);
|
CostCalculator* costCalculator = 0);
|
||||||
|
|
||||||
Target
|
int pickRegisterTarget(Context* c,
|
||||||
pickRegisterTarget(Context* c, Value* v, uint32_t mask,
|
Value* v,
|
||||||
|
uint32_t mask,
|
||||||
|
unsigned* cost,
|
||||||
CostCalculator* costCalculator = 0);
|
CostCalculator* costCalculator = 0);
|
||||||
|
|
||||||
unsigned
|
Target pickRegisterTarget(Context* c,
|
||||||
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator);
|
Value* v,
|
||||||
|
uint32_t mask,
|
||||||
|
CostCalculator* costCalculator = 0);
|
||||||
|
|
||||||
Target
|
unsigned frameCost(Context* c,
|
||||||
pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
|
Value* v,
|
||||||
|
int frameIndex,
|
||||||
Target
|
|
||||||
pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
|
|
||||||
|
|
||||||
Target
|
|
||||||
pickTarget(Context* c, Value* value, const SiteMask& mask,
|
|
||||||
unsigned registerPenalty, Target best,
|
|
||||||
CostCalculator* costCalculator);
|
CostCalculator* costCalculator);
|
||||||
|
|
||||||
Target
|
Target pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
|
||||||
pickTarget(Context* c, Read* read, bool intersectRead,
|
|
||||||
unsigned registerReserveCount, CostCalculator* costCalculator);
|
Target pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
|
||||||
|
|
||||||
|
Target pickTarget(Context* c,
|
||||||
|
Value* value,
|
||||||
|
const SiteMask& mask,
|
||||||
|
unsigned registerPenalty,
|
||||||
|
Target best,
|
||||||
|
CostCalculator* costCalculator);
|
||||||
|
|
||||||
|
Target pickTarget(Context* c,
|
||||||
|
Read* read,
|
||||||
|
bool intersectRead,
|
||||||
|
unsigned registerReserveCount,
|
||||||
|
CostCalculator* costCalculator);
|
||||||
|
|
||||||
} // namespace regalloc
|
} // namespace regalloc
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
|
@ -18,154 +18,173 @@ namespace compiler {
|
|||||||
|
|
||||||
const bool DebugResources = false;
|
const bool DebugResources = false;
|
||||||
|
|
||||||
|
|
||||||
void steal(Context* c, Resource* r, Value* thief);
|
void steal(Context* c, Resource* r, Value* thief);
|
||||||
|
|
||||||
void decrementAvailableGeneralRegisterCount(Context* c) {
|
void decrementAvailableGeneralRegisterCount(Context* c)
|
||||||
|
{
|
||||||
assertT(c, c->availableGeneralRegisterCount);
|
assertT(c, c->availableGeneralRegisterCount);
|
||||||
-- c->availableGeneralRegisterCount;
|
--c->availableGeneralRegisterCount;
|
||||||
|
|
||||||
if (DebugResources) {
|
if (DebugResources) {
|
||||||
fprintf(stderr, "%d registers available\n",
|
fprintf(
|
||||||
c->availableGeneralRegisterCount);
|
stderr, "%d registers available\n", c->availableGeneralRegisterCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void incrementAvailableGeneralRegisterCount(Context* c) {
|
void incrementAvailableGeneralRegisterCount(Context* c)
|
||||||
++ c->availableGeneralRegisterCount;
|
{
|
||||||
|
++c->availableGeneralRegisterCount;
|
||||||
|
|
||||||
if (DebugResources) {
|
if (DebugResources) {
|
||||||
fprintf(stderr, "%d registers available\n",
|
fprintf(
|
||||||
c->availableGeneralRegisterCount);
|
stderr, "%d registers available\n", c->availableGeneralRegisterCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void freezeResource(Context* c, Resource* r, Value* v) {
|
void freezeResource(Context* c, Resource* r, Value* v)
|
||||||
|
{
|
||||||
if (DebugResources) {
|
if (DebugResources) {
|
||||||
char buffer[256]; r->toString(c, buffer, 256);
|
char buffer[256];
|
||||||
|
r->toString(c, buffer, 256);
|
||||||
fprintf(stderr, "%p freeze %s to %d\n", v, buffer, r->freezeCount + 1);
|
fprintf(stderr, "%p freeze %s to %d\n", v, buffer, r->freezeCount + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
++ r->freezeCount;
|
++r->freezeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void thawResource(Context* c, Resource* r, Value* v) {
|
void thawResource(Context* c, Resource* r, Value* v)
|
||||||
|
{
|
||||||
if (not r->reserved) {
|
if (not r->reserved) {
|
||||||
if (DebugResources) {
|
if (DebugResources) {
|
||||||
char buffer[256]; r->toString(c, buffer, 256);
|
char buffer[256];
|
||||||
|
r->toString(c, buffer, 256);
|
||||||
fprintf(stderr, "%p thaw %s to %d\n", v, buffer, r->freezeCount - 1);
|
fprintf(stderr, "%p thaw %s to %d\n", v, buffer, r->freezeCount - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertT(c, r->freezeCount);
|
assertT(c, r->freezeCount);
|
||||||
|
|
||||||
-- r->freezeCount;
|
--r->freezeCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resource::Resource(bool reserved)
|
||||||
|
: value(0),
|
||||||
|
site(0),
|
||||||
|
previousAcquired(0),
|
||||||
|
nextAcquired(0),
|
||||||
|
freezeCount(0),
|
||||||
|
referenceCount(0),
|
||||||
|
reserved(reserved)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Resource::Resource(bool reserved):
|
RegisterResource::RegisterResource(bool reserved) : Resource(reserved)
|
||||||
value(0), site(0), previousAcquired(0), nextAcquired(0), freezeCount(0),
|
{
|
||||||
referenceCount(0), reserved(reserved)
|
}
|
||||||
{ }
|
|
||||||
|
|
||||||
RegisterResource::RegisterResource(bool reserved):
|
void RegisterResource::freeze(Context* c, Value* v)
|
||||||
Resource(reserved)
|
{
|
||||||
{ }
|
|
||||||
|
|
||||||
void RegisterResource::freeze(Context* c, Value* v) {
|
|
||||||
if (not reserved) {
|
if (not reserved) {
|
||||||
freezeResource(c, this, v);
|
freezeResource(c, this, v);
|
||||||
|
|
||||||
if (freezeCount == 1
|
if (freezeCount == 1
|
||||||
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
|
and ((1 << index(c)) & c->regFile->generalRegisters.mask)) {
|
||||||
{
|
|
||||||
decrementAvailableGeneralRegisterCount(c);
|
decrementAvailableGeneralRegisterCount(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterResource::thaw(Context* c, Value* v) {
|
void RegisterResource::thaw(Context* c, Value* v)
|
||||||
|
{
|
||||||
if (not reserved) {
|
if (not reserved) {
|
||||||
thawResource(c, this, v);
|
thawResource(c, this, v);
|
||||||
|
|
||||||
if (freezeCount == 0
|
if (freezeCount == 0
|
||||||
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
|
and ((1 << index(c)) & c->regFile->generalRegisters.mask)) {
|
||||||
{
|
|
||||||
incrementAvailableGeneralRegisterCount(c);
|
incrementAvailableGeneralRegisterCount(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned RegisterResource::toString(Context* c, char* buffer, unsigned bufferSize) {
|
unsigned RegisterResource::toString(Context* c,
|
||||||
|
char* buffer,
|
||||||
|
unsigned bufferSize)
|
||||||
|
{
|
||||||
return vm::snprintf(buffer, bufferSize, "register %d", index(c));
|
return vm::snprintf(buffer, bufferSize, "register %d", index(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned RegisterResource::index(Context* c) {
|
unsigned RegisterResource::index(Context* c)
|
||||||
|
{
|
||||||
return this - c->registerResources;
|
return this - c->registerResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterResource::increment(Context* c) {
|
void RegisterResource::increment(Context* c)
|
||||||
|
{
|
||||||
if (not this->reserved) {
|
if (not this->reserved) {
|
||||||
if (DebugResources) {
|
if (DebugResources) {
|
||||||
char buffer[256]; this->toString(c, buffer, 256);
|
char buffer[256];
|
||||||
|
this->toString(c, buffer, 256);
|
||||||
fprintf(stderr, "increment %s to %d\n", buffer, this->referenceCount + 1);
|
fprintf(stderr, "increment %s to %d\n", buffer, this->referenceCount + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
++ this->referenceCount;
|
++this->referenceCount;
|
||||||
|
|
||||||
if (this->referenceCount == 1
|
if (this->referenceCount == 1
|
||||||
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask))
|
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask)) {
|
||||||
{
|
|
||||||
decrementAvailableGeneralRegisterCount(c);
|
decrementAvailableGeneralRegisterCount(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterResource::decrement(Context* c) {
|
void RegisterResource::decrement(Context* c)
|
||||||
|
{
|
||||||
if (not this->reserved) {
|
if (not this->reserved) {
|
||||||
if (DebugResources) {
|
if (DebugResources) {
|
||||||
char buffer[256]; this->toString(c, buffer, 256);
|
char buffer[256];
|
||||||
|
this->toString(c, buffer, 256);
|
||||||
fprintf(stderr, "decrement %s to %d\n", buffer, this->referenceCount - 1);
|
fprintf(stderr, "decrement %s to %d\n", buffer, this->referenceCount - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertT(c, this->referenceCount > 0);
|
assertT(c, this->referenceCount > 0);
|
||||||
|
|
||||||
-- this->referenceCount;
|
--this->referenceCount;
|
||||||
|
|
||||||
if (this->referenceCount == 0
|
if (this->referenceCount == 0
|
||||||
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask))
|
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask)) {
|
||||||
{
|
|
||||||
incrementAvailableGeneralRegisterCount(c);
|
incrementAvailableGeneralRegisterCount(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FrameResource::freeze(Context* c, Value* v)
|
||||||
|
{
|
||||||
void FrameResource::freeze(Context* c, Value* v) {
|
|
||||||
freezeResource(c, this, v);
|
freezeResource(c, this, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameResource::thaw(Context* c, Value* v) {
|
void FrameResource::thaw(Context* c, Value* v)
|
||||||
|
{
|
||||||
thawResource(c, this, v);
|
thawResource(c, this, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned FrameResource::toString(Context* c, char* buffer, unsigned bufferSize) {
|
unsigned FrameResource::toString(Context* c, char* buffer, unsigned bufferSize)
|
||||||
|
{
|
||||||
return vm::snprintf(buffer, bufferSize, "frame %d", index(c));
|
return vm::snprintf(buffer, bufferSize, "frame %d", index(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned FrameResource::index(Context* c) {
|
unsigned FrameResource::index(Context* c)
|
||||||
|
{
|
||||||
return this - c->frameResources;
|
return this - c->frameResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void acquire(Context* c, Resource* resource, Value* value, Site* site)
|
||||||
void acquire(Context* c, Resource* resource, Value* value, Site* site) {
|
{
|
||||||
assertT(c, value);
|
assertT(c, value);
|
||||||
assertT(c, site);
|
assertT(c, site);
|
||||||
|
|
||||||
if (not resource->reserved) {
|
if (not resource->reserved) {
|
||||||
if (DebugResources) {
|
if (DebugResources) {
|
||||||
char buffer[256]; resource->toString(c, buffer, 256);
|
char buffer[256];
|
||||||
|
resource->toString(c, buffer, 256);
|
||||||
fprintf(stderr, "%p acquire %s\n", value, buffer);
|
fprintf(stderr, "%p acquire %s\n", value, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,10 +206,15 @@ void acquire(Context* c, Resource* resource, Value* value, Site* site) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNUSED) {
|
void release(Context* c,
|
||||||
|
Resource* resource,
|
||||||
|
Value* value UNUSED,
|
||||||
|
Site* site UNUSED)
|
||||||
|
{
|
||||||
if (not resource->reserved) {
|
if (not resource->reserved) {
|
||||||
if (DebugResources) {
|
if (DebugResources) {
|
||||||
char buffer[256]; resource->toString(c, buffer, 256);
|
char buffer[256];
|
||||||
|
resource->toString(c, buffer, 256);
|
||||||
fprintf(stderr, "%p release %s\n", resource->value, buffer);
|
fprintf(stderr, "%p release %s\n", resource->value, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +244,6 @@ void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNU
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -38,7 +38,7 @@ class Resource {
|
|||||||
bool reserved;
|
bool reserved;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegisterResource: public Resource {
|
class RegisterResource : public Resource {
|
||||||
public:
|
public:
|
||||||
RegisterResource(bool reserved);
|
RegisterResource(bool reserved);
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ class RegisterResource: public Resource {
|
|||||||
void decrement(Context*);
|
void decrement(Context*);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FrameResource: public Resource {
|
class FrameResource : public Resource {
|
||||||
public:
|
public:
|
||||||
virtual void freeze(Context*, Value*);
|
virtual void freeze(Context*, Value*);
|
||||||
|
|
||||||
|
@ -21,25 +21,31 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
|
int intersectFrameIndexes(int a, int b)
|
||||||
|
{
|
||||||
int intersectFrameIndexes(int a, int b) {
|
if (a == NoFrameIndex or b == NoFrameIndex)
|
||||||
if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex;
|
return NoFrameIndex;
|
||||||
if (a == AnyFrameIndex) return b;
|
if (a == AnyFrameIndex)
|
||||||
if (b == AnyFrameIndex) return a;
|
return b;
|
||||||
if (a == b) return a;
|
if (b == AnyFrameIndex)
|
||||||
|
return a;
|
||||||
|
if (a == b)
|
||||||
|
return a;
|
||||||
return NoFrameIndex;
|
return NoFrameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SiteMask SiteMask::intersectionWith(const SiteMask& b)
|
||||||
SiteMask SiteMask::intersectionWith(const SiteMask& b) {
|
{
|
||||||
return SiteMask(typeMask & b.typeMask, registerMask & b.registerMask,
|
return SiteMask(typeMask & b.typeMask,
|
||||||
|
registerMask & b.registerMask,
|
||||||
intersectFrameIndexes(frameIndex, b.frameIndex));
|
intersectFrameIndexes(frameIndex, b.frameIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies,
|
SiteIterator::SiteIterator(Context* c,
|
||||||
bool includeNextWord):
|
Value* v,
|
||||||
c(c),
|
bool includeBuddies,
|
||||||
|
bool includeNextWord)
|
||||||
|
: c(c),
|
||||||
originalValue(v),
|
originalValue(v),
|
||||||
currentValue(v),
|
currentValue(v),
|
||||||
includeBuddies(includeBuddies),
|
includeBuddies(includeBuddies),
|
||||||
@ -47,9 +53,11 @@ SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies,
|
|||||||
pass(0),
|
pass(0),
|
||||||
next_(findNext(&(v->sites))),
|
next_(findNext(&(v->sites))),
|
||||||
previous(0)
|
previous(0)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Site** SiteIterator::findNext(Site** p) {
|
Site** SiteIterator::findNext(Site** p)
|
||||||
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
if (*p) {
|
if (*p) {
|
||||||
if (pass == 0 or (*p)->registerSize(c) > c->targetInfo.pointerSize) {
|
if (pass == 0 or (*p)->registerSize(c) > c->targetInfo.pointerSize) {
|
||||||
@ -83,7 +91,8 @@ Site** SiteIterator::findNext(Site** p) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SiteIterator::hasMore() {
|
bool SiteIterator::hasMore()
|
||||||
|
{
|
||||||
if (previous) {
|
if (previous) {
|
||||||
next_ = findNext(&((*previous)->next));
|
next_ = findNext(&((*previous)->next));
|
||||||
previous = 0;
|
previous = 0;
|
||||||
@ -91,12 +100,14 @@ bool SiteIterator::hasMore() {
|
|||||||
return next_ != 0;
|
return next_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* SiteIterator::next() {
|
Site* SiteIterator::next()
|
||||||
|
{
|
||||||
previous = next_;
|
previous = next_;
|
||||||
return *previous;
|
return *previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SiteIterator::remove(Context* c) {
|
void SiteIterator::remove(Context* c)
|
||||||
|
{
|
||||||
(*previous)->release(c, originalValue);
|
(*previous)->release(c, originalValue);
|
||||||
*previous = (*previous)->next;
|
*previous = (*previous)->next;
|
||||||
next_ = findNext(previous);
|
next_ = findNext(previous);
|
||||||
@ -108,50 +119,59 @@ unsigned Site::registerSize(Context* c)
|
|||||||
return c->targetInfo.pointerSize;
|
return c->targetInfo.pointerSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* constantSite(Context* c, Promise* value) {
|
Site* constantSite(Context* c, Promise* value)
|
||||||
return new(c->zone) ConstantSite(value);
|
{
|
||||||
|
return new (c->zone) ConstantSite(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* constantSite(Context* c, int64_t value) {
|
Site* constantSite(Context* c, int64_t value)
|
||||||
|
{
|
||||||
return constantSite(c, resolvedPromise(c, value));
|
return constantSite(c, resolvedPromise(c, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AddressSite : public Site {
|
||||||
|
|
||||||
class AddressSite: public Site {
|
|
||||||
public:
|
public:
|
||||||
AddressSite(Promise* address): address(address) { }
|
AddressSite(Promise* address) : address(address)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) {
|
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize)
|
||||||
|
{
|
||||||
if (address->resolved()) {
|
if (address->resolved()) {
|
||||||
return vm::snprintf
|
return vm::snprintf(
|
||||||
(buffer, bufferSize, "address %" LLD, address->value());
|
buffer, bufferSize, "address %" LLD, address->value());
|
||||||
} else {
|
} else {
|
||||||
return vm::snprintf(buffer, bufferSize, "address unresolved");
|
return vm::snprintf(buffer, bufferSize, "address unresolved");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned copyCost(Context*, Site* s) {
|
virtual unsigned copyCost(Context*, Site* s)
|
||||||
|
{
|
||||||
return (s == this ? 0 : AddressCopyCost);
|
return (s == this ? 0 : AddressCopyCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool match(Context*, const SiteMask& mask) {
|
virtual bool match(Context*, const SiteMask& mask)
|
||||||
|
{
|
||||||
return mask.typeMask & (1 << lir::AddressOperand);
|
return mask.typeMask & (1 << lir::AddressOperand);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool loneMatch(Context*, const SiteMask&) {
|
virtual bool loneMatch(Context*, const SiteMask&)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool matchNextWord(Context* c, Site*, unsigned) {
|
virtual bool matchNextWord(Context* c, Site*, unsigned)
|
||||||
|
{
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual lir::OperandType type(Context*) {
|
virtual lir::OperandType type(Context*)
|
||||||
|
{
|
||||||
return lir::AddressOperand;
|
return lir::AddressOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
virtual void asAssemblerOperand(Context* c UNUSED,
|
||||||
|
Site* high UNUSED,
|
||||||
lir::Operand* result)
|
lir::Operand* result)
|
||||||
{
|
{
|
||||||
assertT(c, high == this);
|
assertT(c, high == this);
|
||||||
@ -159,66 +179,74 @@ class AddressSite: public Site {
|
|||||||
new (result) lir::Address(address);
|
new (result) lir::Address(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Site* copy(Context* c) {
|
virtual Site* copy(Context* c)
|
||||||
|
{
|
||||||
return addressSite(c, address);
|
return addressSite(c, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Site* copyLow(Context* c) {
|
virtual Site* copyLow(Context* c)
|
||||||
|
{
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Site* copyHigh(Context* c) {
|
virtual Site* copyHigh(Context* c)
|
||||||
|
{
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Site* makeNextWord(Context* c, unsigned) {
|
virtual Site* makeNextWord(Context* c, unsigned)
|
||||||
|
{
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual SiteMask mask(Context*) {
|
virtual SiteMask mask(Context*)
|
||||||
|
{
|
||||||
return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex);
|
return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual SiteMask nextWordMask(Context* c, unsigned) {
|
virtual SiteMask nextWordMask(Context* c, unsigned)
|
||||||
|
{
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise* address;
|
Promise* address;
|
||||||
};
|
};
|
||||||
|
|
||||||
Site* addressSite(Context* c, Promise* address) {
|
Site* addressSite(Context* c, Promise* address)
|
||||||
return new(c->zone) AddressSite(address);
|
{
|
||||||
|
return new (c->zone) AddressSite(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegisterSite::RegisterSite(uint32_t mask, int number)
|
||||||
|
: mask_(mask), number(number)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
RegisterSite::RegisterSite(uint32_t mask, int number):
|
unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize)
|
||||||
mask_(mask), number(number)
|
{
|
||||||
{ }
|
|
||||||
|
|
||||||
unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize) {
|
|
||||||
if (number != lir::NoRegister) {
|
if (number != lir::NoRegister) {
|
||||||
return vm::snprintf(buffer, bufferSize, "%p register %d", this, number);
|
return vm::snprintf(buffer, bufferSize, "%p register %d", this, number);
|
||||||
} else {
|
} else {
|
||||||
return vm::snprintf(buffer, bufferSize,
|
return vm::snprintf(
|
||||||
"%p register unacquired (mask %d)", this, mask_);
|
buffer, bufferSize, "%p register unacquired (mask %d)", this, mask_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned RegisterSite::copyCost(Context* c, Site* s) {
|
unsigned RegisterSite::copyCost(Context* c, Site* s)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
if (s and
|
if (s and (this == s
|
||||||
(this == s or
|
or (s->type(c) == lir::RegisterOperand
|
||||||
(s->type(c) == lir::RegisterOperand
|
and (static_cast<RegisterSite*>(s)->mask_ & (1 << number))))) {
|
||||||
and (static_cast<RegisterSite*>(s)->mask_ & (1 << number)))))
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return RegisterCopyCost;
|
return RegisterCopyCost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) {
|
bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
|
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
|
||||||
@ -228,7 +256,8 @@ bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) {
|
bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
|
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
|
||||||
@ -238,7 +267,8 @@ bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
|
bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
if (s->type(c) != lir::RegisterOperand) {
|
if (s->type(c) != lir::RegisterOperand) {
|
||||||
@ -256,7 +286,8 @@ bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterSite::acquire(Context* c, Value* v) {
|
void RegisterSite::acquire(Context* c, Value* v)
|
||||||
|
{
|
||||||
Target target;
|
Target target;
|
||||||
if (number != lir::NoRegister) {
|
if (number != lir::NoRegister) {
|
||||||
target = Target(number, lir::RegisterOperand, 0);
|
target = Target(number, lir::RegisterOperand, 0);
|
||||||
@ -271,35 +302,41 @@ void RegisterSite::acquire(Context* c, Value* v) {
|
|||||||
number = target.index;
|
number = target.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterSite::release(Context* c, Value* v) {
|
void RegisterSite::release(Context* c, Value* v)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
compiler::release(c, c->registerResources + number, v, this);
|
compiler::release(c, c->registerResources + number, v, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterSite::freeze(Context* c, Value* v) {
|
void RegisterSite::freeze(Context* c, Value* v)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
c->registerResources[number].freeze(c, v);
|
c->registerResources[number].freeze(c, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterSite::thaw(Context* c, Value* v) {
|
void RegisterSite::thaw(Context* c, Value* v)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
c->registerResources[number].thaw(c, v);
|
c->registerResources[number].thaw(c, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RegisterSite::frozen(Context* c UNUSED) {
|
bool RegisterSite::frozen(Context* c UNUSED)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
return c->registerResources[number].freezeCount != 0;
|
return c->registerResources[number].freezeCount != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lir::OperandType RegisterSite::type(Context*) {
|
lir::OperandType RegisterSite::type(Context*)
|
||||||
|
{
|
||||||
return lir::RegisterOperand;
|
return lir::RegisterOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high,
|
void RegisterSite::asAssemblerOperand(Context* c UNUSED,
|
||||||
|
Site* high,
|
||||||
lir::Operand* result)
|
lir::Operand* result)
|
||||||
{
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
@ -315,7 +352,8 @@ void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high,
|
|||||||
new (result) lir::Register(number, highNumber);
|
new (result) lir::Register(number, highNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* RegisterSite::copy(Context* c) {
|
Site* RegisterSite::copy(Context* c)
|
||||||
|
{
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
|
||||||
if (number != lir::NoRegister) {
|
if (number != lir::NoRegister) {
|
||||||
@ -327,38 +365,44 @@ Site* RegisterSite::copy(Context* c) {
|
|||||||
return freeRegisterSite(c, mask);
|
return freeRegisterSite(c, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* RegisterSite::copyLow(Context* c) {
|
Site* RegisterSite::copyLow(Context* c)
|
||||||
|
{
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* RegisterSite::copyHigh(Context* c) {
|
Site* RegisterSite::copyHigh(Context* c)
|
||||||
|
{
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* RegisterSite::makeNextWord(Context* c, unsigned) {
|
Site* RegisterSite::makeNextWord(Context* c, unsigned)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
assertT(c, ((1 << number) & c->regFile->generalRegisters.mask));
|
assertT(c, ((1 << number) & c->regFile->generalRegisters.mask));
|
||||||
|
|
||||||
return freeRegisterSite(c, c->regFile->generalRegisters.mask);
|
return freeRegisterSite(c, c->regFile->generalRegisters.mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
SiteMask RegisterSite::mask(Context* c UNUSED) {
|
SiteMask RegisterSite::mask(Context* c UNUSED)
|
||||||
|
{
|
||||||
return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex);
|
return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
SiteMask RegisterSite::nextWordMask(Context* c, unsigned) {
|
SiteMask RegisterSite::nextWordMask(Context* c, unsigned)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
if (registerSize(c) > c->targetInfo.pointerSize) {
|
if (registerSize(c) > c->targetInfo.pointerSize) {
|
||||||
return SiteMask
|
return SiteMask(1 << lir::RegisterOperand, number, NoFrameIndex);
|
||||||
(1 << lir::RegisterOperand, number, NoFrameIndex);
|
|
||||||
} else {
|
} else {
|
||||||
return SiteMask
|
return SiteMask(1 << lir::RegisterOperand,
|
||||||
(1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex);
|
c->regFile->generalRegisters.mask,
|
||||||
|
NoFrameIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned RegisterSite::registerSize(Context* c) {
|
unsigned RegisterSite::registerSize(Context* c)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
if ((1 << number) & c->regFile->floatRegisters.mask) {
|
if ((1 << number) & c->regFile->floatRegisters.mask) {
|
||||||
@ -368,65 +412,68 @@ unsigned RegisterSite::registerSize(Context* c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned RegisterSite::registerMask(Context* c UNUSED) {
|
unsigned RegisterSite::registerMask(Context* c UNUSED)
|
||||||
|
{
|
||||||
assertT(c, number != lir::NoRegister);
|
assertT(c, number != lir::NoRegister);
|
||||||
|
|
||||||
return 1 << number;
|
return 1 << number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Site* registerSite(Context* c, int number)
|
||||||
|
{
|
||||||
Site* registerSite(Context* c, int number) {
|
|
||||||
assertT(c, number >= 0);
|
assertT(c, number >= 0);
|
||||||
assertT(c,
|
assertT(c,
|
||||||
(1 << number) & (c->regFile->generalRegisters.mask
|
(1 << number) & (c->regFile->generalRegisters.mask
|
||||||
| c->regFile->floatRegisters.mask));
|
| c->regFile->floatRegisters.mask));
|
||||||
|
|
||||||
return new(c->zone) RegisterSite(1 << number, number);
|
return new (c->zone) RegisterSite(1 << number, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* freeRegisterSite(Context* c, uint32_t mask) {
|
Site* freeRegisterSite(Context* c, uint32_t mask)
|
||||||
return new(c->zone) RegisterSite(mask, lir::NoRegister);
|
{
|
||||||
|
return new (c->zone) RegisterSite(mask, lir::NoRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemorySite::MemorySite(int base, int offset, int index, unsigned scale):
|
MemorySite::MemorySite(int base, int offset, int index, unsigned scale)
|
||||||
acquired(false), base(base), offset(offset), index(index), scale(scale)
|
: acquired(false), base(base), offset(offset), index(index), scale(scale)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsigned MemorySite::toString(Context*, char* buffer, unsigned bufferSize) {
|
unsigned MemorySite::toString(Context*, char* buffer, unsigned bufferSize)
|
||||||
|
{
|
||||||
if (acquired) {
|
if (acquired) {
|
||||||
return vm::snprintf(buffer, bufferSize, "memory %d 0x%x %d %d",
|
return vm::snprintf(
|
||||||
base, offset, index, scale);
|
buffer, bufferSize, "memory %d 0x%x %d %d", base, offset, index, scale);
|
||||||
} else {
|
} else {
|
||||||
return vm::snprintf(buffer, bufferSize, "memory unacquired");
|
return vm::snprintf(buffer, bufferSize, "memory unacquired");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned MemorySite::copyCost(Context* c, Site* s) {
|
unsigned MemorySite::copyCost(Context* c, Site* s)
|
||||||
|
{
|
||||||
assertT(c, acquired);
|
assertT(c, acquired);
|
||||||
|
|
||||||
if (s and
|
if (s and (this == s or (s->type(c) == lir::MemoryOperand
|
||||||
(this == s or
|
|
||||||
(s->type(c) == lir::MemoryOperand
|
|
||||||
and static_cast<MemorySite*>(s)->base == base
|
and static_cast<MemorySite*>(s)->base == base
|
||||||
and static_cast<MemorySite*>(s)->offset == offset
|
and static_cast<MemorySite*>(s)->offset == offset
|
||||||
and static_cast<MemorySite*>(s)->index == index
|
and static_cast<MemorySite*>(s)->index == index
|
||||||
and static_cast<MemorySite*>(s)->scale == scale)))
|
and static_cast<MemorySite*>(s)->scale == scale))) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return MemoryCopyCost;
|
return MemoryCopyCost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemorySite::conflicts(const SiteMask& mask) {
|
bool MemorySite::conflicts(const SiteMask& mask)
|
||||||
|
{
|
||||||
return (mask.typeMask & (1 << lir::RegisterOperand)) != 0
|
return (mask.typeMask & (1 << lir::RegisterOperand)) != 0
|
||||||
and (((1 << base) & mask.registerMask) == 0
|
and (((1 << base) & mask.registerMask) == 0
|
||||||
or (index != lir::NoRegister
|
or (index != lir::NoRegister
|
||||||
and ((1 << index) & mask.registerMask) == 0));
|
and ((1 << index) & mask.registerMask) == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemorySite::match(Context* c, const SiteMask& mask) {
|
bool MemorySite::match(Context* c, const SiteMask& mask)
|
||||||
|
{
|
||||||
assertT(c, acquired);
|
assertT(c, acquired);
|
||||||
|
|
||||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||||
@ -446,7 +493,8 @@ bool MemorySite::match(Context* c, const SiteMask& mask) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
|
bool MemorySite::loneMatch(Context* c, const SiteMask& mask)
|
||||||
|
{
|
||||||
assertT(c, acquired);
|
assertT(c, acquired);
|
||||||
|
|
||||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||||
@ -463,7 +511,8 @@ bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) {
|
bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index)
|
||||||
|
{
|
||||||
if (s->type(c) == lir::MemoryOperand) {
|
if (s->type(c) == lir::MemoryOperand) {
|
||||||
MemorySite* ms = static_cast<MemorySite*>(s);
|
MemorySite* ms = static_cast<MemorySite*>(s);
|
||||||
return ms->base == this->base
|
return ms->base == this->base
|
||||||
@ -481,7 +530,8 @@ bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemorySite::acquire(Context* c, Value* v) {
|
void MemorySite::acquire(Context* c, Value* v)
|
||||||
|
{
|
||||||
c->registerResources[base].increment(c);
|
c->registerResources[base].increment(c);
|
||||||
if (index != lir::NoRegister) {
|
if (index != lir::NoRegister) {
|
||||||
c->registerResources[index].increment(c);
|
c->registerResources[index].increment(c);
|
||||||
@ -491,20 +541,21 @@ void MemorySite::acquire(Context* c, Value* v) {
|
|||||||
assertT(c, index == lir::NoRegister);
|
assertT(c, index == lir::NoRegister);
|
||||||
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||||
|
|
||||||
compiler::acquire
|
compiler::acquire(
|
||||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
acquired = true;
|
acquired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemorySite::release(Context* c, Value* v) {
|
void MemorySite::release(Context* c, Value* v)
|
||||||
|
{
|
||||||
if (base == c->arch->stack()) {
|
if (base == c->arch->stack()) {
|
||||||
assertT(c, index == lir::NoRegister);
|
assertT(c, index == lir::NoRegister);
|
||||||
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||||
|
|
||||||
compiler::release
|
compiler::release(
|
||||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
c->registerResources[base].decrement(c);
|
c->registerResources[base].decrement(c);
|
||||||
@ -515,7 +566,8 @@ void MemorySite::release(Context* c, Value* v) {
|
|||||||
acquired = false;
|
acquired = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemorySite::freeze(Context* c, Value* v) {
|
void MemorySite::freeze(Context* c, Value* v)
|
||||||
|
{
|
||||||
if (base == c->arch->stack()) {
|
if (base == c->arch->stack()) {
|
||||||
c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v);
|
c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v);
|
||||||
} else {
|
} else {
|
||||||
@ -526,7 +578,8 @@ void MemorySite::freeze(Context* c, Value* v) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemorySite::thaw(Context* c, Value* v) {
|
void MemorySite::thaw(Context* c, Value* v)
|
||||||
|
{
|
||||||
if (base == c->arch->stack()) {
|
if (base == c->arch->stack()) {
|
||||||
c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v);
|
c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v);
|
||||||
} else {
|
} else {
|
||||||
@ -537,16 +590,19 @@ void MemorySite::thaw(Context* c, Value* v) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemorySite::frozen(Context* c) {
|
bool MemorySite::frozen(Context* c)
|
||||||
|
{
|
||||||
return base == c->arch->stack()
|
return base == c->arch->stack()
|
||||||
and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0;
|
and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lir::OperandType MemorySite::type(Context*) {
|
lir::OperandType MemorySite::type(Context*)
|
||||||
|
{
|
||||||
return lir::MemoryOperand;
|
return lir::MemoryOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
void MemorySite::asAssemblerOperand(Context* c UNUSED,
|
||||||
|
Site* high UNUSED,
|
||||||
lir::Operand* result)
|
lir::Operand* result)
|
||||||
{
|
{
|
||||||
// todo: endianness?
|
// todo: endianness?
|
||||||
@ -563,11 +619,13 @@ void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
|||||||
new (result) lir::Memory(base, offset, index, scale);
|
new (result) lir::Memory(base, offset, index, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* MemorySite::copy(Context* c) {
|
Site* MemorySite::copy(Context* c)
|
||||||
|
{
|
||||||
return memorySite(c, base, offset, index, scale);
|
return memorySite(c, base, offset, index, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* MemorySite::copyHalf(Context* c, bool add) {
|
Site* MemorySite::copyHalf(Context* c, bool add)
|
||||||
|
{
|
||||||
if (add) {
|
if (add) {
|
||||||
return memorySite(
|
return memorySite(
|
||||||
c, base, offset + c->targetInfo.pointerSize, index, scale);
|
c, base, offset + c->targetInfo.pointerSize, index, scale);
|
||||||
@ -576,15 +634,18 @@ Site* MemorySite::copyHalf(Context* c, bool add) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* MemorySite::copyLow(Context* c) {
|
Site* MemorySite::copyLow(Context* c)
|
||||||
|
{
|
||||||
return copyHalf(c, c->arch->bigEndian());
|
return copyHalf(c, c->arch->bigEndian());
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* MemorySite::copyHigh(Context* c) {
|
Site* MemorySite::copyHigh(Context* c)
|
||||||
|
{
|
||||||
return copyHalf(c, not c->arch->bigEndian());
|
return copyHalf(c, not c->arch->bigEndian());
|
||||||
}
|
}
|
||||||
|
|
||||||
Site* MemorySite::makeNextWord(Context* c, unsigned index) {
|
Site* MemorySite::makeNextWord(Context* c, unsigned index)
|
||||||
|
{
|
||||||
return memorySite(c,
|
return memorySite(c,
|
||||||
base,
|
base,
|
||||||
offset + ((index == 1) xor c->arch->bigEndian()
|
offset + ((index == 1) xor c->arch->bigEndian()
|
||||||
@ -594,13 +655,17 @@ Site* MemorySite::makeNextWord(Context* c, unsigned index) {
|
|||||||
scale);
|
scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
SiteMask MemorySite::mask(Context* c) {
|
SiteMask MemorySite::mask(Context* c)
|
||||||
return SiteMask(1 << lir::MemoryOperand, 0, (base == c->arch->stack())
|
{
|
||||||
|
return SiteMask(1 << lir::MemoryOperand,
|
||||||
|
0,
|
||||||
|
(base == c->arch->stack())
|
||||||
? static_cast<int>(offsetToFrameIndex(c, offset))
|
? static_cast<int>(offsetToFrameIndex(c, offset))
|
||||||
: NoFrameIndex);
|
: NoFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
SiteMask MemorySite::nextWordMask(Context* c, unsigned index) {
|
SiteMask MemorySite::nextWordMask(Context* c, unsigned index)
|
||||||
|
{
|
||||||
int frameIndex;
|
int frameIndex;
|
||||||
if (base == c->arch->stack()) {
|
if (base == c->arch->stack()) {
|
||||||
assertT(c, this->index == lir::NoRegister);
|
assertT(c, this->index == lir::NoRegister);
|
||||||
@ -612,19 +677,28 @@ SiteMask MemorySite::nextWordMask(Context* c, unsigned index) {
|
|||||||
return SiteMask(1 << lir::MemoryOperand, 0, frameIndex);
|
return SiteMask(1 << lir::MemoryOperand, 0, frameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemorySite::isVolatile(Context* c) {
|
bool MemorySite::isVolatile(Context* c)
|
||||||
|
{
|
||||||
return base != c->arch->stack();
|
return base != c->arch->stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemorySite* memorySite(Context* c,
|
||||||
MemorySite* memorySite(Context* c, int base, int offset, int index, unsigned scale) {
|
int base,
|
||||||
return new(c->zone) MemorySite(base, offset, index, scale);
|
int offset,
|
||||||
|
int index,
|
||||||
|
unsigned scale)
|
||||||
|
{
|
||||||
|
return new (c->zone) MemorySite(base, offset, index, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemorySite* frameSite(Context* c, int frameIndex) {
|
MemorySite* frameSite(Context* c, int frameIndex)
|
||||||
|
{
|
||||||
assertT(c, frameIndex >= 0);
|
assertT(c, frameIndex >= 0);
|
||||||
return memorySite
|
return memorySite(c,
|
||||||
(c, c->arch->stack(), frameIndexToOffset(c, frameIndex), lir::NoRegister, 0);
|
c->arch->stack(),
|
||||||
|
frameIndexToOffset(c, frameIndex),
|
||||||
|
lir::NoRegister,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
@ -30,23 +30,29 @@ const unsigned CopyPenalty = 10;
|
|||||||
|
|
||||||
class SiteMask {
|
class SiteMask {
|
||||||
public:
|
public:
|
||||||
SiteMask(): typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex) { }
|
SiteMask() : typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex):
|
SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex)
|
||||||
typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex)
|
: typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SiteMask intersectionWith(const SiteMask& b);
|
SiteMask intersectionWith(const SiteMask& b);
|
||||||
|
|
||||||
static SiteMask fixedRegisterMask(int number) {
|
static SiteMask fixedRegisterMask(int number)
|
||||||
|
{
|
||||||
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
|
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SiteMask lowPart(const OperandMask& mask) {
|
static SiteMask lowPart(const OperandMask& mask)
|
||||||
|
{
|
||||||
return SiteMask(mask.typeMask, mask.registerMask, AnyFrameIndex);
|
return SiteMask(mask.typeMask, mask.registerMask, AnyFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SiteMask highPart(const OperandMask& mask) {
|
static SiteMask highPart(const OperandMask& mask)
|
||||||
|
{
|
||||||
return SiteMask(mask.typeMask, mask.registerMask >> 32, AnyFrameIndex);
|
return SiteMask(mask.typeMask, mask.registerMask >> 32, AnyFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,9 +63,14 @@ class SiteMask {
|
|||||||
|
|
||||||
class Site {
|
class Site {
|
||||||
public:
|
public:
|
||||||
Site(): next(0) { }
|
Site() : next(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual Site* readTarget(Context*, Read*) { return this; }
|
virtual Site* readTarget(Context*, Read*)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
virtual unsigned toString(Context*, char*, unsigned) = 0;
|
virtual unsigned toString(Context*, char*, unsigned) = 0;
|
||||||
|
|
||||||
@ -71,15 +82,26 @@ class Site {
|
|||||||
|
|
||||||
virtual bool matchNextWord(Context*, Site*, unsigned) = 0;
|
virtual bool matchNextWord(Context*, Site*, unsigned) = 0;
|
||||||
|
|
||||||
virtual void acquire(Context*, Value*) { }
|
virtual void acquire(Context*, Value*)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual void release(Context*, Value*) { }
|
virtual void release(Context*, Value*)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual void freeze(Context*, Value*) { }
|
virtual void freeze(Context*, Value*)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual void thaw(Context*, Value*) { }
|
virtual void thaw(Context*, Value*)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool frozen(Context*) { return false; }
|
virtual bool frozen(Context*)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
virtual lir::OperandType type(Context*) = 0;
|
virtual lir::OperandType type(Context*) = 0;
|
||||||
|
|
||||||
@ -99,16 +121,24 @@ class Site {
|
|||||||
|
|
||||||
virtual unsigned registerSize(Context*);
|
virtual unsigned registerSize(Context*);
|
||||||
|
|
||||||
virtual unsigned registerMask(Context*) { return 0; }
|
virtual unsigned registerMask(Context*)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool isVolatile(Context*) { return false; }
|
virtual bool isVolatile(Context*)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Site* next;
|
Site* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SiteIterator {
|
class SiteIterator {
|
||||||
public:
|
public:
|
||||||
SiteIterator(Context* c, Value* v, bool includeBuddies = true,
|
SiteIterator(Context* c,
|
||||||
|
Value* v,
|
||||||
|
bool includeBuddies = true,
|
||||||
bool includeNextWord = true);
|
bool includeNextWord = true);
|
||||||
|
|
||||||
Site** findNext(Site** p);
|
Site** findNext(Site** p);
|
||||||
@ -130,43 +160,52 @@ Site* constantSite(Context* c, Promise* value);
|
|||||||
Site* constantSite(Context* c, int64_t value);
|
Site* constantSite(Context* c, int64_t value);
|
||||||
|
|
||||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high);
|
Promise* combinedPromise(Context* c, Promise* low, Promise* high);
|
||||||
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask);
|
Promise* shiftMaskPromise(Context* c,
|
||||||
|
Promise* base,
|
||||||
|
unsigned shift,
|
||||||
|
int64_t mask);
|
||||||
|
|
||||||
class ConstantSite: public Site {
|
class ConstantSite : public Site {
|
||||||
public:
|
public:
|
||||||
ConstantSite(Promise* value): value(value) { }
|
ConstantSite(Promise* value) : value(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) {
|
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize)
|
||||||
|
{
|
||||||
if (value->resolved()) {
|
if (value->resolved()) {
|
||||||
return vm::snprintf
|
return vm::snprintf(buffer, bufferSize, "constant %" LLD, value->value());
|
||||||
(buffer, bufferSize, "constant %" LLD, value->value());
|
|
||||||
} else {
|
} else {
|
||||||
return vm::snprintf(buffer, bufferSize, "constant unresolved");
|
return vm::snprintf(buffer, bufferSize, "constant unresolved");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned copyCost(Context*, Site* s) {
|
virtual unsigned copyCost(Context*, Site* s)
|
||||||
|
{
|
||||||
return (s == this ? 0 : ConstantCopyCost);
|
return (s == this ? 0 : ConstantCopyCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool match(Context*, const SiteMask& mask) {
|
virtual bool match(Context*, const SiteMask& mask)
|
||||||
|
{
|
||||||
return mask.typeMask & (1 << lir::ConstantOperand);
|
return mask.typeMask & (1 << lir::ConstantOperand);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool loneMatch(Context*, const SiteMask&) {
|
virtual bool loneMatch(Context*, const SiteMask&)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool matchNextWord(Context* c, Site* s, unsigned) {
|
virtual bool matchNextWord(Context* c, Site* s, unsigned)
|
||||||
|
{
|
||||||
return s->type(c) == lir::ConstantOperand;
|
return s->type(c) == lir::ConstantOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual lir::OperandType type(Context*) {
|
virtual lir::OperandType type(Context*)
|
||||||
|
{
|
||||||
return lir::ConstantOperand;
|
return lir::ConstantOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void asAssemblerOperand(Context* c, Site* high,
|
virtual void asAssemblerOperand(Context* c, Site* high, lir::Operand* result)
|
||||||
lir::Operand* result)
|
|
||||||
{
|
{
|
||||||
Promise* v = value;
|
Promise* v = value;
|
||||||
if (high != this) {
|
if (high != this) {
|
||||||
@ -175,27 +214,33 @@ class ConstantSite: public Site {
|
|||||||
new (result) lir::Constant(v);
|
new (result) lir::Constant(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Site* copy(Context* c) {
|
virtual Site* copy(Context* c)
|
||||||
|
{
|
||||||
return constantSite(c, value);
|
return constantSite(c, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Site* copyLow(Context* c) {
|
virtual Site* copyLow(Context* c)
|
||||||
|
{
|
||||||
return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF));
|
return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Site* copyHigh(Context* c) {
|
virtual Site* copyHigh(Context* c)
|
||||||
|
{
|
||||||
return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF));
|
return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Site* makeNextWord(Context* c, unsigned) {
|
virtual Site* makeNextWord(Context* c, unsigned)
|
||||||
|
{
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual SiteMask mask(Context*) {
|
virtual SiteMask mask(Context*)
|
||||||
|
{
|
||||||
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
|
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual SiteMask nextWordMask(Context*, unsigned) {
|
virtual SiteMask nextWordMask(Context*, unsigned)
|
||||||
|
{
|
||||||
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
|
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +249,7 @@ class ConstantSite: public Site {
|
|||||||
|
|
||||||
Site* addressSite(Context* c, Promise* address);
|
Site* addressSite(Context* c, Promise* address);
|
||||||
|
|
||||||
class RegisterSite: public Site {
|
class RegisterSite : public Site {
|
||||||
public:
|
public:
|
||||||
RegisterSite(uint32_t mask, int number);
|
RegisterSite(uint32_t mask, int number);
|
||||||
|
|
||||||
@ -230,7 +275,8 @@ class RegisterSite: public Site {
|
|||||||
|
|
||||||
virtual lir::OperandType type(Context*);
|
virtual lir::OperandType type(Context*);
|
||||||
|
|
||||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high,
|
virtual void asAssemblerOperand(Context* c UNUSED,
|
||||||
|
Site* high,
|
||||||
lir::Operand* result);
|
lir::Operand* result);
|
||||||
|
|
||||||
virtual Site* copy(Context* c);
|
virtual Site* copy(Context* c);
|
||||||
@ -256,8 +302,7 @@ class RegisterSite: public Site {
|
|||||||
Site* registerSite(Context* c, int number);
|
Site* registerSite(Context* c, int number);
|
||||||
Site* freeRegisterSite(Context* c, uint32_t mask);
|
Site* freeRegisterSite(Context* c, uint32_t mask);
|
||||||
|
|
||||||
|
class MemorySite : public Site {
|
||||||
class MemorySite: public Site {
|
|
||||||
public:
|
public:
|
||||||
MemorySite(int base, int offset, int index, unsigned scale);
|
MemorySite(int base, int offset, int index, unsigned scale);
|
||||||
|
|
||||||
@ -285,7 +330,8 @@ class MemorySite: public Site {
|
|||||||
|
|
||||||
virtual lir::OperandType type(Context*);
|
virtual lir::OperandType type(Context*);
|
||||||
|
|
||||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
virtual void asAssemblerOperand(Context* c UNUSED,
|
||||||
|
Site* high UNUSED,
|
||||||
lir::Operand* result);
|
lir::Operand* result);
|
||||||
|
|
||||||
virtual Site* copy(Context* c);
|
virtual Site* copy(Context* c);
|
||||||
@ -311,7 +357,11 @@ class MemorySite: public Site {
|
|||||||
unsigned scale;
|
unsigned scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
MemorySite* memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, unsigned scale = 1);
|
MemorySite* memorySite(Context* c,
|
||||||
|
int base,
|
||||||
|
int offset = 0,
|
||||||
|
int index = lir::NoRegister,
|
||||||
|
unsigned scale = 1);
|
||||||
MemorySite* frameSite(Context* c, int frameIndex);
|
MemorySite* frameSite(Context* c, int frameIndex);
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
@ -31,26 +31,33 @@ Value::Value(Site* site, Site* target, ir::Type type)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::findSite(Site* site) {
|
bool Value::findSite(Site* site)
|
||||||
|
{
|
||||||
for (Site* s = this->sites; s; s = s->next) {
|
for (Site* s = this->sites; s; s = s->next) {
|
||||||
if (s == site) return true;
|
if (s == site)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::isBuddyOf(Value* b) {
|
bool Value::isBuddyOf(Value* b)
|
||||||
|
{
|
||||||
Value* a = this;
|
Value* a = this;
|
||||||
if (a == b) return true;
|
if (a == b)
|
||||||
|
return true;
|
||||||
for (Value* p = a->buddy; p != a; p = p->buddy) {
|
for (Value* p = a->buddy; p != a; p = p->buddy) {
|
||||||
if (p == b) return true;
|
if (p == b)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::addSite(Context* c, Site* s) {
|
void Value::addSite(Context* c, Site* s)
|
||||||
|
{
|
||||||
if (not this->findSite(s)) {
|
if (not this->findSite(s)) {
|
||||||
if (DebugSites) {
|
if (DebugSites) {
|
||||||
char buffer[256]; s->toString(c, buffer, 256);
|
char buffer[256];
|
||||||
|
s->toString(c, buffer, 256);
|
||||||
fprintf(stderr, "add site %s to %p\n", buffer, this);
|
fprintf(stderr, "add site %s to %p\n", buffer, this);
|
||||||
}
|
}
|
||||||
s->acquire(c, this);
|
s->acquire(c, this);
|
||||||
@ -59,8 +66,8 @@ void Value::addSite(Context* c, Site* s) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Value::grow(Context* c)
|
||||||
void Value::grow(Context* c) {
|
{
|
||||||
assertT(c, this->nextWord == this);
|
assertT(c, this->nextWord == this);
|
||||||
|
|
||||||
Value* next = value(c, this->type);
|
Value* next = value(c, this->type);
|
||||||
@ -69,14 +76,15 @@ void Value::grow(Context* c) {
|
|||||||
next->wordIndex = 1;
|
next->wordIndex = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Value::maybeSplit(Context* c)
|
||||||
void Value::maybeSplit(Context* c) {
|
{
|
||||||
if (this->nextWord == this) {
|
if (this->nextWord == this) {
|
||||||
this->split(c);
|
this->split(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::split(Context* c) {
|
void Value::split(Context* c)
|
||||||
|
{
|
||||||
this->grow(c);
|
this->grow(c);
|
||||||
for (SiteIterator it(c, this); it.hasMore();) {
|
for (SiteIterator it(c, this); it.hasMore();) {
|
||||||
Site* s = it.next();
|
Site* s = it.next();
|
||||||
@ -87,11 +95,13 @@ void Value::split(Context* c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::removeSite(Context* c, Site* s) {
|
void Value::removeSite(Context* c, Site* s)
|
||||||
|
{
|
||||||
for (SiteIterator it(c, this); it.hasMore();) {
|
for (SiteIterator it(c, this); it.hasMore();) {
|
||||||
if (s == it.next()) {
|
if (s == it.next()) {
|
||||||
if (DebugSites) {
|
if (DebugSites) {
|
||||||
char buffer[256]; s->toString(c, buffer, 256);
|
char buffer[256];
|
||||||
|
s->toString(c, buffer, 256);
|
||||||
fprintf(stderr, "remove site %s from %p\n", buffer, this);
|
fprintf(stderr, "remove site %s from %p\n", buffer, this);
|
||||||
}
|
}
|
||||||
it.remove(c);
|
it.remove(c);
|
||||||
@ -104,12 +114,14 @@ void Value::removeSite(Context* c, Site* s) {
|
|||||||
assertT(c, not this->findSite(s));
|
assertT(c, not this->findSite(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::hasSite(Context* c) {
|
bool Value::hasSite(Context* c)
|
||||||
|
{
|
||||||
SiteIterator it(c, this);
|
SiteIterator it(c, this);
|
||||||
return it.hasMore();
|
return it.hasMore();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::uniqueSite(Context* c, Site* s) {
|
bool Value::uniqueSite(Context* c, Site* s)
|
||||||
|
{
|
||||||
SiteIterator it(c, this);
|
SiteIterator it(c, this);
|
||||||
Site* p UNUSED = it.next();
|
Site* p UNUSED = it.next();
|
||||||
if (it.hasMore()) {
|
if (it.hasMore()) {
|
||||||
@ -133,7 +145,8 @@ bool Value::uniqueSite(Context* c, Site* s) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::clearSites(Context* c) {
|
void Value::clearSites(Context* c)
|
||||||
|
{
|
||||||
if (DebugSites) {
|
if (DebugSites) {
|
||||||
fprintf(stderr, "clear sites for %p\n", this);
|
fprintf(stderr, "clear sites for %p\n", this);
|
||||||
}
|
}
|
||||||
@ -143,9 +156,9 @@ void Value::clearSites(Context* c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
bool Value::hasBuddy(Context* c, Value* b) {
|
bool Value::hasBuddy(Context* c, Value* b)
|
||||||
|
{
|
||||||
Value* a = this;
|
Value* a = this;
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
return true;
|
return true;
|
||||||
@ -166,7 +179,7 @@ bool Value::hasBuddy(Context* c, Value* b) {
|
|||||||
|
|
||||||
Value* value(Context* c, ir::Type type, Site* site, Site* target)
|
Value* value(Context* c, ir::Type type, Site* site, Site* target)
|
||||||
{
|
{
|
||||||
return new(c->zone) Value(site, target, type);
|
return new (c->zone) Value(site, target, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace regalloc
|
} // namespace regalloc
|
||||||
|
@ -63,7 +63,6 @@ class Value : public ir::Value {
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
bool hasBuddy(Context* c, Value* b);
|
bool hasBuddy(Context* c, Value* b);
|
||||||
#endif // not NDEBUG
|
#endif // not NDEBUG
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool isFloatValue(ir::Value* a)
|
inline bool isFloatValue(ir::Value* a)
|
||||||
|
@ -13,20 +13,20 @@
|
|||||||
namespace avian {
|
namespace avian {
|
||||||
namespace codegen {
|
namespace codegen {
|
||||||
|
|
||||||
unsigned
|
unsigned RegisterMask::maskStart(uint32_t mask)
|
||||||
RegisterMask::maskStart(uint32_t mask)
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i <= 31; ++i) {
|
for (int i = 0; i <= 31; ++i) {
|
||||||
if (mask & (1 << i)) return i;
|
if (mask & (1 << i))
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned RegisterMask::maskLimit(uint32_t mask)
|
||||||
RegisterMask::maskLimit(uint32_t mask)
|
|
||||||
{
|
{
|
||||||
for (int i = 31; i >= 0; --i) {
|
for (int i = 31; i >= 0; --i) {
|
||||||
if (mask & (1 << i)) return i + 1;
|
if (mask & (1 << i))
|
||||||
|
return i + 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,9 @@ namespace arm {
|
|||||||
|
|
||||||
namespace isa {
|
namespace isa {
|
||||||
// HARDWARE FLAGS
|
// HARDWARE FLAGS
|
||||||
bool vfpSupported() {
|
bool vfpSupported()
|
||||||
// TODO: Use at runtime detection
|
{
|
||||||
|
// TODO: Use at runtime detection
|
||||||
#if defined(__ARM_PCS_VFP)
|
#if defined(__ARM_PCS_VFP)
|
||||||
// armhf
|
// armhf
|
||||||
return true;
|
return true;
|
||||||
@ -51,7 +52,10 @@ bool vfpSupported() {
|
|||||||
}
|
}
|
||||||
} // namespace isa
|
} // namespace isa
|
||||||
|
|
||||||
inline unsigned lo8(int64_t i) { return (unsigned)(i&MASK_LO8); }
|
inline unsigned lo8(int64_t i)
|
||||||
|
{
|
||||||
|
return (unsigned)(i & MASK_LO8);
|
||||||
|
}
|
||||||
|
|
||||||
const RegisterFile MyRegisterFileWithoutFloats(GPR_MASK, 0);
|
const RegisterFile MyRegisterFileWithoutFloats(GPR_MASK, 0);
|
||||||
const RegisterFile MyRegisterFileWithFloats(GPR_MASK, FPR_MASK);
|
const RegisterFile MyRegisterFileWithFloats(GPR_MASK, FPR_MASK);
|
||||||
@ -59,8 +63,8 @@ const RegisterFile MyRegisterFileWithFloats(GPR_MASK, FPR_MASK);
|
|||||||
const unsigned FrameHeaderSize = 1;
|
const unsigned FrameHeaderSize = 1;
|
||||||
|
|
||||||
const unsigned StackAlignmentInBytes = 8;
|
const unsigned StackAlignmentInBytes = 8;
|
||||||
const unsigned StackAlignmentInWords
|
const unsigned StackAlignmentInWords = StackAlignmentInBytes
|
||||||
= StackAlignmentInBytes / TargetBytesPerWord;
|
/ TargetBytesPerWord;
|
||||||
|
|
||||||
void resolve(MyBlock*);
|
void resolve(MyBlock*);
|
||||||
|
|
||||||
@ -74,16 +78,20 @@ using namespace isa;
|
|||||||
|
|
||||||
// END OPERATION COMPILERS
|
// END OPERATION COMPILERS
|
||||||
|
|
||||||
unsigned
|
unsigned argumentFootprint(unsigned footprint)
|
||||||
argumentFootprint(unsigned footprint)
|
|
||||||
{
|
{
|
||||||
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
|
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void nextFrame(ArchitectureContext* con,
|
||||||
nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
uint32_t* start,
|
||||||
unsigned footprint, void* link, bool,
|
unsigned size UNUSED,
|
||||||
int targetParameterFootprint UNUSED, void** ip, void** stack)
|
unsigned footprint,
|
||||||
|
void* link,
|
||||||
|
bool,
|
||||||
|
int targetParameterFootprint UNUSED,
|
||||||
|
void** ip,
|
||||||
|
void** stack)
|
||||||
{
|
{
|
||||||
assertT(con, *ip >= start);
|
assertT(con, *ip >= start);
|
||||||
assertT(con, *ip <= start + (size / TargetBytesPerWord));
|
assertT(con, *ip <= start + (size / TargetBytesPerWord));
|
||||||
@ -125,9 +133,14 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
|||||||
unsigned value = *instruction & 0xff;
|
unsigned value = *instruction & 0xff;
|
||||||
unsigned rotation = (*instruction >> 8) & 0xf;
|
unsigned rotation = (*instruction >> 8) & 0xf;
|
||||||
switch (rotation) {
|
switch (rotation) {
|
||||||
case 0: offset -= value / TargetBytesPerWord; break;
|
case 0:
|
||||||
case 15: offset -= value; break;
|
offset -= value / TargetBytesPerWord;
|
||||||
default: abort(con);
|
break;
|
||||||
|
case 15:
|
||||||
|
offset -= value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,45 +151,56 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
|||||||
*stack = static_cast<void**>(*stack) + offset;
|
*stack = static_cast<void**>(*stack) + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyArchitecture: public Architecture {
|
class MyArchitecture : public Architecture {
|
||||||
public:
|
public:
|
||||||
MyArchitecture(System* system): con(system), referenceCount(0) {
|
MyArchitecture(System* system) : con(system), referenceCount(0)
|
||||||
|
{
|
||||||
populateTables(&con);
|
populateTables(&con);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned floatRegisterSize() {
|
virtual unsigned floatRegisterSize()
|
||||||
|
{
|
||||||
return vfpSupported() ? 8 : 0;
|
return vfpSupported() ? 8 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const RegisterFile* registerFile() {
|
virtual const RegisterFile* registerFile()
|
||||||
return vfpSupported() ? &MyRegisterFileWithFloats : &MyRegisterFileWithoutFloats;
|
{
|
||||||
|
return vfpSupported() ? &MyRegisterFileWithFloats
|
||||||
|
: &MyRegisterFileWithoutFloats;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int scratch() {
|
virtual int scratch()
|
||||||
|
{
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int stack() {
|
virtual int stack()
|
||||||
|
{
|
||||||
return StackRegister;
|
return StackRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int thread() {
|
virtual int thread()
|
||||||
|
{
|
||||||
return ThreadRegister;
|
return ThreadRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int returnLow() {
|
virtual int returnLow()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int returnHigh() {
|
virtual int returnHigh()
|
||||||
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int virtualCallTarget() {
|
virtual int virtualCallTarget()
|
||||||
|
{
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int virtualCallIndex() {
|
virtual int virtualCallIndex()
|
||||||
|
{
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,15 +209,18 @@ class MyArchitecture: public Architecture {
|
|||||||
return ir::TargetInfo(TargetBytesPerWord);
|
return ir::TargetInfo(TargetBytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool bigEndian() {
|
virtual bool bigEndian()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uintptr_t maximumImmediateJump() {
|
virtual uintptr_t maximumImmediateJump()
|
||||||
|
{
|
||||||
return 0x1FFFFFF;
|
return 0x1FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool reserved(int register_) {
|
virtual bool reserved(int register_)
|
||||||
|
{
|
||||||
switch (register_) {
|
switch (register_) {
|
||||||
case LinkRegister:
|
case LinkRegister:
|
||||||
case StackRegister:
|
case StackRegister:
|
||||||
@ -206,15 +233,18 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameFootprint(unsigned footprint) {
|
virtual unsigned frameFootprint(unsigned footprint)
|
||||||
|
{
|
||||||
return max(footprint, StackAlignmentInWords);
|
return max(footprint, StackAlignmentInWords);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned argumentFootprint(unsigned footprint) {
|
virtual unsigned argumentFootprint(unsigned footprint)
|
||||||
|
{
|
||||||
return arm::argumentFootprint(footprint);
|
return arm::argumentFootprint(footprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool argumentAlignment() {
|
virtual bool argumentAlignment()
|
||||||
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
@ -222,7 +252,8 @@ class MyArchitecture: public Architecture {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool argumentRegisterAlignment() {
|
virtual bool argumentRegisterAlignment()
|
||||||
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
@ -230,29 +261,34 @@ class MyArchitecture: public Architecture {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned argumentRegisterCount() {
|
virtual unsigned argumentRegisterCount()
|
||||||
|
{
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int argumentRegister(unsigned index) {
|
virtual int argumentRegister(unsigned index)
|
||||||
|
{
|
||||||
assertT(&con, index < argumentRegisterCount());
|
assertT(&con, index < argumentRegisterCount());
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool hasLinkRegister() {
|
virtual bool hasLinkRegister()
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned stackAlignmentInWords() {
|
virtual unsigned stackAlignmentInWords()
|
||||||
|
{
|
||||||
return StackAlignmentInWords;
|
return StackAlignmentInWords;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool matchCall(void* returnAddress, void* target) {
|
virtual bool matchCall(void* returnAddress, void* target)
|
||||||
|
{
|
||||||
uint32_t* instruction = static_cast<uint32_t*>(returnAddress) - 1;
|
uint32_t* instruction = static_cast<uint32_t*>(returnAddress) - 1;
|
||||||
|
|
||||||
return *instruction == static_cast<uint32_t>
|
return *instruction == static_cast<uint32_t>(
|
||||||
(bl(static_cast<uint8_t*>(target)
|
bl(static_cast<uint8_t*>(target)
|
||||||
- reinterpret_cast<uint8_t*>(instruction)));
|
- reinterpret_cast<uint8_t*>(instruction)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +301,8 @@ class MyArchitecture: public Architecture {
|
|||||||
case lir::Jump:
|
case lir::Jump:
|
||||||
case lir::AlignedCall:
|
case lir::AlignedCall:
|
||||||
case lir::AlignedJump: {
|
case lir::AlignedJump: {
|
||||||
updateOffset(con.s, static_cast<uint8_t*>(returnAddress) - 4,
|
updateOffset(con.s,
|
||||||
|
static_cast<uint8_t*>(returnAddress) - 4,
|
||||||
reinterpret_cast<intptr_t>(newTarget));
|
reinterpret_cast<intptr_t>(newTarget));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -278,67 +315,90 @@ class MyArchitecture: public Architecture {
|
|||||||
= newTarget;
|
= newTarget;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: abort(&con);
|
default:
|
||||||
|
abort(&con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned constantCallSize() {
|
virtual unsigned constantCallSize()
|
||||||
|
{
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setConstant(void* dst, uint64_t constant) {
|
virtual void setConstant(void* dst, uint64_t constant)
|
||||||
|
{
|
||||||
*static_cast<target_uintptr_t*>(dst) = constant;
|
*static_cast<target_uintptr_t*>(dst) = constant;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned alignFrameSize(unsigned sizeInWords) {
|
virtual unsigned alignFrameSize(unsigned sizeInWords)
|
||||||
|
{
|
||||||
return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords)
|
return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords)
|
||||||
- FrameHeaderSize;
|
- FrameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
virtual void nextFrame(void* start,
|
||||||
void* link, bool mostRecent,
|
unsigned size,
|
||||||
int targetParameterFootprint, void** ip,
|
unsigned footprint,
|
||||||
|
void* link,
|
||||||
|
bool mostRecent,
|
||||||
|
int targetParameterFootprint,
|
||||||
|
void** ip,
|
||||||
void** stack)
|
void** stack)
|
||||||
{
|
{
|
||||||
arm::nextFrame(&con, static_cast<uint32_t*>(start), size, footprint, link,
|
arm::nextFrame(&con,
|
||||||
mostRecent, targetParameterFootprint, ip, stack);
|
static_cast<uint32_t*>(start),
|
||||||
|
size,
|
||||||
|
footprint,
|
||||||
|
link,
|
||||||
|
mostRecent,
|
||||||
|
targetParameterFootprint,
|
||||||
|
ip,
|
||||||
|
stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* frameIp(void* stack) {
|
virtual void* frameIp(void* stack)
|
||||||
|
{
|
||||||
return stack ? static_cast<void**>(stack)[returnAddressOffset()] : 0;
|
return stack ? static_cast<void**>(stack)[returnAddressOffset()] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameHeaderSize() {
|
virtual unsigned frameHeaderSize()
|
||||||
|
{
|
||||||
return FrameHeaderSize;
|
return FrameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameReturnAddressSize() {
|
virtual unsigned frameReturnAddressSize()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameFooterSize() {
|
virtual unsigned frameFooterSize()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int returnAddressOffset() {
|
virtual int returnAddressOffset()
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int framePointerOffset() {
|
virtual int framePointerOffset()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool alwaysCondensed(lir::BinaryOperation) {
|
virtual bool alwaysCondensed(lir::BinaryOperation)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool alwaysCondensed(lir::TernaryOperation) {
|
virtual bool alwaysCondensed(lir::TernaryOperation)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void plan
|
virtual void plan(lir::UnaryOperation,
|
||||||
(lir::UnaryOperation,
|
unsigned,
|
||||||
unsigned, OperandMask& aMask,
|
OperandMask& aMask,
|
||||||
bool* thunk)
|
bool* thunk)
|
||||||
{
|
{
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
|
||||||
@ -346,10 +406,11 @@ class MyArchitecture: public Architecture {
|
|||||||
*thunk = false;
|
*thunk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planSource
|
virtual void planSource(lir::BinaryOperation op,
|
||||||
(lir::BinaryOperation op,
|
unsigned aSize,
|
||||||
unsigned aSize, OperandMask& aMask,
|
OperandMask& aMask,
|
||||||
unsigned bSize, bool* thunk)
|
unsigned bSize,
|
||||||
|
bool* thunk)
|
||||||
{
|
{
|
||||||
*thunk = false;
|
*thunk = false;
|
||||||
aMask.typeMask = ~0;
|
aMask.typeMask = ~0;
|
||||||
@ -404,10 +465,11 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planDestination
|
virtual void planDestination(lir::BinaryOperation op,
|
||||||
(lir::BinaryOperation op,
|
unsigned,
|
||||||
unsigned, const OperandMask& aMask,
|
const OperandMask& aMask,
|
||||||
unsigned, OperandMask& bMask)
|
unsigned,
|
||||||
|
OperandMask& bMask)
|
||||||
{
|
{
|
||||||
bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
||||||
bMask.registerMask = GPR_MASK64;
|
bMask.registerMask = GPR_MASK64;
|
||||||
@ -443,8 +505,8 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planMove
|
virtual void planMove(unsigned,
|
||||||
(unsigned, OperandMask& srcMask,
|
OperandMask& srcMask,
|
||||||
OperandMask& tmpMask,
|
OperandMask& tmpMask,
|
||||||
const OperandMask& dstMask)
|
const OperandMask& dstMask)
|
||||||
{
|
{
|
||||||
@ -459,20 +521,21 @@ class MyArchitecture: public Architecture {
|
|||||||
srcMask.typeMask = 1 << lir::RegisterOperand;
|
srcMask.typeMask = 1 << lir::RegisterOperand;
|
||||||
tmpMask.typeMask = 1 << lir::RegisterOperand;
|
tmpMask.typeMask = 1 << lir::RegisterOperand;
|
||||||
tmpMask.registerMask = GPR_MASK64;
|
tmpMask.registerMask = GPR_MASK64;
|
||||||
} else if (vfpSupported() &&
|
} else if (vfpSupported() && dstMask.typeMask & 1 << lir::RegisterOperand
|
||||||
dstMask.typeMask & 1 << lir::RegisterOperand &&
|
&& dstMask.registerMask & FPR_MASK) {
|
||||||
dstMask.registerMask & FPR_MASK) {
|
srcMask.typeMask = tmpMask.typeMask = 1 << lir::RegisterOperand
|
||||||
srcMask.typeMask = tmpMask.typeMask = 1 << lir::RegisterOperand |
|
| 1 << lir::MemoryOperand;
|
||||||
1 << lir::MemoryOperand;
|
|
||||||
tmpMask.registerMask = ~static_cast<uint64_t>(0);
|
tmpMask.registerMask = ~static_cast<uint64_t>(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planSource
|
virtual void planSource(lir::TernaryOperation op,
|
||||||
(lir::TernaryOperation op,
|
unsigned,
|
||||||
unsigned, OperandMask& aMask,
|
OperandMask& aMask,
|
||||||
unsigned bSize, OperandMask& bMask,
|
unsigned bSize,
|
||||||
unsigned, bool* thunk)
|
OperandMask& bMask,
|
||||||
|
unsigned,
|
||||||
|
bool* thunk)
|
||||||
{
|
{
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
|
||||||
aMask.registerMask = GPR_MASK64;
|
aMask.registerMask = GPR_MASK64;
|
||||||
@ -486,7 +549,8 @@ class MyArchitecture: public Architecture {
|
|||||||
case lir::ShiftLeft:
|
case lir::ShiftLeft:
|
||||||
case lir::ShiftRight:
|
case lir::ShiftRight:
|
||||||
case lir::UnsignedShiftRight:
|
case lir::UnsignedShiftRight:
|
||||||
if (bSize == 8) aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand);
|
if (bSize == 8)
|
||||||
|
aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case lir::Add:
|
case lir::Add:
|
||||||
@ -538,11 +602,13 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planDestination
|
virtual void planDestination(lir::TernaryOperation op,
|
||||||
(lir::TernaryOperation op,
|
unsigned,
|
||||||
unsigned, const OperandMask& aMask UNUSED,
|
const OperandMask& aMask UNUSED,
|
||||||
unsigned, const OperandMask& bMask,
|
unsigned,
|
||||||
unsigned, OperandMask& cMask)
|
const OperandMask& bMask,
|
||||||
|
unsigned,
|
||||||
|
OperandMask& cMask)
|
||||||
{
|
{
|
||||||
if (isBranch(op)) {
|
if (isBranch(op)) {
|
||||||
cMask.typeMask = (1 << lir::ConstantOperand);
|
cMask.typeMask = (1 << lir::ConstantOperand);
|
||||||
@ -555,12 +621,14 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
virtual Assembler* makeAssembler(Allocator* allocator, Zone* zone);
|
virtual Assembler* makeAssembler(Allocator* allocator, Zone* zone);
|
||||||
|
|
||||||
virtual void acquire() {
|
virtual void acquire()
|
||||||
++ referenceCount;
|
{
|
||||||
|
++referenceCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void release() {
|
virtual void release()
|
||||||
if (-- referenceCount == 0) {
|
{
|
||||||
|
if (--referenceCount == 0) {
|
||||||
con.s->free(this);
|
con.s->free(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -569,18 +637,21 @@ class MyArchitecture: public Architecture {
|
|||||||
unsigned referenceCount;
|
unsigned referenceCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyAssembler: public Assembler {
|
class MyAssembler : public Assembler {
|
||||||
public:
|
public:
|
||||||
MyAssembler(System* s, Allocator* a, Zone* zone, MyArchitecture* arch):
|
MyAssembler(System* s, Allocator* a, Zone* zone, MyArchitecture* arch)
|
||||||
con(s, a, zone), arch_(arch)
|
: con(s, a, zone), arch_(arch)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual void setClient(Client* client) {
|
virtual void setClient(Client* client)
|
||||||
|
{
|
||||||
assertT(&con, con.client == 0);
|
assertT(&con, con.client == 0);
|
||||||
con.client = client;
|
con.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Architecture* arch() {
|
virtual Architecture* arch()
|
||||||
|
{
|
||||||
return arch_;
|
return arch_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,12 +660,17 @@ class MyAssembler: public Assembler {
|
|||||||
{
|
{
|
||||||
lir::Register stack(StackRegister);
|
lir::Register stack(StackRegister);
|
||||||
lir::Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread);
|
lir::Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread);
|
||||||
lir::Constant handlerConstant(new(con.zone) ResolvedPromise(handler));
|
lir::Constant handlerConstant(new (con.zone) ResolvedPromise(handler));
|
||||||
branchRM(&con, lir::JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit,
|
branchRM(&con,
|
||||||
|
lir::JumpIfGreaterOrEqual,
|
||||||
|
TargetBytesPerWord,
|
||||||
|
&stack,
|
||||||
|
&stackLimit,
|
||||||
&handlerConstant);
|
&handlerConstant);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) {
|
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset)
|
||||||
|
{
|
||||||
lir::Register link(LinkRegister);
|
lir::Register link(LinkRegister);
|
||||||
lir::Memory linkDst(ThreadRegister, ipOffset);
|
lir::Memory linkDst(ThreadRegister, ipOffset);
|
||||||
moveRM(&con, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst);
|
moveRM(&con, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst);
|
||||||
@ -604,7 +680,8 @@ class MyAssembler: public Assembler {
|
|||||||
moveRM(&con, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst);
|
moveRM(&con, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pushFrame(unsigned argumentCount, ...) {
|
virtual void pushFrame(unsigned argumentCount, ...)
|
||||||
|
{
|
||||||
struct Argument {
|
struct Argument {
|
||||||
unsigned size;
|
unsigned size;
|
||||||
lir::OperandType type;
|
lir::OperandType type;
|
||||||
@ -612,13 +689,16 @@ class MyAssembler: public Assembler {
|
|||||||
};
|
};
|
||||||
RUNTIME_ARRAY(Argument, arguments, argumentCount);
|
RUNTIME_ARRAY(Argument, arguments, argumentCount);
|
||||||
|
|
||||||
va_list a; va_start(a, argumentCount);
|
va_list a;
|
||||||
|
va_start(a, argumentCount);
|
||||||
unsigned footprint = 0;
|
unsigned footprint = 0;
|
||||||
for (unsigned i = 0; i < argumentCount; ++i) {
|
for (unsigned i = 0; i < argumentCount; ++i) {
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned);
|
RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned);
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].type = static_cast<lir::OperandType>(va_arg(a, int));
|
RUNTIME_ARRAY_BODY(arguments)[i].type
|
||||||
|
= static_cast<lir::OperandType>(va_arg(a, int));
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*);
|
RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*);
|
||||||
footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
|
footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
|
TargetBytesPerWord);
|
||||||
}
|
}
|
||||||
va_end(a);
|
va_end(a);
|
||||||
|
|
||||||
@ -630,31 +710,36 @@ class MyAssembler: public Assembler {
|
|||||||
lir::Register dst(arch_->argumentRegister(i));
|
lir::Register dst(arch_->argumentRegister(i));
|
||||||
|
|
||||||
apply(lir::Move,
|
apply(lir::Move,
|
||||||
OperandInfo(
|
OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].size,
|
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
||||||
OperandInfo(
|
OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), lir::RegisterOperand, &dst));
|
TargetBytesPerWord),
|
||||||
|
lir::RegisterOperand,
|
||||||
|
&dst));
|
||||||
|
|
||||||
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
|
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
|
TargetBytesPerWord);
|
||||||
} else {
|
} else {
|
||||||
lir::Memory dst(StackRegister, offset * TargetBytesPerWord);
|
lir::Memory dst(StackRegister, offset * TargetBytesPerWord);
|
||||||
|
|
||||||
apply(lir::Move,
|
apply(lir::Move,
|
||||||
OperandInfo(
|
OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].size,
|
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
||||||
OperandInfo(
|
OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), lir::MemoryOperand, &dst));
|
TargetBytesPerWord),
|
||||||
|
lir::MemoryOperand,
|
||||||
|
&dst));
|
||||||
|
|
||||||
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
|
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
|
TargetBytesPerWord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void allocateFrame(unsigned footprint) {
|
virtual void allocateFrame(unsigned footprint)
|
||||||
|
{
|
||||||
footprint += FrameHeaderSize;
|
footprint += FrameHeaderSize;
|
||||||
|
|
||||||
// larger frames may require multiple subtract/add instructions
|
// larger frames may require multiple subtract/add instructions
|
||||||
@ -668,26 +753,34 @@ class MyAssembler: public Assembler {
|
|||||||
subC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
|
subC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
|
||||||
|
|
||||||
lir::Register returnAddress(LinkRegister);
|
lir::Register returnAddress(LinkRegister);
|
||||||
lir::Memory returnAddressDst
|
lir::Memory returnAddressDst(StackRegister,
|
||||||
(StackRegister, (footprint - 1) * TargetBytesPerWord);
|
(footprint - 1) * TargetBytesPerWord);
|
||||||
moveRM(&con, TargetBytesPerWord, &returnAddress, TargetBytesPerWord,
|
moveRM(&con,
|
||||||
|
TargetBytesPerWord,
|
||||||
|
&returnAddress,
|
||||||
|
TargetBytesPerWord,
|
||||||
&returnAddressDst);
|
&returnAddressDst);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void adjustFrame(unsigned difference) {
|
virtual void adjustFrame(unsigned difference)
|
||||||
|
{
|
||||||
lir::Register stack(StackRegister);
|
lir::Register stack(StackRegister);
|
||||||
ResolvedPromise differencePromise(difference * TargetBytesPerWord);
|
ResolvedPromise differencePromise(difference * TargetBytesPerWord);
|
||||||
lir::Constant differenceConstant(&differencePromise);
|
lir::Constant differenceConstant(&differencePromise);
|
||||||
subC(&con, TargetBytesPerWord, &differenceConstant, &stack, &stack);
|
subC(&con, TargetBytesPerWord, &differenceConstant, &stack, &stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popFrame(unsigned footprint) {
|
virtual void popFrame(unsigned footprint)
|
||||||
|
{
|
||||||
footprint += FrameHeaderSize;
|
footprint += FrameHeaderSize;
|
||||||
|
|
||||||
lir::Register returnAddress(LinkRegister);
|
lir::Register returnAddress(LinkRegister);
|
||||||
lir::Memory returnAddressSrc
|
lir::Memory returnAddressSrc(StackRegister,
|
||||||
(StackRegister, (footprint - 1) * TargetBytesPerWord);
|
(footprint - 1) * TargetBytesPerWord);
|
||||||
moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord,
|
moveMR(&con,
|
||||||
|
TargetBytesPerWord,
|
||||||
|
&returnAddressSrc,
|
||||||
|
TargetBytesPerWord,
|
||||||
&returnAddress);
|
&returnAddress);
|
||||||
|
|
||||||
lir::Register stack(StackRegister);
|
lir::Register stack(StackRegister);
|
||||||
@ -708,14 +801,17 @@ class MyAssembler: public Assembler {
|
|||||||
footprint += FrameHeaderSize;
|
footprint += FrameHeaderSize;
|
||||||
|
|
||||||
lir::Register link(LinkRegister);
|
lir::Register link(LinkRegister);
|
||||||
lir::Memory returnAddressSrc
|
lir::Memory returnAddressSrc(StackRegister,
|
||||||
(StackRegister, (footprint - 1) * TargetBytesPerWord);
|
(footprint - 1) * TargetBytesPerWord);
|
||||||
moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord,
|
moveMR(&con,
|
||||||
|
TargetBytesPerWord,
|
||||||
|
&returnAddressSrc,
|
||||||
|
TargetBytesPerWord,
|
||||||
&link);
|
&link);
|
||||||
|
|
||||||
lir::Register stack(StackRegister);
|
lir::Register stack(StackRegister);
|
||||||
ResolvedPromise footprintPromise
|
ResolvedPromise footprintPromise((footprint - offset)
|
||||||
((footprint - offset) * TargetBytesPerWord);
|
* TargetBytesPerWord);
|
||||||
lir::Constant footprintConstant(&footprintPromise);
|
lir::Constant footprintConstant(&footprintPromise);
|
||||||
addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
|
addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
|
||||||
|
|
||||||
@ -769,46 +865,52 @@ class MyAssembler: public Assembler {
|
|||||||
return_(&con);
|
return_(&con);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(lir::Operation op) {
|
virtual void apply(lir::Operation op)
|
||||||
|
{
|
||||||
arch_->con.operations[op](&con);
|
arch_->con.operations[op](&con);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(lir::UnaryOperation op, OperandInfo a)
|
virtual void apply(lir::UnaryOperation op, OperandInfo a)
|
||||||
{
|
{
|
||||||
arch_->con.unaryOperations[Multimethod::index(op, a.type)]
|
arch_->con.unaryOperations[Multimethod::index(op, a.type)](
|
||||||
(&con, a.size, a.operand);
|
&con, a.size, a.operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b)
|
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b)
|
||||||
{
|
{
|
||||||
arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)]
|
arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)](
|
||||||
(&con, a.size, a.operand, b.size, b.operand);
|
&con, a.size, a.operand, b.size, b.operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c)
|
virtual void apply(lir::TernaryOperation op,
|
||||||
|
OperandInfo a,
|
||||||
|
OperandInfo b,
|
||||||
|
OperandInfo c)
|
||||||
{
|
{
|
||||||
if (isBranch(op)) {
|
if (isBranch(op)) {
|
||||||
assertT(&con, a.size == b.size);
|
assertT(&con, a.size == b.size);
|
||||||
assertT(&con, c.size == TargetBytesPerWord);
|
assertT(&con, c.size == TargetBytesPerWord);
|
||||||
assertT(&con, c.type == lir::ConstantOperand);
|
assertT(&con, c.type == lir::ConstantOperand);
|
||||||
|
|
||||||
arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)]
|
arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)](
|
||||||
(&con, op, a.size, a.operand, b.operand, c.operand);
|
&con, op, a.size, a.operand, b.operand, c.operand);
|
||||||
} else {
|
} else {
|
||||||
assertT(&con, b.size == c.size);
|
assertT(&con, b.size == c.size);
|
||||||
assertT(&con, b.type == lir::RegisterOperand);
|
assertT(&con, b.type == lir::RegisterOperand);
|
||||||
assertT(&con, c.type == lir::RegisterOperand);
|
assertT(&con, c.type == lir::RegisterOperand);
|
||||||
|
|
||||||
arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)]
|
arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)](
|
||||||
(&con, b.size, a.operand, b.operand, c.operand);
|
&con, b.size, a.operand, b.operand, c.operand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setDestination(uint8_t* dst) {
|
virtual void setDestination(uint8_t* dst)
|
||||||
|
{
|
||||||
con.result = dst;
|
con.result = dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void write() {
|
virtual void write()
|
||||||
|
{
|
||||||
uint8_t* dst = con.result;
|
uint8_t* dst = con.result;
|
||||||
unsigned dstOffset = 0;
|
unsigned dstOffset = 0;
|
||||||
for (MyBlock* b = con.firstBlock; b; b = b->next) {
|
for (MyBlock* b = con.firstBlock; b; b = b->next) {
|
||||||
@ -828,8 +930,11 @@ class MyAssembler: public Assembler {
|
|||||||
unsigned poolSize = 0;
|
unsigned poolSize = 0;
|
||||||
for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) {
|
for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) {
|
||||||
if (DebugPool) {
|
if (DebugPool) {
|
||||||
fprintf(stderr, "visit pool offset %p %d in block %p\n",
|
fprintf(stderr,
|
||||||
o, o->offset, b);
|
"visit pool offset %p %d in block %p\n",
|
||||||
|
o,
|
||||||
|
o->offset,
|
||||||
|
b);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned entry = dstOffset + poolSize;
|
unsigned entry = dstOffset + poolSize;
|
||||||
@ -840,8 +945,8 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
o->entry->address = dst + entry;
|
o->entry->address = dst + entry;
|
||||||
|
|
||||||
unsigned instruction = o->block->start
|
unsigned instruction = o->block->start + padding(o->block, o->offset)
|
||||||
+ padding(o->block, o->offset) + o->offset;
|
+ o->offset;
|
||||||
|
|
||||||
int32_t v = (entry - 8) - instruction;
|
int32_t v = (entry - 8) - instruction;
|
||||||
expect(&con, v == (v & PoolOffsetMask));
|
expect(&con, v == (v & PoolOffsetMask));
|
||||||
@ -854,8 +959,8 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
bool jump = needJump(b);
|
bool jump = needJump(b);
|
||||||
if (jump) {
|
if (jump) {
|
||||||
write4
|
write4(dst + dstOffset,
|
||||||
(dst + dstOffset, isa::b((poolSize + TargetBytesPerWord - 8) >> 2));
|
isa::b((poolSize + TargetBytesPerWord - 8) >> 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
dstOffset += poolSize + (jump ? TargetBytesPerWord : 0);
|
dstOffset += poolSize + (jump ? TargetBytesPerWord : 0);
|
||||||
@ -879,20 +984,23 @@ class MyAssembler: public Assembler {
|
|||||||
*static_cast<target_uintptr_t*>(e->address) = e->constant->value();
|
*static_cast<target_uintptr_t*>(e->address) = e->constant->value();
|
||||||
} else {
|
} else {
|
||||||
new (e->constant->listen(sizeof(ConstantPoolListener)))
|
new (e->constant->listen(sizeof(ConstantPoolListener)))
|
||||||
ConstantPoolListener(con.s, static_cast<target_uintptr_t*>(e->address),
|
ConstantPoolListener(
|
||||||
e->callOffset
|
con.s,
|
||||||
? dst + e->callOffset->value() + 8
|
static_cast<target_uintptr_t*>(e->address),
|
||||||
: 0);
|
e->callOffset ? dst + e->callOffset->value() + 8 : 0);
|
||||||
}
|
}
|
||||||
// fprintf(stderr, "constant %p at %p\n", reinterpret_cast<void*>(e->constant->value()), e->address);
|
// fprintf(stderr, "constant %p at %p\n",
|
||||||
|
// reinterpret_cast<void*>(e->constant->value()), e->address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Promise* offset(bool forTrace) {
|
virtual Promise* offset(bool forTrace)
|
||||||
|
{
|
||||||
return arm::offsetPromise(&con, forTrace);
|
return arm::offsetPromise(&con, forTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Block* endBlock(bool startNew) {
|
virtual Block* endBlock(bool startNew)
|
||||||
|
{
|
||||||
MyBlock* b = con.lastBlock;
|
MyBlock* b = con.lastBlock;
|
||||||
b->size = con.code.length() - b->offset;
|
b->size = con.code.length() - b->offset;
|
||||||
if (startNew) {
|
if (startNew) {
|
||||||
@ -903,7 +1011,8 @@ class MyAssembler: public Assembler {
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void endEvent() {
|
virtual void endEvent()
|
||||||
|
{
|
||||||
MyBlock* b = con.lastBlock;
|
MyBlock* b = con.lastBlock;
|
||||||
unsigned thisEventOffset = con.code.length() - b->offset;
|
unsigned thisEventOffset = con.code.length() - b->offset;
|
||||||
if (b->poolOffsetHead) {
|
if (b->poolOffsetHead) {
|
||||||
@ -911,18 +1020,24 @@ class MyAssembler: public Assembler {
|
|||||||
- b->poolOffsetHead->offset;
|
- b->poolOffsetHead->offset;
|
||||||
|
|
||||||
if (v > 0 and v != (v & PoolOffsetMask)) {
|
if (v > 0 and v != (v & PoolOffsetMask)) {
|
||||||
appendPoolEvent
|
appendPoolEvent(&con,
|
||||||
(&con, b, b->lastEventOffset, b->poolOffsetHead,
|
b,
|
||||||
|
b->lastEventOffset,
|
||||||
|
b->poolOffsetHead,
|
||||||
b->lastPoolOffsetTail);
|
b->lastPoolOffsetTail);
|
||||||
|
|
||||||
if (DebugPool) {
|
if (DebugPool) {
|
||||||
for (PoolOffset* o = b->poolOffsetHead;
|
for (PoolOffset* o = b->poolOffsetHead;
|
||||||
o != b->lastPoolOffsetTail->next; o = o->next)
|
o != b->lastPoolOffsetTail->next;
|
||||||
{
|
o = o->next) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"in endEvent, include %p %d in pool event %p at offset %d "
|
"in endEvent, include %p %d in pool event %p at offset %d "
|
||||||
"in block %p\n",
|
"in block %p\n",
|
||||||
o, o->offset, b->poolEventTail, b->lastEventOffset, b);
|
o,
|
||||||
|
o->offset,
|
||||||
|
b->poolEventTail,
|
||||||
|
b->lastEventOffset,
|
||||||
|
b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,15 +1052,18 @@ class MyAssembler: public Assembler {
|
|||||||
b->lastPoolOffsetTail = b->poolOffsetTail;
|
b->lastPoolOffsetTail = b->poolOffsetTail;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned length() {
|
virtual unsigned length()
|
||||||
|
{
|
||||||
return con.code.length();
|
return con.code.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned footerSize() {
|
virtual unsigned footerSize()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose()
|
||||||
|
{
|
||||||
con.code.dispose();
|
con.code.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -953,16 +1071,17 @@ class MyAssembler: public Assembler {
|
|||||||
MyArchitecture* arch_;
|
MyArchitecture* arch_;
|
||||||
};
|
};
|
||||||
|
|
||||||
Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) {
|
Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone)
|
||||||
return new(zone) MyAssembler(this->con.s, allocator, zone, this);
|
{
|
||||||
|
return new (zone) MyAssembler(this->con.s, allocator, zone, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace arm
|
} // namespace arm
|
||||||
|
|
||||||
Architecture*
|
Architecture* makeArchitectureArm(System* system, bool)
|
||||||
makeArchitectureArm(System* system, bool)
|
|
||||||
{
|
{
|
||||||
return new (allocate(system, sizeof(arm::MyArchitecture))) arm::MyArchitecture(system);
|
return new (allocate(system, sizeof(arm::MyArchitecture)))
|
||||||
|
arm::MyArchitecture(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
|
@ -19,13 +19,23 @@ void resolve(MyBlock*);
|
|||||||
|
|
||||||
unsigned padding(MyBlock*, unsigned);
|
unsigned padding(MyBlock*, unsigned);
|
||||||
|
|
||||||
MyBlock::MyBlock(Context* context, unsigned offset):
|
MyBlock::MyBlock(Context* context, unsigned offset)
|
||||||
context(context), next(0), poolOffsetHead(0), poolOffsetTail(0),
|
: context(context),
|
||||||
lastPoolOffsetTail(0), poolEventHead(0), poolEventTail(0),
|
next(0),
|
||||||
lastEventOffset(0), offset(offset), start(~0), size(0)
|
poolOffsetHead(0),
|
||||||
{ }
|
poolOffsetTail(0),
|
||||||
|
lastPoolOffsetTail(0),
|
||||||
|
poolEventHead(0),
|
||||||
|
poolEventTail(0),
|
||||||
|
lastEventOffset(0),
|
||||||
|
offset(offset),
|
||||||
|
start(~0),
|
||||||
|
size(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) {
|
unsigned MyBlock::resolve(unsigned start, Assembler::Block* next)
|
||||||
|
{
|
||||||
this->start = start;
|
this->start = start;
|
||||||
this->next = static_cast<MyBlock*>(next);
|
this->next = static_cast<MyBlock*>(next);
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ namespace arm {
|
|||||||
|
|
||||||
class PoolEvent;
|
class PoolEvent;
|
||||||
|
|
||||||
class MyBlock: public Assembler::Block {
|
class MyBlock : public Assembler::Block {
|
||||||
public:
|
public:
|
||||||
MyBlock(Context* context, unsigned offset);
|
MyBlock(Context* context, unsigned offset);
|
||||||
|
|
||||||
|
@ -57,38 +57,52 @@ typedef void (*OperationType)(Context*);
|
|||||||
|
|
||||||
typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*);
|
typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*);
|
||||||
|
|
||||||
typedef void (*BinaryOperationType)
|
typedef void (*BinaryOperationType)(Context*,
|
||||||
(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*);
|
unsigned,
|
||||||
|
lir::Operand*,
|
||||||
typedef void (*TernaryOperationType)
|
unsigned,
|
||||||
(Context*, unsigned, lir::Operand*, lir::Operand*,
|
|
||||||
lir::Operand*);
|
lir::Operand*);
|
||||||
|
|
||||||
typedef void (*BranchOperationType)
|
typedef void (*TernaryOperationType)(Context*,
|
||||||
(Context*, lir::TernaryOperation, unsigned, lir::Operand*,
|
unsigned,
|
||||||
lir::Operand*, lir::Operand*);
|
lir::Operand*,
|
||||||
|
lir::Operand*,
|
||||||
|
lir::Operand*);
|
||||||
|
|
||||||
|
typedef void (*BranchOperationType)(Context*,
|
||||||
|
lir::TernaryOperation,
|
||||||
|
unsigned,
|
||||||
|
lir::Operand*,
|
||||||
|
lir::Operand*,
|
||||||
|
lir::Operand*);
|
||||||
|
|
||||||
class ArchitectureContext {
|
class ArchitectureContext {
|
||||||
public:
|
public:
|
||||||
ArchitectureContext(vm::System* s): s(s) { }
|
ArchitectureContext(vm::System* s) : s(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
vm::System* s;
|
vm::System* s;
|
||||||
OperationType operations[lir::OperationCount];
|
OperationType operations[lir::OperationCount];
|
||||||
UnaryOperationType unaryOperations[lir::UnaryOperationCount
|
UnaryOperationType
|
||||||
|
unaryOperations[lir::UnaryOperationCount * lir::OperandTypeCount];
|
||||||
|
BinaryOperationType binaryOperations[lir::BinaryOperationCount
|
||||||
|
* lir::OperandTypeCount
|
||||||
|
* lir::OperandTypeCount];
|
||||||
|
TernaryOperationType ternaryOperations[lir::NonBranchTernaryOperationCount
|
||||||
|
* lir::OperandTypeCount];
|
||||||
|
BranchOperationType branchOperations[lir::BranchOperationCount
|
||||||
|
* lir::OperandTypeCount
|
||||||
* lir::OperandTypeCount];
|
* lir::OperandTypeCount];
|
||||||
BinaryOperationType binaryOperations
|
|
||||||
[lir::BinaryOperationCount * lir::OperandTypeCount * lir::OperandTypeCount];
|
|
||||||
TernaryOperationType ternaryOperations
|
|
||||||
[lir::NonBranchTernaryOperationCount * lir::OperandTypeCount];
|
|
||||||
BranchOperationType branchOperations
|
|
||||||
[lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline avian::util::Aborter* getAborter(Context* c) {
|
inline avian::util::Aborter* getAborter(Context* c)
|
||||||
|
{
|
||||||
return c->s;
|
return c->s;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline avian::util::Aborter* getAborter(ArchitectureContext* c) {
|
inline avian::util::Aborter* getAborter(ArchitectureContext* c)
|
||||||
|
{
|
||||||
return c->s;
|
return c->s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,159 +25,665 @@ const int FPSID = 0x0;
|
|||||||
const int FPSCR = 0x1;
|
const int FPSCR = 0x1;
|
||||||
const int FPEXC = 0x8;
|
const int FPEXC = 0x8;
|
||||||
// INSTRUCTION OPTIONS
|
// INSTRUCTION OPTIONS
|
||||||
enum CONDITION { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV };
|
enum CONDITION {
|
||||||
|
EQ,
|
||||||
|
NE,
|
||||||
|
CS,
|
||||||
|
CC,
|
||||||
|
MI,
|
||||||
|
PL,
|
||||||
|
VS,
|
||||||
|
VC,
|
||||||
|
HI,
|
||||||
|
LS,
|
||||||
|
GE,
|
||||||
|
LT,
|
||||||
|
GT,
|
||||||
|
LE,
|
||||||
|
AL,
|
||||||
|
NV
|
||||||
|
};
|
||||||
enum SHIFTOP { LSL, LSR, ASR, ROR };
|
enum SHIFTOP { LSL, LSR, ASR, ROR };
|
||||||
// INSTRUCTION FORMATS
|
// INSTRUCTION FORMATS
|
||||||
inline int DATA(int cond, int opcode, int S, int Rn, int Rd, int shift, int Sh, int Rm)
|
inline int
|
||||||
{ return cond<<28 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | shift<<7 | Sh<<5 | Rm; }
|
DATA(int cond, int opcode, int S, int Rn, int Rd, int shift, int Sh, int Rm)
|
||||||
inline int DATAS(int cond, int opcode, int S, int Rn, int Rd, int Rs, int Sh, int Rm)
|
{
|
||||||
{ return cond<<28 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | Rs<<8 | Sh<<5 | 1<<4 | Rm; }
|
return cond << 28 | opcode << 21 | S << 20 | Rn << 16 | Rd << 12 | shift << 7
|
||||||
|
| Sh << 5 | Rm;
|
||||||
|
}
|
||||||
|
inline int
|
||||||
|
DATAS(int cond, int opcode, int S, int Rn, int Rd, int Rs, int Sh, int Rm)
|
||||||
|
{
|
||||||
|
return cond << 28 | opcode << 21 | S << 20 | Rn << 16 | Rd << 12 | Rs << 8
|
||||||
|
| Sh << 5 | 1 << 4 | Rm;
|
||||||
|
}
|
||||||
inline int DATAI(int cond, int opcode, int S, int Rn, int Rd, int rot, int imm)
|
inline int DATAI(int cond, int opcode, int S, int Rn, int Rd, int rot, int imm)
|
||||||
{ return cond<<28 | 1<<25 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | rot<<8 | (imm&0xff); }
|
{
|
||||||
|
return cond << 28 | 1 << 25 | opcode << 21 | S << 20 | Rn << 16 | Rd << 12
|
||||||
|
| rot << 8 | (imm & 0xff);
|
||||||
|
}
|
||||||
inline int BRANCH(int cond, int L, int offset)
|
inline int BRANCH(int cond, int L, int offset)
|
||||||
{ return cond<<28 | 5<<25 | L<<24 | (offset&0xffffff); }
|
{
|
||||||
|
return cond << 28 | 5 << 25 | L << 24 | (offset & 0xffffff);
|
||||||
|
}
|
||||||
inline int BRANCHX(int cond, int L, int Rm)
|
inline int BRANCHX(int cond, int L, int Rm)
|
||||||
{ return cond<<28 | 0x4bffc<<6 | L<<5 | 1<<4 | Rm; }
|
{
|
||||||
|
return cond << 28 | 0x4bffc << 6 | L << 5 | 1 << 4 | Rm;
|
||||||
|
}
|
||||||
inline int MULTIPLY(int cond, int mul, int S, int Rd, int Rn, int Rs, int Rm)
|
inline int MULTIPLY(int cond, int mul, int S, int Rd, int Rn, int Rs, int Rm)
|
||||||
{ return cond<<28 | mul<<21 | S<<20 | Rd<<16 | Rn<<12 | Rs<<8 | 9<<4 | Rm; }
|
{
|
||||||
inline int XFER(int cond, int P, int U, int B, int W, int L, int Rn, int Rd, int shift, int Sh, int Rm)
|
return cond << 28 | mul << 21 | S << 20 | Rd << 16 | Rn << 12 | Rs << 8
|
||||||
{ return cond<<28 | 3<<25 | P<<24 | U<<23 | B<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | shift<<7 | Sh<<5 | Rm; }
|
| 9 << 4 | Rm;
|
||||||
inline int XFERI(int cond, int P, int U, int B, int W, int L, int Rn, int Rd, int offset)
|
}
|
||||||
{ return cond<<28 | 2<<25 | P<<24 | U<<23 | B<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | (offset&0xfff); }
|
inline int XFER(int cond,
|
||||||
inline int XFER2(int cond, int P, int U, int W, int L, int Rn, int Rd, int S, int H, int Rm)
|
int P,
|
||||||
{ return cond<<28 | P<<24 | U<<23 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | 1<<7 | S<<6 | H<<5 | 1<<4 | Rm; }
|
int U,
|
||||||
inline int XFER2I(int cond, int P, int U, int W, int L, int Rn, int Rd, int offsetH, int S, int H, int offsetL)
|
int B,
|
||||||
{ return cond<<28 | P<<24 | U<<23 | 1<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | offsetH<<8 | 1<<7 | S<<6 | H<<5 | 1<<4 | (offsetL&0xf); }
|
int W,
|
||||||
inline int COOP(int cond, int opcode_1, int CRn, int CRd, int cp_num, int opcode_2, int CRm)
|
int L,
|
||||||
{ return cond<<28 | 0xe<<24 | opcode_1<<20 | CRn<<16 | CRd<<12 | cp_num<<8 | opcode_2<<5 | CRm; }
|
int Rn,
|
||||||
inline int COXFER(int cond, int P, int U, int N, int W, int L, int Rn, int CRd, int cp_num, int offset) // offset is in words, not bytes
|
int Rd,
|
||||||
{ return cond<<28 | 0x6<<25 | P<<24 | U<<23 | N<<22 | W<<21 | L<<20 | Rn<<16 | CRd<<12 | cp_num<<8 | (offset&0xff)>>2; }
|
int shift,
|
||||||
inline int COREG(int cond, int opcode_1, int L, int CRn, int Rd, int cp_num, int opcode_2, int CRm)
|
int Sh,
|
||||||
{ return cond<<28 | 0xe<<24 | opcode_1<<21 | L<<20 | CRn<<16 | Rd<<12 | cp_num<<8 | opcode_2<<5 | 1<<4 | CRm; }
|
int Rm)
|
||||||
inline int COREG2(int cond, int L, int Rn, int Rd, int cp_num, int opcode, int CRm)
|
{
|
||||||
{ return cond<<28 | 0xc4<<20 | L<<20 | Rn<<16 | Rd<<12 | cp_num<<8 | opcode<<4 | CRm;}
|
return cond << 28 | 3 << 25 | P << 24 | U << 23 | B << 22 | W << 21 | L << 20
|
||||||
|
| Rn << 16 | Rd << 12 | shift << 7 | Sh << 5 | Rm;
|
||||||
|
}
|
||||||
|
inline int XFERI(int cond,
|
||||||
|
int P,
|
||||||
|
int U,
|
||||||
|
int B,
|
||||||
|
int W,
|
||||||
|
int L,
|
||||||
|
int Rn,
|
||||||
|
int Rd,
|
||||||
|
int offset)
|
||||||
|
{
|
||||||
|
return cond << 28 | 2 << 25 | P << 24 | U << 23 | B << 22 | W << 21 | L << 20
|
||||||
|
| Rn << 16 | Rd << 12 | (offset & 0xfff);
|
||||||
|
}
|
||||||
|
inline int XFER2(int cond,
|
||||||
|
int P,
|
||||||
|
int U,
|
||||||
|
int W,
|
||||||
|
int L,
|
||||||
|
int Rn,
|
||||||
|
int Rd,
|
||||||
|
int S,
|
||||||
|
int H,
|
||||||
|
int Rm)
|
||||||
|
{
|
||||||
|
return cond << 28 | P << 24 | U << 23 | W << 21 | L << 20 | Rn << 16
|
||||||
|
| Rd << 12 | 1 << 7 | S << 6 | H << 5 | 1 << 4 | Rm;
|
||||||
|
}
|
||||||
|
inline int XFER2I(int cond,
|
||||||
|
int P,
|
||||||
|
int U,
|
||||||
|
int W,
|
||||||
|
int L,
|
||||||
|
int Rn,
|
||||||
|
int Rd,
|
||||||
|
int offsetH,
|
||||||
|
int S,
|
||||||
|
int H,
|
||||||
|
int offsetL)
|
||||||
|
{
|
||||||
|
return cond << 28 | P << 24 | U << 23 | 1 << 22 | W << 21 | L << 20 | Rn << 16
|
||||||
|
| Rd << 12 | offsetH << 8 | 1 << 7 | S << 6 | H << 5 | 1 << 4
|
||||||
|
| (offsetL & 0xf);
|
||||||
|
}
|
||||||
|
inline int COOP(int cond,
|
||||||
|
int opcode_1,
|
||||||
|
int CRn,
|
||||||
|
int CRd,
|
||||||
|
int cp_num,
|
||||||
|
int opcode_2,
|
||||||
|
int CRm)
|
||||||
|
{
|
||||||
|
return cond << 28 | 0xe << 24 | opcode_1 << 20 | CRn << 16 | CRd << 12
|
||||||
|
| cp_num << 8 | opcode_2 << 5 | CRm;
|
||||||
|
}
|
||||||
|
inline int COXFER(int cond,
|
||||||
|
int P,
|
||||||
|
int U,
|
||||||
|
int N,
|
||||||
|
int W,
|
||||||
|
int L,
|
||||||
|
int Rn,
|
||||||
|
int CRd,
|
||||||
|
int cp_num,
|
||||||
|
int offset) // offset is in words, not bytes
|
||||||
|
{
|
||||||
|
return cond << 28 | 0x6 << 25 | P << 24 | U << 23 | N << 22 | W << 21
|
||||||
|
| L << 20 | Rn << 16 | CRd << 12 | cp_num << 8 | (offset & 0xff) >> 2;
|
||||||
|
}
|
||||||
|
inline int COREG(int cond,
|
||||||
|
int opcode_1,
|
||||||
|
int L,
|
||||||
|
int CRn,
|
||||||
|
int Rd,
|
||||||
|
int cp_num,
|
||||||
|
int opcode_2,
|
||||||
|
int CRm)
|
||||||
|
{
|
||||||
|
return cond << 28 | 0xe << 24 | opcode_1 << 21 | L << 20 | CRn << 16
|
||||||
|
| Rd << 12 | cp_num << 8 | opcode_2 << 5 | 1 << 4 | CRm;
|
||||||
|
}
|
||||||
|
inline int
|
||||||
|
COREG2(int cond, int L, int Rn, int Rd, int cp_num, int opcode, int CRm)
|
||||||
|
{
|
||||||
|
return cond << 28 | 0xc4 << 20 | L << 20 | Rn << 16 | Rd << 12 | cp_num << 8
|
||||||
|
| opcode << 4 | CRm;
|
||||||
|
}
|
||||||
// FIELD CALCULATORS
|
// FIELD CALCULATORS
|
||||||
inline int calcU(int imm) { return imm >= 0 ? 1 : 0; }
|
inline int calcU(int imm)
|
||||||
|
{
|
||||||
|
return imm >= 0 ? 1 : 0;
|
||||||
|
}
|
||||||
// INSTRUCTIONS
|
// INSTRUCTIONS
|
||||||
// The "cond" and "S" fields are set using the SETCOND() and SETS() functions
|
// The "cond" and "S" fields are set using the SETCOND() and SETS() functions
|
||||||
inline int b(int offset) { return BRANCH(AL, 0, offset); }
|
inline int b(int offset)
|
||||||
inline int bl(int offset) { return BRANCH(AL, 1, offset); }
|
{
|
||||||
inline int bx(int Rm) { return BRANCHX(AL, 0, Rm); }
|
return BRANCH(AL, 0, offset);
|
||||||
inline int blx(int Rm) { return BRANCHX(AL, 1, Rm); }
|
}
|
||||||
inline int and_(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x0, 0, Rn, Rd, shift, Sh, Rm); }
|
inline int bl(int offset)
|
||||||
inline int eor(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x1, 0, Rn, Rd, shift, Sh, Rm); }
|
{
|
||||||
inline int rsb(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x3, 0, Rn, Rd, shift, Sh, Rm); }
|
return BRANCH(AL, 1, offset);
|
||||||
inline int add(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x4, 0, Rn, Rd, shift, Sh, Rm); }
|
}
|
||||||
inline int adc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x5, 0, Rn, Rd, shift, Sh, Rm); }
|
inline int bx(int Rm)
|
||||||
inline int rsc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x7, 0, Rn, Rd, shift, Sh, Rm); }
|
{
|
||||||
inline int cmp(int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xa, 1, Rn, 0, shift, Sh, Rm); }
|
return BRANCHX(AL, 0, Rm);
|
||||||
inline int orr(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xc, 0, Rn, Rd, shift, Sh, Rm); }
|
}
|
||||||
inline int mov(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xd, 0, 0, Rd, shift, Sh, Rm); }
|
inline int blx(int Rm)
|
||||||
inline int mvn(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xf, 0, 0, Rd, shift, Sh, Rm); }
|
{
|
||||||
inline int andi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x0, 0, Rn, Rd, rot, imm); }
|
return BRANCHX(AL, 1, Rm);
|
||||||
inline int subi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x2, 0, Rn, Rd, rot, imm); }
|
}
|
||||||
inline int rsbi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x3, 0, Rn, Rd, rot, imm); }
|
inline int and_(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||||
inline int addi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x4, 0, Rn, Rd, rot, imm); }
|
{
|
||||||
inline int adci(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x5, 0, Rn, Rd, rot, imm); }
|
return DATA(AL, 0x0, 0, Rn, Rd, shift, Sh, Rm);
|
||||||
inline int bici(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0xe, 0, Rn, Rd, rot, imm); }
|
}
|
||||||
inline int cmpi(int Rn, int imm, int rot=0) { return DATAI(AL, 0xa, 1, Rn, 0, rot, imm); }
|
inline int eor(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||||
inline int movi(int Rd, int imm, int rot=0) { return DATAI(AL, 0xd, 0, 0, Rd, rot, imm); }
|
{
|
||||||
inline int orrsh(int Rd, int Rn, int Rm, int Rs, int Sh) { return DATAS(AL, 0xc, 0, Rn, Rd, Rs, Sh, Rm); }
|
return DATA(AL, 0x1, 0, Rn, Rd, shift, Sh, Rm);
|
||||||
inline int movsh(int Rd, int Rm, int Rs, int Sh) { return DATAS(AL, 0xd, 0, 0, Rd, Rs, Sh, Rm); }
|
}
|
||||||
inline int mul(int Rd, int Rm, int Rs) { return MULTIPLY(AL, 0, 0, Rd, 0, Rs, Rm); }
|
inline int rsb(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||||
inline int mla(int Rd, int Rm, int Rs, int Rn) { return MULTIPLY(AL, 1, 0, Rd, Rn, Rs, Rm); }
|
{
|
||||||
inline int umull(int RdLo, int RdHi, int Rm, int Rs) { return MULTIPLY(AL, 4, 0, RdHi, RdLo, Rs, Rm); }
|
return DATA(AL, 0x3, 0, Rn, Rd, shift, Sh, Rm);
|
||||||
inline int ldr(int Rd, int Rn, int Rm, int W=0) { return XFER(AL, 1, 1, 0, W, 1, Rn, Rd, 0, 0, Rm); }
|
}
|
||||||
inline int ldri(int Rd, int Rn, int imm, int W=0) { return XFERI(AL, 1, calcU(imm), 0, W, 1, Rn, Rd, abs(imm)); }
|
inline int add(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||||
inline int ldrb(int Rd, int Rn, int Rm) { return XFER(AL, 1, 1, 1, 0, 1, Rn, Rd, 0, 0, Rm); }
|
{
|
||||||
inline int ldrbi(int Rd, int Rn, int imm) { return XFERI(AL, 1, calcU(imm), 1, 0, 1, Rn, Rd, abs(imm)); }
|
return DATA(AL, 0x4, 0, Rn, Rd, shift, Sh, Rm);
|
||||||
inline int str(int Rd, int Rn, int Rm, int W=0) { return XFER(AL, 1, 1, 0, W, 0, Rn, Rd, 0, 0, Rm); }
|
}
|
||||||
inline int stri(int Rd, int Rn, int imm, int W=0) { return XFERI(AL, 1, calcU(imm), 0, W, 0, Rn, Rd, abs(imm)); }
|
inline int adc(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||||
inline int strb(int Rd, int Rn, int Rm) { return XFER(AL, 1, 1, 1, 0, 0, Rn, Rd, 0, 0, Rm); }
|
{
|
||||||
inline int strbi(int Rd, int Rn, int imm) { return XFERI(AL, 1, calcU(imm), 1, 0, 0, Rn, Rd, abs(imm)); }
|
return DATA(AL, 0x5, 0, Rn, Rd, shift, Sh, Rm);
|
||||||
inline int ldrh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 0, 1, Rm); }
|
}
|
||||||
inline int ldrhi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 0, 1, abs(imm)&0xf); }
|
inline int rsc(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||||
inline int strh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 0, Rn, Rd, 0, 1, Rm); }
|
{
|
||||||
inline int strhi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 0, Rn, Rd, abs(imm)>>4 & 0xf, 0, 1, abs(imm)&0xf); }
|
return DATA(AL, 0x7, 0, Rn, Rd, shift, Sh, Rm);
|
||||||
inline int ldrsh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 1, Rm); }
|
}
|
||||||
inline int ldrshi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 1, abs(imm)&0xf); }
|
inline int cmp(int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||||
inline int ldrsb(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 0, Rm); }
|
{
|
||||||
inline int ldrsbi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 0, abs(imm)&0xf); }
|
return DATA(AL, 0xa, 1, Rn, 0, shift, Sh, Rm);
|
||||||
|
}
|
||||||
|
inline int orr(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||||
|
{
|
||||||
|
return DATA(AL, 0xc, 0, Rn, Rd, shift, Sh, Rm);
|
||||||
|
}
|
||||||
|
inline int mov(int Rd, int Rm, int Sh = 0, int shift = 0)
|
||||||
|
{
|
||||||
|
return DATA(AL, 0xd, 0, 0, Rd, shift, Sh, Rm);
|
||||||
|
}
|
||||||
|
inline int mvn(int Rd, int Rm, int Sh = 0, int shift = 0)
|
||||||
|
{
|
||||||
|
return DATA(AL, 0xf, 0, 0, Rd, shift, Sh, Rm);
|
||||||
|
}
|
||||||
|
inline int andi(int Rd, int Rn, int imm, int rot = 0)
|
||||||
|
{
|
||||||
|
return DATAI(AL, 0x0, 0, Rn, Rd, rot, imm);
|
||||||
|
}
|
||||||
|
inline int subi(int Rd, int Rn, int imm, int rot = 0)
|
||||||
|
{
|
||||||
|
return DATAI(AL, 0x2, 0, Rn, Rd, rot, imm);
|
||||||
|
}
|
||||||
|
inline int rsbi(int Rd, int Rn, int imm, int rot = 0)
|
||||||
|
{
|
||||||
|
return DATAI(AL, 0x3, 0, Rn, Rd, rot, imm);
|
||||||
|
}
|
||||||
|
inline int addi(int Rd, int Rn, int imm, int rot = 0)
|
||||||
|
{
|
||||||
|
return DATAI(AL, 0x4, 0, Rn, Rd, rot, imm);
|
||||||
|
}
|
||||||
|
inline int adci(int Rd, int Rn, int imm, int rot = 0)
|
||||||
|
{
|
||||||
|
return DATAI(AL, 0x5, 0, Rn, Rd, rot, imm);
|
||||||
|
}
|
||||||
|
inline int bici(int Rd, int Rn, int imm, int rot = 0)
|
||||||
|
{
|
||||||
|
return DATAI(AL, 0xe, 0, Rn, Rd, rot, imm);
|
||||||
|
}
|
||||||
|
inline int cmpi(int Rn, int imm, int rot = 0)
|
||||||
|
{
|
||||||
|
return DATAI(AL, 0xa, 1, Rn, 0, rot, imm);
|
||||||
|
}
|
||||||
|
inline int movi(int Rd, int imm, int rot = 0)
|
||||||
|
{
|
||||||
|
return DATAI(AL, 0xd, 0, 0, Rd, rot, imm);
|
||||||
|
}
|
||||||
|
inline int orrsh(int Rd, int Rn, int Rm, int Rs, int Sh)
|
||||||
|
{
|
||||||
|
return DATAS(AL, 0xc, 0, Rn, Rd, Rs, Sh, Rm);
|
||||||
|
}
|
||||||
|
inline int movsh(int Rd, int Rm, int Rs, int Sh)
|
||||||
|
{
|
||||||
|
return DATAS(AL, 0xd, 0, 0, Rd, Rs, Sh, Rm);
|
||||||
|
}
|
||||||
|
inline int mul(int Rd, int Rm, int Rs)
|
||||||
|
{
|
||||||
|
return MULTIPLY(AL, 0, 0, Rd, 0, Rs, Rm);
|
||||||
|
}
|
||||||
|
inline int mla(int Rd, int Rm, int Rs, int Rn)
|
||||||
|
{
|
||||||
|
return MULTIPLY(AL, 1, 0, Rd, Rn, Rs, Rm);
|
||||||
|
}
|
||||||
|
inline int umull(int RdLo, int RdHi, int Rm, int Rs)
|
||||||
|
{
|
||||||
|
return MULTIPLY(AL, 4, 0, RdHi, RdLo, Rs, Rm);
|
||||||
|
}
|
||||||
|
inline int ldr(int Rd, int Rn, int Rm, int W = 0)
|
||||||
|
{
|
||||||
|
return XFER(AL, 1, 1, 0, W, 1, Rn, Rd, 0, 0, Rm);
|
||||||
|
}
|
||||||
|
inline int ldri(int Rd, int Rn, int imm, int W = 0)
|
||||||
|
{
|
||||||
|
return XFERI(AL, 1, calcU(imm), 0, W, 1, Rn, Rd, abs(imm));
|
||||||
|
}
|
||||||
|
inline int ldrb(int Rd, int Rn, int Rm)
|
||||||
|
{
|
||||||
|
return XFER(AL, 1, 1, 1, 0, 1, Rn, Rd, 0, 0, Rm);
|
||||||
|
}
|
||||||
|
inline int ldrbi(int Rd, int Rn, int imm)
|
||||||
|
{
|
||||||
|
return XFERI(AL, 1, calcU(imm), 1, 0, 1, Rn, Rd, abs(imm));
|
||||||
|
}
|
||||||
|
inline int str(int Rd, int Rn, int Rm, int W = 0)
|
||||||
|
{
|
||||||
|
return XFER(AL, 1, 1, 0, W, 0, Rn, Rd, 0, 0, Rm);
|
||||||
|
}
|
||||||
|
inline int stri(int Rd, int Rn, int imm, int W = 0)
|
||||||
|
{
|
||||||
|
return XFERI(AL, 1, calcU(imm), 0, W, 0, Rn, Rd, abs(imm));
|
||||||
|
}
|
||||||
|
inline int strb(int Rd, int Rn, int Rm)
|
||||||
|
{
|
||||||
|
return XFER(AL, 1, 1, 1, 0, 0, Rn, Rd, 0, 0, Rm);
|
||||||
|
}
|
||||||
|
inline int strbi(int Rd, int Rn, int imm)
|
||||||
|
{
|
||||||
|
return XFERI(AL, 1, calcU(imm), 1, 0, 0, Rn, Rd, abs(imm));
|
||||||
|
}
|
||||||
|
inline int ldrh(int Rd, int Rn, int Rm)
|
||||||
|
{
|
||||||
|
return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 0, 1, Rm);
|
||||||
|
}
|
||||||
|
inline int ldrhi(int Rd, int Rn, int imm)
|
||||||
|
{
|
||||||
|
return XFER2I(AL,
|
||||||
|
1,
|
||||||
|
calcU(imm),
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
Rn,
|
||||||
|
Rd,
|
||||||
|
abs(imm) >> 4 & 0xf,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
abs(imm) & 0xf);
|
||||||
|
}
|
||||||
|
inline int strh(int Rd, int Rn, int Rm)
|
||||||
|
{
|
||||||
|
return XFER2(AL, 1, 1, 0, 0, Rn, Rd, 0, 1, Rm);
|
||||||
|
}
|
||||||
|
inline int strhi(int Rd, int Rn, int imm)
|
||||||
|
{
|
||||||
|
return XFER2I(AL,
|
||||||
|
1,
|
||||||
|
calcU(imm),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
Rn,
|
||||||
|
Rd,
|
||||||
|
abs(imm) >> 4 & 0xf,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
abs(imm) & 0xf);
|
||||||
|
}
|
||||||
|
inline int ldrsh(int Rd, int Rn, int Rm)
|
||||||
|
{
|
||||||
|
return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 1, Rm);
|
||||||
|
}
|
||||||
|
inline int ldrshi(int Rd, int Rn, int imm)
|
||||||
|
{
|
||||||
|
return XFER2I(AL,
|
||||||
|
1,
|
||||||
|
calcU(imm),
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
Rn,
|
||||||
|
Rd,
|
||||||
|
abs(imm) >> 4 & 0xf,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
abs(imm) & 0xf);
|
||||||
|
}
|
||||||
|
inline int ldrsb(int Rd, int Rn, int Rm)
|
||||||
|
{
|
||||||
|
return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 0, Rm);
|
||||||
|
}
|
||||||
|
inline int ldrsbi(int Rd, int Rn, int imm)
|
||||||
|
{
|
||||||
|
return XFER2I(AL,
|
||||||
|
1,
|
||||||
|
calcU(imm),
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
Rn,
|
||||||
|
Rd,
|
||||||
|
abs(imm) >> 4 & 0xf,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
abs(imm) & 0xf);
|
||||||
|
}
|
||||||
// breakpoint instruction, this really has its own instruction format
|
// breakpoint instruction, this really has its own instruction format
|
||||||
inline int bkpt(int16_t immed) { return 0xe1200070 | (((unsigned)immed & 0xffff) >> 4 << 8) | (immed & 0xf); }
|
inline int bkpt(int16_t immed)
|
||||||
|
{
|
||||||
|
return 0xe1200070 | (((unsigned)immed & 0xffff) >> 4 << 8) | (immed & 0xf);
|
||||||
|
}
|
||||||
// COPROCESSOR INSTRUCTIONS
|
// COPROCESSOR INSTRUCTIONS
|
||||||
inline int mcr(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm); }
|
inline int mcr(int coproc,
|
||||||
inline int mcrr(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm); }
|
int opcode_1,
|
||||||
inline int mrc(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm); }
|
int Rd,
|
||||||
inline int mrrc(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm); }
|
int CRn,
|
||||||
|
int CRm,
|
||||||
|
int opcode_2 = 0)
|
||||||
|
{
|
||||||
|
return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm);
|
||||||
|
}
|
||||||
|
inline int mcrr(int coproc, int opcode, int Rd, int Rn, int CRm)
|
||||||
|
{
|
||||||
|
return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm);
|
||||||
|
}
|
||||||
|
inline int mrc(int coproc,
|
||||||
|
int opcode_1,
|
||||||
|
int Rd,
|
||||||
|
int CRn,
|
||||||
|
int CRm,
|
||||||
|
int opcode_2 = 0)
|
||||||
|
{
|
||||||
|
return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm);
|
||||||
|
}
|
||||||
|
inline int mrrc(int coproc, int opcode, int Rd, int Rn, int CRm)
|
||||||
|
{
|
||||||
|
return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm);
|
||||||
|
}
|
||||||
// VFP FLOATING-POINT INSTRUCTIONS
|
// VFP FLOATING-POINT INSTRUCTIONS
|
||||||
inline int fmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); }
|
inline int fmuls(int Sd, int Sn, int Sm)
|
||||||
inline int fadds(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); }
|
{
|
||||||
inline int fsubs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); }
|
return COOP(AL,
|
||||||
inline int fdivs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|8, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); }
|
(Sd & 1) << 2 | 2,
|
||||||
inline int fmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 0, Dm); }
|
Sn >> 1,
|
||||||
inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); }
|
Sd >> 1,
|
||||||
inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); }
|
10,
|
||||||
inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); }
|
(Sn & 1) << 2 | (Sm & 1),
|
||||||
inline int fcpys(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 2|(Sm&1), Sm>>1); }
|
Sm >> 1);
|
||||||
inline int fabss(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 6|(Sm&1), Sm>>1); }
|
}
|
||||||
inline int fnegs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 2|(Sm&1), Sm>>1); }
|
inline int fadds(int Sd, int Sn, int Sm)
|
||||||
inline int fsqrts(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 6|(Sm&1), Sm>>1); }
|
{
|
||||||
inline int fcmps(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 2|(Sm&1), Sm>>1); }
|
return COOP(AL,
|
||||||
inline int fcvtds(int Dd, int Sm) { return COOP(AL, 0xb, 7, Dd, 10, 6|(Sm&1), Sm>>1); }
|
(Sd & 1) << 2 | 3,
|
||||||
inline int fsitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 6|(Sm&1), Sm>>1); }
|
Sn >> 1,
|
||||||
inline int ftosizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 6|(Sm&1), Sm>>1); }
|
Sd >> 1,
|
||||||
inline int fcpyd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); }
|
10,
|
||||||
inline int fabsd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); }
|
(Sn & 1) << 2 | (Sm & 1),
|
||||||
inline int fnegd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); }
|
Sm >> 1);
|
||||||
inline int fsqrtd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 6, Dm); }
|
}
|
||||||
|
inline int fsubs(int Sd, int Sn, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL,
|
||||||
|
(Sd & 1) << 2 | 3,
|
||||||
|
Sn >> 1,
|
||||||
|
Sd >> 1,
|
||||||
|
10,
|
||||||
|
(Sn & 1) << 2 | (Sm & 1) | 2,
|
||||||
|
Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int fdivs(int Sd, int Sn, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL,
|
||||||
|
(Sd & 1) << 2 | 8,
|
||||||
|
Sn >> 1,
|
||||||
|
Sd >> 1,
|
||||||
|
10,
|
||||||
|
(Sn & 1) << 2 | (Sm & 1),
|
||||||
|
Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int fmuld(int Dd, int Dn, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 2, Dn, Dd, 11, 0, Dm);
|
||||||
|
}
|
||||||
|
inline int faddd(int Dd, int Dn, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 3, Dn, Dd, 11, 0, Dm);
|
||||||
|
}
|
||||||
|
inline int fsubd(int Dd, int Dn, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 3, Dn, Dd, 11, 2, Dm);
|
||||||
|
}
|
||||||
|
inline int fdivd(int Dd, int Dn, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 8, Dn, Dd, 11, 0, Dm);
|
||||||
|
}
|
||||||
|
inline int fcpys(int Sd, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb | (Sd & 1) << 2, 0, Sd >> 1, 10, 2 | (Sm & 1), Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int fabss(int Sd, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb | (Sd & 1) << 2, 0, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int fnegs(int Sd, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb | (Sd & 1) << 2, 1, Sd >> 1, 10, 2 | (Sm & 1), Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int fsqrts(int Sd, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb | (Sd & 1) << 2, 1, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int fcmps(int Sd, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb | (Sd & 1) << 2, 4, Sd >> 1, 10, 2 | (Sm & 1), Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int fcvtds(int Dd, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb, 7, Dd, 10, 6 | (Sm & 1), Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int fsitos(int Sd, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb | (Sd & 1) << 2, 8, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int ftosizs(int Sd, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb | (Sd & 1) << 2, 0xd, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int fcpyd(int Dd, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb, 0, Dd, 11, 2, Dm);
|
||||||
|
}
|
||||||
|
inline int fabsd(int Dd, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb, 0, Dd, 11, 6, Dm);
|
||||||
|
}
|
||||||
|
inline int fnegd(int Dd, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb, 1, Dd, 11, 2, Dm);
|
||||||
|
}
|
||||||
|
inline int fsqrtd(int Dd, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb, 1, Dd, 11, 6, Dm);
|
||||||
|
}
|
||||||
// double-precision comparison instructions
|
// double-precision comparison instructions
|
||||||
inline int fcmpd(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); }
|
inline int fcmpd(int Dd, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb, 4, Dd, 11, 2, Dm);
|
||||||
|
}
|
||||||
// double-precision conversion instructions
|
// double-precision conversion instructions
|
||||||
inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 7, Sd>>1, 11, 6, Dm); }
|
inline int fcvtsd(int Sd, int Dm)
|
||||||
inline int fsitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 6|(Sm&1), Sm>>1); }
|
{
|
||||||
inline int ftosizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 6, Dm); }
|
return COOP(AL, 0xb | (Sd & 1) << 2, 7, Sd >> 1, 11, 6, Dm);
|
||||||
|
}
|
||||||
|
inline int fsitod(int Dd, int Sm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb, 8, Dd, 11, 6 | (Sm & 1), Sm >> 1);
|
||||||
|
}
|
||||||
|
inline int ftosizd(int Sd, int Dm)
|
||||||
|
{
|
||||||
|
return COOP(AL, 0xb | (Sd & 1) << 2, 0xd, Sd >> 1, 11, 6, Dm);
|
||||||
|
}
|
||||||
// single load/store instructions for both precision types
|
// single load/store instructions for both precision types
|
||||||
inline int flds(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); };
|
inline int flds(int Sd, int Rn, int offset = 0)
|
||||||
inline int fldd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); };
|
{
|
||||||
inline int fsts(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); };
|
return COXFER(AL, 1, 1, Sd & 1, 0, 1, Rn, Sd >> 1, 10, offset);
|
||||||
inline int fstd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset); };
|
};
|
||||||
|
inline int fldd(int Dd, int Rn, int offset = 0)
|
||||||
|
{
|
||||||
|
return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset);
|
||||||
|
};
|
||||||
|
inline int fsts(int Sd, int Rn, int offset = 0)
|
||||||
|
{
|
||||||
|
return COXFER(AL, 1, 1, Sd & 1, 0, 0, Rn, Sd >> 1, 10, offset);
|
||||||
|
};
|
||||||
|
inline int fstd(int Dd, int Rn, int offset = 0)
|
||||||
|
{
|
||||||
|
return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset);
|
||||||
|
};
|
||||||
// move between GPRs and FPRs
|
// move between GPRs and FPRs
|
||||||
inline int fmsr(int Sn, int Rd) { return mcr(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); }
|
inline int fmsr(int Sn, int Rd)
|
||||||
inline int fmrs(int Rd, int Sn) { return mrc(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); }
|
{
|
||||||
|
return mcr(10, 0, Rd, Sn >> 1, 0, (Sn & 1) << 2);
|
||||||
|
}
|
||||||
|
inline int fmrs(int Rd, int Sn)
|
||||||
|
{
|
||||||
|
return mrc(10, 0, Rd, Sn >> 1, 0, (Sn & 1) << 2);
|
||||||
|
}
|
||||||
// move to/from VFP system registers
|
// move to/from VFP system registers
|
||||||
inline int fmrx(int Rd, int reg) { return mrc(10, 7, Rd, reg, 0); }
|
inline int fmrx(int Rd, int reg)
|
||||||
|
{
|
||||||
|
return mrc(10, 7, Rd, reg, 0);
|
||||||
|
}
|
||||||
// these move around pairs of single-precision registers
|
// these move around pairs of single-precision registers
|
||||||
inline int fmdrr(int Dm, int Rd, int Rn) { return mcrr(11, 1, Rd, Rn, Dm); }
|
inline int fmdrr(int Dm, int Rd, int Rn)
|
||||||
inline int fmrrd(int Rd, int Rn, int Dm) { return mrrc(11, 1, Rd, Rn, Dm); }
|
{
|
||||||
|
return mcrr(11, 1, Rd, Rn, Dm);
|
||||||
|
}
|
||||||
|
inline int fmrrd(int Rd, int Rn, int Dm)
|
||||||
|
{
|
||||||
|
return mrrc(11, 1, Rd, Rn, Dm);
|
||||||
|
}
|
||||||
// FLAG SETTERS
|
// FLAG SETTERS
|
||||||
inline int SETCOND(int ins, int cond) { return ((ins&0x0fffffff) | (cond<<28)); }
|
inline int SETCOND(int ins, int cond)
|
||||||
inline int SETS(int ins) { return ins | 1<<20; }
|
{
|
||||||
|
return ((ins & 0x0fffffff) | (cond << 28));
|
||||||
|
}
|
||||||
|
inline int SETS(int ins)
|
||||||
|
{
|
||||||
|
return ins | 1 << 20;
|
||||||
|
}
|
||||||
// PSEUDO-INSTRUCTIONS
|
// PSEUDO-INSTRUCTIONS
|
||||||
inline int lsl(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSL); }
|
inline int lsl(int Rd, int Rm, int Rs)
|
||||||
inline int lsli(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSL, imm); }
|
{
|
||||||
inline int lsr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSR); }
|
return movsh(Rd, Rm, Rs, LSL);
|
||||||
inline int lsri(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSR, imm); }
|
}
|
||||||
inline int asr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, ASR); }
|
inline int lsli(int Rd, int Rm, int imm)
|
||||||
inline int asri(int Rd, int Rm, int imm) { return mov(Rd, Rm, ASR, imm); }
|
{
|
||||||
inline int beq(int offset) { return SETCOND(b(offset), EQ); }
|
return mov(Rd, Rm, LSL, imm);
|
||||||
inline int bne(int offset) { return SETCOND(b(offset), NE); }
|
}
|
||||||
inline int bls(int offset) { return SETCOND(b(offset), LS); }
|
inline int lsr(int Rd, int Rm, int Rs)
|
||||||
inline int bhi(int offset) { return SETCOND(b(offset), HI); }
|
{
|
||||||
inline int blt(int offset) { return SETCOND(b(offset), LT); }
|
return movsh(Rd, Rm, Rs, LSR);
|
||||||
inline int bgt(int offset) { return SETCOND(b(offset), GT); }
|
}
|
||||||
inline int ble(int offset) { return SETCOND(b(offset), LE); }
|
inline int lsri(int Rd, int Rm, int imm)
|
||||||
inline int bge(int offset) { return SETCOND(b(offset), GE); }
|
{
|
||||||
inline int blo(int offset) { return SETCOND(b(offset), CC); }
|
return mov(Rd, Rm, LSR, imm);
|
||||||
inline int bhs(int offset) { return SETCOND(b(offset), CS); }
|
}
|
||||||
inline int bpl(int offset) { return SETCOND(b(offset), PL); }
|
inline int asr(int Rd, int Rm, int Rs)
|
||||||
inline int fmstat() { return fmrx(15, FPSCR); }
|
{
|
||||||
|
return movsh(Rd, Rm, Rs, ASR);
|
||||||
|
}
|
||||||
|
inline int asri(int Rd, int Rm, int imm)
|
||||||
|
{
|
||||||
|
return mov(Rd, Rm, ASR, imm);
|
||||||
|
}
|
||||||
|
inline int beq(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), EQ);
|
||||||
|
}
|
||||||
|
inline int bne(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), NE);
|
||||||
|
}
|
||||||
|
inline int bls(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), LS);
|
||||||
|
}
|
||||||
|
inline int bhi(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), HI);
|
||||||
|
}
|
||||||
|
inline int blt(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), LT);
|
||||||
|
}
|
||||||
|
inline int bgt(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), GT);
|
||||||
|
}
|
||||||
|
inline int ble(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), LE);
|
||||||
|
}
|
||||||
|
inline int bge(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), GE);
|
||||||
|
}
|
||||||
|
inline int blo(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), CC);
|
||||||
|
}
|
||||||
|
inline int bhs(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), CS);
|
||||||
|
}
|
||||||
|
inline int bpl(int offset)
|
||||||
|
{
|
||||||
|
return SETCOND(b(offset), PL);
|
||||||
|
}
|
||||||
|
inline int fmstat()
|
||||||
|
{
|
||||||
|
return fmrx(15, FPSCR);
|
||||||
|
}
|
||||||
// todo: make this pretty:
|
// todo: make this pretty:
|
||||||
inline int dmb() { return 0xf57ff05f; }
|
inline int dmb()
|
||||||
|
{
|
||||||
|
return 0xf57ff05f;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace isa
|
} // namespace isa
|
||||||
|
|
||||||
inline void emit(Context* con, int code) { con->code.append4(code); }
|
inline void emit(Context* con, int code)
|
||||||
|
{
|
||||||
|
con->code.append4(code);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace arm
|
} // namespace arm
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
|
@ -20,65 +20,78 @@ using namespace util;
|
|||||||
|
|
||||||
unsigned padding(MyBlock*, unsigned);
|
unsigned padding(MyBlock*, unsigned);
|
||||||
|
|
||||||
OffsetPromise::OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace):
|
OffsetPromise::OffsetPromise(Context* con,
|
||||||
con(con), block(block), offset(offset), forTrace(forTrace)
|
MyBlock* block,
|
||||||
{ }
|
unsigned offset,
|
||||||
|
bool forTrace)
|
||||||
|
: con(con), block(block), offset(offset), forTrace(forTrace)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool OffsetPromise::resolved() {
|
bool OffsetPromise::resolved()
|
||||||
|
{
|
||||||
return block->start != static_cast<unsigned>(~0);
|
return block->start != static_cast<unsigned>(~0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t OffsetPromise::value() {
|
int64_t OffsetPromise::value()
|
||||||
|
{
|
||||||
assertT(con, resolved());
|
assertT(con, resolved());
|
||||||
|
|
||||||
unsigned o = offset - block->offset;
|
unsigned o = offset - block->offset;
|
||||||
return block->start + padding
|
return block->start
|
||||||
(block, forTrace ? o - vm::TargetBytesPerWord : o) + o;
|
+ padding(block, forTrace ? o - vm::TargetBytesPerWord : o) + o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Promise* offsetPromise(Context* con, bool forTrace)
|
||||||
Promise* offsetPromise(Context* con, bool forTrace) {
|
{
|
||||||
return new(con->zone) OffsetPromise(con, con->lastBlock, con->code.length(), forTrace);
|
return new (con->zone)
|
||||||
|
OffsetPromise(con, con->lastBlock, con->code.length(), forTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction)
|
||||||
|
: s(s), instruction(instruction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction):
|
bool OffsetListener::resolve(int64_t value, void** location)
|
||||||
s(s),
|
{
|
||||||
instruction(instruction)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
bool OffsetListener::resolve(int64_t value, void** location) {
|
|
||||||
void* p = updateOffset(s, instruction, value);
|
void* p = updateOffset(s, instruction, value);
|
||||||
if (location) *location = p;
|
if (location)
|
||||||
|
*location = p;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset)
|
||||||
|
: Task(next), promise(promise), instructionOffset(instructionOffset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset):
|
void OffsetTask::run(Context* con)
|
||||||
Task(next),
|
{
|
||||||
promise(promise),
|
|
||||||
instructionOffset(instructionOffset)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void OffsetTask::run(Context* con) {
|
|
||||||
if (promise->resolved()) {
|
if (promise->resolved()) {
|
||||||
updateOffset
|
updateOffset(
|
||||||
(con->s, con->result + instructionOffset->value(), promise->value());
|
con->s, con->result + instructionOffset->value(), promise->value());
|
||||||
} else {
|
} else {
|
||||||
new (promise->listen(sizeof(OffsetListener)))
|
new (promise->listen(sizeof(OffsetListener)))
|
||||||
OffsetListener(con->s, con->result + instructionOffset->value());
|
OffsetListener(con->s, con->result + instructionOffset->value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset) {
|
void appendOffsetTask(Context* con,
|
||||||
con->tasks = new(con->zone) OffsetTask(con->tasks, promise, instructionOffset);
|
Promise* promise,
|
||||||
|
Promise* instructionOffset)
|
||||||
|
{
|
||||||
|
con->tasks = new (con->zone)
|
||||||
|
OffsetTask(con->tasks, promise, instructionOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bounded(int right, int left, int32_t v) {
|
bool bounded(int right, int left, int32_t v)
|
||||||
|
{
|
||||||
return ((v << left) >> left) == v and ((v >> right) << right) == v;
|
return ((v << left) >> left) == v and ((v >> right) << right) == v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value) {
|
void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value)
|
||||||
|
{
|
||||||
// ARM's PC is two words ahead, and branches drop the bottom 2 bits.
|
// ARM's PC is two words ahead, and branches drop the bottom 2 bits.
|
||||||
int32_t v = (reinterpret_cast<uint8_t*>(value) - (instruction + 8)) >> 2;
|
int32_t v = (reinterpret_cast<uint8_t*>(value) - (instruction + 8)) >> 2;
|
||||||
|
|
||||||
@ -92,30 +105,39 @@ void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value) {
|
|||||||
return instruction + 4;
|
return instruction + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantPoolEntry::ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next,
|
ConstantPoolEntry::ConstantPoolEntry(Context* con,
|
||||||
Promise* callOffset):
|
Promise* constant,
|
||||||
con(con), constant(constant), next(next), callOffset(callOffset),
|
ConstantPoolEntry* next,
|
||||||
|
Promise* callOffset)
|
||||||
|
: con(con),
|
||||||
|
constant(constant),
|
||||||
|
next(next),
|
||||||
|
callOffset(callOffset),
|
||||||
address(0)
|
address(0)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int64_t ConstantPoolEntry::value() {
|
int64_t ConstantPoolEntry::value()
|
||||||
|
{
|
||||||
assertT(con, resolved());
|
assertT(con, resolved());
|
||||||
|
|
||||||
return reinterpret_cast<int64_t>(address);
|
return reinterpret_cast<int64_t>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConstantPoolEntry::resolved() {
|
bool ConstantPoolEntry::resolved()
|
||||||
|
{
|
||||||
return address != 0;
|
return address != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantPoolListener::ConstantPoolListener(vm::System* s, vm::target_uintptr_t* address,
|
ConstantPoolListener::ConstantPoolListener(vm::System* s,
|
||||||
uint8_t* returnAddress):
|
vm::target_uintptr_t* address,
|
||||||
s(s),
|
uint8_t* returnAddress)
|
||||||
address(address),
|
: s(s), address(address), returnAddress(returnAddress)
|
||||||
returnAddress(returnAddress)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
bool ConstantPoolListener::resolve(int64_t value, void** location) {
|
bool ConstantPoolListener::resolve(int64_t value, void** location)
|
||||||
|
{
|
||||||
*address = value;
|
*address = value;
|
||||||
if (location) {
|
if (location) {
|
||||||
*location = returnAddress ? static_cast<void*>(returnAddress) : address;
|
*location = returnAddress ? static_cast<void*>(returnAddress) : address;
|
||||||
@ -123,32 +145,49 @@ bool ConstantPoolListener::resolve(int64_t value, void** location) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PoolOffset::PoolOffset(MyBlock* block, ConstantPoolEntry* entry, unsigned offset):
|
PoolOffset::PoolOffset(MyBlock* block,
|
||||||
block(block), entry(entry), next(0), offset(offset)
|
ConstantPoolEntry* entry,
|
||||||
{ }
|
unsigned offset)
|
||||||
|
: block(block), entry(entry), next(0), offset(offset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PoolEvent::PoolEvent(PoolOffset* poolOffsetHead, PoolOffset* poolOffsetTail,
|
PoolEvent::PoolEvent(PoolOffset* poolOffsetHead,
|
||||||
unsigned offset):
|
PoolOffset* poolOffsetTail,
|
||||||
poolOffsetHead(poolOffsetHead), poolOffsetTail(poolOffsetTail), next(0),
|
unsigned offset)
|
||||||
|
: poolOffsetHead(poolOffsetHead),
|
||||||
|
poolOffsetTail(poolOffsetTail),
|
||||||
|
next(0),
|
||||||
offset(offset)
|
offset(offset)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset) {
|
void appendConstantPoolEntry(Context* con,
|
||||||
|
Promise* constant,
|
||||||
|
Promise* callOffset)
|
||||||
|
{
|
||||||
if (constant->resolved()) {
|
if (constant->resolved()) {
|
||||||
// make a copy, since the original might be allocated on the
|
// make a copy, since the original might be allocated on the
|
||||||
// stack, and we need our copy to live until assembly is complete
|
// stack, and we need our copy to live until assembly is complete
|
||||||
constant = new(con->zone) ResolvedPromise(constant->value());
|
constant = new (con->zone) ResolvedPromise(constant->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
con->constantPool = new(con->zone) ConstantPoolEntry(con, constant, con->constantPool, callOffset);
|
con->constantPool = new (con->zone)
|
||||||
|
ConstantPoolEntry(con, constant, con->constantPool, callOffset);
|
||||||
|
|
||||||
++ con->constantPoolCount;
|
++con->constantPoolCount;
|
||||||
|
|
||||||
PoolOffset* o = new(con->zone) PoolOffset(con->lastBlock, con->constantPool, con->code.length() - con->lastBlock->offset);
|
PoolOffset* o = new (con->zone)
|
||||||
|
PoolOffset(con->lastBlock,
|
||||||
|
con->constantPool,
|
||||||
|
con->code.length() - con->lastBlock->offset);
|
||||||
|
|
||||||
if (DebugPool) {
|
if (DebugPool) {
|
||||||
fprintf(stderr, "add pool offset %p %d to block %p\n",
|
fprintf(stderr,
|
||||||
o, o->offset, con->lastBlock);
|
"add pool offset %p %d to block %p\n",
|
||||||
|
o,
|
||||||
|
o->offset,
|
||||||
|
con->lastBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (con->lastBlock->poolOffsetTail) {
|
if (con->lastBlock->poolOffsetTail) {
|
||||||
@ -159,10 +198,13 @@ void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffse
|
|||||||
con->lastBlock->poolOffsetTail = o;
|
con->lastBlock->poolOffsetTail = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head,
|
void appendPoolEvent(Context* con,
|
||||||
|
MyBlock* b,
|
||||||
|
unsigned offset,
|
||||||
|
PoolOffset* head,
|
||||||
PoolOffset* tail)
|
PoolOffset* tail)
|
||||||
{
|
{
|
||||||
PoolEvent* e = new(con->zone) PoolEvent(head, tail, offset);
|
PoolEvent* e = new (con->zone) PoolEvent(head, tail, offset);
|
||||||
|
|
||||||
if (b->poolEventTail) {
|
if (b->poolEventTail) {
|
||||||
b->poolEventTail->next = e;
|
b->poolEventTail->next = e;
|
||||||
|
@ -31,14 +31,16 @@ const int32_t PoolOffsetMask = 0xFFF;
|
|||||||
|
|
||||||
class Task {
|
class Task {
|
||||||
public:
|
public:
|
||||||
Task(Task* next): next(next) { }
|
Task(Task* next) : next(next)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual void run(Context* con) = 0;
|
virtual void run(Context* con) = 0;
|
||||||
|
|
||||||
Task* next;
|
Task* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OffsetPromise: public Promise {
|
class OffsetPromise : public Promise {
|
||||||
public:
|
public:
|
||||||
OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace);
|
OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace);
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ class OffsetPromise: public Promise {
|
|||||||
|
|
||||||
Promise* offsetPromise(Context* con, bool forTrace = false);
|
Promise* offsetPromise(Context* con, bool forTrace = false);
|
||||||
|
|
||||||
class OffsetListener: public Promise::Listener {
|
class OffsetListener : public Promise::Listener {
|
||||||
public:
|
public:
|
||||||
OffsetListener(vm::System* s, uint8_t* instruction);
|
OffsetListener(vm::System* s, uint8_t* instruction);
|
||||||
|
|
||||||
@ -64,7 +66,7 @@ class OffsetListener: public Promise::Listener {
|
|||||||
uint8_t* instruction;
|
uint8_t* instruction;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OffsetTask: public Task {
|
class OffsetTask : public Task {
|
||||||
public:
|
public:
|
||||||
OffsetTask(Task* next, Promise* promise, Promise* instructionOffset);
|
OffsetTask(Task* next, Promise* promise, Promise* instructionOffset);
|
||||||
|
|
||||||
@ -74,13 +76,17 @@ class OffsetTask: public Task {
|
|||||||
Promise* instructionOffset;
|
Promise* instructionOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
void appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset);
|
void appendOffsetTask(Context* con,
|
||||||
|
Promise* promise,
|
||||||
|
Promise* instructionOffset);
|
||||||
|
|
||||||
void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value);
|
void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value);
|
||||||
|
|
||||||
class ConstantPoolEntry: public Promise {
|
class ConstantPoolEntry : public Promise {
|
||||||
public:
|
public:
|
||||||
ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next,
|
ConstantPoolEntry(Context* con,
|
||||||
|
Promise* constant,
|
||||||
|
ConstantPoolEntry* next,
|
||||||
Promise* callOffset);
|
Promise* callOffset);
|
||||||
|
|
||||||
virtual int64_t value();
|
virtual int64_t value();
|
||||||
@ -95,9 +101,10 @@ class ConstantPoolEntry: public Promise {
|
|||||||
unsigned constantPoolCount;
|
unsigned constantPoolCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConstantPoolListener: public Promise::Listener {
|
class ConstantPoolListener : public Promise::Listener {
|
||||||
public:
|
public:
|
||||||
ConstantPoolListener(vm::System* s, vm::target_uintptr_t* address,
|
ConstantPoolListener(vm::System* s,
|
||||||
|
vm::target_uintptr_t* address,
|
||||||
uint8_t* returnAddress);
|
uint8_t* returnAddress);
|
||||||
|
|
||||||
virtual bool resolve(int64_t value, void** location);
|
virtual bool resolve(int64_t value, void** location);
|
||||||
@ -119,7 +126,8 @@ class PoolOffset {
|
|||||||
|
|
||||||
class PoolEvent {
|
class PoolEvent {
|
||||||
public:
|
public:
|
||||||
PoolEvent(PoolOffset* poolOffsetHead, PoolOffset* poolOffsetTail,
|
PoolEvent(PoolOffset* poolOffsetHead,
|
||||||
|
PoolOffset* poolOffsetTail,
|
||||||
unsigned offset);
|
unsigned offset);
|
||||||
|
|
||||||
PoolOffset* poolOffsetHead;
|
PoolOffset* poolOffsetHead;
|
||||||
@ -128,9 +136,14 @@ class PoolEvent {
|
|||||||
unsigned offset;
|
unsigned offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset);
|
void appendConstantPoolEntry(Context* con,
|
||||||
|
Promise* constant,
|
||||||
|
Promise* callOffset);
|
||||||
|
|
||||||
void appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head,
|
void appendPoolEvent(Context* con,
|
||||||
|
MyBlock* b,
|
||||||
|
unsigned offset,
|
||||||
|
PoolOffset* head,
|
||||||
PoolOffset* tail);
|
PoolOffset* tail);
|
||||||
|
|
||||||
} // namespace arm
|
} // namespace arm
|
||||||
|
@ -25,8 +25,7 @@ unsigned index(ArchitectureContext*,
|
|||||||
lir::OperandType operand1,
|
lir::OperandType operand1,
|
||||||
lir::OperandType operand2)
|
lir::OperandType operand2)
|
||||||
{
|
{
|
||||||
return operation
|
return operation + (lir::BinaryOperationCount * operand1)
|
||||||
+ (lir::BinaryOperationCount * operand1)
|
|
||||||
+ (lir::BinaryOperationCount * lir::OperandTypeCount * operand2);
|
+ (lir::BinaryOperationCount * lir::OperandTypeCount * operand2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,13 +38,15 @@ unsigned index(ArchitectureContext* con UNUSED,
|
|||||||
return operation + (lir::NonBranchTernaryOperationCount * operand1);
|
return operation + (lir::NonBranchTernaryOperationCount * operand1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1,
|
unsigned branchIndex(ArchitectureContext* con UNUSED,
|
||||||
|
lir::OperandType operand1,
|
||||||
lir::OperandType operand2)
|
lir::OperandType operand2)
|
||||||
{
|
{
|
||||||
return operand1 + (lir::OperandTypeCount * operand2);
|
return operand1 + (lir::OperandTypeCount * operand2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void populateTables(ArchitectureContext* con) {
|
void populateTables(ArchitectureContext* con)
|
||||||
|
{
|
||||||
const lir::OperandType C = lir::ConstantOperand;
|
const lir::OperandType C = lir::ConstantOperand;
|
||||||
const lir::OperandType A = lir::AddressOperand;
|
const lir::OperandType A = lir::AddressOperand;
|
||||||
const lir::OperandType R = lir::RegisterOperand;
|
const lir::OperandType R = lir::RegisterOperand;
|
||||||
|
@ -32,7 +32,8 @@ unsigned index(ArchitectureContext* con UNUSED,
|
|||||||
lir::TernaryOperation operation,
|
lir::TernaryOperation operation,
|
||||||
lir::OperandType operand1);
|
lir::OperandType operand1);
|
||||||
|
|
||||||
unsigned branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1,
|
unsigned branchIndex(ArchitectureContext* con UNUSED,
|
||||||
|
lir::OperandType operand1,
|
||||||
lir::OperandType operand2);
|
lir::OperandType operand2);
|
||||||
|
|
||||||
void populateTables(ArchitectureContext* con);
|
void populateTables(ArchitectureContext* con);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -25,51 +25,87 @@ class Context;
|
|||||||
|
|
||||||
// shortcut functions
|
// shortcut functions
|
||||||
|
|
||||||
inline int newTemp(Context* con) {
|
inline int newTemp(Context* con)
|
||||||
|
{
|
||||||
return con->client->acquireTemporary(GPR_MASK);
|
return con->client->acquireTemporary(GPR_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int newTemp(Context* con, unsigned mask) {
|
inline int newTemp(Context* con, unsigned mask)
|
||||||
|
{
|
||||||
return con->client->acquireTemporary(mask);
|
return con->client->acquireTemporary(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void freeTemp(Context* con, int r) {
|
inline void freeTemp(Context* con, int r)
|
||||||
|
{
|
||||||
con->client->releaseTemporary(r);
|
con->client->releaseTemporary(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int64_t getValue(lir::Constant* con) {
|
inline int64_t getValue(lir::Constant* con)
|
||||||
|
{
|
||||||
return con->value->value();
|
return con->value->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline lir::Register makeTemp(Context* con) {
|
inline lir::Register makeTemp(Context* con)
|
||||||
|
{
|
||||||
lir::Register tmp(newTemp(con));
|
lir::Register tmp(newTemp(con));
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline lir::Register makeTemp64(Context* con) {
|
inline lir::Register makeTemp64(Context* con)
|
||||||
|
{
|
||||||
lir::Register tmp(newTemp(con), newTemp(con));
|
lir::Register tmp(newTemp(con), newTemp(con));
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void freeTemp(Context* con, const lir::Register& tmp) {
|
inline void freeTemp(Context* con, const lir::Register& tmp)
|
||||||
if (tmp.low != lir::NoRegister) freeTemp(con, tmp.low);
|
{
|
||||||
if (tmp.high != lir::NoRegister) freeTemp(con, tmp.high);
|
if (tmp.low != lir::NoRegister)
|
||||||
|
freeTemp(con, tmp.low);
|
||||||
|
if (tmp.high != lir::NoRegister)
|
||||||
|
freeTemp(con, tmp.high);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void shiftLeftR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void moveRR(Context* con, unsigned srcSize, lir::Register* src,
|
void moveRR(Context* con,
|
||||||
unsigned dstSize, lir::Register* dst);
|
unsigned srcSize,
|
||||||
|
lir::Register* src,
|
||||||
|
unsigned dstSize,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void shiftLeftC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t);
|
void shiftLeftC(Context* con,
|
||||||
|
unsigned size UNUSED,
|
||||||
|
lir::Constant* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void shiftRightR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void shiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t);
|
void shiftRightC(Context* con,
|
||||||
|
unsigned size UNUSED,
|
||||||
|
lir::Constant* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void unsignedShiftRightR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void unsignedShiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t);
|
void unsignedShiftRightC(Context* con,
|
||||||
|
unsigned size UNUSED,
|
||||||
|
lir::Constant* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
bool needJump(MyBlock* b);
|
bool needJump(MyBlock* b);
|
||||||
|
|
||||||
@ -79,142 +115,297 @@ void resolve(MyBlock* b);
|
|||||||
|
|
||||||
void jumpR(Context* con, unsigned size UNUSED, lir::Register* target);
|
void jumpR(Context* con, unsigned size UNUSED, lir::Register* target);
|
||||||
|
|
||||||
void swapRR(Context* con, unsigned aSize, lir::Register* a,
|
void swapRR(Context* con,
|
||||||
unsigned bSize, lir::Register* b);
|
unsigned aSize,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned bSize,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void moveRR(Context* con, unsigned srcSize, lir::Register* src,
|
void moveRR(Context* con,
|
||||||
unsigned dstSize, lir::Register* dst);
|
unsigned srcSize,
|
||||||
|
lir::Register* src,
|
||||||
|
unsigned dstSize,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void moveZRR(Context* con, unsigned srcSize, lir::Register* src,
|
void moveZRR(Context* con,
|
||||||
unsigned, lir::Register* dst);
|
unsigned srcSize,
|
||||||
|
lir::Register* src,
|
||||||
|
unsigned,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void moveCR(Context* con, unsigned size, lir::Constant* src,
|
void moveCR(Context* con,
|
||||||
unsigned, lir::Register* dst);
|
unsigned size,
|
||||||
|
lir::Constant* src,
|
||||||
|
unsigned,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void moveCR2(Context* con, unsigned size, lir::Constant* src,
|
void moveCR2(Context* con,
|
||||||
lir::Register* dst, Promise* callOffset);
|
unsigned size,
|
||||||
|
lir::Constant* src,
|
||||||
|
lir::Register* dst,
|
||||||
|
Promise* callOffset);
|
||||||
|
|
||||||
void moveCR(Context* con, unsigned size, lir::Constant* src,
|
void moveCR(Context* con,
|
||||||
unsigned, lir::Register* dst);
|
unsigned size,
|
||||||
|
lir::Constant* src,
|
||||||
|
unsigned,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void addR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void subR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void addC(Context* con, unsigned size, lir::Constant* a,
|
void addC(Context* con,
|
||||||
lir::Register* b, lir::Register* dst);
|
unsigned size,
|
||||||
|
lir::Constant* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void subC(Context* con, unsigned size, lir::Constant* a,
|
void subC(Context* con,
|
||||||
lir::Register* b, lir::Register* dst);
|
unsigned size,
|
||||||
|
lir::Constant* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void multiplyR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void floatAbsoluteRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
void floatAbsoluteRR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void floatNegateRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
void floatNegateRR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void float2FloatRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
void float2FloatRR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void float2IntRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
void float2IntRR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void int2FloatRR(Context* con, unsigned, lir::Register* a, unsigned size, lir::Register* b);
|
void int2FloatRR(Context* con,
|
||||||
|
unsigned,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void floatSqrtRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
void floatSqrtRR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void floatAddR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void floatAddR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void floatSubtractR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void floatSubtractR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void floatMultiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void floatMultiplyR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
void floatDivideR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
void floatDivideR(Context* con,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* t);
|
||||||
|
|
||||||
int normalize(Context* con, int offset, int index, unsigned scale,
|
int normalize(Context* con,
|
||||||
bool* preserveIndex, bool* release);
|
int offset,
|
||||||
|
int index,
|
||||||
|
unsigned scale,
|
||||||
|
bool* preserveIndex,
|
||||||
|
bool* release);
|
||||||
|
|
||||||
void store(Context* con, unsigned size, lir::Register* src,
|
void store(Context* con,
|
||||||
int base, int offset, int index, unsigned scale, bool preserveIndex);
|
unsigned size,
|
||||||
|
lir::Register* src,
|
||||||
|
int base,
|
||||||
|
int offset,
|
||||||
|
int index,
|
||||||
|
unsigned scale,
|
||||||
|
bool preserveIndex);
|
||||||
|
|
||||||
void moveRM(Context* con, unsigned srcSize, lir::Register* src,
|
void moveRM(Context* con,
|
||||||
unsigned dstSize UNUSED, lir::Memory* dst);
|
unsigned srcSize,
|
||||||
|
lir::Register* src,
|
||||||
|
unsigned dstSize UNUSED,
|
||||||
|
lir::Memory* dst);
|
||||||
|
|
||||||
void load(Context* con, unsigned srcSize, int base, int offset, int index,
|
void load(Context* con,
|
||||||
unsigned scale, unsigned dstSize, lir::Register* dst,
|
unsigned srcSize,
|
||||||
bool preserveIndex, bool signExtend);
|
int base,
|
||||||
|
int offset,
|
||||||
|
int index,
|
||||||
|
unsigned scale,
|
||||||
|
unsigned dstSize,
|
||||||
|
lir::Register* dst,
|
||||||
|
bool preserveIndex,
|
||||||
|
bool signExtend);
|
||||||
|
|
||||||
void moveMR(Context* con, unsigned srcSize, lir::Memory* src,
|
void moveMR(Context* con,
|
||||||
unsigned dstSize, lir::Register* dst);
|
unsigned srcSize,
|
||||||
|
lir::Memory* src,
|
||||||
|
unsigned dstSize,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void moveZMR(Context* con, unsigned srcSize, lir::Memory* src,
|
void moveZMR(Context* con,
|
||||||
unsigned dstSize, lir::Register* dst);
|
unsigned srcSize,
|
||||||
|
lir::Memory* src,
|
||||||
|
unsigned dstSize,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void andR(Context* con, unsigned size, lir::Register* a,
|
void andR(Context* con,
|
||||||
lir::Register* b, lir::Register* dst);
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void andC(Context* con, unsigned size, lir::Constant* a,
|
void andC(Context* con,
|
||||||
lir::Register* b, lir::Register* dst);
|
unsigned size,
|
||||||
|
lir::Constant* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void orR(Context* con, unsigned size, lir::Register* a,
|
void orR(Context* con,
|
||||||
lir::Register* b, lir::Register* dst);
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void xorR(Context* con, unsigned size, lir::Register* a,
|
void xorR(Context* con,
|
||||||
lir::Register* b, lir::Register* dst);
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void moveAR2(Context* con, unsigned srcSize, lir::Address* src,
|
void moveAR2(Context* con,
|
||||||
unsigned dstSize, lir::Register* dst);
|
unsigned srcSize,
|
||||||
|
lir::Address* src,
|
||||||
|
unsigned dstSize,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void moveAR(Context* con, unsigned srcSize, lir::Address* src,
|
void moveAR(Context* con,
|
||||||
unsigned dstSize, lir::Register* dst);
|
unsigned srcSize,
|
||||||
|
lir::Address* src,
|
||||||
|
unsigned dstSize,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void compareRR(Context* con, unsigned aSize, lir::Register* a,
|
void compareRR(Context* con,
|
||||||
unsigned bSize UNUSED, lir::Register* b);
|
unsigned aSize,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned bSize UNUSED,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void compareCR(Context* con, unsigned aSize, lir::Constant* a,
|
void compareCR(Context* con,
|
||||||
unsigned bSize, lir::Register* b);
|
unsigned aSize,
|
||||||
|
lir::Constant* a,
|
||||||
|
unsigned bSize,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void compareCM(Context* con, unsigned aSize, lir::Constant* a,
|
void compareCM(Context* con,
|
||||||
unsigned bSize, lir::Memory* b);
|
unsigned aSize,
|
||||||
|
lir::Constant* a,
|
||||||
|
unsigned bSize,
|
||||||
|
lir::Memory* b);
|
||||||
|
|
||||||
void compareRM(Context* con, unsigned aSize, lir::Register* a,
|
void compareRM(Context* con,
|
||||||
unsigned bSize, lir::Memory* b);
|
unsigned aSize,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned bSize,
|
||||||
|
lir::Memory* b);
|
||||||
|
|
||||||
int32_t
|
int32_t branch(Context* con, lir::TernaryOperation op);
|
||||||
branch(Context* con, lir::TernaryOperation op);
|
|
||||||
|
|
||||||
void conditional(Context* con, int32_t branch, lir::Constant* target);
|
void conditional(Context* con, int32_t branch, lir::Constant* target);
|
||||||
|
|
||||||
void branch(Context* con, lir::TernaryOperation op, lir::Constant* target);
|
void branch(Context* con, lir::TernaryOperation op, lir::Constant* target);
|
||||||
|
|
||||||
void branchLong(Context* con, lir::TernaryOperation op, lir::Operand* al,
|
void branchLong(Context* con,
|
||||||
lir::Operand* ah, lir::Operand* bl,
|
lir::TernaryOperation op,
|
||||||
lir::Operand* bh, lir::Constant* target,
|
lir::Operand* al,
|
||||||
|
lir::Operand* ah,
|
||||||
|
lir::Operand* bl,
|
||||||
|
lir::Operand* bh,
|
||||||
|
lir::Constant* target,
|
||||||
BinaryOperationType compareSigned,
|
BinaryOperationType compareSigned,
|
||||||
BinaryOperationType compareUnsigned);
|
BinaryOperationType compareUnsigned);
|
||||||
|
|
||||||
void branchRR(Context* con, lir::TernaryOperation op, unsigned size,
|
void branchRR(Context* con,
|
||||||
lir::Register* a, lir::Register* b,
|
lir::TernaryOperation op,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Register* b,
|
||||||
lir::Constant* target);
|
lir::Constant* target);
|
||||||
|
|
||||||
void branchCR(Context* con, lir::TernaryOperation op, unsigned size,
|
void branchCR(Context* con,
|
||||||
lir::Constant* a, lir::Register* b,
|
lir::TernaryOperation op,
|
||||||
|
unsigned size,
|
||||||
|
lir::Constant* a,
|
||||||
|
lir::Register* b,
|
||||||
lir::Constant* target);
|
lir::Constant* target);
|
||||||
|
|
||||||
void branchRM(Context* con, lir::TernaryOperation op, unsigned size,
|
void branchRM(Context* con,
|
||||||
lir::Register* a, lir::Memory* b,
|
lir::TernaryOperation op,
|
||||||
|
unsigned size,
|
||||||
|
lir::Register* a,
|
||||||
|
lir::Memory* b,
|
||||||
lir::Constant* target);
|
lir::Constant* target);
|
||||||
|
|
||||||
void branchCM(Context* con, lir::TernaryOperation op, unsigned size,
|
void branchCM(Context* con,
|
||||||
lir::Constant* a, lir::Memory* b,
|
lir::TernaryOperation op,
|
||||||
|
unsigned size,
|
||||||
|
lir::Constant* a,
|
||||||
|
lir::Memory* b,
|
||||||
lir::Constant* target);
|
lir::Constant* target);
|
||||||
|
|
||||||
ShiftMaskPromise*
|
ShiftMaskPromise* shiftMaskPromise(Context* con,
|
||||||
shiftMaskPromise(Context* con, Promise* base, unsigned shift, int64_t mask);
|
Promise* base,
|
||||||
|
unsigned shift,
|
||||||
|
int64_t mask);
|
||||||
|
|
||||||
void moveCM(Context* con, unsigned srcSize, lir::Constant* src,
|
void moveCM(Context* con,
|
||||||
unsigned dstSize, lir::Memory* dst);
|
unsigned srcSize,
|
||||||
|
lir::Constant* src,
|
||||||
|
unsigned dstSize,
|
||||||
|
lir::Memory* dst);
|
||||||
|
|
||||||
void negateRR(Context* con, unsigned srcSize, lir::Register* src,
|
void negateRR(Context* con,
|
||||||
unsigned dstSize UNUSED, lir::Register* dst);
|
unsigned srcSize,
|
||||||
|
lir::Register* src,
|
||||||
|
unsigned dstSize UNUSED,
|
||||||
|
lir::Register* dst);
|
||||||
|
|
||||||
void callR(Context* con, unsigned size UNUSED, lir::Register* target);
|
void callR(Context* con, unsigned size UNUSED, lir::Register* target);
|
||||||
|
|
||||||
@ -241,4 +432,3 @@ void storeLoadBarrier(Context*);
|
|||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
|
||||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H
|
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace arm {
|
namespace arm {
|
||||||
|
|
||||||
|
|
||||||
const uint64_t MASK_LO32 = 0xffffffff;
|
const uint64_t MASK_LO32 = 0xffffffff;
|
||||||
const unsigned MASK_LO16 = 0xffff;
|
const unsigned MASK_LO16 = 0xffff;
|
||||||
const unsigned MASK_LO8 = 0xff;
|
const unsigned MASK_LO8 = 0xff;
|
||||||
@ -31,14 +30,27 @@ const uint32_t FPR_MASK = 0xffff0000;
|
|||||||
const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32;
|
const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32;
|
||||||
const uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32;
|
const uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32;
|
||||||
|
|
||||||
inline bool isFpr(lir::Register* reg) {
|
inline bool isFpr(lir::Register* reg)
|
||||||
|
{
|
||||||
return reg->low >= N_GPRS;
|
return reg->low >= N_GPRS;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int fpr64(int reg) { return reg - N_GPRS; }
|
inline int fpr64(int reg)
|
||||||
inline int fpr64(lir::Register* reg) { return fpr64(reg->low); }
|
{
|
||||||
inline int fpr32(int reg) { return fpr64(reg) << 1; }
|
return reg - N_GPRS;
|
||||||
inline int fpr32(lir::Register* reg) { return fpr64(reg) << 1; }
|
}
|
||||||
|
inline int fpr64(lir::Register* reg)
|
||||||
|
{
|
||||||
|
return fpr64(reg->low);
|
||||||
|
}
|
||||||
|
inline int fpr32(int reg)
|
||||||
|
{
|
||||||
|
return fpr64(reg) << 1;
|
||||||
|
}
|
||||||
|
inline int fpr32(lir::Register* reg)
|
||||||
|
{
|
||||||
|
return fpr64(reg) << 1;
|
||||||
|
}
|
||||||
|
|
||||||
const int ThreadRegister = 8;
|
const int ThreadRegister = 8;
|
||||||
const int StackRegister = 13;
|
const int StackRegister = 13;
|
||||||
|
@ -11,13 +11,14 @@
|
|||||||
#ifndef AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
#ifndef AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
||||||
#define AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
#define AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
||||||
|
|
||||||
|
|
||||||
namespace avian {
|
namespace avian {
|
||||||
namespace codegen {
|
namespace codegen {
|
||||||
|
|
||||||
class Multimethod {
|
class Multimethod {
|
||||||
public:
|
public:
|
||||||
inline static unsigned index(lir::UnaryOperation operation, lir::OperandType operand) {
|
inline static unsigned index(lir::UnaryOperation operation,
|
||||||
|
lir::OperandType operand)
|
||||||
|
{
|
||||||
return operation + (lir::UnaryOperationCount * operand);
|
return operation + (lir::UnaryOperationCount * operand);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -26,4 +27,3 @@ public:
|
|||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
|
||||||
#endif // AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
#endif // AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
||||||
|
|
||||||
|
@ -54,25 +54,30 @@ namespace x86 {
|
|||||||
const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1);
|
const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1);
|
||||||
|
|
||||||
const unsigned StackAlignmentInBytes = 16;
|
const unsigned StackAlignmentInBytes = 16;
|
||||||
const unsigned StackAlignmentInWords = StackAlignmentInBytes / TargetBytesPerWord;
|
const unsigned StackAlignmentInWords = StackAlignmentInBytes
|
||||||
|
/ TargetBytesPerWord;
|
||||||
|
|
||||||
unsigned
|
unsigned argumentFootprint(unsigned footprint)
|
||||||
argumentFootprint(unsigned footprint)
|
|
||||||
{
|
{
|
||||||
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
|
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t read4(uint8_t* p)
|
||||||
read4(uint8_t* p)
|
|
||||||
{
|
{
|
||||||
uint32_t v; memcpy(&v, p, 4);
|
uint32_t v;
|
||||||
|
memcpy(&v, p, 4);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void nextFrame(ArchitectureContext* c UNUSED,
|
||||||
nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED,
|
uint8_t* start,
|
||||||
unsigned footprint, void*, bool mostRecent,
|
unsigned size UNUSED,
|
||||||
int targetParameterFootprint, void** ip, void** stack)
|
unsigned footprint,
|
||||||
|
void*,
|
||||||
|
bool mostRecent,
|
||||||
|
int targetParameterFootprint,
|
||||||
|
void** ip,
|
||||||
|
void** stack)
|
||||||
{
|
{
|
||||||
assertT(c, *ip >= start);
|
assertT(c, *ip >= start);
|
||||||
assertT(c, *ip <= start + size);
|
assertT(c, *ip <= start + size);
|
||||||
@ -124,16 +129,14 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED,
|
|||||||
// $offset,%rsp":
|
// $offset,%rsp":
|
||||||
if (TargetBytesPerWord == 4) {
|
if (TargetBytesPerWord == 4) {
|
||||||
if ((*instruction == 0x83 or *instruction == 0x81)
|
if ((*instruction == 0x83 or *instruction == 0x81)
|
||||||
and instruction[1] == 0xec)
|
and instruction[1] == 0xec) {
|
||||||
{
|
|
||||||
offset
|
offset
|
||||||
-= (*instruction == 0x83 ? instruction[2] : read4(instruction + 2))
|
-= (*instruction == 0x83 ? instruction[2] : read4(instruction + 2))
|
||||||
/ TargetBytesPerWord;
|
/ TargetBytesPerWord;
|
||||||
}
|
}
|
||||||
} else if (*instruction == 0x48
|
} else if (*instruction == 0x48
|
||||||
and (instruction[1] == 0x83 or instruction[1] == 0x81)
|
and (instruction[1] == 0x83 or instruction[1] == 0x81)
|
||||||
and instruction[2] == 0xec)
|
and instruction[2] == 0xec) {
|
||||||
{
|
|
||||||
offset
|
offset
|
||||||
-= (instruction[1] == 0x83 ? instruction[3] : read4(instruction + 3))
|
-= (instruction[1] == 0x83 ? instruction[3] : read4(instruction + 3))
|
||||||
/ TargetBytesPerWord;
|
/ TargetBytesPerWord;
|
||||||
@ -156,17 +159,18 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED,
|
|||||||
*stack = static_cast<void**>(*stack) + offset;
|
*stack = static_cast<void**>(*stack) + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyArchitecture: public Architecture {
|
class MyArchitecture : public Architecture {
|
||||||
public:
|
public:
|
||||||
MyArchitecture(System* system, bool useNativeFeatures):
|
MyArchitecture(System* system, bool useNativeFeatures)
|
||||||
c(system, useNativeFeatures),
|
: c(system, useNativeFeatures),
|
||||||
referenceCount(0),
|
referenceCount(0),
|
||||||
myRegisterFile(GeneralRegisterMask, useSSE(&c) ? FloatRegisterMask : 0)
|
myRegisterFile(GeneralRegisterMask, useSSE(&c) ? FloatRegisterMask : 0)
|
||||||
{
|
{
|
||||||
populateTables(&c);
|
populateTables(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned floatRegisterSize() {
|
virtual unsigned floatRegisterSize()
|
||||||
|
{
|
||||||
if (useSSE(&c)) {
|
if (useSSE(&c)) {
|
||||||
return 8;
|
return 8;
|
||||||
} else {
|
} else {
|
||||||
@ -174,35 +178,43 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const RegisterFile* registerFile() {
|
virtual const RegisterFile* registerFile()
|
||||||
|
{
|
||||||
return &myRegisterFile;
|
return &myRegisterFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int scratch() {
|
virtual int scratch()
|
||||||
|
{
|
||||||
return rax;
|
return rax;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int stack() {
|
virtual int stack()
|
||||||
|
{
|
||||||
return rsp;
|
return rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int thread() {
|
virtual int thread()
|
||||||
|
{
|
||||||
return rbx;
|
return rbx;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int returnLow() {
|
virtual int returnLow()
|
||||||
|
{
|
||||||
return rax;
|
return rax;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int returnHigh() {
|
virtual int returnHigh()
|
||||||
|
{
|
||||||
return (TargetBytesPerWord == 4 ? rdx : lir::NoRegister);
|
return (TargetBytesPerWord == 4 ? rdx : lir::NoRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int virtualCallTarget() {
|
virtual int virtualCallTarget()
|
||||||
|
{
|
||||||
return rax;
|
return rax;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int virtualCallIndex() {
|
virtual int virtualCallIndex()
|
||||||
|
{
|
||||||
return rdx;
|
return rdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,15 +223,18 @@ class MyArchitecture: public Architecture {
|
|||||||
return ir::TargetInfo(TargetBytesPerWord);
|
return ir::TargetInfo(TargetBytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool bigEndian() {
|
virtual bool bigEndian()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uintptr_t maximumImmediateJump() {
|
virtual uintptr_t maximumImmediateJump()
|
||||||
|
{
|
||||||
return 0x7FFFFFFF;
|
return 0x7FFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool reserved(int register_) {
|
virtual bool reserved(int register_)
|
||||||
|
{
|
||||||
switch (register_) {
|
switch (register_) {
|
||||||
case rbp:
|
case rbp:
|
||||||
return UseFramePointer;
|
return UseFramePointer;
|
||||||
@ -233,38 +248,49 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameFootprint(unsigned footprint) {
|
virtual unsigned frameFootprint(unsigned footprint)
|
||||||
|
{
|
||||||
#if AVIAN_TARGET_FORMAT == AVIAN_FORMAT_PE
|
#if AVIAN_TARGET_FORMAT == AVIAN_FORMAT_PE
|
||||||
return max(footprint, StackAlignmentInWords);
|
return max(footprint, StackAlignmentInWords);
|
||||||
#else
|
#else
|
||||||
return max(footprint > argumentRegisterCount() ?
|
return max(footprint > argumentRegisterCount()
|
||||||
footprint - argumentRegisterCount() : 0,
|
? footprint - argumentRegisterCount()
|
||||||
|
: 0,
|
||||||
StackAlignmentInWords);
|
StackAlignmentInWords);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned argumentFootprint(unsigned footprint) {
|
virtual unsigned argumentFootprint(unsigned footprint)
|
||||||
|
{
|
||||||
return x86::argumentFootprint(footprint);
|
return x86::argumentFootprint(footprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool argumentAlignment() {
|
virtual bool argumentAlignment()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool argumentRegisterAlignment() {
|
virtual bool argumentRegisterAlignment()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned argumentRegisterCount() {
|
virtual unsigned argumentRegisterCount()
|
||||||
|
{
|
||||||
#if AVIAN_TARGET_FORMAT == AVIAN_FORMAT_PE
|
#if AVIAN_TARGET_FORMAT == AVIAN_FORMAT_PE
|
||||||
if (TargetBytesPerWord == 8) return 4; else
|
if (TargetBytesPerWord == 8)
|
||||||
|
return 4;
|
||||||
|
else
|
||||||
#else
|
#else
|
||||||
if (TargetBytesPerWord == 8) return 6; else
|
if (TargetBytesPerWord == 8)
|
||||||
|
return 6;
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int argumentRegister(unsigned index) {
|
virtual int argumentRegister(unsigned index)
|
||||||
|
{
|
||||||
assertT(&c, TargetBytesPerWord == 8);
|
assertT(&c, TargetBytesPerWord == 8);
|
||||||
switch (index) {
|
switch (index) {
|
||||||
#if AVIAN_TARGET_FORMAT == AVIAN_FORMAT_PE
|
#if AVIAN_TARGET_FORMAT == AVIAN_FORMAT_PE
|
||||||
@ -295,23 +321,28 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool hasLinkRegister() {
|
virtual bool hasLinkRegister()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned stackAlignmentInWords() {
|
virtual unsigned stackAlignmentInWords()
|
||||||
|
{
|
||||||
return StackAlignmentInWords;
|
return StackAlignmentInWords;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool matchCall(void* returnAddress, void* target) {
|
virtual bool matchCall(void* returnAddress, void* target)
|
||||||
|
{
|
||||||
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
|
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
|
||||||
int32_t actualOffset; memcpy(&actualOffset, instruction + 1, 4);
|
int32_t actualOffset;
|
||||||
|
memcpy(&actualOffset, instruction + 1, 4);
|
||||||
void* actualTarget = static_cast<uint8_t*>(returnAddress) + actualOffset;
|
void* actualTarget = static_cast<uint8_t*>(returnAddress) + actualOffset;
|
||||||
|
|
||||||
return *instruction == 0xE8 and actualTarget == target;
|
return *instruction == 0xE8 and actualTarget == target;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateCall(lir::UnaryOperation op, void* returnAddress,
|
virtual void updateCall(lir::UnaryOperation op,
|
||||||
|
void* returnAddress,
|
||||||
void* newTarget)
|
void* newTarget)
|
||||||
{
|
{
|
||||||
bool assertTAlignment UNUSED;
|
bool assertTAlignment UNUSED;
|
||||||
@ -378,43 +409,61 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setConstant(void* dst, uint64_t constant) {
|
virtual void setConstant(void* dst, uint64_t constant)
|
||||||
|
{
|
||||||
target_uintptr_t v = targetVW(constant);
|
target_uintptr_t v = targetVW(constant);
|
||||||
memcpy(dst, &v, TargetBytesPerWord);
|
memcpy(dst, &v, TargetBytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned alignFrameSize(unsigned sizeInWords) {
|
virtual unsigned alignFrameSize(unsigned sizeInWords)
|
||||||
|
{
|
||||||
return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords)
|
return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords)
|
||||||
- FrameHeaderSize;
|
- FrameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
virtual void nextFrame(void* start,
|
||||||
void* link, bool mostRecent,
|
unsigned size,
|
||||||
int targetParameterFootprint, void** ip,
|
unsigned footprint,
|
||||||
|
void* link,
|
||||||
|
bool mostRecent,
|
||||||
|
int targetParameterFootprint,
|
||||||
|
void** ip,
|
||||||
void** stack)
|
void** stack)
|
||||||
{
|
{
|
||||||
x86::nextFrame(&c, static_cast<uint8_t*>(start), size, footprint,
|
x86::nextFrame(&c,
|
||||||
link, mostRecent, targetParameterFootprint, ip, stack);
|
static_cast<uint8_t*>(start),
|
||||||
|
size,
|
||||||
|
footprint,
|
||||||
|
link,
|
||||||
|
mostRecent,
|
||||||
|
targetParameterFootprint,
|
||||||
|
ip,
|
||||||
|
stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* frameIp(void* stack) {
|
virtual void* frameIp(void* stack)
|
||||||
|
{
|
||||||
return stack ? *static_cast<void**>(stack) : 0;
|
return stack ? *static_cast<void**>(stack) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameHeaderSize() {
|
virtual unsigned frameHeaderSize()
|
||||||
|
{
|
||||||
return FrameHeaderSize;
|
return FrameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameReturnAddressSize() {
|
virtual unsigned frameReturnAddressSize()
|
||||||
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameFooterSize() {
|
virtual unsigned frameFooterSize()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool alwaysCondensed(lir::BinaryOperation op) {
|
virtual bool alwaysCondensed(lir::BinaryOperation op)
|
||||||
switch(op) {
|
{
|
||||||
|
switch (op) {
|
||||||
case lir::Float2Float:
|
case lir::Float2Float:
|
||||||
case lir::Float2Int:
|
case lir::Float2Int:
|
||||||
case lir::Int2Float:
|
case lir::Int2Float:
|
||||||
@ -432,34 +481,39 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool alwaysCondensed(lir::TernaryOperation) {
|
virtual bool alwaysCondensed(lir::TernaryOperation)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int returnAddressOffset() {
|
virtual int returnAddressOffset()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int framePointerOffset() {
|
virtual int framePointerOffset()
|
||||||
|
{
|
||||||
return UseFramePointer ? -1 : 0;
|
return UseFramePointer ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void plan
|
virtual void plan(lir::UnaryOperation,
|
||||||
(lir::UnaryOperation,
|
unsigned,
|
||||||
unsigned, OperandMask& aMask,
|
OperandMask& aMask,
|
||||||
bool* thunk)
|
bool* thunk)
|
||||||
{
|
{
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand) | (1 << lir::ConstantOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand)
|
||||||
|
| (1 << lir::ConstantOperand);
|
||||||
*thunk = false;
|
*thunk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planSource
|
virtual void planSource(lir::BinaryOperation op,
|
||||||
(lir::BinaryOperation op,
|
unsigned aSize,
|
||||||
unsigned aSize, OperandMask& aMask,
|
OperandMask& aMask,
|
||||||
unsigned bSize, bool* thunk)
|
unsigned bSize,
|
||||||
|
bool* thunk)
|
||||||
{
|
{
|
||||||
aMask.registerMask = GeneralRegisterMask |
|
aMask.registerMask = GeneralRegisterMask
|
||||||
(static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
||||||
|
|
||||||
*thunk = false;
|
*thunk = false;
|
||||||
|
|
||||||
@ -501,7 +555,8 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
case lir::FloatSquareRoot:
|
case lir::FloatSquareRoot:
|
||||||
if (useSSE(&c)) {
|
if (useSSE(&c)) {
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
|
| (1 << lir::MemoryOperand);
|
||||||
aMask.registerMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
aMask.registerMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
||||||
| FloatRegisterMask;
|
| FloatRegisterMask;
|
||||||
} else {
|
} else {
|
||||||
@ -511,7 +566,8 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
case lir::Float2Float:
|
case lir::Float2Float:
|
||||||
if (useSSE(&c)) {
|
if (useSSE(&c)) {
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
|
| (1 << lir::MemoryOperand);
|
||||||
aMask.registerMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
aMask.registerMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
||||||
| FloatRegisterMask;
|
| FloatRegisterMask;
|
||||||
} else {
|
} else {
|
||||||
@ -525,7 +581,8 @@ class MyArchitecture: public Architecture {
|
|||||||
// thunks or produce inline machine code which handles edge
|
// thunks or produce inline machine code which handles edge
|
||||||
// cases properly.
|
// cases properly.
|
||||||
if (false and useSSE(&c) and bSize <= TargetBytesPerWord) {
|
if (false and useSSE(&c) and bSize <= TargetBytesPerWord) {
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
|
| (1 << lir::MemoryOperand);
|
||||||
aMask.registerMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
aMask.registerMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
||||||
| FloatRegisterMask;
|
| FloatRegisterMask;
|
||||||
} else {
|
} else {
|
||||||
@ -535,8 +592,10 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
case lir::Int2Float:
|
case lir::Int2Float:
|
||||||
if (useSSE(&c) and aSize <= TargetBytesPerWord) {
|
if (useSSE(&c) and aSize <= TargetBytesPerWord) {
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
aMask.registerMask = GeneralRegisterMask
|
| (1 << lir::MemoryOperand);
|
||||||
|
aMask.registerMask
|
||||||
|
= GeneralRegisterMask
|
||||||
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
||||||
} else {
|
} else {
|
||||||
*thunk = true;
|
*thunk = true;
|
||||||
@ -549,14 +608,16 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
if (TargetBytesPerWord == 4) {
|
if (TargetBytesPerWord == 4) {
|
||||||
if (aSize == 4 and bSize == 8) {
|
if (aSize == 4 and bSize == 8) {
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
const uint32_t mask
|
| (1 << lir::MemoryOperand);
|
||||||
= GeneralRegisterMask & ~((1 << rax) | (1 << rdx));
|
const uint32_t mask = GeneralRegisterMask
|
||||||
|
& ~((1 << rax) | (1 << rdx));
|
||||||
aMask.registerMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
aMask.registerMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||||
} else if (aSize == 1 or bSize == 1) {
|
} else if (aSize == 1 or bSize == 1) {
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
const uint32_t mask
|
| (1 << lir::MemoryOperand);
|
||||||
= (1 << rax) | (1 << rcx) | (1 << rdx) | (1 << rbx);
|
const uint32_t mask = (1 << rax) | (1 << rcx) | (1 << rdx)
|
||||||
|
| (1 << rbx);
|
||||||
aMask.registerMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
aMask.registerMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -567,10 +628,11 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planDestination
|
virtual void planDestination(lir::BinaryOperation op,
|
||||||
(lir::BinaryOperation op,
|
unsigned aSize,
|
||||||
unsigned aSize, const OperandMask& aMask,
|
const OperandMask& aMask,
|
||||||
unsigned bSize, OperandMask& bMask)
|
unsigned bSize,
|
||||||
|
OperandMask& bMask)
|
||||||
{
|
{
|
||||||
bMask.typeMask = ~0;
|
bMask.typeMask = ~0;
|
||||||
bMask.registerMask = GeneralRegisterMask
|
bMask.registerMask = GeneralRegisterMask
|
||||||
@ -606,21 +668,25 @@ class MyArchitecture: public Architecture {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case lir::Move:
|
case lir::Move:
|
||||||
if (aMask.typeMask & ((1 << lir::MemoryOperand) | 1 << lir::AddressOperand)) {
|
if (aMask.typeMask
|
||||||
|
& ((1 << lir::MemoryOperand) | 1 << lir::AddressOperand)) {
|
||||||
bMask.typeMask = (1 << lir::RegisterOperand);
|
bMask.typeMask = (1 << lir::RegisterOperand);
|
||||||
bMask.registerMask = GeneralRegisterMask
|
bMask.registerMask = GeneralRegisterMask
|
||||||
| (static_cast<uint64_t>(GeneralRegisterMask) << 32)
|
| (static_cast<uint64_t>(GeneralRegisterMask)
|
||||||
| FloatRegisterMask;
|
<< 32) | FloatRegisterMask;
|
||||||
} else if (aMask.typeMask & (1 << lir::RegisterOperand)) {
|
} else if (aMask.typeMask & (1 << lir::RegisterOperand)) {
|
||||||
bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
bMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
|
| (1 << lir::MemoryOperand);
|
||||||
if (aMask.registerMask & FloatRegisterMask) {
|
if (aMask.registerMask & FloatRegisterMask) {
|
||||||
bMask.registerMask = FloatRegisterMask;
|
bMask.registerMask = FloatRegisterMask;
|
||||||
} else {
|
} else {
|
||||||
bMask.registerMask = GeneralRegisterMask
|
bMask.registerMask
|
||||||
|
= GeneralRegisterMask
|
||||||
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
bMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
|
| (1 << lir::MemoryOperand);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TargetBytesPerWord == 4) {
|
if (TargetBytesPerWord == 4) {
|
||||||
@ -628,8 +694,8 @@ class MyArchitecture: public Architecture {
|
|||||||
bMask.registerMask = (static_cast<uint64_t>(1) << (rdx + 32))
|
bMask.registerMask = (static_cast<uint64_t>(1) << (rdx + 32))
|
||||||
| (static_cast<uint64_t>(1) << rax);
|
| (static_cast<uint64_t>(1) << rax);
|
||||||
} else if (aSize == 1 or bSize == 1) {
|
} else if (aSize == 1 or bSize == 1) {
|
||||||
const uint32_t mask
|
const uint32_t mask = (1 << rax) | (1 << rcx) | (1 << rdx)
|
||||||
= (1 << rax) | (1 << rcx) | (1 << rdx) | (1 << rbx);
|
| (1 << rbx);
|
||||||
bMask.registerMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
bMask.registerMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -640,8 +706,8 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planMove
|
virtual void planMove(unsigned size,
|
||||||
(unsigned size, OperandMask& srcMask,
|
OperandMask& srcMask,
|
||||||
OperandMask& tmpMask,
|
OperandMask& tmpMask,
|
||||||
const OperandMask& dstMask)
|
const OperandMask& dstMask)
|
||||||
{
|
{
|
||||||
@ -653,20 +719,24 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
if (dstMask.typeMask & (1 << lir::MemoryOperand)) {
|
if (dstMask.typeMask & (1 << lir::MemoryOperand)) {
|
||||||
// can't move directly from memory to memory
|
// can't move directly from memory to memory
|
||||||
srcMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
|
srcMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
|
| (1 << lir::ConstantOperand);
|
||||||
tmpMask.typeMask = 1 << lir::RegisterOperand;
|
tmpMask.typeMask = 1 << lir::RegisterOperand;
|
||||||
tmpMask.registerMask = GeneralRegisterMask
|
tmpMask.registerMask
|
||||||
|
= GeneralRegisterMask
|
||||||
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
||||||
} else if (dstMask.typeMask & (1 << lir::RegisterOperand)) {
|
} else if (dstMask.typeMask & (1 << lir::RegisterOperand)) {
|
||||||
if (size > TargetBytesPerWord) {
|
if (size > TargetBytesPerWord) {
|
||||||
// can't move directly from FPR to GPR or vice-versa for
|
// can't move directly from FPR to GPR or vice-versa for
|
||||||
// values larger than the GPR size
|
// values larger than the GPR size
|
||||||
if (dstMask.registerMask & FloatRegisterMask) {
|
if (dstMask.registerMask & FloatRegisterMask) {
|
||||||
srcMask.registerMask = FloatRegisterMask
|
srcMask.registerMask
|
||||||
|
= FloatRegisterMask
|
||||||
| (static_cast<uint64_t>(FloatRegisterMask) << 32);
|
| (static_cast<uint64_t>(FloatRegisterMask) << 32);
|
||||||
tmpMask.typeMask = 1 << lir::MemoryOperand;
|
tmpMask.typeMask = 1 << lir::MemoryOperand;
|
||||||
} else if (dstMask.registerMask & GeneralRegisterMask) {
|
} else if (dstMask.registerMask & GeneralRegisterMask) {
|
||||||
srcMask.registerMask = GeneralRegisterMask
|
srcMask.registerMask
|
||||||
|
= GeneralRegisterMask
|
||||||
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
||||||
tmpMask.typeMask = 1 << lir::MemoryOperand;
|
tmpMask.typeMask = 1 << lir::MemoryOperand;
|
||||||
}
|
}
|
||||||
@ -677,19 +747,23 @@ class MyArchitecture: public Architecture {
|
|||||||
if (size > TargetBytesPerWord) {
|
if (size > TargetBytesPerWord) {
|
||||||
tmpMask.typeMask = 1 << lir::MemoryOperand;
|
tmpMask.typeMask = 1 << lir::MemoryOperand;
|
||||||
} else {
|
} else {
|
||||||
tmpMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
tmpMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
tmpMask.registerMask = GeneralRegisterMask
|
| (1 << lir::MemoryOperand);
|
||||||
|
tmpMask.registerMask
|
||||||
|
= GeneralRegisterMask
|
||||||
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planSource
|
virtual void planSource(lir::TernaryOperation op,
|
||||||
(lir::TernaryOperation op,
|
unsigned aSize,
|
||||||
unsigned aSize, OperandMask& aMask,
|
OperandMask& aMask,
|
||||||
unsigned bSize, OperandMask& bMask,
|
unsigned bSize,
|
||||||
unsigned, bool* thunk)
|
OperandMask& bMask,
|
||||||
|
unsigned,
|
||||||
|
bool* thunk)
|
||||||
{
|
{
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
|
||||||
aMask.registerMask = GeneralRegisterMask
|
aMask.registerMask = GeneralRegisterMask
|
||||||
@ -707,11 +781,11 @@ class MyArchitecture: public Architecture {
|
|||||||
case lir::FloatMultiply:
|
case lir::FloatMultiply:
|
||||||
case lir::FloatDivide:
|
case lir::FloatDivide:
|
||||||
if (useSSE(&c)) {
|
if (useSSE(&c)) {
|
||||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
aMask.typeMask = (1 << lir::RegisterOperand)
|
||||||
|
| (1 << lir::MemoryOperand);
|
||||||
bMask.typeMask = (1 << lir::RegisterOperand);
|
bMask.typeMask = (1 << lir::RegisterOperand);
|
||||||
|
|
||||||
const uint64_t mask
|
const uint64_t mask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
||||||
= (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
|
||||||
| FloatRegisterMask;
|
| FloatRegisterMask;
|
||||||
aMask.registerMask = mask;
|
aMask.registerMask = mask;
|
||||||
bMask.registerMask = mask;
|
bMask.registerMask = mask;
|
||||||
@ -796,11 +870,13 @@ class MyArchitecture: public Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void planDestination
|
virtual void planDestination(lir::TernaryOperation op,
|
||||||
(lir::TernaryOperation op,
|
unsigned,
|
||||||
unsigned, const OperandMask&,
|
const OperandMask&,
|
||||||
unsigned, const OperandMask& bMask,
|
unsigned,
|
||||||
unsigned, OperandMask& cMask)
|
const OperandMask& bMask,
|
||||||
|
unsigned,
|
||||||
|
OperandMask& cMask)
|
||||||
{
|
{
|
||||||
if (isBranch(op)) {
|
if (isBranch(op)) {
|
||||||
cMask.typeMask = (1 << lir::ConstantOperand);
|
cMask.typeMask = (1 << lir::ConstantOperand);
|
||||||
@ -813,12 +889,14 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
virtual Assembler* makeAssembler(util::Allocator* allocator, Zone* zone);
|
virtual Assembler* makeAssembler(util::Allocator* allocator, Zone* zone);
|
||||||
|
|
||||||
virtual void acquire() {
|
virtual void acquire()
|
||||||
++ referenceCount;
|
{
|
||||||
|
++referenceCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void release() {
|
virtual void release()
|
||||||
if (-- referenceCount == 0) {
|
{
|
||||||
|
if (--referenceCount == 0) {
|
||||||
c.s->free(this);
|
c.s->free(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -828,18 +906,21 @@ class MyArchitecture: public Architecture {
|
|||||||
const RegisterFile myRegisterFile;
|
const RegisterFile myRegisterFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyAssembler: public Assembler {
|
class MyAssembler : public Assembler {
|
||||||
public:
|
public:
|
||||||
MyAssembler(System* s, util::Allocator* a, Zone* zone, MyArchitecture* arch)
|
MyAssembler(System* s, util::Allocator* a, Zone* zone, MyArchitecture* arch)
|
||||||
: c(s, a, zone, &(arch->c)), arch_(arch)
|
: c(s, a, zone, &(arch->c)), arch_(arch)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual void setClient(Client* client) {
|
virtual void setClient(Client* client)
|
||||||
|
{
|
||||||
assertT(&c, c.client == 0);
|
assertT(&c, c.client == 0);
|
||||||
c.client = client;
|
c.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Architecture* arch() {
|
virtual Architecture* arch()
|
||||||
|
{
|
||||||
return arch_;
|
return arch_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,11 +930,16 @@ class MyAssembler: public Assembler {
|
|||||||
lir::Register stack(rsp);
|
lir::Register stack(rsp);
|
||||||
lir::Memory stackLimit(rbx, stackLimitOffsetFromThread);
|
lir::Memory stackLimit(rbx, stackLimitOffsetFromThread);
|
||||||
lir::Constant handlerConstant(resolvedPromise(&c, handler));
|
lir::Constant handlerConstant(resolvedPromise(&c, handler));
|
||||||
branchRM(&c, lir::JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit,
|
branchRM(&c,
|
||||||
|
lir::JumpIfGreaterOrEqual,
|
||||||
|
TargetBytesPerWord,
|
||||||
|
&stack,
|
||||||
|
&stackLimit,
|
||||||
&handlerConstant);
|
&handlerConstant);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void saveFrame(unsigned stackOffset, unsigned) {
|
virtual void saveFrame(unsigned stackOffset, unsigned)
|
||||||
|
{
|
||||||
lir::Register stack(rsp);
|
lir::Register stack(rsp);
|
||||||
lir::Memory stackDst(rbx, stackOffset);
|
lir::Memory stackDst(rbx, stackOffset);
|
||||||
apply(lir::Move,
|
apply(lir::Move,
|
||||||
@ -861,7 +947,8 @@ class MyAssembler: public Assembler {
|
|||||||
OperandInfo(TargetBytesPerWord, lir::MemoryOperand, &stackDst));
|
OperandInfo(TargetBytesPerWord, lir::MemoryOperand, &stackDst));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pushFrame(unsigned argumentCount, ...) {
|
virtual void pushFrame(unsigned argumentCount, ...)
|
||||||
|
{
|
||||||
// TODO: Argument should be replaced by OperandInfo...
|
// TODO: Argument should be replaced by OperandInfo...
|
||||||
struct Argument {
|
struct Argument {
|
||||||
unsigned size;
|
unsigned size;
|
||||||
@ -869,15 +956,16 @@ class MyAssembler: public Assembler {
|
|||||||
lir::Operand* operand;
|
lir::Operand* operand;
|
||||||
};
|
};
|
||||||
RUNTIME_ARRAY(Argument, arguments, argumentCount);
|
RUNTIME_ARRAY(Argument, arguments, argumentCount);
|
||||||
va_list a; va_start(a, argumentCount);
|
va_list a;
|
||||||
|
va_start(a, argumentCount);
|
||||||
unsigned footprint = 0;
|
unsigned footprint = 0;
|
||||||
for (unsigned i = 0; i < argumentCount; ++i) {
|
for (unsigned i = 0; i < argumentCount; ++i) {
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned);
|
RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned);
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].type
|
RUNTIME_ARRAY_BODY(arguments)[i].type
|
||||||
= static_cast<lir::OperandType>(va_arg(a, int));
|
= static_cast<lir::OperandType>(va_arg(a, int));
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*);
|
RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*);
|
||||||
footprint += ceilingDivide
|
footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
|
TargetBytesPerWord);
|
||||||
}
|
}
|
||||||
va_end(a);
|
va_end(a);
|
||||||
|
|
||||||
@ -888,32 +976,31 @@ class MyAssembler: public Assembler {
|
|||||||
if (i < arch_->argumentRegisterCount()) {
|
if (i < arch_->argumentRegisterCount()) {
|
||||||
lir::Register dst(arch_->argumentRegister(i));
|
lir::Register dst(arch_->argumentRegister(i));
|
||||||
apply(lir::Move,
|
apply(lir::Move,
|
||||||
OperandInfo(
|
OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].size,
|
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
||||||
OperandInfo(
|
OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord),
|
TargetBytesPerWord),
|
||||||
lir::RegisterOperand,
|
lir::RegisterOperand,
|
||||||
&dst));
|
&dst));
|
||||||
} else {
|
} else {
|
||||||
lir::Memory dst(rsp, offset * TargetBytesPerWord);
|
lir::Memory dst(rsp, offset * TargetBytesPerWord);
|
||||||
apply(lir::Move,
|
apply(lir::Move,
|
||||||
OperandInfo(
|
OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].size,
|
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
||||||
OperandInfo(
|
OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord),
|
TargetBytesPerWord),
|
||||||
lir::MemoryOperand,
|
lir::MemoryOperand,
|
||||||
&dst));
|
&dst));
|
||||||
offset += ceilingDivide
|
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||||
(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
|
TargetBytesPerWord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void allocateFrame(unsigned footprint) {
|
virtual void allocateFrame(unsigned footprint)
|
||||||
|
{
|
||||||
lir::Register stack(rsp);
|
lir::Register stack(rsp);
|
||||||
|
|
||||||
if (UseFramePointer) {
|
if (UseFramePointer) {
|
||||||
@ -925,23 +1012,29 @@ class MyAssembler: public Assembler {
|
|||||||
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &base));
|
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &base));
|
||||||
}
|
}
|
||||||
|
|
||||||
lir::Constant footprintConstant(resolvedPromise(&c, footprint * TargetBytesPerWord));
|
lir::Constant footprintConstant(
|
||||||
|
resolvedPromise(&c, footprint * TargetBytesPerWord));
|
||||||
apply(lir::Subtract,
|
apply(lir::Subtract,
|
||||||
OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &footprintConstant),
|
OperandInfo(
|
||||||
|
TargetBytesPerWord, lir::ConstantOperand, &footprintConstant),
|
||||||
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack),
|
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack),
|
||||||
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack));
|
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void adjustFrame(unsigned difference) {
|
virtual void adjustFrame(unsigned difference)
|
||||||
|
{
|
||||||
lir::Register stack(rsp);
|
lir::Register stack(rsp);
|
||||||
lir::Constant differenceConstant(resolvedPromise(&c, difference * TargetBytesPerWord));
|
lir::Constant differenceConstant(
|
||||||
|
resolvedPromise(&c, difference * TargetBytesPerWord));
|
||||||
apply(lir::Subtract,
|
apply(lir::Subtract,
|
||||||
OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &differenceConstant),
|
OperandInfo(
|
||||||
|
TargetBytesPerWord, lir::ConstantOperand, &differenceConstant),
|
||||||
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack),
|
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack),
|
||||||
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack));
|
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popFrame(unsigned frameFootprint) {
|
virtual void popFrame(unsigned frameFootprint)
|
||||||
|
{
|
||||||
if (UseFramePointer) {
|
if (UseFramePointer) {
|
||||||
lir::Register base(rbp);
|
lir::Register base(rbp);
|
||||||
lir::Register stack(rsp);
|
lir::Register stack(rsp);
|
||||||
@ -952,7 +1045,8 @@ class MyAssembler: public Assembler {
|
|||||||
popR(&c, TargetBytesPerWord, &base);
|
popR(&c, TargetBytesPerWord, &base);
|
||||||
} else {
|
} else {
|
||||||
lir::Register stack(rsp);
|
lir::Register stack(rsp);
|
||||||
lir::Constant footprint(resolvedPromise(&c, frameFootprint * TargetBytesPerWord));
|
lir::Constant footprint(
|
||||||
|
resolvedPromise(&c, frameFootprint * TargetBytesPerWord));
|
||||||
apply(lir::Add,
|
apply(lir::Add,
|
||||||
OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &footprint),
|
OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &footprint),
|
||||||
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack),
|
OperandInfo(TargetBytesPerWord, lir::RegisterOperand, &stack),
|
||||||
@ -971,14 +1065,20 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
unsigned baseSize = UseFramePointer ? 1 : 0;
|
unsigned baseSize = UseFramePointer ? 1 : 0;
|
||||||
|
|
||||||
lir::Memory returnAddressSrc
|
lir::Memory returnAddressSrc(
|
||||||
(rsp, (frameFootprint + baseSize) * TargetBytesPerWord);
|
rsp, (frameFootprint + baseSize) * TargetBytesPerWord);
|
||||||
moveMR(&c, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord,
|
moveMR(&c,
|
||||||
|
TargetBytesPerWord,
|
||||||
|
&returnAddressSrc,
|
||||||
|
TargetBytesPerWord,
|
||||||
&tmp);
|
&tmp);
|
||||||
|
|
||||||
lir::Memory returnAddressDst
|
lir::Memory returnAddressDst(
|
||||||
(rsp, (frameFootprint - offset + baseSize) * TargetBytesPerWord);
|
rsp, (frameFootprint - offset + baseSize) * TargetBytesPerWord);
|
||||||
moveRM(&c, TargetBytesPerWord, &tmp, TargetBytesPerWord,
|
moveRM(&c,
|
||||||
|
TargetBytesPerWord,
|
||||||
|
&tmp,
|
||||||
|
TargetBytesPerWord,
|
||||||
&returnAddressDst);
|
&returnAddressDst);
|
||||||
|
|
||||||
c.client->releaseTemporary(tmp.low);
|
c.client->releaseTemporary(tmp.low);
|
||||||
@ -990,9 +1090,8 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lir::Register stack(rsp);
|
lir::Register stack(rsp);
|
||||||
lir::Constant footprint
|
lir::Constant footprint(resolvedPromise(
|
||||||
(resolvedPromise
|
&c, (frameFootprint - offset + baseSize) * TargetBytesPerWord));
|
||||||
(&c, (frameFootprint - offset + baseSize) * TargetBytesPerWord));
|
|
||||||
|
|
||||||
addCR(&c, TargetBytesPerWord, &footprint, TargetBytesPerWord, &stack);
|
addCR(&c, TargetBytesPerWord, &footprint, TargetBytesPerWord, &stack);
|
||||||
|
|
||||||
@ -1032,9 +1131,9 @@ class MyAssembler: public Assembler {
|
|||||||
popR(&c, TargetBytesPerWord, &returnAddress);
|
popR(&c, TargetBytesPerWord, &returnAddress);
|
||||||
|
|
||||||
lir::Register stack(rsp);
|
lir::Register stack(rsp);
|
||||||
lir::Constant adjustment
|
lir::Constant adjustment(resolvedPromise(
|
||||||
(resolvedPromise(&c, (argumentFootprint - StackAlignmentInWords)
|
&c,
|
||||||
* TargetBytesPerWord));
|
(argumentFootprint - StackAlignmentInWords) * TargetBytesPerWord));
|
||||||
addCR(&c, TargetBytesPerWord, &adjustment, TargetBytesPerWord, &stack);
|
addCR(&c, TargetBytesPerWord, &adjustment, TargetBytesPerWord, &stack);
|
||||||
|
|
||||||
jumpR(&c, TargetBytesPerWord, &returnAddress);
|
jumpR(&c, TargetBytesPerWord, &returnAddress);
|
||||||
@ -1058,45 +1157,51 @@ class MyAssembler: public Assembler {
|
|||||||
jumpR(&c, TargetBytesPerWord, &returnAddress);
|
jumpR(&c, TargetBytesPerWord, &returnAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(lir::Operation op) {
|
virtual void apply(lir::Operation op)
|
||||||
|
{
|
||||||
arch_->c.operations[op](&c);
|
arch_->c.operations[op](&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(lir::UnaryOperation op, OperandInfo a)
|
virtual void apply(lir::UnaryOperation op, OperandInfo a)
|
||||||
{
|
{
|
||||||
arch_->c.unaryOperations[Multimethod::index(op, a.type)]
|
arch_->c.unaryOperations[Multimethod::index(op, a.type)](
|
||||||
(&c, a.size, a.operand);
|
&c, a.size, a.operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b)
|
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b)
|
||||||
{
|
{
|
||||||
arch_->c.binaryOperations[index(&(arch_->c), op, a.type, b.type)]
|
arch_->c.binaryOperations[index(&(arch_->c), op, a.type, b.type)](
|
||||||
(&c, a.size, a.operand, b.size, b.operand);
|
&c, a.size, a.operand, b.size, b.operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c)
|
virtual void apply(lir::TernaryOperation op,
|
||||||
|
OperandInfo a,
|
||||||
|
OperandInfo b,
|
||||||
|
OperandInfo c)
|
||||||
{
|
{
|
||||||
if (isBranch(op)) {
|
if (isBranch(op)) {
|
||||||
assertT(&this->c, a.size == b.size);
|
assertT(&this->c, a.size == b.size);
|
||||||
assertT(&this->c, c.size == TargetBytesPerWord);
|
assertT(&this->c, c.size == TargetBytesPerWord);
|
||||||
assertT(&this->c, c.type == lir::ConstantOperand);
|
assertT(&this->c, c.type == lir::ConstantOperand);
|
||||||
|
|
||||||
arch_->c.branchOperations[branchIndex(&(arch_->c), a.type, b.type)]
|
arch_->c.branchOperations[branchIndex(&(arch_->c), a.type, b.type)](
|
||||||
(&this->c, op, a.size, a.operand, b.operand, c.operand);
|
&this->c, op, a.size, a.operand, b.operand, c.operand);
|
||||||
} else {
|
} else {
|
||||||
assertT(&this->c, b.size == c.size);
|
assertT(&this->c, b.size == c.size);
|
||||||
assertT(&this->c, b.type == c.type);
|
assertT(&this->c, b.type == c.type);
|
||||||
|
|
||||||
arch_->c.binaryOperations[index(&(arch_->c), op, a.type, b.type)]
|
arch_->c.binaryOperations[index(&(arch_->c), op, a.type, b.type)](
|
||||||
(&this->c, a.size, a.operand, b.size, b.operand);
|
&this->c, a.size, a.operand, b.size, b.operand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setDestination(uint8_t* dst) {
|
virtual void setDestination(uint8_t* dst)
|
||||||
|
{
|
||||||
c.result = dst;
|
c.result = dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void write() {
|
virtual void write()
|
||||||
|
{
|
||||||
uint8_t* dst = c.result;
|
uint8_t* dst = c.result;
|
||||||
for (MyBlock* b = c.firstBlock; b; b = b->next) {
|
for (MyBlock* b = c.firstBlock; b; b = b->next) {
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
@ -1111,10 +1216,9 @@ class MyAssembler: public Assembler {
|
|||||||
index += size;
|
index += size;
|
||||||
|
|
||||||
while ((b->start + index + padding + p->instructionOffset)
|
while ((b->start + index + padding + p->instructionOffset)
|
||||||
% p->alignment)
|
% p->alignment) {
|
||||||
{
|
|
||||||
*(dst + b->start + index + padding) = 0x90;
|
*(dst + b->start + index + padding) = 0x90;
|
||||||
++ padding;
|
++padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,34 +1232,40 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Promise* offset(bool) {
|
virtual Promise* offset(bool)
|
||||||
|
{
|
||||||
return x86::offsetPromise(&c);
|
return x86::offsetPromise(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Block* endBlock(bool startNew) {
|
virtual Block* endBlock(bool startNew)
|
||||||
|
{
|
||||||
MyBlock* b = c.lastBlock;
|
MyBlock* b = c.lastBlock;
|
||||||
b->size = c.code.length() - b->offset;
|
b->size = c.code.length() - b->offset;
|
||||||
if (startNew) {
|
if (startNew) {
|
||||||
c.lastBlock = new(c.zone) MyBlock(c.code.length());
|
c.lastBlock = new (c.zone) MyBlock(c.code.length());
|
||||||
} else {
|
} else {
|
||||||
c.lastBlock = 0;
|
c.lastBlock = 0;
|
||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void endEvent() {
|
virtual void endEvent()
|
||||||
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned length() {
|
virtual unsigned length()
|
||||||
|
{
|
||||||
return c.code.length();
|
return c.code.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned footerSize() {
|
virtual unsigned footerSize()
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose()
|
||||||
|
{
|
||||||
c.code.dispose();
|
c.code.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1165,8 +1275,7 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
Assembler* MyArchitecture::makeAssembler(util::Allocator* allocator, Zone* zone)
|
Assembler* MyArchitecture::makeAssembler(util::Allocator* allocator, Zone* zone)
|
||||||
{
|
{
|
||||||
return
|
return new (zone) MyAssembler(c.s, allocator, zone, this);
|
||||||
new(zone) MyAssembler(c.s, allocator, zone, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace x86
|
} // namespace x86
|
||||||
|
@ -16,15 +16,23 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace x86 {
|
namespace x86 {
|
||||||
|
|
||||||
unsigned
|
unsigned padding(AlignmentPadding* p,
|
||||||
padding(AlignmentPadding* p, unsigned index, unsigned offset, AlignmentPadding* limit);
|
unsigned index,
|
||||||
|
unsigned offset,
|
||||||
|
AlignmentPadding* limit);
|
||||||
|
|
||||||
MyBlock::MyBlock(unsigned offset):
|
MyBlock::MyBlock(unsigned offset)
|
||||||
next(0), firstPadding(0), lastPadding(0), offset(offset), start(~0),
|
: next(0),
|
||||||
|
firstPadding(0),
|
||||||
|
lastPadding(0),
|
||||||
|
offset(offset),
|
||||||
|
start(~0),
|
||||||
size(0)
|
size(0)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) {
|
unsigned MyBlock::resolve(unsigned start, Assembler::Block* next)
|
||||||
|
{
|
||||||
this->start = start;
|
this->start = start;
|
||||||
this->next = static_cast<MyBlock*>(next);
|
this->next = static_cast<MyBlock*>(next);
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ namespace x86 {
|
|||||||
|
|
||||||
class AlignmentPadding;
|
class AlignmentPadding;
|
||||||
|
|
||||||
class MyBlock: public Assembler::Block {
|
class MyBlock : public Assembler::Block {
|
||||||
public:
|
public:
|
||||||
MyBlock(unsigned offset);
|
MyBlock(unsigned offset);
|
||||||
|
|
||||||
|
@ -18,9 +18,10 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace x86 {
|
namespace x86 {
|
||||||
|
|
||||||
ArchitectureContext::ArchitectureContext(vm::System* s, bool useNativeFeatures):
|
ArchitectureContext::ArchitectureContext(vm::System* s, bool useNativeFeatures)
|
||||||
s(s), useNativeFeatures(useNativeFeatures)
|
: s(s), useNativeFeatures(useNativeFeatures)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Context::Context(vm::System* s,
|
Context::Context(vm::System* s,
|
||||||
util::Allocator* a,
|
util::Allocator* a,
|
||||||
|
@ -47,12 +47,18 @@ typedef void (*OperationType)(Context*);
|
|||||||
|
|
||||||
typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*);
|
typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*);
|
||||||
|
|
||||||
typedef void (*BinaryOperationType)
|
typedef void (*BinaryOperationType)(Context*,
|
||||||
(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*);
|
unsigned,
|
||||||
|
lir::Operand*,
|
||||||
|
unsigned,
|
||||||
|
lir::Operand*);
|
||||||
|
|
||||||
typedef void (*BranchOperationType)
|
typedef void (*BranchOperationType)(Context*,
|
||||||
(Context*, lir::TernaryOperation, unsigned, lir::Operand*,
|
lir::TernaryOperation,
|
||||||
lir::Operand*, lir::Operand*);
|
unsigned,
|
||||||
|
lir::Operand*,
|
||||||
|
lir::Operand*,
|
||||||
|
lir::Operand*);
|
||||||
|
|
||||||
class ArchitectureContext {
|
class ArchitectureContext {
|
||||||
public:
|
public:
|
||||||
@ -61,14 +67,12 @@ class ArchitectureContext {
|
|||||||
vm::System* s;
|
vm::System* s;
|
||||||
bool useNativeFeatures;
|
bool useNativeFeatures;
|
||||||
OperationType operations[lir::OperationCount];
|
OperationType operations[lir::OperationCount];
|
||||||
UnaryOperationType unaryOperations[lir::UnaryOperationCount
|
UnaryOperationType
|
||||||
* lir::OperandTypeCount];
|
unaryOperations[lir::UnaryOperationCount * lir::OperandTypeCount];
|
||||||
BinaryOperationType binaryOperations
|
BinaryOperationType binaryOperations
|
||||||
[(lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount)
|
[(lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount)
|
||||||
* lir::OperandTypeCount
|
* lir::OperandTypeCount * lir::OperandTypeCount];
|
||||||
* lir::OperandTypeCount];
|
BranchOperationType branchOperations[lir::BranchOperationCount
|
||||||
BranchOperationType branchOperations
|
|
||||||
[lir::BranchOperationCount
|
|
||||||
* lir::OperandTypeCount
|
* lir::OperandTypeCount
|
||||||
* lir::OperandTypeCount];
|
* lir::OperandTypeCount];
|
||||||
};
|
};
|
||||||
@ -91,11 +95,13 @@ class Context {
|
|||||||
ArchitectureContext* ac;
|
ArchitectureContext* ac;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline avian::util::Aborter* getAborter(Context* c) {
|
inline avian::util::Aborter* getAborter(Context* c)
|
||||||
|
{
|
||||||
return c->s;
|
return c->s;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline avian::util::Aborter* getAborter(ArchitectureContext* c) {
|
inline avian::util::Aborter* getAborter(ArchitectureContext* c)
|
||||||
|
{
|
||||||
return c->s;
|
return c->s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,10 +17,10 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace x86 {
|
namespace x86 {
|
||||||
|
|
||||||
extern "C" bool
|
extern "C" bool detectFeature(unsigned ecx, unsigned edx);
|
||||||
detectFeature(unsigned ecx, unsigned edx);
|
|
||||||
|
|
||||||
bool useSSE(ArchitectureContext* c) {
|
bool useSSE(ArchitectureContext* c)
|
||||||
|
{
|
||||||
if (vm::TargetBytesPerWord == 8) {
|
if (vm::TargetBytesPerWord == 8) {
|
||||||
// amd64 implies SSE2 support
|
// amd64 implies SSE2 support
|
||||||
return true;
|
return true;
|
||||||
|
@ -26,8 +26,7 @@ using namespace avian::util;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
int64_t
|
int64_t signExtend(unsigned size, int64_t v)
|
||||||
signExtend(unsigned size, int64_t v)
|
|
||||||
{
|
{
|
||||||
if (size == 4) {
|
if (size == 4) {
|
||||||
return static_cast<int32_t>(v);
|
return static_cast<int32_t>(v);
|
||||||
@ -46,14 +45,19 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace x86 {
|
namespace x86 {
|
||||||
|
|
||||||
|
|
||||||
#define REX_W 0x48
|
#define REX_W 0x48
|
||||||
#define REX_R 0x44
|
#define REX_R 0x44
|
||||||
#define REX_X 0x42
|
#define REX_X 0x42
|
||||||
#define REX_B 0x41
|
#define REX_B 0x41
|
||||||
#define REX_NONE 0x40
|
#define REX_NONE 0x40
|
||||||
|
|
||||||
void maybeRex(Context* c, unsigned size, int a, int index, int base, bool always) {
|
void maybeRex(Context* c,
|
||||||
|
unsigned size,
|
||||||
|
int a,
|
||||||
|
int index,
|
||||||
|
int base,
|
||||||
|
bool always)
|
||||||
|
{
|
||||||
if (vm::TargetBytesPerWord == 8) {
|
if (vm::TargetBytesPerWord == 8) {
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
if (size == 8) {
|
if (size == 8) {
|
||||||
@ -61,46 +65,60 @@ void maybeRex(Context* c, unsigned size, int a, int index, int base, bool always
|
|||||||
} else {
|
} else {
|
||||||
byte = REX_NONE;
|
byte = REX_NONE;
|
||||||
}
|
}
|
||||||
if (a != lir::NoRegister and (a & 8)) byte |= REX_R;
|
if (a != lir::NoRegister and (a & 8))
|
||||||
if (index != lir::NoRegister and (index & 8)) byte |= REX_X;
|
byte |= REX_R;
|
||||||
if (base != lir::NoRegister and (base & 8)) byte |= REX_B;
|
if (index != lir::NoRegister and (index & 8))
|
||||||
if (always or byte != REX_NONE) c->code.append(byte);
|
byte |= REX_X;
|
||||||
|
if (base != lir::NoRegister and (base & 8))
|
||||||
|
byte |= REX_B;
|
||||||
|
if (always or byte != REX_NONE)
|
||||||
|
c->code.append(byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Register* b) {
|
void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Register* b)
|
||||||
|
{
|
||||||
maybeRex(c, size, a->low, lir::NoRegister, b->low, false);
|
maybeRex(c, size, a->low, lir::NoRegister, b->low, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void alwaysRex(Context* c, unsigned size, lir::Register* a, lir::Register* b) {
|
void alwaysRex(Context* c, unsigned size, lir::Register* a, lir::Register* b)
|
||||||
|
{
|
||||||
maybeRex(c, size, a->low, lir::NoRegister, b->low, true);
|
maybeRex(c, size, a->low, lir::NoRegister, b->low, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void maybeRex(Context* c, unsigned size, lir::Register* a) {
|
void maybeRex(Context* c, unsigned size, lir::Register* a)
|
||||||
|
{
|
||||||
maybeRex(c, size, lir::NoRegister, lir::NoRegister, a->low, false);
|
maybeRex(c, size, lir::NoRegister, lir::NoRegister, a->low, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Memory* b) {
|
void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Memory* b)
|
||||||
|
{
|
||||||
maybeRex(c, size, a->low, b->index, b->base, size == 1 and (a->low & 4));
|
maybeRex(c, size, a->low, b->index, b->base, size == 1 and (a->low & 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
void maybeRex(Context* c, unsigned size, lir::Memory* a) {
|
void maybeRex(Context* c, unsigned size, lir::Memory* a)
|
||||||
|
{
|
||||||
maybeRex(c, size, lir::NoRegister, a->index, a->base, false);
|
maybeRex(c, size, lir::NoRegister, a->index, a->base, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void modrm(Context* c, uint8_t mod, int a, int b) {
|
void modrm(Context* c, uint8_t mod, int a, int b)
|
||||||
|
{
|
||||||
c->code.append(mod | (regCode(b) << 3) | regCode(a));
|
c->code.append(mod | (regCode(b) << 3) | regCode(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
void modrm(Context* c, uint8_t mod, lir::Register* a, lir::Register* b) {
|
void modrm(Context* c, uint8_t mod, lir::Register* a, lir::Register* b)
|
||||||
|
{
|
||||||
modrm(c, mod, a->low, b->low);
|
modrm(c, mod, a->low, b->low);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sib(Context* c, unsigned scale, int index, int base) {
|
void sib(Context* c, unsigned scale, int index, int base)
|
||||||
c->code.append((util::log(scale) << 6) | (regCode(index) << 3) | regCode(base));
|
{
|
||||||
|
c->code.append((util::log(scale) << 6) | (regCode(index) << 3)
|
||||||
|
| regCode(base));
|
||||||
}
|
}
|
||||||
|
|
||||||
void modrmSib(Context* c, int width, int a, int scale, int index, int base) {
|
void modrmSib(Context* c, int width, int a, int scale, int index, int base)
|
||||||
|
{
|
||||||
if (index == lir::NoRegister) {
|
if (index == lir::NoRegister) {
|
||||||
modrm(c, width, base, a);
|
modrm(c, width, base, a);
|
||||||
if (regCode(base) == rsp) {
|
if (regCode(base) == rsp) {
|
||||||
@ -112,7 +130,8 @@ void modrmSib(Context* c, int width, int a, int scale, int index, int base) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void modrmSibImm(Context* c, int a, int scale, int index, int base, int offset) {
|
void modrmSibImm(Context* c, int a, int scale, int index, int base, int offset)
|
||||||
|
{
|
||||||
if (offset == 0 and regCode(base) != rbp) {
|
if (offset == 0 and regCode(base) != rbp) {
|
||||||
modrmSib(c, 0x00, a, scale, index, base);
|
modrmSib(c, 0x00, a, scale, index, base);
|
||||||
} else if (vm::fitsInInt8(offset)) {
|
} else if (vm::fitsInInt8(offset)) {
|
||||||
@ -124,35 +143,43 @@ void modrmSibImm(Context* c, int a, int scale, int index, int base, int offset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void modrmSibImm(Context* c, lir::Register* a, lir::Memory* b) {
|
void modrmSibImm(Context* c, lir::Register* a, lir::Memory* b)
|
||||||
|
{
|
||||||
modrmSibImm(c, a->low, b->scale, b->index, b->base, b->offset);
|
modrmSibImm(c, a->low, b->scale, b->index, b->base, b->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void opcode(Context* c, uint8_t op) {
|
void opcode(Context* c, uint8_t op)
|
||||||
|
{
|
||||||
c->code.append(op);
|
c->code.append(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
void opcode(Context* c, uint8_t op1, uint8_t op2) {
|
void opcode(Context* c, uint8_t op1, uint8_t op2)
|
||||||
|
{
|
||||||
c->code.append(op1);
|
c->code.append(op1);
|
||||||
c->code.append(op2);
|
c->code.append(op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unconditional(Context* c, unsigned jump, lir::Constant* a) {
|
void unconditional(Context* c, unsigned jump, lir::Constant* a)
|
||||||
|
{
|
||||||
appendOffsetTask(c, a->value, offsetPromise(c), 5);
|
appendOffsetTask(c, a->value, offsetPromise(c), 5);
|
||||||
|
|
||||||
opcode(c, jump);
|
opcode(c, jump);
|
||||||
c->code.append4(0);
|
c->code.append4(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void conditional(Context* c, unsigned condition, lir::Constant* a) {
|
void conditional(Context* c, unsigned condition, lir::Constant* a)
|
||||||
|
{
|
||||||
appendOffsetTask(c, a->value, offsetPromise(c), 6);
|
appendOffsetTask(c, a->value, offsetPromise(c), 6);
|
||||||
|
|
||||||
opcode(c, 0x0f, condition);
|
opcode(c, 0x0f, condition);
|
||||||
c->code.append4(0);
|
c->code.append4(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sseMoveRR(Context* c, unsigned aSize, lir::Register* a,
|
void sseMoveRR(Context* c,
|
||||||
unsigned bSize UNUSED, lir::Register* b)
|
unsigned aSize,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned bSize UNUSED,
|
||||||
|
lir::Register* b)
|
||||||
{
|
{
|
||||||
assertT(c, aSize >= 4);
|
assertT(c, aSize >= 4);
|
||||||
assertT(c, aSize == bSize);
|
assertT(c, aSize == bSize);
|
||||||
@ -182,8 +209,11 @@ void sseMoveRR(Context* c, unsigned aSize, lir::Register* a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sseMoveCR(Context* c, unsigned aSize, lir::Constant* a,
|
void sseMoveCR(Context* c,
|
||||||
unsigned bSize, lir::Register* b)
|
unsigned aSize,
|
||||||
|
lir::Constant* a,
|
||||||
|
unsigned bSize,
|
||||||
|
lir::Register* b)
|
||||||
{
|
{
|
||||||
assertT(c, aSize <= vm::TargetBytesPerWord);
|
assertT(c, aSize <= vm::TargetBytesPerWord);
|
||||||
lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask));
|
lir::Register tmp(c->client->acquireTemporary(GeneralRegisterMask));
|
||||||
@ -192,8 +222,11 @@ void sseMoveCR(Context* c, unsigned aSize, lir::Constant* a,
|
|||||||
c->client->releaseTemporary(tmp.low);
|
c->client->releaseTemporary(tmp.low);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sseMoveMR(Context* c, unsigned aSize, lir::Memory* a,
|
void sseMoveMR(Context* c,
|
||||||
unsigned bSize UNUSED, lir::Register* b)
|
unsigned aSize,
|
||||||
|
lir::Memory* a,
|
||||||
|
unsigned bSize UNUSED,
|
||||||
|
lir::Register* b)
|
||||||
{
|
{
|
||||||
assertT(c, aSize >= 4);
|
assertT(c, aSize >= 4);
|
||||||
|
|
||||||
@ -209,8 +242,11 @@ void sseMoveMR(Context* c, unsigned aSize, lir::Memory* a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sseMoveRM(Context* c, unsigned aSize, lir::Register* a,
|
void sseMoveRM(Context* c,
|
||||||
UNUSED unsigned bSize, lir::Memory* b)
|
unsigned aSize,
|
||||||
|
lir::Register* a,
|
||||||
|
UNUSED unsigned bSize,
|
||||||
|
lir::Memory* b)
|
||||||
{
|
{
|
||||||
assertT(c, aSize >= 4);
|
assertT(c, aSize >= 4);
|
||||||
assertT(c, aSize == bSize);
|
assertT(c, aSize == bSize);
|
||||||
@ -227,7 +263,8 @@ void sseMoveRM(Context* c, unsigned aSize, lir::Register* a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void branch(Context* c, lir::TernaryOperation op, lir::Constant* target) {
|
void branch(Context* c, lir::TernaryOperation op, lir::Constant* target)
|
||||||
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case lir::JumpIfEqual:
|
case lir::JumpIfEqual:
|
||||||
conditional(c, 0x84, target);
|
conditional(c, 0x84, target);
|
||||||
@ -258,7 +295,8 @@ void branch(Context* c, lir::TernaryOperation op, lir::Constant* target) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target) {
|
void branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target)
|
||||||
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case lir::JumpIfFloatEqual:
|
case lir::JumpIfFloatEqual:
|
||||||
// jp past the je so we don't jump to the target if unordered:
|
// jp past the je so we don't jump to the target if unordered:
|
||||||
@ -313,8 +351,13 @@ void branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void floatRegOp(Context* c, unsigned aSize, lir::Register* a, unsigned bSize,
|
void floatRegOp(Context* c,
|
||||||
lir::Register* b, uint8_t op, uint8_t mod)
|
unsigned aSize,
|
||||||
|
lir::Register* a,
|
||||||
|
unsigned bSize,
|
||||||
|
lir::Register* b,
|
||||||
|
uint8_t op,
|
||||||
|
uint8_t mod)
|
||||||
{
|
{
|
||||||
if (aSize == 4) {
|
if (aSize == 4) {
|
||||||
opcode(c, 0xf3);
|
opcode(c, 0xf3);
|
||||||
@ -326,8 +369,12 @@ void floatRegOp(Context* c, unsigned aSize, lir::Register* a, unsigned bSize,
|
|||||||
modrm(c, mod, a, b);
|
modrm(c, mod, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void floatMemOp(Context* c, unsigned aSize, lir::Memory* a, unsigned bSize,
|
void floatMemOp(Context* c,
|
||||||
lir::Register* b, uint8_t op)
|
unsigned aSize,
|
||||||
|
lir::Memory* a,
|
||||||
|
unsigned bSize,
|
||||||
|
lir::Register* b,
|
||||||
|
uint8_t op)
|
||||||
{
|
{
|
||||||
if (aSize == 4) {
|
if (aSize == 4) {
|
||||||
opcode(c, 0xf3);
|
opcode(c, 0xf3);
|
||||||
@ -339,11 +386,18 @@ void floatMemOp(Context* c, unsigned aSize, lir::Memory* a, unsigned bSize,
|
|||||||
modrmSibImm(c, b, a);
|
modrmSibImm(c, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveCR(Context* c, unsigned aSize, lir::Constant* a,
|
void moveCR(Context* c,
|
||||||
unsigned bSize, lir::Register* b);
|
unsigned aSize,
|
||||||
|
lir::Constant* a,
|
||||||
|
unsigned bSize,
|
||||||
|
lir::Register* b);
|
||||||
|
|
||||||
void moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a,
|
void moveCR2(Context* c,
|
||||||
UNUSED unsigned bSize, lir::Register* b, unsigned promiseOffset)
|
UNUSED unsigned aSize,
|
||||||
|
lir::Constant* a,
|
||||||
|
UNUSED unsigned bSize,
|
||||||
|
lir::Register* b,
|
||||||
|
unsigned promiseOffset)
|
||||||
{
|
{
|
||||||
if (vm::TargetBytesPerWord == 4 and bSize == 8) {
|
if (vm::TargetBytesPerWord == 4 and bSize == 8) {
|
||||||
int64_t v = signExtend(aSize, a->value->value());
|
int64_t v = signExtend(aSize, a->value->value());
|
||||||
@ -366,8 +420,8 @@ void moveCR2(Context* c, UNUSED unsigned aSize, lir::Constant* a,
|
|||||||
} else {
|
} else {
|
||||||
expect(c, aSize == vm::TargetBytesPerWord);
|
expect(c, aSize == vm::TargetBytesPerWord);
|
||||||
|
|
||||||
appendImmediateTask
|
appendImmediateTask(
|
||||||
(c, a->value, offsetPromise(c), vm::TargetBytesPerWord, promiseOffset);
|
c, a->value, offsetPromise(c), vm::TargetBytesPerWord, promiseOffset);
|
||||||
c->code.appendTargetAddress(static_cast<vm::target_uintptr_t>(0));
|
c->code.appendTargetAddress(static_cast<vm::target_uintptr_t>(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user