bulk, global reformat

This commit is contained in:
Joshua Warner
2014-07-11 09:50:18 -06:00
parent 7642b94308
commit 836cc41320
157 changed files with 18636 additions and 14484 deletions

View File

@ -53,7 +53,8 @@
#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;
@ -105,7 +106,10 @@ typedef char char_t;
#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,14 +220,15 @@ 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);
} }
@ -250,8 +252,8 @@ 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));
} }
} }
@ -264,8 +266,8 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
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
@ -299,25 +301,24 @@ Java_java_io_File_length(JNIEnv* e, jclass, jstring 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;
} }
@ -432,7 +433,11 @@ 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) {
@ -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;
} }
@ -550,11 +559,11 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
// 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)
@ -563,8 +572,7 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
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;
} }
@ -572,8 +580,8 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
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;
} }
@ -595,8 +603,8 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
#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
} }
@ -623,7 +631,12 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
#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),
FindExInfoStandard,
&(d->data),
FindExSearchNameMatch,
NULL,
0);
#endif #endif
if (d->handle == INVALID_HANDLE_VALUE) { if (d->handle == INVALID_HANDLE_VALUE) {
d->dispose(); d->dispose();
@ -687,8 +700,7 @@ Java_java_io_File_readDir(JNIEnv* e, jclass, jlong 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);
@ -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) {
@ -759,12 +775,16 @@ Java_java_io_FileInputStream_close(JNIEnv* e, jclass, jint 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;
@ -781,8 +801,12 @@ Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c)
} }
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));
@ -806,8 +830,11 @@ Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint 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) {
@ -834,15 +861,16 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
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;
@ -858,9 +886,13 @@ 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;
@ -869,8 +901,8 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
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);
@ -888,8 +920,8 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
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)) {
@ -904,9 +936,13 @@ 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;
@ -915,8 +951,8 @@ Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, jclass, jlong peer,
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);
@ -934,8 +970,8 @@ Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, jclass, jlong peer,
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)) {

View File

@ -129,10 +129,18 @@ void add(JNIEnv* e,
} }
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
char* getErrorStr(DWORD err) { char* getErrorStr(DWORD err)
LPSTR errorStr = 0;
if(!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, LANG_SYSTEM_DEFAULT, (LPSTR)&errorStr, 0, 0))
{ {
LPSTR errorStr = 0;
if (!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
0,
err,
LANG_SYSTEM_DEFAULT,
(LPSTR)&errorStr,
0,
0)) {
char* errStr = (char*)malloc(9 * sizeof(char)); char* errStr = (char*)malloc(9 * sizeof(char));
snprintf(errStr, 9, "%d", (int)err); snprintf(errStr, 9, "%d", (int)err);
return errStr; return errStr;
@ -142,10 +150,17 @@ void add(JNIEnv* e,
return errStr; return errStr;
} }
#else #else
char* getErrorStr(DWORD err) { char* getErrorStr(DWORD err)
LPSTR errorStr = (LPSTR)malloc(4096); //NOTE: something constant
if(!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, LANG_SYSTEM_DEFAULT, errorStr, 0, 0))
{ {
LPSTR errorStr = (LPSTR)malloc(4096); // NOTE: something constant
if (!FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0,
err,
LANG_SYSTEM_DEFAULT,
errorStr,
0,
0)) {
free(errorStr); free(errorStr);
char* errStr = (char*)malloc(9 * sizeof(char)); char* errStr = (char*)malloc(9 * sizeof(char));
@ -191,7 +206,8 @@ void add(JNIEnv* e,
void safeClose(int& fd) void safeClose(int& fd)
{ {
if(fd != -1) close(fd); if (fd != -1)
close(fd);
fd = -1; fd = -1;
} }
@ -223,60 +239,81 @@ class Locale { // represents an ISO two-char language/country pair
char language[FIELDSIZE]; char language[FIELDSIZE];
char region[FIELDSIZE]; char region[FIELDSIZE];
bool isLanguage(const char* language) { bool isLanguage(const char* language)
if (!language) return false; {
if (!language)
return false;
unsigned len = strlen(language); unsigned len = strlen(language);
if (len != FIELDLEN) return false; if (len != FIELDLEN)
return false;
const char* p = language - 1; const char* p = language - 1;
while (islower(*++p)) ; while (islower(*++p))
if (*p != '\0') return false; ;
if (*p != '\0')
return false;
return true; return true;
} }
bool isRegion(const char* region) { bool isRegion(const char* region)
if (!region) return false; {
if (!region)
return false;
unsigned len = strlen(region); unsigned len = strlen(region);
if (len != FIELDLEN) return false; if (len != FIELDLEN)
return false;
const char* p = region - 1; const char* p = region - 1;
while (isupper(*++p)) ; while (isupper(*++p))
if (*p != '\0') return false; ;
if (*p != '\0')
return false;
return true; return true;
} }
public: public:
Locale(const char* language = "") { Locale(const char* language = "")
{
Locale l(language, ""); Locale l(language, "");
*this = l; *this = l;
} }
Locale(const char* language, const char* region) { Locale(const char* language, const char* region)
{
language = isLanguage(language) ? language : DEFAULT_LANGUAGE; language = isLanguage(language) ? language : DEFAULT_LANGUAGE;
region = isRegion(region) ? region : DEFAULT_REGION; region = isRegion(region) ? region : DEFAULT_REGION;
memcpy(this->language, language, FIELDSIZE); memcpy(this->language, language, FIELDSIZE);
memcpy(this->region, region, FIELDSIZE); memcpy(this->region, region, FIELDSIZE);
} }
Locale& operator=(const Locale& l) { Locale& operator=(const Locale& l)
{
memcpy(language, l.language, FIELDSIZE); memcpy(language, l.language, FIELDSIZE);
memcpy(region, l.region, FIELDSIZE); memcpy(region, l.region, FIELDSIZE);
return *this; return *this;
} }
const char* getLanguage() { return reinterpret_cast<const char*>(language); } const char* getLanguage()
const char* getRegion() { return reinterpret_cast<const char*>(region); } {
return reinterpret_cast<const char*>(language);
}
const char* getRegion()
{
return reinterpret_cast<const char*>(region);
}
}; };
const char* Locale::DEFAULT_LANGUAGE = "en"; const char* Locale::DEFAULT_LANGUAGE = "en";
const char* Locale::DEFAULT_REGION = ""; const char* Locale::DEFAULT_REGION = "";
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
void appendN(char** dest, char ch, size_t length) { void appendN(char** dest, char ch, size_t length)
{
for (size_t i = 0; i < length; i++) { for (size_t i = 0; i < length; i++) {
*((*dest)++) = ch; *((*dest)++) = ch;
} }
} }
bool needsEscape(const char* src, size_t length) { bool needsEscape(const char* src, size_t length)
{
const char* end = src + length; const char* end = src + length;
for (const char* ptr = src; ptr < end; ptr++) { for (const char* ptr = src; ptr < end; ptr++) {
switch (*ptr) { switch (*ptr) {
@ -290,10 +327,10 @@ bool needsEscape(const char* src, size_t length) {
} }
return false; return false;
} }
void copyAndEscape(char** dest, const char* src, size_t length) { void copyAndEscape(char** dest, const char* src, size_t length)
{
char* destp = *dest; char* destp = *dest;
const char* end = src + length; const char* end = src + length;
@ -302,7 +339,6 @@ void copyAndEscape(char** dest, const char* src, size_t length) {
*(destp++) = *ptr; *(destp++) = *ptr;
} }
} else { } else {
*(destp++) = '"'; *(destp++) = '"';
for (const char* ptr = src;; ptr++) { for (const char* ptr = src;; ptr++) {
@ -332,8 +368,10 @@ void copyAndEscape(char** dest, const char* src, size_t length) {
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_lang_Runtime_exec(JNIEnv* e, jclass, Java_java_lang_Runtime_exec(JNIEnv* e,
jobjectArray command, jlongArray process) jclass,
jobjectArray command,
jlongArray process)
{ {
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
int size = 0; int size = 0;
@ -343,14 +381,17 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
// worst case, assuming every character is '"', and we escape all of them // worst case, assuming every character is '"', and we escape all of them
size += 2 * e->GetStringUTFLength(element) + 3; size += 2 * e->GetStringUTFLength(element) + 3;
} else { } else {
throwNew(e, "java/lang/NullPointerException", strdup("null string array element")); throwNew(e,
"java/lang/NullPointerException",
strdup("null string array element"));
} }
} }
RUNTIME_ARRAY(char, line, size); RUNTIME_ARRAY(char, line, size);
char* linep = RUNTIME_ARRAY_BODY(line); char* linep = RUNTIME_ARRAY_BODY(line);
for (int i = 0; i < e->GetArrayLength(command); ++i) { for (int i = 0; i < e->GetArrayLength(command); ++i) {
if (i) *(linep++) = _T(' '); if (i)
*(linep++) = _T(' ');
jstring element = (jstring)e->GetObjectArrayElement(command, i); jstring element = (jstring)e->GetObjectArrayElement(command, i);
const char* s = e->GetStringUTFChars(element, 0); const char* s = e->GetStringUTFChars(element, 0);
@ -367,17 +408,20 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
makePipe(e, in); makePipe(e, in);
SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0); SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0);
jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0])); jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0]));
if(e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
e->SetLongArrayRegion(process, 2, 1, &inDescriptor); e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
makePipe(e, out); makePipe(e, out);
SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0); SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1])); jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1]));
if(e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
e->SetLongArrayRegion(process, 3, 1, &outDescriptor); e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
makePipe(e, err); makePipe(e, err);
SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0); SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0])); jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0]));
if(e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
e->SetLongArrayRegion(process, 4, 1, &errDescriptor); e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
@ -391,9 +435,16 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
si.hStdInput = out[0]; si.hStdInput = out[0];
si.hStdError = err[1]; si.hStdError = err[1];
BOOL success = CreateProcess(0, (LPSTR) RUNTIME_ARRAY_BODY(line), 0, 0, 1, BOOL success = CreateProcess(0,
(LPSTR)RUNTIME_ARRAY_BODY(line),
0,
0,
1,
CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
0, 0, &si, &pi); 0,
0,
&si,
&pi);
CloseHandle(in[1]); CloseHandle(in[1]);
CloseHandle(out[0]); CloseHandle(out[0]);
@ -435,7 +486,8 @@ Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid)
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_lang_Runtime_kill(JNIEnv* e UNUSED, jclass, jlong pid) { Java_java_lang_Runtime_kill(JNIEnv* e UNUSED, jclass, jlong pid)
{
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
TerminateProcess(reinterpret_cast<HANDLE>(pid), 1); TerminateProcess(reinterpret_cast<HANDLE>(pid), 1);
#else #else
@ -443,7 +495,8 @@ Java_java_lang_Runtime_kill(JNIEnv* e UNUSED, jclass, jlong pid) {
#endif #endif
} }
Locale getLocale() { Locale getLocale()
{
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
const char* lang = ""; const char* lang = "";
const char* reg = ""; const char* reg = "";
@ -455,74 +508,148 @@ Locale getLocale() {
case 0x004: { case 0x004: {
lang = "zh"; lang = "zh";
switch (sublang) { switch (sublang) {
case 0x01: reg = "CN"; break; case 0x01:
case 0x02: reg = "TW"; break; reg = "CN";
case 0x03: reg = "HK"; break; break;
case 0x04: reg = "SG"; break; case 0x02:
reg = "TW";
break;
case 0x03:
reg = "HK";
break;
case 0x04:
reg = "SG";
break;
} }
} break; } break;
case 0x006: lang = "da"; reg = "DK"; break; case 0x006:
case 0x007: lang = "de"; reg = "DE"; break; lang = "da";
reg = "DK";
break;
case 0x007:
lang = "de";
reg = "DE";
break;
case 0x009: { case 0x009: {
lang = "en"; lang = "en";
switch (sublang) { switch (sublang) {
case 0x01: reg = "US"; break; case 0x01:
case 0x02: reg = "GB"; break; reg = "US";
case 0x03: reg = "AU"; break; break;
case 0x04: reg = "CA"; break; case 0x02:
case 0x05: reg = "NZ"; break; reg = "GB";
case 0x06: reg = "IE"; break; break;
case 0x07: reg = "ZA"; break; case 0x03:
case 0x10: reg = "IN"; break; reg = "AU";
break;
case 0x04:
reg = "CA";
break;
case 0x05:
reg = "NZ";
break;
case 0x06:
reg = "IE";
break;
case 0x07:
reg = "ZA";
break;
case 0x10:
reg = "IN";
break;
} }
} break; } break;
case 0x00a: { case 0x00a: {
lang = "es"; lang = "es";
switch (sublang) { switch (sublang) {
case 0x01: case 0x03: reg = "ES"; break; case 0x01:
case 0x02: reg = "MX"; break; case 0x03:
reg = "ES";
break;
case 0x02:
reg = "MX";
break;
} }
} break; } break;
case 0x00c: { case 0x00c: {
lang = "fr"; lang = "fr";
switch (sublang) { switch (sublang) {
case 0x01: reg = "FR"; break; case 0x01:
case 0x02: reg = "BE"; break; reg = "FR";
case 0x03: reg = "CA"; break; break;
case 0x02:
reg = "BE";
break;
case 0x03:
reg = "CA";
break;
} }
} break; } break;
case 0x010: lang = "it"; reg = "IT"; break; case 0x010:
case 0x011: lang = "ja"; reg = "JP"; break; lang = "it";
case 0x012: lang = "ko"; reg = "KR"; break; reg = "IT";
break;
case 0x011:
lang = "ja";
reg = "JP";
break;
case 0x012:
lang = "ko";
reg = "KR";
break;
case 0x013: { case 0x013: {
lang = "nl"; lang = "nl";
switch (sublang) { switch (sublang) {
case 0x01: reg = "NL"; break; case 0x01:
case 0x02: reg = "BE"; break; reg = "NL";
break;
case 0x02:
reg = "BE";
break;
} }
} break; } break;
case 0x014: lang = "no"; reg = "NO"; break; case 0x014:
case 0x015: lang = "pl"; reg = "PL"; break; lang = "no";
reg = "NO";
break;
case 0x015:
lang = "pl";
reg = "PL";
break;
case 0x016: { case 0x016: {
lang = "pt"; lang = "pt";
switch (sublang) { switch (sublang) {
case 0x01: reg = "BR"; break; case 0x01:
case 0x02: reg = "PT"; break; reg = "BR";
break;
case 0x02:
reg = "PT";
break;
} }
} break; } break;
case 0x018: lang = "ro"; reg = "RO"; break; case 0x018:
case 0x019: lang = "ru"; reg = "RU"; break; lang = "ro";
case 0x01d: lang = "sv"; reg = "SE"; break; reg = "RO";
default: lang = "en"; break;
case 0x019:
lang = "ru";
reg = "RU";
break;
case 0x01d:
lang = "sv";
reg = "SE";
break;
default:
lang = "en";
} }
return Locale(lang, reg); return Locale(lang, reg);
#else #else
std::wstring culture = AvianInterop::GetCurrentUICulture(); std::wstring culture = AvianInterop::GetCurrentUICulture();
char* cultureName = strdup(std::string(culture.begin(), culture.end()).c_str()); char* cultureName
= strdup(std::string(culture.begin(), culture.end()).c_str());
char* delimiter = strchr(cultureName, '-'); char* delimiter = strchr(cultureName, '-');
if(!delimiter) if (!delimiter) {
{
free(cultureName); free(cultureName);
return Locale("en", "US"); return Locale("en", "US");
} }
@ -536,11 +663,13 @@ Locale getLocale() {
} }
#else #else
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_lang_Runtime_exec(JNIEnv* e, jclass, Java_java_lang_Runtime_exec(JNIEnv* e,
jobjectArray command, jlongArray process) jclass,
jobjectArray command,
jlongArray process)
{ {
char** argv = static_cast<char**> char** argv = static_cast<char**>(
(malloc((e->GetArrayLength(command) + 1) * sizeof(char*))); malloc((e->GetArrayLength(command) + 1) * sizeof(char*)));
int i; int i;
for (i = 0; i < e->GetArrayLength(command); i++) { for (i = 0; i < e->GetArrayLength(command); i++) {
jstring element = (jstring)e->GetObjectArrayElement(command, i); jstring element = (jstring)e->GetObjectArrayElement(command, i);
@ -555,19 +684,23 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
int msg[] = {-1, -1}; int msg[] = {-1, -1};
makePipe(e, in); makePipe(e, in);
if(e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
jlong inDescriptor = static_cast<jlong>(in[0]); jlong inDescriptor = static_cast<jlong>(in[0]);
e->SetLongArrayRegion(process, 2, 1, &inDescriptor); e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
makePipe(e, out); makePipe(e, out);
if(e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
jlong outDescriptor = static_cast<jlong>(out[1]); jlong outDescriptor = static_cast<jlong>(out[1]);
e->SetLongArrayRegion(process, 3, 1, &outDescriptor); e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
makePipe(e, err); makePipe(e, err);
if(e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
jlong errDescriptor = static_cast<jlong>(err[0]); jlong errDescriptor = static_cast<jlong>(err[0]);
e->SetLongArrayRegion(process, 4, 1, &errDescriptor); e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
makePipe(e, msg); makePipe(e, msg);
if(e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
if (fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) { if (fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) {
throwNewErrno(e, "java/io/IOException"); throwNewErrno(e, "java/io/IOException");
return; return;
@ -656,15 +789,18 @@ Java_java_lang_Runtime_waitFor(JNIEnv*, jclass, jlong pid, jlong)
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_lang_Runtime_kill(JNIEnv*, jclass, jlong pid) { Java_java_lang_Runtime_kill(JNIEnv*, jclass, jlong pid)
{
kill((pid_t)pid, SIGTERM); kill((pid_t)pid, SIGTERM);
} }
Locale getLocale() { Locale getLocale()
{
Locale fallback; Locale fallback;
const char* LANG = getenv("LANG"); const char* LANG = getenv("LANG");
if (!LANG || strcmp(LANG, "C") == 0) return fallback; if (!LANG || strcmp(LANG, "C") == 0)
return fallback;
int len = strlen(LANG); int len = strlen(LANG);
char buf[len + 1]; // + 1 for the '\0' char char buf[len + 1]; // + 1 for the '\0' char
@ -673,13 +809,17 @@ Locale getLocale() {
char* tracer = buf; char* tracer = buf;
const char* reg; const char* reg;
while (*tracer && *tracer != '_') ++tracer; while (*tracer && *tracer != '_')
if (!*tracer) return fallback; ++tracer;
if (!*tracer)
return fallback;
*tracer = '\0'; *tracer = '\0';
reg = ++tracer; reg = ++tracer;
while (*tracer && *tracer != '.') ++tracer; while (*tracer && *tracer != '.')
if (tracer == reg) return fallback; ++tracer;
if (tracer == reg)
return fallback;
*tracer = '\0'; *tracer = '\0';
Locale locale(buf, reg); Locale locale(buf, reg);
@ -858,20 +998,22 @@ namespace {
#elif defined __APPLE__ #elif defined __APPLE__
#include <crt_externs.h> #include <crt_externs.h>
#define environ (*_NSGetEnviron()) #define environ (*_NSGetEnviron())
#elif defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #elif defined(WINAPI_FAMILY) \
&& !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
// WinRT/WP8 does not provide alternative for environment variables // WinRT/WP8 does not provide alternative for environment variables
char* environ[] = {0}; char* environ[] = {0};
#else #else
extern char** environ; extern char** environ;
#endif #endif
extern "C" JNIEXPORT jobjectArray JNICALL extern "C" JNIEXPORT jobjectArray JNICALL
Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) { Java_java_lang_System_getEnvironment(JNIEnv* env, jclass)
{
int length; int length;
for (length = 0; environ[length] != 0; ++length) ; for (length = 0; environ[length] != 0; ++length)
;
jobjectArray stringArray = jobjectArray stringArray = env->NewObjectArray(
env->NewObjectArray(length, env->FindClass("java/lang/String"), length, env->FindClass("java/lang/String"), env->NewStringUTF(""));
env->NewStringUTF(""));
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
jobject varString = env->NewStringUTF(environ[i]); jobject varString = env->NewStringUTF(environ[i]);
@ -890,13 +1032,13 @@ Java_java_lang_System_currentTimeMillis(JNIEnv*, jclass)
// doesn't have it as of this writing. So we use this mess instead: // doesn't have it as of this writing. So we use this mess instead:
FILETIME time; FILETIME time;
GetSystemTimeAsFileTime(&time); GetSystemTimeAsFileTime(&time);
return (((static_cast<jlong>(time.dwHighDateTime) << 32) return (((static_cast<jlong>(time.dwHighDateTime) << 32) | time.dwLowDateTime)
| time.dwLowDateTime) / 10000) - 11644473600000LL; / 10000) - 11644473600000LL;
#else #else
timeval tv = {0, 0}; timeval tv = {0, 0};
gettimeofday(&tv, 0); gettimeofday(&tv, 0);
return (static_cast<jlong>(tv.tv_sec) * 1000) + return (static_cast<jlong>(tv.tv_sec) * 1000)
(static_cast<jlong>(tv.tv_usec) / 1000); + (static_cast<jlong>(tv.tv_usec) / 1000);
#endif #endif
} }
@ -909,8 +1051,7 @@ Java_java_lang_System_doMapLibraryName(JNIEnv* e, jclass, jstring name)
unsigned nameLength = strlen(chars); unsigned nameLength = strlen(chars);
unsigned size = sizeof(SO_PREFIX) + nameLength + sizeof(SO_SUFFIX); unsigned size = sizeof(SO_PREFIX) + nameLength + sizeof(SO_SUFFIX);
RUNTIME_ARRAY(char, buffer, size); RUNTIME_ARRAY(char, buffer, size);
snprintf snprintf(RUNTIME_ARRAY_BODY(buffer), size, SO_PREFIX "%s" SO_SUFFIX, chars);
(RUNTIME_ARRAY_BODY(buffer), size, SO_PREFIX "%s" SO_SUFFIX, chars);
r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer)); r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer));
e->ReleaseStringUTFChars(name, chars); e->ReleaseStringUTFChars(name, chars);
@ -931,7 +1072,9 @@ Java_java_lang_Double_isNaN(JNIEnv*, jclass, jdouble val)
} }
extern "C" JNIEXPORT jdouble JNICALL extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Double_doubleFromString(JNIEnv*e, jclass, jstring s, Java_java_lang_Double_doubleFromString(JNIEnv* e,
jclass,
jstring s,
jintArray numDoublesRead) jintArray numDoublesRead)
{ {
const char* chars = e->GetStringUTFChars(s, 0); const char* chars = e->GetStringUTFChars(s, 0);
@ -963,7 +1106,9 @@ Java_java_lang_Float_isNaN(JNIEnv*, jclass, jfloat val)
} }
extern "C" JNIEXPORT jfloat JNICALL extern "C" JNIEXPORT jfloat JNICALL
Java_java_lang_Float_floatFromString(JNIEnv*e, jclass, jstring s, Java_java_lang_Float_floatFromString(JNIEnv* e,
jclass,
jstring s,
jintArray numFloatsRead) jintArray numFloatsRead)
{ {
const char* chars = e->GetStringUTFChars(s, 0); const char* chars = e->GetStringUTFChars(s, 0);
@ -1079,8 +1224,12 @@ Java_java_lang_Math_exp(JNIEnv*, jclass, jdouble exp)
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_java_lang_Double_fillBufferWithDouble(JNIEnv* e, jclass, jdouble val, Java_java_lang_Double_fillBufferWithDouble(JNIEnv* e,
jbyteArray buffer, jint bufferSize) { jclass,
jdouble val,
jbyteArray buffer,
jint bufferSize)
{
jboolean isCopy; jboolean isCopy;
jbyte* buf = e->GetByteArrayElements(buffer, &isCopy); jbyte* buf = e->GetByteArrayElements(buffer, &isCopy);
jint count = snprintf(reinterpret_cast<char*>(buf), bufferSize, "%g", val); jint count = snprintf(reinterpret_cast<char*>(buf), bufferSize, "%g", val);

View File

@ -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]));
@ -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;
} }
} }

View File

@ -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);
} }
@ -446,8 +436,8 @@ Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e,
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
@ -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);
@ -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,8 +581,10 @@ 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;
@ -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);
@ -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
@ -705,8 +695,8 @@ Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e,
{ {
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) {
@ -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,7 +862,9 @@ 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
@ -864,7 +875,8 @@ 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()) {
@ -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,7 +1084,6 @@ 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)
{ {

View File

@ -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) {
@ -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,8 +79,7 @@ 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)};
@ -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) {
@ -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,8 +159,7 @@ 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)};

View File

@ -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') {

View File

@ -26,8 +26,7 @@
#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
@ -73,8 +72,7 @@ typedef unsigned __int64 uint64_t;
#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) {

View File

@ -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
@ -65,16 +69,17 @@ void connect(JNIEnv* e, SOCKET sock, long addr, short port) {
#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
@ -84,8 +89,7 @@ void bind(JNIEnv* e, SOCKET sock, long addr, short port) {
#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,12 +97,15 @@ 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;
} }
@ -118,35 +125,44 @@ SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_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) {
} }
} }
} }
} }
} }
} }

View File

@ -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
@ -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);
} }
} }
} }

View File

@ -34,15 +34,14 @@ 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 {
@ -83,16 +82,21 @@ 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;
@ -101,37 +105,43 @@ 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;

View File

@ -28,11 +28,12 @@ public:
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;

View File

@ -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

View File

@ -40,7 +40,6 @@ enum UnaryOperation {
#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
}; };
@ -56,7 +55,6 @@ enum BinaryOperation {
#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
}; };
@ -72,16 +70,14 @@ enum TernaryOperation {
#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,62 +86,73 @@ 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;
@ -153,9 +160,10 @@ class Register: public Operand {
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;

View File

@ -29,18 +29,25 @@ 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;
} }
@ -49,15 +56,18 @@ class ResolvedPromise: public Promise {
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();
} }
@ -68,15 +78,17 @@ class ShiftMaskPromise: public Promise {
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();
} }
@ -86,15 +98,17 @@ class CombinedPromise: public Promise {
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();
} }
@ -106,17 +120,21 @@ 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;
@ -136,17 +154,21 @@ class DelayedPromise: public ListenPromise {
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;

View File

@ -25,11 +25,10 @@ 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 {
@ -38,11 +37,12 @@ public:
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 {
@ -50,15 +50,18 @@ 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++;

View File

@ -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);

View File

@ -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,

View File

@ -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;
}; };

View File

@ -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,8 +180,7 @@ sysAbort(System* s)
// #endif // not NDEBUG // #endif // not NDEBUG
AVIAN_EXPORT System* AVIAN_EXPORT System* makeSystem();
makeSystem();
} // namespace vm } // namespace vm

View File

@ -32,6 +32,7 @@ public:
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();
@ -47,12 +48,14 @@ 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 {
@ -124,11 +127,13 @@ 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;
} }
}; };
@ -137,20 +142,16 @@ 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

View File

@ -29,13 +29,15 @@ inline Aborter* getAborter(Aborter* 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);
} }

View File

@ -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

View File

@ -19,11 +19,12 @@ 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) {

View File

@ -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;
} }

View File

@ -16,11 +16,12 @@
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);
} }

View File

@ -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();
} }
@ -96,12 +107,14 @@ class AbstractStream {
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);
} }

View File

@ -21,34 +21,39 @@ 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);
} }

View File

@ -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
} }

View File

@ -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;
} }

View File

@ -21,14 +21,16 @@
#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();

View File

@ -37,8 +37,7 @@
#define THREAD_STATE_THREAD(state) ((state).FIELD(r[8])) #define THREAD_STATE_THREAD(state) ((state).FIELD(r[8]))
#define THREAD_STATE_LINK(state) ((state).FIELD(lr)) #define THREAD_STATE_LINK(state) ((state).FIELD(lr))
# 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) \
@ -62,15 +61,17 @@
#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,8 +87,7 @@ trap()
// performant choice. // performant choice.
#ifndef _MSC_VER #ifndef _MSC_VER
inline void inline void memoryBarrier()
memoryBarrier()
{ {
#ifdef __APPLE__ #ifdef __APPLE__
OSMemoryBarrier(); OSMemoryBarrier();
@ -101,8 +101,7 @@ memoryBarrier()
} }
#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
} }
@ -158,28 +155,30 @@ 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(
old, new_, reinterpret_cast<int32_t*>(p));
#elif(defined __QNX__) #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,7 +196,10 @@ 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;
@ -240,10 +242,8 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
#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 {
@ -287,10 +287,13 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
} }
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

View File

@ -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;

View File

@ -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_())
@ -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");
@ -134,8 +135,7 @@ runOnLoadIfFound(Thread* t, System::Library* library)
} }
} }
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);
@ -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);

View File

@ -43,8 +43,8 @@
#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:
@ -56,7 +56,8 @@ 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;
} }
@ -142,8 +143,8 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
#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
@ -200,8 +201,13 @@ 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; \
@ -213,22 +219,19 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
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,76 +403,71 @@ 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) {
@ -492,8 +476,7 @@ replace(char a, char b, char* dst, const char* src)
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;

View File

@ -30,4 +30,3 @@
#define AVIAN_ARCH_ARM (3 << 8) #define AVIAN_ARCH_ARM (3 << 8)
#endif #endif

View File

@ -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(&currentSize))
current(it->next(&currentSize)) {
{ } }
~Iterator() { ~Iterator()
{
it->dispose(); it->dispose();
} }
bool hasMore() { bool hasMore()
if (current) return true; {
if (current)
return true;
current = it->next(&currentSize); current = it->next(&currentSize);
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;

View File

@ -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,8 +42,7 @@ 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

View File

@ -27,8 +27,7 @@
namespace vm { namespace vm {
void void populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
} // namespace vm } // namespace vm

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -11,7 +11,6 @@
#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)
@ -61,4 +60,3 @@
#endif #endif
#endif #endif

View File

@ -17,85 +17,72 @@
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;
} }
@ -105,8 +92,7 @@ targetV8(T v)
#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);
} }
@ -123,8 +109,7 @@ 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);
} }
@ -156,11 +141,10 @@ const target_uintptr_t TargetPointerMask
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

View File

@ -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,
@ -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);
} }

View File

@ -53,8 +53,7 @@
#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) \
@ -84,15 +83,19 @@
#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);
} }
@ -112,8 +115,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
#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) \
@ -139,26 +141,38 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
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,
unsigned stackSize,
void* gprTable,
void* sseTable,
unsigned returnType);
#endif #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,9 +206,12 @@ 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
@ -206,8 +223,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
namespace vm { namespace vm {
inline void inline void trap()
trap()
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
__asm int 3 __asm int 3
@ -216,20 +232,17 @@ 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();
@ -240,25 +253,22 @@ storeLoadMemoryBarrier()
#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
@ -275,12 +285,11 @@ 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
@ -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_);

View File

@ -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

View File

@ -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);
} }

View File

@ -19,17 +19,14 @@
#endif #endif
extern "C" { extern "C" {
extern const uint8_t SYMBOL(start)[]; extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[]; extern const uint8_t SYMBOL(end)[];
AVIAN_EXPORT const uint8_t* AVIAN_EXPORT const uint8_t* javahomeJar(unsigned* size)
javahomeJar(unsigned* size)
{ {
*size = SYMBOL(end) - SYMBOL(start); *size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start); return SYMBOL(start);
} }
} }
#undef SYMBOL #undef SYMBOL

View File

@ -14,7 +14,10 @@
// 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
@ -27,12 +30,10 @@ extern "C" void __cxa_pure_virtual(void) { abort(); }
#endif #endif
extern "C" { extern "C" {
extern const uint8_t BOOTIMAGE_SYMBOL(start)[]; extern const uint8_t BOOTIMAGE_SYMBOL(start)[];
extern const uint8_t BOOTIMAGE_SYMBOL(end)[]; extern const uint8_t BOOTIMAGE_SYMBOL(end)[];
AVIAN_EXPORT const uint8_t* AVIAN_EXPORT const uint8_t* bootimageBin(unsigned* size)
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);
@ -41,13 +42,11 @@ extern "C" {
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
@ -63,17 +62,14 @@ extern "C" {
#endif #endif
extern "C" { extern "C" {
extern const uint8_t SYMBOL(start)[]; extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[]; extern const uint8_t SYMBOL(end)[];
AVIAN_EXPORT const uint8_t* AVIAN_EXPORT const uint8_t* classpathJar(unsigned* size)
classpathJar(unsigned* size)
{ {
*size = SYMBOL(end) - SYMBOL(start); *size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start); return SYMBOL(start);
} }
} }
#undef SYMBOL #undef SYMBOL

View File

@ -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);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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));
} }
@ -244,9 +235,11 @@ void enumerateThreads(Thread* t,
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

View File

@ -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));
} }
} }

View File

@ -38,7 +38,8 @@ 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

View File

@ -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);

View File

@ -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,29 +62,35 @@ 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;
@ -95,7 +104,8 @@ bool FrameIterator::hasMore() {
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) {
@ -112,12 +122,11 @@ FrameIterator::Element FrameIterator::next(Context* c) {
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

View File

@ -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;

View File

@ -23,28 +23,32 @@ 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);
} }

View File

@ -26,15 +26,19 @@ class ForkElement {
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;

View File

@ -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

View File

@ -15,7 +15,6 @@ 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);

View File

@ -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;
@ -117,11 +128,13 @@ void MultiRead::append(Context* c, Read* r) {
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);
@ -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,26 +175,29 @@ 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);

View File

@ -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,7 +46,8 @@ 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();
} }
@ -69,7 +73,6 @@ class SingleRead: public Read {
Value* successor_; Value* successor_;
}; };
class MultiRead : public Read { class MultiRead : public Read {
public: public:
MultiRead(); MultiRead();
@ -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

View File

@ -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:

View File

@ -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

View File

@ -18,41 +18,46 @@ 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);
} }
@ -62,69 +67,81 @@ void thawResource(Context* c, Resource* r, Value* v) {
} }
} }
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);
} }
@ -133,39 +150,41 @@ void RegisterResource::decrement(Context* c) {
--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

View File

@ -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,15 +412,15 @@ 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
@ -385,48 +429,51 @@ Site* registerSite(Context* c, int number) {
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,
int offset,
int index,
unsigned scale)
{
return new (c->zone) MemorySite(base, offset, index, 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

View File

@ -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);
} }
@ -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,7 +302,6 @@ 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

View File

@ -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;

View File

@ -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)

View File

@ -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;
} }

View File

@ -36,7 +36,8 @@ 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
@ -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);
} }
} }
@ -140,43 +153,54 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
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,11 +621,13 @@ 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);
} }
@ -571,16 +639,19 @@ class MyArchitecture: public Architecture {
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_;
} }
@ -590,11 +661,16 @@ 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

View File

@ -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);

View File

@ -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;
} }

View File

@ -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

View File

@ -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,7 +198,10 @@ 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);

View File

@ -31,7 +31,9 @@ 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;
@ -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();
@ -97,7 +103,8 @@ class ConstantPoolEntry: public Promise {
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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;
@ -158,15 +161,16 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED,
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,42 +409,60 @@ 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:
@ -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,11 +889,13 @@ 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);
} }
@ -832,14 +910,17 @@ 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,8 +1216,7 @@ 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,11 +1232,13 @@ 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) {
@ -1143,19 +1249,23 @@ class MyAssembler: public Assembler {
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

View File

@ -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);

View File

@ -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,

View File

@ -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;
} }

View File

@ -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;

View File

@ -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));
} }
} }

View File

@ -25,7 +25,12 @@ namespace x86 {
class Context; class Context;
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);
void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Register* b); void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Register* b);
@ -37,15 +42,18 @@ void maybeRex(Context* c, unsigned size, lir::Register* a, lir::Memory* b);
void maybeRex(Context* c, unsigned size, lir::Memory* a); void maybeRex(Context* c, unsigned size, lir::Memory* a);
inline int regCode(int a) { inline int regCode(int a)
{
return a & 7; return a & 7;
} }
inline int regCode(lir::Register* a) { inline int regCode(lir::Register* a)
{
return regCode(a->low); return regCode(a->low);
} }
inline bool isFloatReg(lir::Register* a) { inline bool isFloatReg(lir::Register* a)
{
return a->low >= xmm0; return a->low >= xmm0;
} }
@ -69,30 +77,55 @@ void unconditional(Context* c, unsigned jump, lir::Constant* a);
void conditional(Context* c, unsigned condition, lir::Constant* a); void conditional(Context* c, unsigned condition, lir::Constant* a);
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);
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);
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);
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);
void branch(Context* c, lir::TernaryOperation op, lir::Constant* target); 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);
void floatRegOp(Context* c, unsigned aSize, lir::Register* a, unsigned bSize, void floatRegOp(Context* c,
lir::Register* b, uint8_t op, uint8_t mod = 0xc0); unsigned aSize,
lir::Register* a,
unsigned bSize,
lir::Register* b,
uint8_t op,
uint8_t mod = 0xc0);
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);
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);
} // namespace x86 } // namespace x86
} // namespace codegen } // namespace codegen

View File

@ -29,19 +29,26 @@ namespace x86 {
using namespace util; using namespace util;
ResolvedPromise* resolvedPromise(Context* c, int64_t value) { ResolvedPromise* resolvedPromise(Context* c, int64_t value)
{
return new (c->zone) ResolvedPromise(value); return new (c->zone) ResolvedPromise(value);
} }
OffsetPromise::OffsetPromise(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit): OffsetPromise::OffsetPromise(Context* c,
c(c), block(block), offset(offset), limit(limit), value_(-1) MyBlock* block,
{ } unsigned offset,
AlignmentPadding* limit)
: c(c), block(block), offset(offset), limit(limit), value_(-1)
{
}
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(c, resolved()); assertT(c, resolved());
if (value_ == -1) { if (value_ == -1) {
@ -51,16 +58,19 @@ int64_t OffsetPromise::value() {
return value_; return value_;
} }
Promise* offsetPromise(Context* c) { Promise* offsetPromise(Context* c)
return new(c->zone) OffsetPromise(c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); {
return new (c->zone) OffsetPromise(
c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding);
} }
void* void* resolveOffset(vm::System* s,
resolveOffset(vm::System* s, uint8_t* instruction, unsigned instructionSize, uint8_t* instruction,
unsigned instructionSize,
int64_t value) int64_t value)
{ {
intptr_t v = reinterpret_cast<uint8_t*>(value) intptr_t v = reinterpret_cast<uint8_t*>(value) - instruction
- instruction - instructionSize; - instructionSize;
expect(s, vm::fitsInInt32(v)); expect(s, vm::fitsInInt32(v));
@ -69,54 +79,66 @@ resolveOffset(vm::System* s, uint8_t* instruction, unsigned instructionSize,
return instruction + instructionSize; return instruction + instructionSize;
} }
OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction, OffsetListener::OffsetListener(vm::System* s,
unsigned instructionSize): uint8_t* instruction,
s(s), unsigned instructionSize)
instruction(instruction), : s(s), instruction(instruction), instructionSize(instructionSize)
instructionSize(instructionSize) {
{ } }
bool OffsetListener::resolve(int64_t value, void** location) { bool OffsetListener::resolve(int64_t value, void** location)
{
void* p = resolveOffset(s, instruction, instructionSize, value); void* p = resolveOffset(s, instruction, instructionSize, value);
if (location) *location = p; if (location)
*location = p;
return false; return false;
} }
OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset, OffsetTask::OffsetTask(Task* next,
unsigned instructionSize): Promise* promise,
Task(next), Promise* instructionOffset,
unsigned instructionSize)
: Task(next),
promise(promise), promise(promise),
instructionOffset(instructionOffset), instructionOffset(instructionOffset),
instructionSize(instructionSize) instructionSize(instructionSize)
{ } {
}
void OffsetTask::run(Context* c) { void OffsetTask::run(Context* c)
{
if (promise->resolved()) { if (promise->resolved()) {
resolveOffset resolveOffset(c->s,
(c->s, c->result + instructionOffset->value(), instructionSize, c->result + instructionOffset->value(),
instructionSize,
promise->value()); promise->value());
} else { } else {
new (promise->listen(sizeof(OffsetListener))) new (promise->listen(sizeof(OffsetListener))) OffsetListener(
OffsetListener(c->s, c->result + instructionOffset->value(), c->s, c->result + instructionOffset->value(), instructionSize);
instructionSize);
} }
} }
void void appendOffsetTask(Context* c,
appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, Promise* promise,
Promise* instructionOffset,
unsigned instructionSize) unsigned instructionSize)
{ {
OffsetTask* task = OffsetTask* task = new (c->zone)
new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, instructionSize); OffsetTask(c->tasks, promise, instructionOffset, instructionSize);
c->tasks = task; c->tasks = task;
} }
ImmediateListener::ImmediateListener(vm::System* s, void* dst, unsigned size, unsigned offset): ImmediateListener::ImmediateListener(vm::System* s,
s(s), dst(dst), size(size), offset(offset) void* dst,
{ } unsigned size,
unsigned offset)
: s(s), dst(dst), size(size), offset(offset)
{
}
void copy(vm::System* s, void* dst, int64_t src, unsigned size) { void copy(vm::System* s, void* dst, int64_t src, unsigned size)
{
switch (size) { switch (size) {
case 4: { case 4: {
int32_t v = src; int32_t v = src;
@ -128,43 +150,57 @@ void copy(vm::System* s, void* dst, int64_t src, unsigned size) {
memcpy(dst, &v, 8); memcpy(dst, &v, 8);
} break; } break;
default: abort(s); default:
abort(s);
} }
} }
bool ImmediateListener::resolve(int64_t value, void** location) { bool ImmediateListener::resolve(int64_t value, void** location)
{
copy(s, dst, value, size); copy(s, dst, value, size);
if (location) *location = static_cast<uint8_t*>(dst) + offset; if (location)
*location = static_cast<uint8_t*>(dst) + offset;
return offset == 0; return offset == 0;
} }
ImmediateTask::ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size, ImmediateTask::ImmediateTask(Task* next,
unsigned promiseOffset): Promise* promise,
Task(next), Promise* offset,
unsigned size,
unsigned promiseOffset)
: Task(next),
promise(promise), promise(promise),
offset(offset), offset(offset),
size(size), size(size),
promiseOffset(promiseOffset) promiseOffset(promiseOffset)
{ } {
}
void ImmediateTask::run(Context* c) { void ImmediateTask::run(Context* c)
{
if (promise->resolved()) { if (promise->resolved()) {
copy(c->s, c->result + offset->value(), promise->value(), size); copy(c->s, c->result + offset->value(), promise->value(), size);
} else { } else {
new (promise->listen(sizeof(ImmediateListener))) ImmediateListener new (promise->listen(sizeof(ImmediateListener))) ImmediateListener(
(c->s, c->result + offset->value(), size, promiseOffset); c->s, c->result + offset->value(), size, promiseOffset);
} }
} }
void void appendImmediateTask(Context* c,
appendImmediateTask(Context* c, Promise* promise, Promise* offset, Promise* promise,
unsigned size, unsigned promiseOffset) Promise* offset,
unsigned size,
unsigned promiseOffset)
{ {
c->tasks = new(c->zone) ImmediateTask c->tasks = new (c->zone)
(c->tasks, promise, offset, size, promiseOffset); ImmediateTask(c->tasks, promise, offset, size, promiseOffset);
} }
ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { ShiftMaskPromise* 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);
} }

View File

@ -31,7 +31,9 @@ ResolvedPromise* resolvedPromise(Context* c, int64_t value);
class Task { class Task {
public: public:
Task(Task* next): next(next) { } Task(Task* next) : next(next)
{
}
virtual void run(Context* c) = 0; virtual void run(Context* c) = 0;
@ -40,7 +42,10 @@ class Task {
class OffsetPromise : public Promise { class OffsetPromise : public Promise {
public: public:
OffsetPromise(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit); OffsetPromise(Context* c,
MyBlock* block,
unsigned offset,
AlignmentPadding* limit);
virtual bool resolved(); virtual bool resolved();
@ -55,7 +60,10 @@ class OffsetPromise: public Promise {
Promise* offsetPromise(Context* c); Promise* offsetPromise(Context* c);
void* resolveOffset(vm::System* s, uint8_t* instruction, unsigned instructionSize, int64_t value); void* resolveOffset(vm::System* s,
uint8_t* instruction,
unsigned instructionSize,
int64_t value);
class OffsetListener : public Promise::Listener { class OffsetListener : public Promise::Listener {
public: public:
@ -70,7 +78,10 @@ class OffsetListener: public Promise::Listener {
class OffsetTask : public Task { class OffsetTask : public Task {
public: public:
OffsetTask(Task* next, Promise* promise, Promise* instructionOffset, unsigned instructionSize); OffsetTask(Task* next,
Promise* promise,
Promise* instructionOffset,
unsigned instructionSize);
virtual void run(Context* c); virtual void run(Context* c);
@ -79,7 +90,10 @@ class OffsetTask: public Task {
unsigned instructionSize; unsigned instructionSize;
}; };
void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, unsigned instructionSize); void appendOffsetTask(Context* c,
Promise* promise,
Promise* instructionOffset,
unsigned instructionSize);
class ImmediateListener : public Promise::Listener { class ImmediateListener : public Promise::Listener {
public: public:
@ -95,7 +109,10 @@ class ImmediateListener: public Promise::Listener {
class ImmediateTask : public Task { class ImmediateTask : public Task {
public: public:
ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size, ImmediateTask(Task* next,
Promise* promise,
Promise* offset,
unsigned size,
unsigned promiseOffset); unsigned promiseOffset);
virtual void run(Context* c); virtual void run(Context* c);
@ -106,11 +123,16 @@ class ImmediateTask: public Task {
unsigned promiseOffset; unsigned promiseOffset;
}; };
void void appendImmediateTask(Context* c,
appendImmediateTask(Context* c, Promise* promise, Promise* offset, Promise* promise,
unsigned size, unsigned promiseOffset = 0); Promise* offset,
unsigned size,
unsigned promiseOffset = 0);
ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask); ShiftMaskPromise* shiftMaskPromise(Context* c,
Promise* base,
unsigned shift,
int64_t mask);
} // namespace x86 } // namespace x86
} // namespace codegen } // namespace codegen

View File

@ -26,35 +26,40 @@ namespace x86 {
using namespace util; using namespace util;
unsigned index(ArchitectureContext*, lir::BinaryOperation operation, unsigned index(ArchitectureContext*,
lir::BinaryOperation operation,
lir::OperandType operand1, lir::OperandType operand1,
lir::OperandType operand2) lir::OperandType operand2)
{ {
return operation return operation + ((lir::BinaryOperationCount
+ ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) * operand1) + lir::NonBranchTernaryOperationCount) * operand1)
+ ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount)
* lir::OperandTypeCount * operand2); * lir::OperandTypeCount * operand2);
} }
unsigned index(ArchitectureContext* c UNUSED, lir::TernaryOperation operation, unsigned index(ArchitectureContext* c UNUSED,
lir::OperandType operand1, lir::OperandType operand2) lir::TernaryOperation operation,
lir::OperandType operand1,
lir::OperandType operand2)
{ {
assertT(c, not isBranch(operation)); assertT(c, not isBranch(operation));
return lir::BinaryOperationCount + operation return lir::BinaryOperationCount + operation
+ ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) * operand1) + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount)
* operand1)
+ ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount)
* lir::OperandTypeCount * operand2); * lir::OperandTypeCount * operand2);
} }
unsigned branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, unsigned branchIndex(ArchitectureContext* c UNUSED,
lir::OperandType operand1,
lir::OperandType operand2) lir::OperandType operand2)
{ {
return operand1 + (lir::OperandTypeCount * operand2); return operand1 + (lir::OperandTypeCount * operand2);
} }
void populateTables(ArchitectureContext* c)
void populateTables(ArchitectureContext* c) { {
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;

View File

@ -21,14 +21,18 @@ namespace x86 {
class ArchitectureContext; class ArchitectureContext;
unsigned index(ArchitectureContext*, lir::BinaryOperation operation, unsigned index(ArchitectureContext*,
lir::BinaryOperation operation,
lir::OperandType operand1, lir::OperandType operand1,
lir::OperandType operand2); lir::OperandType operand2);
unsigned index(ArchitectureContext* c UNUSED, lir::TernaryOperation operation, unsigned index(ArchitectureContext* c UNUSED,
lir::OperandType operand1, lir::OperandType operand2); lir::TernaryOperation operation,
lir::OperandType operand1,
lir::OperandType operand2);
unsigned branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1, unsigned branchIndex(ArchitectureContext* c UNUSED,
lir::OperandType operand1,
lir::OperandType operand2); lir::OperandType operand2);
void populateTables(ArchitectureContext* c); void populateTables(ArchitectureContext* c);

File diff suppressed because it is too large Load Diff

View File

@ -59,209 +59,398 @@ void popR(Context* c, unsigned size, lir::Register* a);
void negateR(Context* c, unsigned size, lir::Register* a); void negateR(Context* c, unsigned size, lir::Register* a);
void negateRR(Context* c, unsigned aSize, lir::Register* a, void negateRR(Context* c,
unsigned bSize UNUSED, lir::Register* b UNUSED); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b UNUSED);
void moveCR(Context* c, unsigned aSize, lir::Constant* a, void moveCR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Constant* a,
void moveZCR(Context* c, unsigned aSize, lir::Constant* a, unsigned bSize,
unsigned bSize, lir::Register* b);
void swapRR(Context* c, unsigned aSize UNUSED, lir::Register* a,
unsigned bSize UNUSED, lir::Register* b);
void moveRR(Context* c, unsigned aSize, lir::Register* a,
UNUSED unsigned bSize, lir::Register* b);
void moveMR(Context* c, unsigned aSize, lir::Memory* a,
unsigned bSize, lir::Register* b);
void moveRM(Context* c, unsigned aSize, lir::Register* a,
unsigned bSize UNUSED, lir::Memory* b);
void moveAR(Context* c, unsigned aSize, lir::Address* a,
unsigned bSize, lir::Register* b);
void moveCM(Context* c, unsigned aSize UNUSED, lir::Constant* a,
unsigned bSize, lir::Memory* b);
void moveZRR(Context* c, unsigned aSize, lir::Register* a,
unsigned bSize UNUSED, lir::Register* b);
void moveZMR(Context* c, unsigned aSize UNUSED, lir::Memory* a,
unsigned bSize UNUSED, lir::Register* b);
void addCarryRR(Context* c, unsigned size, lir::Register* a,
lir::Register* b); lir::Register* b);
void addRR(Context* c, unsigned aSize, lir::Register* a, void moveZCR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Constant* a,
void addCarryCR(Context* c, unsigned size, lir::Constant* a, unsigned bSize,
lir::Register* b); lir::Register* b);
void addCR(Context* c, unsigned aSize, lir::Constant* a, void swapRR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize UNUSED,
lir::Register* a,
void subtractBorrowCR(Context* c, unsigned size UNUSED, lir::Constant* a, unsigned bSize UNUSED,
lir::Register* b); lir::Register* b);
void subtractCR(Context* c, unsigned aSize, lir::Constant* a, void moveRR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Register* a,
void subtractBorrowRR(Context* c, unsigned size, lir::Register* a, UNUSED unsigned bSize,
lir::Register* b); lir::Register* b);
void subtractRR(Context* c, unsigned aSize, lir::Register* a, void moveMR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Memory* a,
unsigned bSize,
lir::Register* b);
void andRR(Context* c, unsigned aSize, lir::Register* a, void moveRM(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Memory* b);
void andCR(Context* c, unsigned aSize, lir::Constant* a, void moveAR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Address* a,
unsigned bSize,
lir::Register* b);
void orRR(Context* c, unsigned aSize, lir::Register* a, void moveCM(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize UNUSED,
lir::Constant* a,
unsigned bSize,
lir::Memory* b);
void orCR(Context* c, unsigned aSize, lir::Constant* a, void moveZRR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void xorRR(Context* c, unsigned aSize, lir::Register* a, void moveZMR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize UNUSED,
lir::Memory* a,
unsigned bSize UNUSED,
lir::Register* b);
void xorCR(Context* c, unsigned aSize, lir::Constant* a, void addCarryRR(Context* c, unsigned size, lir::Register* a, lir::Register* b);
unsigned bSize, lir::Register* b);
void multiplyRR(Context* c, unsigned aSize, lir::Register* a, void addRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void compareRR(Context* c, unsigned aSize, lir::Register* a, void addCarryCR(Context* c, unsigned size, lir::Constant* a, lir::Register* b);
unsigned bSize UNUSED, lir::Register* b);
void compareCR(Context* c, unsigned aSize, lir::Constant* a, void addCR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void compareRM(Context* c, unsigned aSize, lir::Register* a, void subtractBorrowCR(Context* c,
unsigned bSize UNUSED, lir::Memory* b); unsigned size UNUSED,
lir::Constant* a,
lir::Register* b);
void compareCM(Context* c, unsigned aSize, lir::Constant* a, void subtractCR(Context* c,
unsigned bSize, lir::Memory* b); unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void compareFloatRR(Context* c, unsigned aSize, lir::Register* a, void subtractBorrowRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned size,
lir::Register* a,
lir::Register* b);
void branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al, void subtractRR(Context* c,
lir::Operand* ah, lir::Operand* bl, unsigned aSize,
lir::Operand* bh, lir::Constant* target, lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void andRR(Context* c,
unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void andCR(Context* c,
unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void orRR(Context* c,
unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void orCR(Context* c,
unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void xorRR(Context* c,
unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void xorCR(Context* c,
unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void multiplyRR(Context* c,
unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void compareRR(Context* c,
unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void compareCR(Context* c,
unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void compareRM(Context* c,
unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Memory* b);
void compareCM(Context* c,
unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Memory* b);
void compareFloatRR(Context* c,
unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void branchLong(Context* c,
lir::TernaryOperation op,
lir::Operand* al,
lir::Operand* ah,
lir::Operand* bl,
lir::Operand* bh,
lir::Constant* target,
BinaryOperationType compare); BinaryOperationType compare);
void branchRR(Context* c, lir::TernaryOperation op, unsigned size, void branchRR(Context* c,
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* c, lir::TernaryOperation op, unsigned size, void branchCR(Context* c,
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* c, lir::TernaryOperation op, unsigned size, void branchRM(Context* c,
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* c, lir::TernaryOperation op, unsigned size, void branchCM(Context* c,
lir::Constant* a, lir::Memory* b, lir::TernaryOperation op,
unsigned size,
lir::Constant* a,
lir::Memory* b,
lir::Constant* target); lir::Constant* target);
void multiplyCR(Context* c, unsigned aSize, lir::Constant* a, void multiplyCR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void divideRR(Context* c, unsigned aSize, lir::Register* a, void divideRR(Context* c,
unsigned bSize UNUSED, lir::Register* b UNUSED); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b UNUSED);
void remainderRR(Context* c, unsigned aSize, lir::Register* a, void remainderRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void doShift(Context* c, UNUSED void (*shift) void doShift(Context* c,
(Context*, unsigned, lir::Register*, unsigned, UNUSED void (*shift)(Context*,
unsigned,
lir::Register*,
unsigned,
lir::Register*), lir::Register*),
int type, UNUSED unsigned aSize, lir::Constant* a, int type,
unsigned bSize, lir::Register* b); UNUSED unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void shiftLeftRR(Context* c, UNUSED unsigned aSize, lir::Register* a, void shiftLeftRR(Context* c,
unsigned bSize, lir::Register* b); UNUSED unsigned aSize,
lir::Register* a,
unsigned bSize,
lir::Register* b);
void shiftLeftCR(Context* c, unsigned aSize, lir::Constant* a, void shiftLeftCR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void shiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, void shiftRightRR(Context* c,
unsigned bSize, lir::Register* b); UNUSED unsigned aSize,
lir::Register* a,
unsigned bSize,
lir::Register* b);
void shiftRightCR(Context* c, unsigned aSize, lir::Constant* a, void shiftRightCR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void unsignedShiftRightRR(Context* c, UNUSED unsigned aSize, lir::Register* a, void unsignedShiftRightRR(Context* c,
unsigned bSize, lir::Register* b); UNUSED unsigned aSize,
lir::Register* a,
unsigned bSize,
lir::Register* b);
void unsignedShiftRightCR(Context* c, unsigned aSize UNUSED, lir::Constant* a, void unsignedShiftRightCR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize UNUSED,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void floatSqrtRR(Context* c, unsigned aSize, lir::Register* a, void floatSqrtRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatSqrtMR(Context* c, unsigned aSize, lir::Memory* a, void floatSqrtMR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Memory* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatAddRR(Context* c, unsigned aSize, lir::Register* a, void floatAddRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatAddMR(Context* c, unsigned aSize, lir::Memory* a, void floatAddMR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Memory* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatSubtractRR(Context* c, unsigned aSize, lir::Register* a, void floatSubtractRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatSubtractMR(Context* c, unsigned aSize, lir::Memory* a, void floatSubtractMR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Memory* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatMultiplyRR(Context* c, unsigned aSize, lir::Register* a, void floatMultiplyRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatMultiplyMR(Context* c, unsigned aSize, lir::Memory* a, void floatMultiplyMR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Memory* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatDivideRR(Context* c, unsigned aSize, lir::Register* a, void floatDivideRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatDivideMR(Context* c, unsigned aSize, lir::Memory* a, void floatDivideMR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Memory* a,
unsigned bSize UNUSED,
lir::Register* b);
void float2FloatRR(Context* c, unsigned aSize, lir::Register* a, void float2FloatRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void float2FloatMR(Context* c, unsigned aSize, lir::Memory* a, void float2FloatMR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Memory* a,
unsigned bSize UNUSED,
lir::Register* b);
void float2IntRR(Context* c, unsigned aSize, lir::Register* a, void float2IntRR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize,
lir::Register* b);
void float2IntMR(Context* c, unsigned aSize, lir::Memory* a, void float2IntMR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Memory* a,
unsigned bSize,
lir::Register* b);
void int2FloatRR(Context* c, unsigned aSize, lir::Register* a, void int2FloatRR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize,
lir::Register* b);
void int2FloatMR(Context* c, unsigned aSize, lir::Memory* a, void int2FloatMR(Context* c,
unsigned bSize, lir::Register* b); unsigned aSize,
lir::Memory* a,
unsigned bSize,
lir::Register* b);
void floatNegateRR(Context* c, unsigned aSize, lir::Register* a, void floatNegateRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void floatAbsoluteRR(Context* c, unsigned aSize UNUSED, lir::Register* a, void floatAbsoluteRR(Context* c,
unsigned bSize UNUSED, lir::Register* b); unsigned aSize UNUSED,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void absoluteRR(Context* c, unsigned aSize, lir::Register* a, void absoluteRR(Context* c,
unsigned bSize UNUSED, lir::Register* b UNUSED); unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b UNUSED);
} // namespace x86 } // namespace x86
} // namespace codegen } // namespace codegen

Some files were not shown because too many files have changed in this diff Show More