Merge pull request #289 from joshuawarner32/refactor-type-gen

Refactor type generator
This commit is contained in:
Joel Dice 2014-07-12 16:21:32 -06:00
commit a80ac91728
171 changed files with 28601 additions and 23814 deletions

View File

@ -11,7 +11,7 @@
package avian;
public class Addendum {
public Object pool;
public Singleton pool;
public Object annotationTable;
public Object signature;
}

View File

@ -21,6 +21,10 @@ public class ClassAddendum extends Addendum {
* extended by that class.
*/
public int declaredMethodCount;
// Either a byte[] or a Pair, apparently...
// TODO: make it monomorphic
public Object enclosingClass;
public Object enclosingMethod;
}

View File

@ -0,0 +1,5 @@
package avian;
abstract class Code {
// VM-visible fields in types.def
}

View File

@ -302,11 +302,11 @@ public class Continuations {
}
private static class UnwindResult {
public final Callback continuation;
public final Continuation continuation;
public final Object result;
public final Throwable exception;
public UnwindResult(Callback continuation, Object result,
public UnwindResult(Continuation continuation, Object result,
Throwable exception)
{
this.continuation = continuation;

View File

@ -14,4 +14,6 @@ public abstract class Singleton {
public static native int getInt(Object singleton, int offset);
public static native long getLong(Object singleton, int offset);
public static native Object getObject(Object singleton, int offset);
// Fields in types.def
}

View File

@ -16,6 +16,7 @@ public class VMClass {
public short fixedSize;
public byte arrayElementSize;
public byte arrayDimensions;
public VMClass arrayElementClass;
public int runtimeDataIndex;
public int[] objectMask;
public byte[] name;
@ -35,7 +36,7 @@ public class VMClass {
*/
public VMMethod[] methodTable;
public ClassAddendum addendum;
public Object staticTable;
public Singleton staticTable;
public ClassLoader loader;
public byte[] source;
}

View File

@ -23,7 +23,7 @@ public class VMMethod {
public byte[] spec;
public MethodAddendum addendum;
public VMClass class_;
public Object code;
public Code code;
public boolean hasAnnotations() {
return addendum != null && addendum.annotationTable != null;

View File

@ -53,7 +53,8 @@
#endif
#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;
@ -105,7 +106,10 @@ typedef char char_t;
#endif // WINAPI_FAMILY
#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
typedef const char_t* string_t;
@ -113,8 +117,7 @@ typedef const char_t* string_t;
namespace {
#ifdef _MSC_VER
inline int
OPEN(string_t path, int mask, int mode)
inline int OPEN(string_t path, int mask, int mode)
{
int fd;
if (_wsopen_s(&fd, path, mask, _SH_DENYNO, mode) == 0) {
@ -125,8 +128,7 @@ OPEN(string_t path, int mask, int mode)
}
#endif
inline bool
exists(string_t path)
inline bool exists(string_t path)
{
#ifdef PLATFORM_WINDOWS
return GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES;
@ -136,8 +138,7 @@ exists(string_t path)
#endif
}
inline int
doOpen(JNIEnv* e, string_t path, int mask)
inline int doOpen(JNIEnv* e, string_t path, int mask)
{
int fd = OPEN(path, mask | OPEN_MASK, S_IRUSR | S_IWUSR);
if (fd == -1) {
@ -150,8 +151,7 @@ doOpen(JNIEnv* e, string_t path, int mask)
return fd;
}
inline void
doClose(JNIEnv* e, jint fd)
inline void doClose(JNIEnv* e, jint fd)
{
int r = CLOSE(fd);
if (r == -1) {
@ -159,8 +159,7 @@ doClose(JNIEnv* e, jint fd)
}
}
inline int
doRead(JNIEnv* e, jint fd, jbyte* data, jint length)
inline int doRead(JNIEnv* e, jint fd, jbyte* data, jint length)
{
int r = READ(fd, data, length);
if (r > 0) {
@ -173,8 +172,7 @@ doRead(JNIEnv* e, jint fd, jbyte* data, jint length)
}
}
inline void
doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
inline void doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
{
int r = WRITE(fd, data, length);
if (r != length) {
@ -182,14 +180,16 @@ doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length)
}
}
#ifdef PLATFORM_WINDOWS
class Directory {
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 (findNext) {
if (FindNextFileW(handle, &data)) {
@ -203,7 +203,8 @@ class Directory {
return 0;
}
virtual void dispose() {
virtual void dispose()
{
if (handle and handle != INVALID_HANDLE_VALUE) {
FindClose(handle);
}
@ -219,14 +220,15 @@ class Directory {
#endif // not PLATFORM_WINDOWS
} // 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));
}
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);
}
@ -250,8 +252,8 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
releaseChars(e, path, chars);
if (success) {
return e->NewString
(reinterpret_cast<const jchar*>(buffer), wcslen(buffer));
return e->NewString(reinterpret_cast<const jchar*>(buffer),
wcslen(buffer));
}
}
@ -264,8 +266,8 @@ Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path)
std::wstring fullPath = AvianInterop::GetFullPath(partialPath);
return e->NewString
(reinterpret_cast<const jchar*>(fullPath.c_str()), fullPath.length());
return e->NewString(reinterpret_cast<const jchar*>(fullPath.c_str()),
fullPath.length());
}
return path;
#endif
@ -299,25 +301,24 @@ Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
if (chars) {
LARGE_INTEGER fileSize;
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
HANDLE file = CreateFileW
(chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
HANDLE file = CreateFileW(
chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
#else
HANDLE file = CreateFile2
(chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
HANDLE file = CreateFile2(
chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
#endif
releaseChars(e, path, chars);
if (file == INVALID_HANDLE_VALUE)
return 0;
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
if(!GetFileSizeEx(file, &fileSize))
{
if (!GetFileSizeEx(file, &fileSize)) {
CloseHandle(file);
return 0;
}
#else
FILE_STANDARD_INFO info;
if(!GetFileInformationByHandleEx(file, FileStandardInfo, &info, sizeof(info)))
{
if (!GetFileInformationByHandleEx(
file, FileStandardInfo, &info, sizeof(info))) {
CloseHandle(file);
return 0;
}
@ -432,7 +433,11 @@ Java_java_io_File_canExecute(JNIEnv* e, jclass, jstring path)
#ifndef PLATFORM_WINDOWS
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);
if (chars) {
@ -470,7 +475,11 @@ Java_java_io_File_setExecutable(JNIEnv* e, jclass, jstring path, jboolean execut
#else // ifndef PLATFORM_WINDOWS
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;
}
@ -550,11 +559,11 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
// Option: without opening file
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
HANDLE hFile = CreateFileW
(chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
HANDLE hFile = CreateFileW(
chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
#else
HANDLE hFile = CreateFile2
(chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
HANDLE hFile = CreateFile2(
chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
#endif
releaseChars(e, path, chars);
if (hFile == INVALID_HANDLE_VALUE)
@ -563,8 +572,7 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
filetimeToUnixEpochAdjustment.QuadPart = 11644473600000L * 10000L;
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
FILETIME fileLastWriteTime;
if (!GetFileTime(hFile, 0, 0, &fileLastWriteTime))
{
if (!GetFileTime(hFile, 0, 0, &fileLastWriteTime)) {
CloseHandle(hFile);
return 0;
}
@ -572,8 +580,8 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
fileDate.LowPart = fileLastWriteTime.dwLowDateTime;
#else
FILE_BASIC_INFO fileInfo;
if (!GetFileInformationByHandleEx(hFile, FileBasicInfo, &fileInfo, sizeof(fileInfo)))
{
if (!GetFileInformationByHandleEx(
hFile, FileBasicInfo, &fileInfo, sizeof(fileInfo))) {
CloseHandle(hFile);
return 0;
}
@ -595,8 +603,8 @@ Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path)
#else
#define MTIME st_mtim
#endif
return (static_cast<jlong>(fileStat.MTIME.tv_sec) * 1000) +
(static_cast<jlong>(fileStat.MTIME.tv_nsec) / (1000*1000));
return (static_cast<jlong>(fileStat.MTIME.tv_sec) * 1000)
+ (static_cast<jlong>(fileStat.MTIME.tv_nsec) / (1000 * 1000));
#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)
d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data));
#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
if (d->handle == INVALID_HANDLE_VALUE) {
d->dispose();
@ -687,8 +700,7 @@ Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
if (directoryEntry == NULL) {
return NULL;
} else if (strcmp(directoryEntry->d_name, ".") == 0
|| strcmp(directoryEntry->d_name, "..") == 0)
{
|| strcmp(directoryEntry->d_name, "..") == 0) {
// skip . or .. and try again
} else {
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
Java_java_io_FileInputStream_read__I_3BII
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
Java_java_io_FileInputStream_read__I_3BII(JNIEnv* e,
jclass,
jint fd,
jbyteArray b,
jint offset,
jint length)
{
jbyte* data = static_cast<jbyte*>(malloc(length));
if (data == 0) {
@ -759,12 +775,16 @@ Java_java_io_FileInputStream_close(JNIEnv* e, jclass, jint fd)
}
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);
if (chars) {
int fd = doOpen(e, chars, append
? (O_WRONLY | O_CREAT | O_APPEND)
int fd = doOpen(e,
chars,
append ? (O_WRONLY | O_CREAT | O_APPEND)
: (O_WRONLY | O_CREAT | O_TRUNC));
releaseChars(e, path, chars);
return fd;
@ -781,8 +801,12 @@ Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c)
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_write__I_3BII
(JNIEnv* e, jclass, jint fd, jbyteArray b, jint offset, jint length)
Java_java_io_FileOutputStream_write__I_3BII(JNIEnv* e,
jclass,
jint fd,
jbyteArray b,
jint offset,
jint 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
Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
jboolean allowWrite, jlongArray result)
Java_java_io_RandomAccessFile_open(JNIEnv* e,
jclass,
jstring path,
jboolean allowWrite,
jlongArray result)
{
string_t chars = getChars(e, path);
if (chars) {
@ -834,15 +861,16 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
peer = fd;
length = fileStats.st_size;
#else
HANDLE hFile = CreateFile2
(chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
HANDLE hFile = CreateFile2(
chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
if (hFile == INVALID_HANDLE_VALUE) {
throwNewErrno(e, "java/io/IOException");
return;
}
FILE_STANDARD_INFO info;
if(!GetFileInformationByHandleEx(hFile, FileStandardInfo, &info, sizeof(info))) {
if (!GetFileInformationByHandleEx(
hFile, FileStandardInfo, &info, sizeof(info))) {
CloseHandle(hFile);
throwNewErrno(e, "java/io/IOException");
return;
@ -858,9 +886,13 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
}
extern "C" JNIEXPORT jint JNICALL
Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
jlong position, jbyteArray buffer,
int offset, int length)
Java_java_io_RandomAccessFile_readBytes(JNIEnv* e,
jclass,
jlong peer,
jlong position,
jbyteArray buffer,
int offset,
int length)
{
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
int fd = (int)peer;
@ -869,8 +901,8 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
return -1;
}
uint8_t* dst = reinterpret_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, 0));
uint8_t* dst
= reinterpret_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, 0));
int64_t bytesRead = ::read(fd, dst + offset, length);
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
@ -888,8 +920,8 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
return -1;
}
uint8_t* dst = reinterpret_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, 0));
uint8_t* dst
= reinterpret_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, 0));
DWORD bytesRead = 0;
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
Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, jclass, jlong peer,
jlong position, jbyteArray buffer,
int offset, int length)
Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e,
jclass,
jlong peer,
jlong position,
jbyteArray buffer,
int offset,
int length)
{
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
int fd = (int)peer;
@ -915,8 +951,8 @@ Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, jclass, jlong peer,
return -1;
}
uint8_t* dst = reinterpret_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, 0));
uint8_t* dst
= reinterpret_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, 0));
int64_t bytesWritten = ::write(fd, dst + offset, length);
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
@ -934,8 +970,8 @@ Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, jclass, jlong peer,
return -1;
}
uint8_t* dst = reinterpret_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, 0));
uint8_t* dst
= reinterpret_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, 0));
DWORD bytesWritten = 0;
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)
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))
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)) {
char* errStr = (char*)malloc(9 * sizeof(char));
snprintf(errStr, 9, "%d", (int)err);
return errStr;
@ -142,10 +150,17 @@ void add(JNIEnv* e,
return errStr;
}
#else
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))
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)) {
free(errorStr);
char* errStr = (char*)malloc(9 * sizeof(char));
@ -191,7 +206,8 @@ void add(JNIEnv* e,
void safeClose(int& fd)
{
if(fd != -1) close(fd);
if (fd != -1)
close(fd);
fd = -1;
}
@ -223,60 +239,81 @@ class Locale { // represents an ISO two-char language/country pair
char language[FIELDSIZE];
char region[FIELDSIZE];
bool isLanguage(const char* language) {
if (!language) return false;
bool isLanguage(const char* language)
{
if (!language)
return false;
unsigned len = strlen(language);
if (len != FIELDLEN) return false;
if (len != FIELDLEN)
return false;
const char* p = language - 1;
while (islower(*++p)) ;
if (*p != '\0') return false;
while (islower(*++p))
;
if (*p != '\0')
return false;
return true;
}
bool isRegion(const char* region) {
if (!region) return false;
bool isRegion(const char* region)
{
if (!region)
return false;
unsigned len = strlen(region);
if (len != FIELDLEN) return false;
if (len != FIELDLEN)
return false;
const char* p = region - 1;
while (isupper(*++p)) ;
if (*p != '\0') return false;
while (isupper(*++p))
;
if (*p != '\0')
return false;
return true;
}
public:
Locale(const char* language = "") {
Locale(const char* language = "")
{
Locale l(language, "");
*this = l;
}
Locale(const char* language, const char* region) {
Locale(const char* language, const char* region)
{
language = isLanguage(language) ? language : DEFAULT_LANGUAGE;
region = isRegion(region) ? region : DEFAULT_REGION;
memcpy(this->language, language, FIELDSIZE);
memcpy(this->region, region, FIELDSIZE);
}
Locale& operator=(const Locale& l) {
Locale& operator=(const Locale& l)
{
memcpy(language, l.language, FIELDSIZE);
memcpy(region, l.region, FIELDSIZE);
return *this;
}
const char* getLanguage() { return reinterpret_cast<const char*>(language); }
const char* getRegion() { return reinterpret_cast<const char*>(region); }
const char* getLanguage()
{
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_REGION = "";
#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++) {
*((*dest)++) = ch;
}
}
bool needsEscape(const char* src, size_t length) {
bool needsEscape(const char* src, size_t length)
{
const char* end = src + length;
for (const char* ptr = src; ptr < end; ptr++) {
switch (*ptr) {
@ -290,10 +327,10 @@ bool needsEscape(const char* src, size_t length) {
}
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;
const char* end = src + length;
@ -302,7 +339,6 @@ void copyAndEscape(char** dest, const char* src, size_t length) {
*(destp++) = *ptr;
}
} else {
*(destp++) = '"';
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
Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
jobjectArray command, jlongArray process)
Java_java_lang_Runtime_exec(JNIEnv* e,
jclass,
jobjectArray command,
jlongArray process)
{
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
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
size += 2 * e->GetStringUTFLength(element) + 3;
} 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);
char* linep = RUNTIME_ARRAY_BODY(line);
for (int i = 0; i < e->GetArrayLength(command); ++i) {
if (i) *(linep++) = _T(' ');
if (i)
*(linep++) = _T(' ');
jstring element = (jstring)e->GetObjectArrayElement(command, i);
const char* s = e->GetStringUTFChars(element, 0);
@ -367,17 +408,20 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
makePipe(e, in);
SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0);
jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0]));
if(e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
makePipe(e, out);
SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1]));
if(e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
makePipe(e, err);
SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0]));
if(e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
PROCESS_INFORMATION pi;
@ -391,9 +435,16 @@ Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
si.hStdInput = out[0];
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,
0, 0, &si, &pi);
0,
0,
&si,
&pi);
CloseHandle(in[1]);
CloseHandle(out[0]);
@ -435,7 +486,8 @@ Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid)
}
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)
TerminateProcess(reinterpret_cast<HANDLE>(pid), 1);
#else
@ -443,7 +495,8 @@ Java_java_lang_Runtime_kill(JNIEnv* e UNUSED, jclass, jlong pid) {
#endif
}
Locale getLocale() {
Locale getLocale()
{
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
const char* lang = "";
const char* reg = "";
@ -455,74 +508,148 @@ Locale getLocale() {
case 0x004: {
lang = "zh";
switch (sublang) {
case 0x01: reg = "CN"; break;
case 0x02: reg = "TW"; break;
case 0x03: reg = "HK"; break;
case 0x04: reg = "SG"; break;
case 0x01:
reg = "CN";
break;
case 0x02:
reg = "TW";
break;
case 0x03:
reg = "HK";
break;
case 0x04:
reg = "SG";
break;
}
} break;
case 0x006: lang = "da"; reg = "DK"; break;
case 0x007: lang = "de"; reg = "DE"; break;
case 0x006:
lang = "da";
reg = "DK";
break;
case 0x007:
lang = "de";
reg = "DE";
break;
case 0x009: {
lang = "en";
switch (sublang) {
case 0x01: reg = "US"; break;
case 0x02: reg = "GB"; break;
case 0x03: 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;
case 0x01:
reg = "US";
break;
case 0x02:
reg = "GB";
break;
case 0x03:
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;
case 0x00a: {
lang = "es";
switch (sublang) {
case 0x01: case 0x03: reg = "ES"; break;
case 0x02: reg = "MX"; break;
case 0x01:
case 0x03:
reg = "ES";
break;
case 0x02:
reg = "MX";
break;
}
} break;
case 0x00c: {
lang = "fr";
switch (sublang) {
case 0x01: reg = "FR"; break;
case 0x02: reg = "BE"; break;
case 0x03: reg = "CA"; break;
case 0x01:
reg = "FR";
break;
case 0x02:
reg = "BE";
break;
case 0x03:
reg = "CA";
break;
}
} break;
case 0x010: lang = "it"; reg = "IT"; break;
case 0x011: lang = "ja"; reg = "JP"; break;
case 0x012: lang = "ko"; reg = "KR"; break;
case 0x010:
lang = "it";
reg = "IT";
break;
case 0x011:
lang = "ja";
reg = "JP";
break;
case 0x012:
lang = "ko";
reg = "KR";
break;
case 0x013: {
lang = "nl";
switch (sublang) {
case 0x01: reg = "NL"; break;
case 0x02: reg = "BE"; break;
case 0x01:
reg = "NL";
break;
case 0x02:
reg = "BE";
break;
}
} break;
case 0x014: lang = "no"; reg = "NO"; break;
case 0x015: lang = "pl"; reg = "PL"; break;
case 0x014:
lang = "no";
reg = "NO";
break;
case 0x015:
lang = "pl";
reg = "PL";
break;
case 0x016: {
lang = "pt";
switch (sublang) {
case 0x01: reg = "BR"; break;
case 0x02: reg = "PT"; break;
case 0x01:
reg = "BR";
break;
case 0x02:
reg = "PT";
break;
}
} break;
case 0x018: lang = "ro"; reg = "RO"; break;
case 0x019: lang = "ru"; reg = "RU"; break;
case 0x01d: lang = "sv"; reg = "SE"; break;
default: lang = "en";
case 0x018:
lang = "ro";
reg = "RO";
break;
case 0x019:
lang = "ru";
reg = "RU";
break;
case 0x01d:
lang = "sv";
reg = "SE";
break;
default:
lang = "en";
}
return Locale(lang, reg);
#else
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, '-');
if(!delimiter)
{
if (!delimiter) {
free(cultureName);
return Locale("en", "US");
}
@ -536,11 +663,13 @@ Locale getLocale() {
}
#else
extern "C" JNIEXPORT void JNICALL
Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
jobjectArray command, jlongArray process)
Java_java_lang_Runtime_exec(JNIEnv* e,
jclass,
jobjectArray command,
jlongArray process)
{
char** argv = static_cast<char**>
(malloc((e->GetArrayLength(command) + 1) * sizeof(char*)));
char** argv = static_cast<char**>(
malloc((e->GetArrayLength(command) + 1) * sizeof(char*)));
int i;
for (i = 0; i < e->GetArrayLength(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};
makePipe(e, in);
if(e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
jlong inDescriptor = static_cast<jlong>(in[0]);
e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
makePipe(e, out);
if(e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
jlong outDescriptor = static_cast<jlong>(out[1]);
e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
makePipe(e, err);
if(e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
jlong errDescriptor = static_cast<jlong>(err[0]);
e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
makePipe(e, msg);
if(e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
if (fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) {
throwNewErrno(e, "java/io/IOException");
return;
@ -656,15 +789,18 @@ Java_java_lang_Runtime_waitFor(JNIEnv*, jclass, jlong pid, jlong)
}
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);
}
Locale getLocale() {
Locale getLocale()
{
Locale fallback;
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);
char buf[len + 1]; // + 1 for the '\0' char
@ -673,13 +809,17 @@ Locale getLocale() {
char* tracer = buf;
const char* reg;
while (*tracer && *tracer != '_') ++tracer;
if (!*tracer) return fallback;
while (*tracer && *tracer != '_')
++tracer;
if (!*tracer)
return fallback;
*tracer = '\0';
reg = ++tracer;
while (*tracer && *tracer != '.') ++tracer;
if (tracer == reg) return fallback;
while (*tracer && *tracer != '.')
++tracer;
if (tracer == reg)
return fallback;
*tracer = '\0';
Locale locale(buf, reg);
@ -858,20 +998,22 @@ namespace {
#elif defined __APPLE__
#include <crt_externs.h>
#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
char* environ[] = {0};
#else
extern char** environ;
#endif
extern "C" JNIEXPORT jobjectArray JNICALL
Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) {
Java_java_lang_System_getEnvironment(JNIEnv* env, jclass)
{
int length;
for (length = 0; environ[length] != 0; ++length) ;
for (length = 0; environ[length] != 0; ++length)
;
jobjectArray stringArray =
env->NewObjectArray(length, env->FindClass("java/lang/String"),
env->NewStringUTF(""));
jobjectArray stringArray = env->NewObjectArray(
length, env->FindClass("java/lang/String"), env->NewStringUTF(""));
for (int i = 0; i < length; 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:
FILETIME time;
GetSystemTimeAsFileTime(&time);
return (((static_cast<jlong>(time.dwHighDateTime) << 32)
| time.dwLowDateTime) / 10000) - 11644473600000LL;
return (((static_cast<jlong>(time.dwHighDateTime) << 32) | time.dwLowDateTime)
/ 10000) - 11644473600000LL;
#else
timeval tv = {0, 0};
gettimeofday(&tv, 0);
return (static_cast<jlong>(tv.tv_sec) * 1000) +
(static_cast<jlong>(tv.tv_usec) / 1000);
return (static_cast<jlong>(tv.tv_sec) * 1000)
+ (static_cast<jlong>(tv.tv_usec) / 1000);
#endif
}
@ -909,8 +1051,7 @@ Java_java_lang_System_doMapLibraryName(JNIEnv* e, jclass, jstring name)
unsigned nameLength = strlen(chars);
unsigned size = sizeof(SO_PREFIX) + nameLength + sizeof(SO_SUFFIX);
RUNTIME_ARRAY(char, buffer, size);
snprintf
(RUNTIME_ARRAY_BODY(buffer), size, SO_PREFIX "%s" SO_SUFFIX, chars);
snprintf(RUNTIME_ARRAY_BODY(buffer), size, SO_PREFIX "%s" SO_SUFFIX, chars);
r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer));
e->ReleaseStringUTFChars(name, chars);
@ -931,7 +1072,9 @@ Java_java_lang_Double_isNaN(JNIEnv*, jclass, jdouble val)
}
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)
{
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
Java_java_lang_Float_floatFromString(JNIEnv*e, jclass, jstring s,
Java_java_lang_Float_floatFromString(JNIEnv* e,
jclass,
jstring s,
jintArray numFloatsRead)
{
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
Java_java_lang_Double_fillBufferWithDouble(JNIEnv* e, jclass, jdouble val,
jbyteArray buffer, jint bufferSize) {
Java_java_lang_Double_fillBufferWithDouble(JNIEnv* e,
jclass,
jdouble val,
jbyteArray buffer,
jint bufferSize)
{
jboolean isCopy;
jbyte* buf = e->GetByteArrayElements(buffer, &isCopy);
jint count = snprintf(reinterpret_cast<char*>(buf), bufferSize, "%g", val);

View File

@ -15,63 +15,80 @@
using namespace avian::classpath::sockets;
extern "C" JNIEXPORT void JNICALL
Java_java_net_Socket_init(JNIEnv* e, jclass) {
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_init(JNIEnv* e, jclass)
{
init(e);
}
extern "C" JNIEXPORT SOCKET JNICALL
Java_java_net_Socket_create(JNIEnv* e, jclass) {
Java_java_net_Socket_create(JNIEnv* e, jclass)
{
return create(e);
}
extern "C" JNIEXPORT void JNICALL
Java_java_net_Socket_connect(JNIEnv* e, jclass, SOCKET sock, long addr, short port) {
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_connect(JNIEnv* e,
jclass,
SOCKET sock,
long addr,
short port)
{
connect(e, sock, addr, port);
}
extern "C" JNIEXPORT void JNICALL
Java_java_net_Socket_bind(JNIEnv* e, jclass, SOCKET sock, long addr, short port) {
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_bind(JNIEnv* e,
jclass,
SOCKET sock,
long addr,
short port)
{
bind(e, sock, addr, port);
}
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);
}
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);
}
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);
}
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);
}
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]));
vm::object buffer_obj = reinterpret_cast<vm::object>(arguments[2]);
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
t, reinterpret_cast<vm::object>(arguments[2]));
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
char* buffer = reinterpret_cast<char*>(&vm::byteArrayBody(t, buffer_obj, start_pos));
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
}
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]));
vm::object buffer_obj = reinterpret_cast<vm::object>(arguments[2]);
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
t, reinterpret_cast<vm::object>(arguments[2]));
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
char* buffer = reinterpret_cast<char*>(&vm::byteArrayBody(t, buffer_obj, start_pos));
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count);
}
@ -105,8 +122,8 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
throwNew(e, "java/net/UnknownHostException", 0);
return 0;
} else {
int address = ntohl
(reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
int address = ntohl(
reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
freeaddrinfo(result);
return address;
@ -117,4 +134,3 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
return 0;
}
}

View File

@ -47,12 +47,14 @@
typedef int socklen_t;
#endif
inline void* operator new(size_t, void* p) throw() { return p; }
inline void* operator new(size_t, void* p) throw()
{
return p;
}
namespace {
inline jbyteArray
charsToArray(JNIEnv* e, const char* s)
inline jbyteArray charsToArray(JNIEnv* e, const char* s)
{
unsigned length = strlen(s);
jbyteArray a = e->NewByteArray(length + 1);
@ -60,8 +62,7 @@ charsToArray(JNIEnv* e, const char* s)
return a;
}
inline void
doClose(int socket)
inline void doClose(int socket)
{
#ifdef PLATFORM_WINDOWS
closesocket(socket);
@ -70,8 +71,7 @@ doClose(int socket)
#endif
}
inline jbyteArray
errorString(JNIEnv* e, int n)
inline jbyteArray errorString(JNIEnv* e, int n)
{
#ifdef _MSC_VER
const unsigned size = 128;
@ -83,8 +83,7 @@ errorString(JNIEnv* e, int n)
#endif
}
inline jbyteArray
socketErrorString(JNIEnv* e, int n)
inline jbyteArray socketErrorString(JNIEnv* e, int n)
{
#ifdef PLATFORM_WINDOWS
const unsigned size = 64;
@ -96,8 +95,7 @@ socketErrorString(JNIEnv* e, int n)
#endif
}
inline jbyteArray
errorString(JNIEnv* e)
inline jbyteArray errorString(JNIEnv* e)
{
#ifdef PLATFORM_WINDOWS
const unsigned size = 64;
@ -109,8 +107,7 @@ errorString(JNIEnv* e)
#endif
}
void
throwIOException(JNIEnv* e, const char* s)
void throwIOException(JNIEnv* e, const char* s)
{
throwNew(e, "java/io/IOException", s);
}
@ -128,20 +125,17 @@ void throwIOException(JNIEnv* e, jbyteArray a)
}
}
void
throwIOException(JNIEnv* e)
void throwIOException(JNIEnv* e)
{
throwIOException(e, errorString(e));
}
void
throwSocketException(JNIEnv* e, const char* s)
void throwSocketException(JNIEnv* e, const char* s)
{
throwNew(e, "java/net/SocketException", s);
}
void
throwSocketException(JNIEnv* e, jbyteArray a)
void throwSocketException(JNIEnv* e, jbyteArray a)
{
size_t length = e->GetArrayLength(a);
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
@ -154,8 +148,7 @@ throwSocketException(JNIEnv* e, jbyteArray a)
}
}
void
throwSocketException(JNIEnv* e)
void throwSocketException(JNIEnv* 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);
}
inline bool
einProgress(int error)
inline bool einProgress(int error)
{
#ifdef PLATFORM_WINDOWS
return error == WSAEINPROGRESS
or error == WSAEWOULDBLOCK;
return error == WSAEINPROGRESS or error == WSAEWOULDBLOCK;
#else
return error == EINPROGRESS;
#endif
}
inline bool
einProgress()
inline bool einProgress()
{
#ifdef PLATFORM_WINDOWS
return WSAGetLastError() == WSAEINPROGRESS
@ -190,8 +180,7 @@ einProgress()
#endif
}
inline bool
eagain()
inline bool eagain()
{
#ifdef PLATFORM_WINDOWS
return WSAGetLastError() == WSAEINPROGRESS
@ -201,8 +190,7 @@ eagain()
#endif
}
bool
setBlocking(JNIEnv* e, int d, bool blocking)
bool setBlocking(JNIEnv* e, int d, bool blocking)
{
#ifdef PLATFORM_WINDOWS
u_long a = (blocking ? 0 : 1);
@ -212,8 +200,9 @@ setBlocking(JNIEnv* e, int d, bool blocking)
return false;
}
#else
int r = fcntl(d, F_SETFL, (blocking
? (fcntl(d, F_GETFL) & (~O_NONBLOCK))
int r = fcntl(d,
F_SETFL,
(blocking ? (fcntl(d, F_GETFL) & (~O_NONBLOCK))
: (fcntl(d, F_GETFL) | O_NONBLOCK)));
if (r < 0) {
throwIOException(e);
@ -223,12 +212,11 @@ setBlocking(JNIEnv* e, int d, bool blocking)
return true;
}
bool
setTcpNoDelay(JNIEnv* e, int d, bool on)
bool setTcpNoDelay(JNIEnv* e, int d, bool on)
{
int flag = on;
int r = setsockopt
(d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&flag), sizeof(int));
int r = setsockopt(
d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&flag), sizeof(int));
if (r < 0) {
throwSocketException(e);
return false;
@ -236,12 +224,15 @@ setTcpNoDelay(JNIEnv* e, int d, bool on)
return true;
}
void
doBind(JNIEnv* e, int s, sockaddr_in* address)
void doBind(JNIEnv* e, int s, sockaddr_in* address)
{
{ int opt = 1;
int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char*>(&opt), sizeof(int));
{
int opt = 1;
int r = ::setsockopt(s,
SOL_SOCKET,
SO_REUSEADDR,
reinterpret_cast<char*>(&opt),
sizeof(int));
if (r != 0) {
throwIOException(e);
return;
@ -249,9 +240,13 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
}
#ifdef SO_NOSIGPIPE
{ int opt = 1;
int r = ::setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE,
reinterpret_cast<char*>(&opt), sizeof(int));
{
int opt = 1;
int r = ::setsockopt(s,
SOL_SOCKET,
SO_NOSIGPIPE,
reinterpret_cast<char*>(&opt),
sizeof(int));
if (r != 0) {
throwIOException(e);
return;
@ -259,8 +254,9 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
}
#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) {
throwIOException(e);
return;
@ -268,8 +264,7 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
}
}
void
doListen(JNIEnv* e, int s)
void doListen(JNIEnv* e, int s)
{
int r = ::listen(s, 100);
if (r != 0) {
@ -277,13 +272,12 @@ doListen(JNIEnv* e, int s)
}
}
void
doFinishConnect(JNIEnv* e, int socket)
void doFinishConnect(JNIEnv* e, int socket)
{
int error;
socklen_t size = sizeof(int);
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR,
reinterpret_cast<char*>(&error), &size);
int r = getsockopt(
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
if (r != 0 or size != sizeof(int)) {
throwIOException(e);
@ -292,11 +286,10 @@ doFinishConnect(JNIEnv* e, int socket)
}
}
bool
doConnect(JNIEnv* e, int s, sockaddr_in* address)
bool doConnect(JNIEnv* e, int s, sockaddr_in* address)
{
int r = ::connect(s, reinterpret_cast<sockaddr*>(address),
sizeof(sockaddr_in));
int r
= ::connect(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
if (r == 0) {
return true;
} else if (not einProgress()) {
@ -307,8 +300,7 @@ doConnect(JNIEnv* e, int s, sockaddr_in* address)
}
}
int
doAccept(JNIEnv* e, int s)
int doAccept(JNIEnv* e, int s)
{
sockaddr address;
socklen_t length = sizeof(address);
@ -321,8 +313,7 @@ doAccept(JNIEnv* e, int s)
return -1;
}
int
doRead(int fd, void* buffer, size_t count)
int doRead(int fd, void* buffer, size_t count)
{
#ifdef PLATFORM_WINDOWS
return recv(fd, static_cast<char*>(buffer), count, 0);
@ -331,16 +322,15 @@ doRead(int fd, void* buffer, size_t count)
#endif
}
int
doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
int doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
{
sockaddr address;
socklen_t length = sizeof(address);
int r = recvfrom
(fd, static_cast<char*>(buffer), count, 0, &address, &length);
int r = recvfrom(fd, static_cast<char*>(buffer), count, 0, &address, &length);
if (r > 0) {
sockaddr_in a; memcpy(&a, &address, length);
sockaddr_in a;
memcpy(&a, &address, length);
*host = ntohl(a.sin_addr.s_addr);
*port = ntohs(a.sin_port);
} else {
@ -351,8 +341,7 @@ doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
return r;
}
int
doWrite(int fd, const void* buffer, size_t count)
int doWrite(int fd, const void* buffer, size_t count)
{
#ifdef PLATFORM_WINDOWS
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>
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);
}
@ -446,8 +436,8 @@ Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e,
jint socket,
jboolean blocking)
{
return Java_java_nio_channels_SocketChannel_configureBlocking
(e, c, socket, blocking);
return Java_java_nio_channels_SocketChannel_configureBlocking(
e, c, socket, blocking);
}
extern "C" JNIEXPORT void JNICALL
@ -520,8 +510,7 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
if (buf) {
r = ::doRead(socket, buf, length);
if (r > 0) {
e->SetByteArrayRegion
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
}
free(buf);
} else {
@ -529,8 +518,8 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
}
} else {
jboolean isCopy;
uint8_t* buf = static_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
uint8_t* buf
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
r = ::doRead(socket, buf + offset, length);
@ -567,8 +556,7 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
if (buf) {
r = ::doRecv(socket, buf, length, &host, &port);
if (r > 0) {
e->SetByteArrayRegion
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
}
free(buf);
} else {
@ -576,8 +564,8 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
}
} else {
jboolean isCopy;
uint8_t* buf = static_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
uint8_t* buf
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
r = ::doRecv(socket, buf + offset, length, &host, &port);
@ -593,8 +581,10 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
} else if (r == 0) {
return -1;
} else {
jint jhost = host; e->SetIntArrayRegion(address, 0, 1, &jhost);
jint jport = port; e->SetIntArrayRegion(address, 1, 1, &jport);
jint jhost = host;
e->SetIntArrayRegion(address, 0, 1, &jhost);
jint jport = port;
e->SetIntArrayRegion(address, 1, 1, &jport);
}
return r;
@ -613,8 +603,8 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
if (blocking) {
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
if (buf) {
e->GetByteArrayRegion
(buffer, offset, length, reinterpret_cast<jbyte*>(buf));
e->GetByteArrayRegion(
buffer, offset, length, reinterpret_cast<jbyte*>(buf));
r = ::doWrite(socket, buf, length);
free(buf);
} else {
@ -622,8 +612,8 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
}
} else {
jboolean isCopy;
uint8_t* buf = static_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
uint8_t* buf
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
r = ::doWrite(socket, buf + offset, length);
@ -649,8 +639,8 @@ Java_java_nio_channels_DatagramChannel_write(JNIEnv* e,
jint length,
jboolean blocking)
{
return Java_java_nio_channels_SocketChannel_natWrite
(e, c, socket, buffer, offset, length, blocking);
return Java_java_nio_channels_SocketChannel_natWrite(
e, c, socket, buffer, offset, length, blocking);
}
extern "C" JNIEXPORT jint JNICALL
@ -705,8 +695,8 @@ Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e,
{
int error;
socklen_t size = sizeof(int);
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR,
reinterpret_cast<char*>(&error), &size);
int r = getsockopt(
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
if (r != 0 or size != sizeof(int)) {
throwIOException(e);
} else if (error != 0) {
@ -723,9 +713,7 @@ Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv *,
}
extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_DatagramChannel_close(JNIEnv *,
jclass,
jint socket)
Java_java_nio_channels_DatagramChannel_close(JNIEnv*, jclass, jint socket)
{
doClose(socket);
}
@ -739,69 +727,85 @@ class Pipe {
// pipe descriptors or others. Thus, to implement
// Selector.wakeup(), we make a socket connection via the loopback
// 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;
address.sin_family = AF_INET;
address.sin_port = 0;
address.sin_addr.s_addr = inet_addr("127.0.0.1"); // INADDR_LOOPBACK;
listener_ = makeSocket(e);
if (e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
setBlocking(e, listener_, false);
::doBind(e, listener_, &address);
if (e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
::doListen(e, listener_);
if (e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
socklen_t length = sizeof(sockaddr_in);
int r = getsockname(listener_, reinterpret_cast<sockaddr*>(&address),
&length);
int r = getsockname(
listener_, reinterpret_cast<sockaddr*>(&address), &length);
if (r) {
throwIOException(e);
return;
}
writer_ = makeSocket(e);
if (e->ExceptionCheck()) return;
if (e->ExceptionCheck())
return;
setBlocking(e, writer_, true);
connected_ = ::doConnect(e, writer_, &address);
}
void dispose() {
if (listener_ >= 0) ::doClose(listener_);
if (reader_ >= 0) ::doClose(reader_);
if (writer_ >= 0) ::doClose(writer_);
void dispose()
{
if (listener_ >= 0)
::doClose(listener_);
if (reader_ >= 0)
::doClose(reader_);
if (writer_ >= 0)
::doClose(writer_);
}
bool connected() {
bool connected()
{
return connected_;
}
void setConnected(bool v) {
void setConnected(bool v)
{
connected_ = v;
}
int listener() {
int listener()
{
return listener_;
}
void setListener(int v) {
void setListener(int v)
{
listener_ = v;
}
int reader() {
int reader()
{
return reader_;
}
void setReader(int v) {
void setReader(int v)
{
reader_ = v;
}
int writer() {
int writer()
{
return writer_;
}
@ -811,7 +815,8 @@ class Pipe {
int reader_;
int writer_;
#else
Pipe(JNIEnv* e) {
Pipe(JNIEnv* e)
{
if (::pipe(pipe) != 0) {
throwIOException(e);
return;
@ -824,21 +829,25 @@ class Pipe {
open_ = true;
}
void dispose() {
void dispose()
{
::doClose(pipe[0]);
::doClose(pipe[1]);
open_ = false;
}
bool connected() {
bool connected()
{
return open_;
}
int reader() {
int reader()
{
return pipe[0];
}
int writer() {
int writer()
{
return pipe[1];
}
@ -853,7 +862,9 @@ struct SelectorState {
fd_set write;
fd_set except;
Pipe control;
SelectorState(JNIEnv* e) : control(e) { }
SelectorState(JNIEnv* e) : control(e)
{
}
};
} // namespace
@ -864,7 +875,8 @@ Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass)
void* mem = malloc(sizeof(SelectorState));
if (mem) {
SelectorState* s = new (mem) SelectorState(e);
if (e->ExceptionCheck()) return 0;
if (e->ExceptionCheck())
return 0;
if (s) {
FD_ZERO(&(s->read));
@ -878,7 +890,9 @@ Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass)
}
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);
if (s->control.connected()) {
@ -899,7 +913,8 @@ Java_java_nio_channels_SocketSelector_natClose(JNIEnv *, jclass, jlong state)
}
extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv *, jclass,
Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv*,
jclass,
jint socket,
jlong state)
{
@ -910,7 +925,8 @@ Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv *, jclass,
}
extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *,
Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(
JNIEnv*,
jclass,
jint socket,
jint interest,
@ -918,19 +934,21 @@ Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *,
jint max)
{
SelectorState* s = reinterpret_cast<SelectorState*>(state);
if (interest & (java_nio_channels_SelectionKey_OP_READ |
java_nio_channels_SelectionKey_OP_ACCEPT)) {
if (interest & (java_nio_channels_SelectionKey_OP_READ
| java_nio_channels_SelectionKey_OP_ACCEPT)) {
FD_SET(static_cast<unsigned>(socket), &(s->read));
if (max < socket) max = socket;
if (max < socket)
max = socket;
} else {
FD_CLR(static_cast<unsigned>(socket), &(s->read));
}
if (interest & (java_nio_channels_SelectionKey_OP_WRITE |
java_nio_channels_SelectionKey_OP_CONNECT)) {
if (interest & (java_nio_channels_SelectionKey_OP_WRITE
| java_nio_channels_SelectionKey_OP_CONNECT)) {
FD_SET(static_cast<unsigned>(socket), &(s->write));
FD_SET(static_cast<unsigned>(socket), &(s->except));
if (max < socket) max = socket;
if (max < socket)
max = socket;
} else {
FD_CLR(static_cast<unsigned>(socket), &(s->write));
}
@ -938,7 +956,8 @@ Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *,
}
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,
jint max,
jlong interval)
@ -947,21 +966,24 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
if (s->control.reader() >= 0) {
int socket = s->control.reader();
FD_SET(static_cast<unsigned>(socket), &(s->read));
if (max < socket) max = socket;
if (max < socket)
max = socket;
}
#ifdef PLATFORM_WINDOWS
if (s->control.listener() >= 0) {
int socket = s->control.listener();
FD_SET(static_cast<unsigned>(socket), &(s->read));
if (max < socket) max = socket;
if (max < socket)
max = socket;
}
if (not s->control.connected()) {
int socket = s->control.writer();
FD_SET(static_cast<unsigned>(socket), &(s->write));
FD_SET(static_cast<unsigned>(socket), &(s->except));
if (max < socket) max = socket;
if (max < socket)
max = socket;
}
#endif
@ -986,17 +1008,16 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
}
#ifdef PLATFORM_WINDOWS
if (FD_ISSET(s->control.writer(), &(s->write)) or
FD_ISSET(s->control.writer(), &(s->except)))
{
if (FD_ISSET(s->control.writer(), &(s->write))
or FD_ISSET(s->control.writer(), &(s->except))) {
int socket = s->control.writer();
FD_CLR(static_cast<unsigned>(socket), &(s->write));
FD_CLR(static_cast<unsigned>(socket), &(s->except));
int error;
socklen_t size = sizeof(int);
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR,
reinterpret_cast<char*>(&error), &size);
int r = getsockopt(
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
if (r != 0 or size != sizeof(int)) {
throwIOException(e);
} else if (error != 0) {
@ -1005,9 +1026,8 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
s->control.setConnected(true);
}
if (s->control.listener() >= 0 and
FD_ISSET(s->control.listener(), &(s->read)))
{
if (s->control.listener() >= 0
and FD_ISSET(s->control.listener(), &(s->read))) {
FD_CLR(static_cast<unsigned>(s->control.listener()), &(s->read));
s->control.setReader(::doAccept(e, s->control.listener()));
@ -1015,9 +1035,7 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
}
#endif
if (s->control.reader() >= 0 and
FD_ISSET(s->control.reader(), &(s->read)))
{
if (s->control.reader() >= 0 and FD_ISSET(s->control.reader(), &(s->read))) {
FD_CLR(static_cast<unsigned>(s->control.reader()), &(s->read));
char c;
@ -1034,7 +1052,8 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
}
extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass,
Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv*,
jclass,
jint socket,
jint interest,
jlong state)
@ -1065,7 +1084,6 @@ Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass,
return ready;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv*, jclass)
{

View File

@ -16,8 +16,7 @@
#include "jni-util.h"
extern "C" JNIEXPORT jlong JNICALL
Java_java_util_zip_Inflater_make
(JNIEnv* e, jclass, jboolean nowrap)
Java_java_util_zip_Inflater_make(JNIEnv* e, jclass, jboolean nowrap)
{
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
if (s == 0) {
@ -46,10 +45,15 @@ Java_java_util_zip_Inflater_dispose(JNIEnv*, jclass, jlong peer)
}
extern "C" JNIEXPORT void JNICALL
Java_java_util_zip_Inflater_inflate
(JNIEnv* e, jclass, jlong peer,
jbyteArray input, jint inputOffset, jint inputLength,
jbyteArray output, jint outputOffset, jint outputLength,
Java_java_util_zip_Inflater_inflate(JNIEnv* e,
jclass,
jlong peer,
jbyteArray input,
jint inputOffset,
jint inputLength,
jbyteArray output,
jint outputOffset,
jint outputLength,
jintArray results)
{
z_stream* s = reinterpret_cast<z_stream*>(peer);
@ -75,8 +79,7 @@ Java_java_util_zip_Inflater_inflate
s->avail_out = outputLength;
int r = inflate(s, Z_SYNC_FLUSH);
jint resultArray[3]
= { r,
jint resultArray[3] = {r,
static_cast<jint>(inputLength - s->avail_in),
static_cast<jint>(outputLength - s->avail_out)};
@ -89,8 +92,10 @@ Java_java_util_zip_Inflater_inflate
}
extern "C" JNIEXPORT jlong JNICALL
Java_java_util_zip_Deflater_make
(JNIEnv* e, jclass, jboolean nowrap, jint level)
Java_java_util_zip_Deflater_make(JNIEnv* e,
jclass,
jboolean nowrap,
jint level)
{
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
if (s == 0) {
@ -119,11 +124,17 @@ Java_java_util_zip_Deflater_dispose(JNIEnv*, jclass, jlong peer)
}
extern "C" JNIEXPORT void JNICALL
Java_java_util_zip_Deflater_deflate
(JNIEnv* e, jclass, jlong peer,
jbyteArray input, jint inputOffset, jint inputLength,
jbyteArray output, jint outputOffset, jint outputLength,
jboolean finish, jintArray results)
Java_java_util_zip_Deflater_deflate(JNIEnv* e,
jclass,
jlong peer,
jbyteArray input,
jint inputOffset,
jint inputLength,
jbyteArray output,
jint outputOffset,
jint outputLength,
jboolean finish,
jintArray results)
{
z_stream* s = reinterpret_cast<z_stream*>(peer);
@ -148,8 +159,7 @@ Java_java_util_zip_Deflater_deflate
s->avail_out = outputLength;
int r = deflate(s, finish ? Z_FINISH : Z_NO_FLUSH);
jint resultArray[3]
= { r,
jint resultArray[3] = {r,
static_cast<jint>(inputLength - s->avail_in),
static_cast<jint>(outputLength - s->avail_out)};

View File

@ -16,8 +16,7 @@ namespace {
#if (!defined PLATFORM_WINDOWS) || (defined _MSC_VER)
void
removeNewline(char* s)
void removeNewline(char* s)
{
for (; s; ++s) {
if (*s == '\n') {

View File

@ -171,8 +171,8 @@ public final class Class <T> implements Type, AnnotatedElement {
return SystemClassLoader.getClass(Classes.primitiveClass('D'));
}
if (vmClass.staticTable == null) throw new AssertionError();
return SystemClassLoader.getClass((VMClass) vmClass.staticTable);
if (vmClass.arrayElementClass == null) throw new AssertionError();
return SystemClassLoader.getClass((VMClass) vmClass.arrayElementClass);
} else {
return null;
}

View File

@ -26,8 +26,7 @@
#else // not (defined __MINGW32__) || (defined _MSC_VER)
#define PLATFORM_POSIX
#define PATH_SEPARATOR ':'
# define JNIEXPORT __attribute__ ((visibility("default"))) \
__attribute__ ((used))
#define JNIEXPORT __attribute__((visibility("default"))) __attribute__((used))
#endif // not (defined __MINGW32__) || (defined _MSC_VER)
#ifdef _MSC_VER
@ -73,8 +72,7 @@ typedef unsigned __int64 uint64_t;
#endif // not _MSC_VER
inline void
throwNew(JNIEnv* e, const char* class_, const char* message, ...)
inline void throwNew(JNIEnv* e, const char* class_, const char* message, ...)
{
jclass c = e->FindClass(class_);
if (c) {
@ -99,8 +97,7 @@ throwNew(JNIEnv* e, const char* class_, const char* message, ...)
}
}
inline void
throwNewErrno(JNIEnv* e, const char* class_)
inline void throwNewErrno(JNIEnv* e, const char* class_)
{
#ifdef _MSC_VER
const unsigned size = 128;
@ -112,8 +109,7 @@ throwNewErrno(JNIEnv* e, const char* class_)
#endif
}
inline void*
allocate(JNIEnv* e, unsigned size)
inline void* allocate(JNIEnv* e, unsigned size)
{
void* p = malloc(size);
if (p == 0) {

View File

@ -19,7 +19,8 @@ namespace avian {
namespace classpath {
namespace sockets {
int last_socket_error() {
int last_socket_error()
{
#ifdef PLATFORM_WINDOWS
int error = WSAGetLastError();
#else
@ -28,8 +29,8 @@ int last_socket_error() {
return error;
}
void init(JNIEnv* ONLY_ON_WINDOWS(e)) {
void init(JNIEnv* ONLY_ON_WINDOWS(e))
{
#ifdef PLATFORM_WINDOWS
static bool wsaInitialized = false;
if (not wsaInitialized) {
@ -44,18 +45,21 @@ void init(JNIEnv* ONLY_ON_WINDOWS(e)) {
#endif
}
SOCKET create(JNIEnv* e) {
SOCKET create(JNIEnv* e)
{
SOCKET sock;
if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
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);
return 0; // This doesn't matter cause we have risen an exception
}
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;
adr.sin_family = AF_INET;
#ifdef PLATFORM_WINDOWS
@ -65,16 +69,17 @@ void connect(JNIEnv* e, SOCKET sock, long addr, short port) {
#endif
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];
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);
return;
}
}
void bind(JNIEnv* e, SOCKET sock, long addr, short port) {
void bind(JNIEnv* e, SOCKET sock, long addr, short port)
{
sockaddr_in adr;
adr.sin_family = AF_INET;
#ifdef PLATFORM_WINDOWS
@ -84,8 +89,7 @@ void bind(JNIEnv* e, SOCKET sock, long addr, short port) {
#endif
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];
sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error());
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;
SOCKET client_socket = ::accept(sock, (sockaddr*)&adr, NULL);
if (INVALID_SOCKET == client_socket) {
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);
return INVALID_SOCKET;
}
@ -118,35 +125,44 @@ SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port) {
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)) {
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);
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);
if (SOCKET_ERROR == length) {
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);
return 0; // This doesn't matter cause we have risen an exception
}
return length;
}
void abort(JNIEnv* e, SOCKET sock) {
void abort(JNIEnv* e, SOCKET sock)
{
if (SOCKET_ERROR == ::closesocket(sock)) {
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);
}
}
void close(JNIEnv* e, SOCKET sock) {
void close(JNIEnv* e, SOCKET sock)
{
if (SOCKET_ERROR == ::shutdown(sock, SD_BOTH)) {
int errcode = last_socket_error();
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)) {
int errcode = last_socket_error();
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)) {
int errcode = last_socket_error();
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
details. */
/*
* This file represents a simple cross-platform JNI sockets API
* 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_input(JNIEnv* e, SOCKET sock);
void close_output(JNIEnv* e, SOCKET sock);
}
}
}

View File

@ -34,15 +34,14 @@ public:
uint8_t typeMask;
uint64_t registerMask;
OperandMask(uint8_t typeMask, uint64_t registerMask):
typeMask(typeMask),
registerMask(registerMask)
{ }
OperandMask(uint8_t typeMask, uint64_t registerMask)
: typeMask(typeMask), registerMask(registerMask)
{
}
OperandMask():
typeMask(~0),
registerMask(~static_cast<uint64_t>(0))
{ }
OperandMask() : typeMask(~0), registerMask(~static_cast<uint64_t>(0))
{
}
};
class Architecture {
@ -83,16 +82,21 @@ virtual unsigned stackAlignmentInWords() = 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;
virtual void setConstant(void* dst, uint64_t constant) = 0;
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
void* link, bool mostRecent,
int targetParameterFootprint, void** ip,
virtual void nextFrame(void* start,
unsigned size,
unsigned footprint,
void* link,
bool mostRecent,
int targetParameterFootprint,
void** ip,
void** stack) = 0;
virtual void* frameIp(void* stack) = 0;
virtual unsigned frameHeaderSize() = 0;
@ -101,37 +105,43 @@ virtual unsigned frameFooterSize() = 0;
virtual int returnAddressOffset() = 0;
virtual int framePointerOffset() = 0;
virtual void plan
(lir::UnaryOperation op,
unsigned aSize, OperandMask& aMask,
virtual void plan(lir::UnaryOperation op,
unsigned aSize,
OperandMask& aMask,
bool* thunk) = 0;
virtual void planSource
(lir::BinaryOperation op,
unsigned aSize, OperandMask& aMask,
unsigned bSize, bool* thunk) = 0;
virtual void planSource(lir::BinaryOperation op,
unsigned aSize,
OperandMask& aMask,
unsigned bSize,
bool* thunk) = 0;
virtual void planDestination
(lir::BinaryOperation op,
unsigned aSize, const OperandMask& aMask,
unsigned bSize, OperandMask& bMask) = 0;
virtual void planDestination(lir::BinaryOperation op,
unsigned aSize,
const OperandMask& aMask,
unsigned bSize,
OperandMask& bMask) = 0;
virtual void planMove
(unsigned size, OperandMask& src,
virtual void planMove(unsigned size,
OperandMask& src,
OperandMask& tmp,
const OperandMask& dst) = 0;
virtual void planSource
(lir::TernaryOperation op,
unsigned aSize, OperandMask& aMask,
unsigned bSize, OperandMask& bMask,
unsigned cSize, bool* thunk) = 0;
virtual void planSource(lir::TernaryOperation op,
unsigned aSize,
OperandMask& aMask,
unsigned bSize,
OperandMask& bMask,
unsigned cSize,
bool* thunk) = 0;
virtual void planDestination
(lir::TernaryOperation op,
unsigned aSize, const OperandMask& aMask,
unsigned bSize, const OperandMask& bMask,
unsigned cSize, OperandMask& cMask) = 0;
virtual void planDestination(lir::TernaryOperation op,
unsigned aSize,
const OperandMask& aMask,
unsigned bSize,
const OperandMask& bMask,
unsigned cSize,
OperandMask& cMask) = 0;
virtual Assembler* makeAssembler(util::Allocator*, vm::Zone*) = 0;

View File

@ -28,11 +28,12 @@ public:
const lir::OperandType type;
lir::Operand* const operand;
inline OperandInfo(unsigned size, lir::OperandType type, lir::Operand* operand):
size(size),
type(type),
operand(operand)
{ }
inline OperandInfo(unsigned size,
lir::OperandType type,
lir::Operand* operand)
: size(size), type(type), operand(operand)
{
}
};
#ifdef AVIAN_TAILS
@ -49,11 +50,9 @@ const bool UseFramePointer = false;
class Assembler {
public:
class Client {
public:
virtual int acquireTemporary
(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
virtual int acquireTemporary(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
virtual void releaseTemporary(int r) = 0;
virtual void save(int r) = 0;
@ -75,12 +74,12 @@ class Assembler {
virtual void allocateFrame(unsigned footprint) = 0;
virtual void adjustFrame(unsigned difference) = 0;
virtual void popFrame(unsigned footprint) = 0;
virtual void popFrameForTailCall(unsigned footprint, int offset,
virtual void popFrameForTailCall(unsigned footprint,
int offset,
int returnAddressSurrogate,
int framePointerSurrogate) = 0;
virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint,
unsigned argumentFootprint)
= 0;
unsigned argumentFootprint) = 0;
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
unsigned stackOffsetFromThread)
= 0;
@ -88,7 +87,10 @@ class Assembler {
virtual void apply(lir::Operation op) = 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::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;

View File

@ -30,10 +30,13 @@ class Compiler {
class Client {
public:
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;
virtual intptr_t getThunk(lir::TernaryOperation op, unsigned size,
unsigned resultSize, bool* threadParameter) = 0;
virtual intptr_t getThunk(lir::TernaryOperation op,
unsigned size,
unsigned resultSize,
bool* threadParameter) = 0;
};
static const unsigned Aligned = 1 << 0;
@ -41,13 +44,16 @@ class Compiler {
static const unsigned TailJump = 1 << 2;
static const unsigned LongJumpOrCall = 1 << 3;
class State { };
class State {
};
virtual State* saveState() = 0;
virtual void restoreState(State* state) = 0;
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
unsigned localFootprint, unsigned alignedFrameSize) = 0;
virtual void init(unsigned logicalCodeSize,
unsigned parameterFootprint,
unsigned localFootprint,
unsigned alignedFrameSize) = 0;
virtual void extendLogicalCode(unsigned more) = 0;
@ -128,8 +134,7 @@ class Compiler {
ir::Type type,
ir::Value* a,
ir::Value* b) = 0;
virtual ir::Value* unaryOp(lir::BinaryOperation op,
ir::Value* a) = 0;
virtual ir::Value* unaryOp(lir::BinaryOperation op, ir::Value* a) = 0;
virtual void nullaryOp(lir::Operation op) = 0;
virtual ir::Value* f2f(ir::Type resType, ir::Value* a) = 0;
@ -145,8 +150,9 @@ class Compiler {
virtual void dispose() = 0;
};
Compiler*
makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone,
Compiler* makeCompiler(vm::System* system,
Assembler* assembler,
vm::Zone* zone,
Compiler::Client* client);
} // namespace codegen

View File

@ -40,7 +40,6 @@ enum UnaryOperation {
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
NoUnaryOperation = -1
};
@ -56,7 +55,6 @@ enum BinaryOperation {
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
NoBinaryOperation = -1
};
@ -72,16 +70,14 @@ enum TernaryOperation {
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
NoTernaryOperation = -1
};
const unsigned TernaryOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered + 1;
const unsigned TernaryOperationCount = JumpIfFloatGreaterOrEqualOrUnordered + 1;
const unsigned NonBranchTernaryOperationCount = FloatMin + 1;
const unsigned BranchOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered - FloatMin;
const unsigned BranchOperationCount = JumpIfFloatGreaterOrEqualOrUnordered
- FloatMin;
enum OperandType {
ConstantOperand,
@ -90,62 +86,73 @@ enum OperandType {
MemoryOperand
};
enum ValueType {
ValueGeneral,
ValueFloat
};
enum ValueType { ValueGeneral, ValueFloat };
const unsigned OperandTypeCount = MemoryOperand + 1;
const int NoRegister = -1;
inline bool isBranch(lir::TernaryOperation op) {
inline bool isBranch(lir::TernaryOperation op)
{
return op > FloatMin;
}
inline bool isFloatBranch(lir::TernaryOperation op) {
inline bool isFloatBranch(lir::TernaryOperation op)
{
return op > JumpIfNotEqual;
}
inline bool isGeneralBranch(lir::TernaryOperation op) {
inline bool isGeneralBranch(lir::TernaryOperation op)
{
return isBranch(op) && !isFloatBranch(op);
}
inline bool isGeneralBinaryOp(lir::TernaryOperation op) {
inline bool isGeneralBinaryOp(lir::TernaryOperation op)
{
return op < FloatAdd;
}
inline bool isFloatBinaryOp(lir::TernaryOperation op) {
inline bool isFloatBinaryOp(lir::TernaryOperation op)
{
return op >= FloatAdd && op <= FloatMin;
}
inline bool isGeneralUnaryOp(lir::BinaryOperation op) {
inline bool isGeneralUnaryOp(lir::BinaryOperation op)
{
return op == Negate || op == Absolute;
}
inline bool isFloatUnaryOp(lir::BinaryOperation op) {
inline bool isFloatUnaryOp(lir::BinaryOperation op)
{
return op == FloatNegate || op == FloatSquareRoot || op == FloatAbsolute;
}
class Operand { };
class Operand {
};
class Constant : public Operand {
public:
Constant(Promise* value): value(value) { }
Constant(Promise* value) : value(value)
{
}
Promise* value;
};
class Address : public Operand {
public:
Address(Promise* address): address(address) { }
Address(Promise* address) : address(address)
{
}
Promise* address;
};
class Register : public Operand {
public:
Register(int low, int high = NoRegister): low(low), high(high) { }
Register(int low, int high = NoRegister) : low(low), high(high)
{
}
int low;
int high;
@ -153,9 +160,10 @@ class Register: public Operand {
class Memory : public Operand {
public:
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1):
base(base), offset(offset), index(index), scale(scale)
{ }
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1)
: base(base), offset(offset), index(index), scale(scale)
{
}
int base;
int offset;

View File

@ -29,18 +29,25 @@ class Promise {
virtual int64_t value() = 0;
virtual bool resolved() = 0;
virtual Listener* listen(unsigned) { return 0; }
virtual Listener* listen(unsigned)
{
return 0;
}
};
class ResolvedPromise : public Promise {
public:
ResolvedPromise(int64_t value): value_(value) { }
ResolvedPromise(int64_t value) : value_(value)
{
}
virtual int64_t value() {
virtual int64_t value()
{
return value_;
}
virtual bool resolved() {
virtual bool resolved()
{
return true;
}
@ -49,15 +56,18 @@ class ResolvedPromise: public Promise {
class ShiftMaskPromise : public Promise {
public:
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
base(base), shift(shift), mask(mask)
{ }
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask)
: base(base), shift(shift), mask(mask)
{
}
virtual int64_t value() {
virtual int64_t value()
{
return (base->value() >> shift) & mask;
}
virtual bool resolved() {
virtual bool resolved()
{
return base->resolved();
}
@ -68,15 +78,17 @@ class ShiftMaskPromise: public Promise {
class CombinedPromise : public Promise {
public:
CombinedPromise(Promise* low, Promise* high):
low(low), high(high)
{ }
CombinedPromise(Promise* low, Promise* high) : low(low), high(high)
{
}
virtual int64_t value() {
virtual int64_t value()
{
return low->value() | (high->value() << 32);
}
virtual bool resolved() {
virtual bool resolved()
{
return low->resolved() and high->resolved();
}
@ -86,15 +98,17 @@ class CombinedPromise: public Promise {
class OffsetPromise : public Promise {
public:
OffsetPromise(Promise* base, int64_t offset):
base(base), offset(offset)
{ }
OffsetPromise(Promise* base, int64_t offset) : base(base), offset(offset)
{
}
virtual int64_t value() {
virtual int64_t value()
{
return base->value() + offset;
}
virtual bool resolved() {
virtual bool resolved()
{
return base->resolved();
}
@ -106,17 +120,21 @@ class ListenPromise: public Promise {
public:
ListenPromise(vm::System* s, util::Allocator* allocator)
: s(s), allocator(allocator), listener(0)
{ }
{
}
virtual int64_t value() {
virtual int64_t value()
{
abort(s);
}
virtual bool resolved() {
virtual bool resolved()
{
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
virtual Listener* listen(unsigned sizeInBytes)
{
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;
@ -136,17 +154,21 @@ class DelayedPromise: public ListenPromise {
Promise* basis,
DelayedPromise* next)
: ListenPromise(s, allocator), basis(basis), next(next)
{ }
{
}
virtual int64_t value() {
virtual int64_t value()
{
abort(s);
}
virtual bool resolved() {
virtual bool resolved()
{
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
virtual Listener* listen(unsigned sizeInBytes)
{
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;

View File

@ -25,11 +25,10 @@ public:
static unsigned maskStart(uint32_t mask);
static unsigned maskLimit(uint32_t mask);
inline RegisterMask(uint32_t mask):
mask(mask),
start(maskStart(mask)),
limit(maskLimit(mask))
{ }
inline RegisterMask(uint32_t mask)
: mask(mask), start(maskStart(mask)), limit(maskLimit(mask))
{
}
};
class RegisterFile {
@ -38,11 +37,12 @@ public:
RegisterMask generalRegisters;
RegisterMask floatRegisters;
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask):
allRegisters(generalRegisterMask | floatRegisterMask),
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask)
: allRegisters(generalRegisterMask | floatRegisterMask),
generalRegisters(generalRegisterMask),
floatRegisters(floatRegisterMask)
{ }
{
}
};
class RegisterIterator {
@ -50,15 +50,18 @@ public:
int index;
const RegisterMask& mask;
inline RegisterIterator(const RegisterMask& mask):
index(mask.start),
mask(mask) {}
inline RegisterIterator(const RegisterMask& mask)
: index(mask.start), mask(mask)
{
}
inline bool hasNext() {
inline bool hasNext()
{
return index < mask.limit;
}
inline int next() {
inline int next()
{
int r = index;
do {
index++;

View File

@ -20,7 +20,8 @@ namespace codegen {
class Architecture;
Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures);
Architecture* makeArchitectureNative(vm::System* system,
bool useNativeFeatures);
Architecture* makeArchitectureX86(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 {
public:
enum CollectionType {
MinorCollection,
MajorCollection
};
enum CollectionType { MinorCollection, MajorCollection };
enum Status {
Null,
Reachable,
Unreachable,
Tenured
};
enum Status { Null, Reachable, Unreachable, Tenured };
class Visitor {
public:
@ -62,7 +54,8 @@ class Heap : public avian::util::Allocator {
virtual unsigned remaining() = 0;
virtual unsigned limit() = 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;
virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) = 0;
virtual void* allocateFixed(avian::util::Allocator* allocator,
@ -74,6 +67,13 @@ class Heap : public avian::util::Allocator {
virtual void mark(void* p, unsigned offset, unsigned count) = 0;
virtual void pad(void* p) = 0;
virtual void* follow(void* p) = 0;
template <class T>
T* follow(T* p)
{
return static_cast<T*>(follow(static_cast<void*>(p)));
}
virtual void postVisit() = 0;
virtual Status status(void* p) = 0;
virtual CollectionType collectionType() = 0;

View File

@ -21,7 +21,8 @@ namespace system {
// order to trigger the crash dump logic.
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"
// register. Use a thread-local variable instead.
class SignalRegistrar {
@ -40,7 +41,6 @@ class SignalRegistrar {
// "Segmentation fault" exceptions (mostly null pointer dereference, but
// generally access to any non-mapped memory)
SegFault,
DivideByZero,
};
@ -72,7 +72,6 @@ class SignalRegistrar {
struct Data;
private:
Data* data;
};

View File

@ -21,12 +21,7 @@ class System : public avian::util::Aborter {
public:
typedef intptr_t Status;
enum FileType {
TypeUnknown,
TypeDoesNotExist,
TypeFile,
TypeDirectory
};
enum FileType { TypeUnknown, TypeDoesNotExist, TypeFile, TypeDirectory };
class Thread {
public:
@ -100,11 +95,13 @@ class System : public avian::util::Aborter {
class MonitorResource {
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);
}
~MonitorResource() {
~MonitorResource()
{
m->release(t);
}
@ -126,8 +123,8 @@ class System : public avian::util::Aborter {
virtual Status make(Monitor**) = 0;
virtual Status make(Local**) = 0;
virtual Status visit(Thread* thread, Thread* target,
ThreadVisitor* visitor) = 0;
virtual Status visit(Thread* thread, Thread* target, ThreadVisitor* visitor)
= 0;
virtual Status map(Region**, const char* name) = 0;
virtual FileType stat(const char* name, unsigned* length) = 0;
@ -145,46 +142,45 @@ class System : public avian::util::Aborter {
virtual void dispose() = 0;
};
inline void*
allocate(System* s, unsigned size)
inline void* allocate(System* s, unsigned size)
{
void* p = s->tryAllocate(size);
if (p == 0) s->abort();
if (p == 0)
s->abort();
return p;
}
#define ACQUIRE_MONITOR(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;
}
inline void NO_RETURN
sysAbort(System* s)
inline void NO_RETURN sysAbort(System* s)
{
abort(s);
}
// #ifdef NDEBUG
// # define assert(a, b)
// # define assertT(a, b)
// # define vm_assert(a, b)
// #else // not NDEBUG
// inline void
// assert(System* s, bool v)
// assertT(System* s, bool v)
// {
// expect(s, v);
// }
// # define vm_assert(a, b) vm::assert(a, b)
// # define vm_assert(a, b) vm::assertT(a, b)
// #endif // not NDEBUG
AVIAN_EXPORT System*
makeSystem();
AVIAN_EXPORT System* makeSystem();
} // namespace vm

View File

@ -32,6 +32,7 @@ public:
class FileOutputStream : public OutputStream {
private:
FILE* file;
public:
FileOutputStream(const char* name);
~FileOutputStream();
@ -47,12 +48,14 @@ public:
unsigned addr;
util::String name;
inline SymbolInfo(uint64_t addr, const util::String& name):
addr(addr),
name(name) {}
inline SymbolInfo(uint64_t addr, const util::String& name)
: addr(addr), name(name)
{
}
inline SymbolInfo():
name("") {}
inline SymbolInfo() : name("")
{
}
};
class Buffer {
@ -124,11 +127,13 @@ public:
static Format formatFromString(const char* format);
static Architecture archFromString(const char* arch);
inline PlatformInfo(Format format, Architecture arch):
format(format),
arch(arch) {}
inline PlatformInfo(Format format, Architecture arch)
: format(format), arch(arch)
{
}
inline bool operator == (const PlatformInfo& other) {
inline bool operator==(const PlatformInfo& other)
{
return format == other.format && arch == other.arch;
}
};
@ -137,20 +142,16 @@ class Platform {
private:
Platform* next;
static Platform* first;
public:
PlatformInfo info;
inline Platform(PlatformInfo info):
next(first),
info(info)
inline Platform(PlatformInfo info) : next(first), info(info)
{
first = this;
}
enum AccessFlags {
Writable = 1 << 0,
Executable = 1 << 1
};
enum AccessFlags { Writable = 1 << 0, Executable = 1 << 1 };
virtual bool writeObject(OutputStream* out,
util::Slice<SymbolInfo> symbols,
@ -166,4 +167,3 @@ public:
} // namespace avian
#endif

View File

@ -29,23 +29,26 @@ inline Aborter* getAborter(Aborter* a)
}
template <class T>
inline void NO_RETURN abort(T t) {
inline void NO_RETURN abort(T t)
{
getAborter(t)->abort();
::abort();
}
template <class T>
inline void expect(T t, bool v) {
inline void expect(T t, bool v)
{
if (UNLIKELY(!v)) {
abort(t);
}
}
#ifdef NDEBUG
#define assert(t, v)
#define assertT(t, v)
#else
template <class T>
inline void assert(T t, bool v) {
inline void assertT(T t, bool v)
{
expect(t, v);
}
#endif

View File

@ -18,13 +18,16 @@ class Arg;
class ArgParser {
public:
Arg* first;
Arg** last;
ArgParser();
bool parse(int ac, const char* const* av);
void printUsage(const char* exe);
private:
friend class Arg;
Arg* first;
Arg** last;
};
class Arg {
@ -39,7 +42,6 @@ public:
Arg(ArgParser& parser, bool required, const char* name, const char* desc);
};
} // namespace avian
} // namespace util

57
include/avian/util/hash.h Normal file
View File

@ -0,0 +1,57 @@
/* Copyright (c) 2008-2014, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_UTIL_HASH_H
#define AVIAN_UTIL_HASH_H
#include "slice.h"
namespace avian {
namespace util {
inline uint32_t hash(const char* s)
{
uint32_t h = 0;
for (unsigned i = 0; s[i]; ++i) {
h = (h * 31) + s[i];
}
return h;
}
inline uint32_t hash(Slice<const uint8_t> data)
{
const uint8_t* s = data.begin();
uint32_t h = 0;
for (size_t i = 0; i < data.count; ++i) {
h = (h * 31) + s[i];
}
return h;
}
inline uint32_t hash(Slice<const int8_t> data)
{
return hash(Slice<const uint8_t>(
reinterpret_cast<const uint8_t*>(data.begin()), data.count));
}
inline uint32_t hash(Slice<const uint16_t> data)
{
const uint16_t* s = data.begin();
uint32_t h = 0;
for (size_t i = 0; i < data.count; ++i) {
h = (h * 31) + s[i];
}
return h;
}
} // namespace util
} // namespace avian
#endif // AVIAN_UTIL_HASH_H

View File

@ -19,11 +19,12 @@ namespace util {
template <class T>
class List {
public:
List(const T& item, List<T>* next):
item(item),
next(next) {}
List(const T& item, List<T>* next) : item(item), next(next)
{
}
unsigned count() {
unsigned count()
{
unsigned count = 0;
List<T>* c = this;
while (c) {

View File

@ -17,36 +17,47 @@
namespace avian {
namespace util {
inline unsigned max(unsigned a, unsigned b) {
inline unsigned max(unsigned a, unsigned 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);
}
inline unsigned avg(unsigned a, unsigned b) {
inline unsigned avg(unsigned a, unsigned b)
{
return (a + b) / 2;
}
inline unsigned ceilingDivide(unsigned n, unsigned d) {
inline unsigned ceilingDivide(unsigned n, unsigned d)
{
return (n + d - 1) / d;
}
inline bool powerOfTwo(unsigned n) {
for (; n > 2; n >>= 1) if (n & 1) return false;
inline bool powerOfTwo(unsigned n)
{
for (; n > 2; n >>= 1)
if (n & 1)
return false;
return true;
}
inline unsigned nextPowerOfTwo(unsigned n) {
inline unsigned nextPowerOfTwo(unsigned n)
{
unsigned r = 1;
while (r < n) r <<= 1;
while (r < n)
r <<= 1;
return r;
}
inline unsigned log(unsigned n) {
inline unsigned log(unsigned n)
{
unsigned r = 0;
for (unsigned i = 1; i < n; ++r) i <<= 1;
for (unsigned i = 1; i < n; ++r)
i <<= 1;
return r;
}

View File

@ -16,11 +16,12 @@
template <class T>
class RuntimeArray {
public:
RuntimeArray(unsigned size):
body(static_cast<T*>(malloc(size * sizeof(T))))
{ }
RuntimeArray(unsigned size) : body(static_cast<T*>(malloc(size * sizeof(T))))
{
}
~RuntimeArray() {
~RuntimeArray()
{
free(body);
}

View File

@ -18,6 +18,19 @@
namespace avian {
namespace util {
template <class T>
struct NonConst;
template <class T>
struct NonConst<const T> {
typedef T Type;
};
template <class T>
struct NonConst {
typedef T Type;
};
template <class T>
class Slice {
public:
@ -28,7 +41,8 @@ class Slice {
{
}
inline Slice(const Slice<T>& copy) : items(copy.items), count(copy.count)
inline Slice(const Slice<typename NonConst<T>::Type>& copy)
: items(copy.items), count(copy.count)
{
}
@ -48,6 +62,13 @@ class Slice {
return items + count;
}
inline Slice<T> subslice(size_t begin, size_t count)
{
ASSERT(begin <= this->count);
ASSERT(begin + count <= this->count);
return Slice<T>(this->begin() + begin, count);
}
static Slice<T> alloc(Allocator* a, size_t count)
{
return Slice<T>((T*)a->allocate(sizeof(T) * count), count);

View File

@ -22,19 +22,23 @@ class AbstractStream {
virtual void handleError() = 0;
};
AbstractStream(Client* client, unsigned size):
client(client), size(size), position_(0)
{ }
AbstractStream(Client* client, unsigned size)
: client(client), size(size), position_(0)
{
}
unsigned position() {
unsigned position()
{
return position_;
}
void setPosition(unsigned p) {
void setPosition(unsigned p)
{
position_ = p;
}
void skip(unsigned size) {
void skip(unsigned size)
{
if (size > this->size - position_) {
client->handleError();
} 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_) {
memset(dst, 0, size);
@ -53,35 +58,41 @@ class AbstractStream {
}
}
uint8_t read1() {
uint8_t read1()
{
uint8_t v;
read(&v, 1);
return v;
}
uint16_t read2() {
uint16_t read2()
{
uint16_t a = read1();
uint16_t b = read1();
return (a << 8) | b;
}
uint32_t read4() {
uint32_t read4()
{
uint32_t a = read2();
uint32_t b = read2();
return (a << 16) | b;
}
uint64_t read8() {
uint64_t read8()
{
uint64_t a = read4();
uint64_t b = read4();
return (a << 32) | b;
}
uint32_t readFloat() {
uint32_t readFloat()
{
return read4();
}
uint64_t readDouble() {
uint64_t readDouble()
{
return read8();
}
@ -96,12 +107,14 @@ class AbstractStream {
class Stream : public AbstractStream {
public:
Stream(Client* client, const uint8_t* data, unsigned size):
AbstractStream(client, size), data(data)
{ }
Stream(Client* client, const uint8_t* data, unsigned size)
: AbstractStream(client, size), data(data)
{
}
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);
}

View File

@ -21,34 +21,39 @@ public:
const char* text;
size_t length;
String(const char* text):
text(text),
length(strlen(text)) {}
String(const char* text) : text(text), length(strlen(text))
{
}
inline String(const char* text, size_t length):
text(text),
length(length) {}
inline String(const char* text, size_t length) : text(text), length(length)
{
}
};
class Tokenizer {
public:
Tokenizer(const char* s, char delimiter)
: s(s), limit(0), delimiter(delimiter)
{
}
Tokenizer(const char* s, char delimiter):
s(s), limit(0), delimiter(delimiter)
{ }
Tokenizer(String str, char delimiter)
: s(str.text), limit(str.text + str.length), delimiter(delimiter)
{
}
Tokenizer(String str, char delimiter):
s(str.text), limit(str.text + str.length), delimiter(delimiter)
{ }
bool hasMore() {
while (s != limit and *s == delimiter) ++s;
bool hasMore()
{
while (s != limit and *s == delimiter)
++s;
return s != limit and *s != 0;
}
String next() {
String next()
{
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);
}

View File

@ -443,6 +443,7 @@ asm-format = S
as = $(cc)
ld = $(cc)
build-ld = $(build-cc)
build-ld-cpp = $(build-cxx)
default-remote-test-host = localhost
default-remote-test-port = 22
@ -1268,7 +1269,8 @@ generator-sources = \
$(src)/tools/type-generator/main.cpp \
$(src)/system/$(build-system).cpp \
$(src)/system/$(build-system)/signal.cpp \
$(src)/finder.cpp
$(src)/finder.cpp \
$(src)/util/arg-parser.cpp
ifneq ($(lzma),)
common-cflags += -I$(lzma) -DAVIAN_USE_LZMA -D_7ZIP_ST
@ -1353,6 +1355,7 @@ ifneq ($(classpath),avian)
# them to synthesize a class:
classpath-sources := \
$(classpath-src)/avian/Addendum.java \
$(classpath-src)/avian/Code.java \
$(classpath-src)/avian/AnnotationInvocationHandler.java \
$(classpath-src)/avian/Assembler.java \
$(classpath-src)/avian/Callback.java \
@ -1573,7 +1576,7 @@ gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:')
$(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep)
@echo "generating $(@)"
@mkdir -p $(dir $(@))
$(generator) $(boot-classpath) $(<) $(@) $(call gen-arg,$(@))
$(generator) -cp $(boot-classpath) -i $(<) -o $(@) -t $(call gen-arg,$(@))
$(classpath-build)/%.class: $(classpath-src)/%.java
@echo $(<)
@ -1982,7 +1985,7 @@ endif
$(generator): $(generator-objects) $(generator-lzma-objects)
@echo "linking $(@)"
$(build-ld) $(^) $(build-lflags) -o $(@)
$(build-ld-cpp) $(^) $(build-lflags) -o $(@)
$(openjdk-objects): $(build)/openjdk/%-openjdk.o: $(openjdk-src)/%.c \
$(openjdk-headers-dep)

View File

@ -11,8 +11,7 @@ struct JniConstants {
static void init(_JNIEnv* env);
};
void
JniConstants::init(_JNIEnv*)
void JniConstants::init(_JNIEnv*)
{
// ignore
}

View File

@ -33,13 +33,16 @@ class Vector {
data(0, 0),
position(0),
minimumCapacity(minimumCapacity)
{ }
{
}
~Vector() {
~Vector()
{
dispose();
}
void dispose() {
void dispose()
{
if (data.items and minimumCapacity > 0) {
allocator->free(data.items, data.count);
data.items = 0;
@ -50,7 +53,7 @@ class Vector {
void ensure(size_t space)
{
if (position + space > data.count) {
assert(a, minimumCapacity > 0);
assertT(a, minimumCapacity > 0);
size_t newCapacity = avian::util::max(
position + space, avian::util::max(minimumCapacity, data.count * 2));
@ -64,13 +67,13 @@ class Vector {
void get(size_t offset, void* dst, size_t size)
{
assert(a, offset + size <= position);
assertT(a, offset + size <= position);
memcpy(dst, data.begin() + offset, size);
}
void set(size_t offset, const void* src, size_t size)
{
assert(a, offset + size <= position);
assertT(a, offset + size <= position);
memcpy(data.begin() + offset, src, size);
}
@ -95,57 +98,67 @@ class Vector {
return r;
}
void append(uint8_t v) {
void append(uint8_t v)
{
append(&v, 1);
}
void append2(uint16_t v) {
void append2(uint16_t v)
{
append(&v, 2);
}
void append4(uint32_t v) {
void append4(uint32_t v)
{
append(&v, 4);
}
void appendTargetAddress(target_uintptr_t v) {
void appendTargetAddress(target_uintptr_t v)
{
append(&v, TargetBytesPerWord);
}
void appendAddress(uintptr_t v) {
void appendAddress(uintptr_t v)
{
append(&v, BytesPerWord);
}
void appendAddress(void* v) {
void appendAddress(void* v)
{
append(&v, BytesPerWord);
}
void set2(size_t offset, uint16_t v)
{
assert(a, offset <= position - 2);
assertT(a, offset <= position - 2);
memcpy(data.begin() + offset, &v, 2);
}
size_t get(size_t offset)
{
uint8_t v; get(offset, &v, 1);
uint8_t v;
get(offset, &v, 1);
return v;
}
size_t get2(size_t offset)
{
uint16_t v; get(offset, &v, 2);
uint16_t v;
get(offset, &v, 2);
return v;
}
size_t get4(size_t offset)
{
uint32_t v; get(offset, &v, 4);
uint32_t v;
get(offset, &v, 4);
return v;
}
uintptr_t getAddress(size_t offset)
{
uintptr_t v; get(offset, &v, BytesPerWord);
uintptr_t v;
get(offset, &v, BytesPerWord);
return v;
}
@ -157,7 +170,7 @@ class Vector {
template <class T>
T* peek(size_t offset)
{
assert(a, offset + sizeof(T) <= position);
assertT(a, offset + sizeof(T) <= position);
return reinterpret_cast<T*>(data.begin() + offset);
}

View File

@ -21,14 +21,16 @@
#include "avian/common.h"
extern "C" void NO_RETURN
vmJump(void* address, void* frame, void* stack, void* thread,
uintptr_t returnLow, uintptr_t returnHigh);
extern "C" void NO_RETURN vmJump(void* address,
void* frame,
void* stack,
void* thread,
uintptr_t returnLow,
uintptr_t returnHigh);
namespace vm {
inline void
compileTimeMemoryBarrier()
inline void compileTimeMemoryBarrier()
{
#ifdef _MSC_VER
_ReadWriteBarrier();

View File

@ -37,8 +37,7 @@
#define THREAD_STATE_THREAD(state) ((state).FIELD(r[8]))
#define THREAD_STATE_LINK(state) ((state).FIELD(lr))
# define IP_REGISTER(context) \
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
#define STACK_REGISTER(context) \
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
#define THREAD_REGISTER(context) \
@ -62,15 +61,17 @@
#define VA_LIST(x) (&(x))
extern "C" uint64_t
vmNativeCall(void* function, unsigned stackTotal, void* memoryTable,
unsigned memoryCount, void* gprTable, void* vfpTable,
extern "C" uint64_t vmNativeCall(void* function,
unsigned stackTotal,
void* memoryTable,
unsigned memoryCount,
void* gprTable,
void* vfpTable,
unsigned returnType);
namespace vm {
inline void
trap()
inline void trap()
{
#ifdef _MSC_VER
__debugbreak();
@ -86,8 +87,7 @@ trap()
// performant choice.
#ifndef _MSC_VER
inline void
memoryBarrier()
inline void memoryBarrier()
{
#ifdef __APPLE__
OSMemoryBarrier();
@ -101,8 +101,7 @@ memoryBarrier()
}
#endif
inline void
storeStoreMemoryBarrier()
inline void storeStoreMemoryBarrier()
{
#ifdef _MSC_VER
_ReadWriteBarrier();
@ -111,8 +110,7 @@ storeStoreMemoryBarrier()
#endif
}
inline void
storeLoadMemoryBarrier()
inline void storeLoadMemoryBarrier()
{
#ifdef _MSC_VER
MemoryBarrier();
@ -121,8 +119,7 @@ storeLoadMemoryBarrier()
#endif
}
inline void
loadMemoryBarrier()
inline void loadMemoryBarrier()
{
#ifdef _MSC_VER
_ReadWriteBarrier();
@ -135,18 +132,18 @@ loadMemoryBarrier()
#if defined(__ANDROID__)
// 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
inline void
syncInstructionCache(const void* start, unsigned size)
inline void syncInstructionCache(const void* start, unsigned size)
{
#ifdef __APPLE__
sys_icache_invalidate(const_cast<void*>(start), size);
#elif(defined __QNX__)
msync(const_cast<void*>(start), size, MS_INVALIDATE_ICACHE);
#else
__clear_cache
(const_cast<void*>(start),
__clear_cache(
const_cast<void*>(start),
const_cast<uint8_t*>(static_cast<const uint8_t*>(start) + size));
#endif
}
@ -158,28 +155,30 @@ typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
#define __kernel_cmpxchg (*(__kernel_cmpxchg_t*)0xffff0fc0)
#endif
inline bool
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
{
#ifdef __APPLE__
return OSAtomicCompareAndSwap32Barrier(old, new_, reinterpret_cast<int32_t*>(p));
return OSAtomicCompareAndSwap32Barrier(
old, new_, reinterpret_cast<int32_t*>(p));
#elif(defined __QNX__)
return old == _smp_cmpxchg(p, old, new_);
#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);
#endif
}
inline bool
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
{
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
}
inline uint64_t
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
unsigned argumentCount, unsigned argumentsSize UNUSED,
inline uint64_t dynamicCall(void* function,
uintptr_t* arguments,
uint8_t* argumentTypes,
unsigned argumentCount,
unsigned argumentsSize UNUSED,
unsigned returnType)
{
#ifdef __APPLE__
@ -197,7 +196,10 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
unsigned vfpIndex = 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 ai = 0;
@ -240,10 +242,8 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
#endif
case INT64_TYPE: {
if (gprIndex + Alignment <= GprCount) { // pass argument in register(s)
if (Alignment == 1
and BytesPerWord < 8
and gprIndex + Alignment == GprCount)
{
if (Alignment == 1 and BytesPerWord < 8
and gprIndex + Alignment == GprCount) {
gprTable[gprIndex++] = arguments[ai];
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1];
} else {
@ -287,10 +287,13 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
}
unsigned stackSize = stackIndex * BytesPerWord + ((stackIndex & 1) << 2);
return vmNativeCall
(function, stackSize, RUNTIME_ARRAY_BODY(stack), stackIndex * BytesPerWord,
return vmNativeCall(function,
stackSize,
RUNTIME_ARRAY_BODY(stack),
stackIndex * BytesPerWord,
(gprIndex ? gprTable : 0),
(vfpIndex ? vfpTable : 0), returnType);
(vfpIndex ? vfpTable : 0),
returnType);
}
} // namespace vm

View File

@ -24,13 +24,14 @@ class BootImage {
public:
class Thunk {
public:
Thunk():
start(0), frameSavedOffset(0), length(0)
{ }
Thunk() : start(0), frameSavedOffset(0), length(0)
{
}
Thunk(uint32_t start, uint32_t frameSavedOffset, uint32_t length):
start(start), frameSavedOffset(frameSavedOffset), length(length)
{ }
Thunk(uint32_t start, uint32_t frameSavedOffset, uint32_t length)
: start(start), frameSavedOffset(frameSavedOffset), length(length)
{
}
uint32_t start;
uint32_t frameSavedOffset;
@ -53,9 +54,11 @@ class BootImage {
ThunkCollection thunks;
} PACKED;
class GcField;
class OffsetResolver {
public:
virtual unsigned fieldOffset(Thread*, object) = 0;
virtual unsigned fieldOffset(Thread*, GcField*) = 0;
};
#define NAME(x) Target##x

View File

@ -18,24 +18,21 @@ using namespace avian::util;
namespace vm {
object
getTrace(Thread* t, unsigned skipCount)
object getTrace(Thread* t, unsigned skipCount)
{
class Visitor : public Processor::StackVisitor {
public:
Visitor(Thread* t, int skipCount):
t(t), trace(0), skipCount(skipCount)
{ }
virtual bool visit(Processor::StackWalker* walker) {
if (skipCount == 0) {
object method = walker->method();
if (isAssignableFrom
(t, type(t, Machine::ThrowableType), methodClass(t, method))
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, method), 0))
== 0)
Visitor(Thread* t, int skipCount) : t(t), trace(0), skipCount(skipCount)
{
}
virtual bool visit(Processor::StackWalker* walker)
{
if (skipCount == 0) {
GcMethod* method = walker->method();
if (isAssignableFrom(t, type(t, GcThrowable::Type), method->class_())
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
method->name()->body().begin()) == 0) {
return true;
} else {
trace = makeTrace(t, walker);
@ -54,38 +51,37 @@ getTrace(Thread* t, unsigned skipCount)
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;
}
bool
compatibleArrayTypes(Thread* t, object a, object b)
bool compatibleArrayTypes(Thread* t UNUSED, GcClass* a, GcClass* b)
{
return classArrayElementSize(t, a)
and classArrayElementSize(t, b)
and (a == b
or (not ((classVmFlags(t, a) & PrimitiveFlag)
or (classVmFlags(t, b) & PrimitiveFlag))));
return a->arrayElementSize() and b->arrayElementSize()
and (a == b or (not((a->vmFlags() & PrimitiveFlag)
or (b->vmFlags() & PrimitiveFlag))));
}
void
arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
int32_t dstOffset, int32_t length)
void arrayCopy(Thread* t,
object src,
int32_t srcOffset,
object dst,
int32_t dstOffset,
int32_t length)
{
if (LIKELY(src and dst)) {
if (LIKELY(compatibleArrayTypes
(t, objectClass(t, src), objectClass(t, dst))))
{
unsigned elementSize = classArrayElementSize(t, objectClass(t, src));
if (LIKELY(compatibleArrayTypes(
t, objectClass(t, src), objectClass(t, dst)))) {
unsigned elementSize = objectClass(t, src)->arrayElementSize();
if (LIKELY(elementSize)) {
intptr_t sl = fieldAtOffset<uintptr_t>(src, BytesPerWord);
intptr_t dl = fieldAtOffset<uintptr_t>(dst, BytesPerWord);
if (LIKELY(length > 0)) {
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
dstOffset >= 0 and dstOffset + length <= dl))
{
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl
and dstOffset >= 0 and dstOffset + length <= dl)) {
uint8_t* sbody = &fieldAtOffset<uint8_t>(src, ArrayBody);
uint8_t* dbody = &fieldAtOffset<uint8_t>(dst, ArrayBody);
if (src == dst) {
@ -98,13 +94,13 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
length * elementSize);
}
if (classObjectMask(t, objectClass(t, dst))) {
if (objectClass(t, dst)->objectMask()) {
mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length);
}
return;
} else {
throwNew(t, Machine::IndexOutOfBoundsExceptionType);
throwNew(t, GcIndexOutOfBoundsException::Type);
}
} else {
return;
@ -112,15 +108,14 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
}
}
} else {
throwNew(t, Machine::NullPointerExceptionType);
throwNew(t, GcNullPointerException::Type);
return;
}
throwNew(t, Machine::ArrayStoreExceptionType);
throwNew(t, GcArrayStoreException::Type);
}
void
runOnLoadIfFound(Thread* t, System::Library* library)
void runOnLoadIfFound(Thread* t, System::Library* library)
{
void* p = library->resolve("JNI_OnLoad");
@ -140,8 +135,7 @@ runOnLoadIfFound(Thread* t, System::Library* library)
}
}
System::Library*
loadLibrary(Thread* t, const char* name)
System::Library* loadLibrary(Thread* t, const char* name)
{
ACQUIRE(t, t->m->classLock);
@ -163,9 +157,12 @@ loadLibrary(Thread* t, const char* name)
}
}
System::Library*
loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
bool runOnLoad, bool throw_ = true)
System::Library* loadLibrary(Thread* t,
const char* path,
const char* name,
bool mapName,
bool runOnLoad,
bool throw_ = true)
{
ACQUIRE(t, t->m->classLock);
@ -177,8 +174,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
const char* s = builtins;
while (*s) {
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
if (runOnLoad and not t->m->triedBuiltinOnLoad) {
t->m->triedBuiltinOnLoad = true;
@ -188,8 +184,10 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
}
return t->m->libraries;
} else {
while (*s and *s != ',') ++ s;
if (*s) ++ s;
while (*s and *s != ',')
++s;
if (*s)
++s;
}
}
}
@ -198,8 +196,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
const char* suffix = t->m->system->librarySuffix();
unsigned mappedNameLength = nameLength + strlen(prefix) + strlen(suffix);
mappedName = static_cast<char*>
(t->m->heap->allocate(mappedNameLength + 1));
mappedName = static_cast<char*>(t->m->heap->allocate(mappedNameLength + 1));
snprintf(mappedName, mappedNameLength + 1, "%s%s%s", prefix, name, suffix);
@ -209,25 +206,28 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
mappedName = 0;
}
THREAD_RESOURCE2
(t, char*, mappedName, unsigned, nameLength, if (mappedName) {
THREAD_RESOURCE2(t, char*, mappedName, unsigned, nameLength, if (mappedName) {
t->m->heap->free(mappedName, nameLength + 1);
});
System::Library* lib = 0;
for (Tokenizer tokenizer(path, t->m->system->pathSeparator());
tokenizer.hasMore();)
{
tokenizer.hasMore();) {
String token(tokenizer.next());
unsigned fullNameLength = token.length + 1 + nameLength;
THREAD_RUNTIME_ARRAY(t, char, fullName, fullNameLength + 1);
snprintf(RUNTIME_ARRAY_BODY(fullName), fullNameLength + 1,
"%.*s/%s", token.length, token.text, name);
snprintf(RUNTIME_ARRAY_BODY(fullName),
fullNameLength + 1,
"%.*s/%s",
token.length,
token.text,
name);
lib = loadLibrary(t, RUNTIME_ARRAY_BODY(fullName));
if (lib) break;
if (lib)
break;
}
if (lib == 0) {
@ -239,108 +239,120 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
runOnLoadIfFound(t, lib);
}
} else if (throw_) {
throwNew(t, Machine::UnsatisfiedLinkErrorType,
"library not found in %s: %s", path, name);
throwNew(t,
GcUnsatisfiedLinkError::Type,
"library not found in %s: %s",
path,
name);
}
return lib;
}
object
clone(Thread* t, object o)
object clone(Thread* t, object o)
{
PROTECT(t, o);
object class_ = objectClass(t, o);
GcClass* class_ = objectClass(t, o);
unsigned size = baseSize(t, o, class_) * BytesPerWord;
object clone;
if (classArrayElementSize(t, class_)) {
clone = static_cast<object>(allocate(t, size, classObjectMask(t, class_)));
if (class_->arrayElementSize()) {
clone = static_cast<object>(allocate(t, size, class_->objectMask()));
memcpy(clone, o, size);
// clear any object header flags:
setObjectClass(t, o, objectClass(t, o));
} else if (instanceOf(t, type(t, Machine::CloneableType), o)) {
} else if (instanceOf(t, type(t, GcCloneable::Type), o)) {
clone = make(t, class_);
memcpy(reinterpret_cast<void**>(clone) + 1,
reinterpret_cast<void**>(o) + 1,
size - BytesPerWord);
} else {
object classNameSlash = className(t, objectClass(t, o));
THREAD_RUNTIME_ARRAY(t, char, classNameDot, byteArrayLength(t, classNameSlash));
replace('/', '.', RUNTIME_ARRAY_BODY(classNameDot),
reinterpret_cast<char*>(&byteArrayBody(t, classNameSlash, 0)));
throwNew(t, Machine::CloneNotSupportedExceptionType, "%s",
GcByteArray* classNameSlash = objectClass(t, o)->name();
THREAD_RUNTIME_ARRAY(t, char, classNameDot, classNameSlash->length());
replace('/',
'.',
RUNTIME_ARRAY_BODY(classNameDot),
reinterpret_cast<char*>(classNameSlash->body().begin()));
throwNew(t,
GcCloneNotSupportedException::Type,
"%s",
RUNTIME_ARRAY_BODY(classNameDot));
}
return clone;
}
object
makeStackTraceElement(Thread* t, object e)
GcStackTraceElement* makeStackTraceElement(Thread* t, GcTraceElement* e)
{
PROTECT(t, e);
object class_ = className(t, methodClass(t, traceElementMethod(t, e)));
PROTECT(t, class_);
THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, class_));
replace('/', '.', RUNTIME_ARRAY_BODY(s),
reinterpret_cast<char*>(&byteArrayBody(t, class_, 0)));
class_ = makeString(t, "%s", RUNTIME_ARRAY_BODY(s));
object method = methodName(t, traceElementMethod(t, e));
GcMethod* method = cast<GcMethod>(t, e->method());
PROTECT(t, method);
method = t->m->classpath->makeString
(t, method, 0, byteArrayLength(t, method) - 1);
GcByteArray* class_name = method->class_()->name();
PROTECT(t, class_name);
unsigned line = t->m->processor->lineNumber
(t, traceElementMethod(t, e), traceElementIp(t, e));
THREAD_RUNTIME_ARRAY(t, char, s, class_name->length());
replace('/',
'.',
RUNTIME_ARRAY_BODY(s),
reinterpret_cast<char*>(class_name->body().begin()));
GcString* class_name_string = makeString(t, "%s", RUNTIME_ARRAY_BODY(s));
PROTECT(t, class_name_string);
object file = classSourceFile(t, methodClass(t, traceElementMethod(t, e)));
file = file ? t->m->classpath->makeString
(t, file, 0, byteArrayLength(t, file) - 1) : 0;
GcByteArray* method_name = method->name();
PROTECT(t, method_name);
return makeStackTraceElement(t, class_, method, file, line);
GcString* method_name_string = t->m->classpath->makeString(
t, method_name, 0, method_name->length() - 1);
PROTECT(t, method_name_string);
unsigned line = t->m->processor->lineNumber(t, method, e->ip());
GcByteArray* file = method->class_()->sourceFile();
GcString* file_string
= file ? t->m->classpath->makeString(t, file, 0, file->length() - 1) : 0;
return makeStackTraceElement(
t, class_name_string, method_name_string, file_string, line);
}
object
translateInvokeResult(Thread* t, unsigned returnCode, object o)
GcObject* translateInvokeResult(Thread* t, unsigned returnCode, object o)
{
switch (returnCode) {
case ByteField:
return makeByte(t, intValue(t, o));
return makeByte(t, cast<GcInt>(t, o)->value());
case BooleanField:
return makeBoolean(t, intValue(t, o) != 0);
return makeBoolean(t, cast<GcInt>(t, o)->value() != 0);
case CharField:
return makeChar(t, intValue(t, o));
return makeChar(t, cast<GcInt>(t, o)->value());
case ShortField:
return makeShort(t, intValue(t, o));
return makeShort(t, cast<GcInt>(t, o)->value());
case FloatField:
return makeFloat(t, intValue(t, o));
return makeFloat(t, cast<GcInt>(t, o)->value());
case IntField:
case LongField:
case ObjectField:
case VoidField:
return o;
return reinterpret_cast<GcObject*>(o);
case DoubleField:
return makeDouble(t, longValue(t, o));
return makeDouble(t, cast<GcLong>(t, o)->value());
default:
abort(t);
}
}
object
resolveClassBySpec(Thread* t, object loader, const char* spec,
GcClass* resolveClassBySpec(Thread* t,
GcClassLoader* loader,
const char* spec,
unsigned specLength)
{
switch (*spec) {
@ -363,34 +375,41 @@ resolveClassBySpec(Thread* t, object loader, const char* spec,
}
}
object
resolveJType(Thread* t, object loader, const char* spec, unsigned specLength)
GcJclass* resolveJType(Thread* t,
GcClassLoader* loader,
const char* spec,
unsigned specLength)
{
return getJClass(t, resolveClassBySpec(t, loader, spec, specLength));
}
object
resolveParameterTypes(Thread* t, object loader, object spec,
unsigned* parameterCount, unsigned* returnTypeSpec)
GcPair* resolveParameterTypes(Thread* t,
GcClassLoader* loader,
GcByteArray* spec,
unsigned* parameterCount,
unsigned* returnTypeSpec)
{
PROTECT(t, loader);
PROTECT(t, spec);
object list = 0;
GcPair* list = 0;
PROTECT(t, list);
unsigned offset = 1;
unsigned count = 0;
while (byteArrayBody(t, spec, offset) != ')') {
switch (byteArrayBody(t, spec, offset)) {
while (spec->body()[offset] != ')') {
switch (spec->body()[offset]) {
case 'L': {
unsigned start = offset;
++offset;
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
while (spec->body()[offset] != ';')
++offset;
++offset;
object type = resolveClassBySpec
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
GcClass* type
= resolveClassBySpec(t,
loader,
reinterpret_cast<char*>(&spec->body()[start]),
offset - start);
list = makePair(t, type, list);
@ -400,11 +419,13 @@ resolveParameterTypes(Thread* t, object loader, object spec,
case '[': {
unsigned start = offset;
while (byteArrayBody(t, spec, offset) == '[') ++ offset;
switch (byteArrayBody(t, spec, offset)) {
while (spec->body()[offset] == '[')
++offset;
switch (spec->body()[offset]) {
case 'L':
++offset;
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
while (spec->body()[offset] != ';')
++offset;
++offset;
break;
@ -413,8 +434,10 @@ resolveParameterTypes(Thread* t, object loader, object spec,
break;
}
object type = resolveClassBySpec
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
GcClass* type
= resolveClassBySpec(t,
loader,
reinterpret_cast<char*>(&spec->body()[start]),
offset - start);
list = makePair(t, type, list);
@ -422,8 +445,7 @@ resolveParameterTypes(Thread* t, object loader, object spec,
} break;
default:
list = makePair
(t, primitiveClass(t, byteArrayBody(t, spec, offset)), list);
list = makePair(t, primitiveClass(t, spec->body()[offset]), list);
++offset;
++count;
break;
@ -435,102 +457,118 @@ resolveParameterTypes(Thread* t, object loader, object spec,
return list;
}
object
resolveParameterJTypes(Thread* t, object loader, object spec,
unsigned* parameterCount, unsigned* returnTypeSpec)
object resolveParameterJTypes(Thread* t,
GcClassLoader* loader,
GcByteArray* spec,
unsigned* parameterCount,
unsigned* returnTypeSpec)
{
object list = resolveParameterTypes
(t, loader, spec, parameterCount, returnTypeSpec);
GcPair* list
= resolveParameterTypes(t, loader, spec, parameterCount, returnTypeSpec);
PROTECT(t, list);
object array = makeObjectArray
(t, type(t, Machine::JclassType), *parameterCount);
object array = makeObjectArray(t, type(t, GcJclass::Type), *parameterCount);
PROTECT(t, array);
for (int i = *parameterCount - 1; i >= 0; --i) {
object c = getJClass(t, pairFirst(t, list));
set(t, array, ArrayBody + (i * BytesPerWord), c);
list = pairSecond(t, list);
object c = getJClass(t, cast<GcClass>(t, list->first()));
reinterpret_cast<GcArray*>(array)->setBodyElement(t, i, c);
list = cast<GcPair>(t, list->second());
}
return array;
}
object
resolveExceptionJTypes(Thread* t, object loader, object addendum)
object resolveExceptionJTypes(Thread* t,
GcClassLoader* loader,
GcMethodAddendum* addendum)
{
if (addendum == 0 or methodAddendumExceptionTable(t, addendum) == 0) {
return makeObjectArray(t, type(t, Machine::JclassType), 0);
if (addendum == 0 or addendum->exceptionTable() == 0) {
return makeObjectArray(t, type(t, GcJclass::Type), 0);
}
PROTECT(t, loader);
PROTECT(t, addendum);
object array = makeObjectArray
(t, type(t, Machine::JclassType),
shortArrayLength(t, methodAddendumExceptionTable(t, addendum)));
GcShortArray* exceptionTable
= cast<GcShortArray>(t, addendum->exceptionTable());
PROTECT(t, exceptionTable);
object array
= makeObjectArray(t, type(t, GcJclass::Type), exceptionTable->length());
PROTECT(t, array);
for (unsigned i = 0; i < shortArrayLength
(t, methodAddendumExceptionTable(t, addendum)); ++i)
{
uint16_t index = shortArrayBody
(t, methodAddendumExceptionTable(t, addendum), i) - 1;
for (unsigned i = 0; i < exceptionTable->length(); ++i) {
uint16_t index = exceptionTable->body()[i] - 1;
object o = singletonObject(t, addendumPool(t, addendum), index);
object o = singletonObject(t, addendum->pool()->as<GcSingleton>(t), index);
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
o = resolveClass(t, loader, referenceName(t, o));
if (objectClass(t, o) == type(t, GcReference::Type)) {
o = resolveClass(t, loader, cast<GcReference>(t, o)->name());
set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord),
o);
addendum->pool()->setBodyElement(
t, index, reinterpret_cast<uintptr_t>(o));
}
o = getJClass(t, o);
o = getJClass(t, cast<GcClass>(t, o));
set(t, array, ArrayBody + (i * BytesPerWord), o);
reinterpret_cast<GcArray*>(array)->setBodyElement(t, i, o);
}
return array;
}
object
invoke(Thread* t, object method, object instance, object args)
object invoke(Thread* t, GcMethod* method, object instance, object args)
{
PROTECT(t, method);
PROTECT(t, instance);
PROTECT(t, args);
if (methodFlags(t, method) & ACC_STATIC) {
if (method->flags() & ACC_STATIC) {
instance = 0;
}
if ((args == 0 ? 0 : objectArrayLength(t, args))
!= methodParameterCount(t, method))
{
throwNew(t, Machine::IllegalArgumentExceptionType);
!= method->parameterCount()) {
throwNew(t, GcIllegalArgumentException::Type);
}
if (methodParameterCount(t, method)) {
unsigned specLength = byteArrayLength(t, methodSpec(t, method));
if (method->parameterCount()) {
unsigned specLength = method->spec()->length();
THREAD_RUNTIME_ARRAY(t, char, spec, specLength);
memcpy(RUNTIME_ARRAY_BODY(spec),
&byteArrayBody(t, methodSpec(t, method), 0), specLength);
memcpy(
RUNTIME_ARRAY_BODY(spec), method->spec()->body().begin(), specLength);
unsigned i = 0;
for (MethodSpecIterator it(t, RUNTIME_ARRAY_BODY(spec)); it.hasNext();) {
object type;
GcClass* type;
bool objectType = false;
const char* p = it.next();
switch (*p) {
case 'Z': type = vm::type(t, Machine::BooleanType); break;
case 'B': type = vm::type(t, Machine::ByteType); break;
case 'S': type = vm::type(t, Machine::ShortType); break;
case 'C': type = vm::type(t, Machine::CharType); break;
case 'I': type = vm::type(t, Machine::IntType); break;
case 'F': type = vm::type(t, Machine::FloatType); break;
case 'J': type = vm::type(t, Machine::LongType); break;
case 'D': type = vm::type(t, Machine::DoubleType); break;
case 'Z':
type = vm::type(t, GcBoolean::Type);
break;
case 'B':
type = vm::type(t, GcByte::Type);
break;
case 'S':
type = vm::type(t, GcShort::Type);
break;
case 'C':
type = vm::type(t, GcChar::Type);
break;
case 'I':
type = vm::type(t, GcInt::Type);
break;
case 'F':
type = vm::type(t, GcFloat::Type);
break;
case 'J':
type = vm::type(t, GcLong::Type);
break;
case 'D':
type = vm::type(t, GcDouble::Type);
break;
case 'L':
case '[': {
@ -545,9 +583,8 @@ invoke(Thread* t, object method, object instance, object args)
THREAD_RUNTIME_ARRAY(t, char, name, nameLength);
memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1);
RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0;
type = resolveClass
(t, classLoader(t, methodClass(t, method)),
RUNTIME_ARRAY_BODY(name));
type = resolveClass(
t, method->class_()->loader(), RUNTIME_ARRAY_BODY(name));
} break;
default:
@ -556,26 +593,31 @@ invoke(Thread* t, object method, object instance, object args)
object arg = objectArrayBody(t, args, i++);
if ((arg == 0 and (not objectType))
or (arg and (not instanceOf(t, type, arg))))
{
// 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));
or (arg and (not instanceOf(t, type, arg)))) {
if (false) {
fprintf(stderr,
"%s is not a %s\n",
arg ? objectClass(t, arg)->name()->body().begin()
: reinterpret_cast<const int8_t*>("<null>"),
type->name()->body().begin());
}
throwNew(t, Machine::IllegalArgumentExceptionType);
throwNew(t, GcIllegalArgumentException::Type);
}
}
}
initClass(t, methodClass(t, method));
initClass(t, method->class_());
unsigned returnCode = methodReturnCode(t, method);
unsigned returnCode = method->returnCode();
THREAD_RESOURCE0(t, {
if (t->exception) {
t->exception = makeThrowable
(t, Machine::InvocationTargetExceptionType, 0, 0, t->exception);
t->exception = makeThrowable(
t, GcInvocationTargetException::Type, 0, 0, t->exception);
set(t, t->exception, InvocationTargetExceptionTarget,
throwableCause(t, t->exception));
t->exception->as<GcInvocationTargetException>(t)
->setTarget(t, t->exception->cause());
}
});
@ -591,66 +633,70 @@ invoke(Thread* t, object method, object instance, object args)
// only safe to call during bootstrap when there's only one thread
// running:
void
intercept(Thread* t, object c, const char* name, const char* spec,
void* function, bool updateRuntimeData)
void intercept(Thread* t,
GcClass* c,
const char* name,
const char* spec,
void* function,
bool updateRuntimeData)
{
object m = findMethodOrNull(t, c, name, spec);
GcMethod* m = findMethodOrNull(t, c, name, spec);
if (m) {
PROTECT(t, m);
methodFlags(t, m) |= ACC_NATIVE;
m->flags() |= ACC_NATIVE;
if (updateRuntimeData) {
object clone = methodClone(t, m);
GcMethod* clone = methodClone(t, m);
// make clone private to prevent vtable updates at compilation
// time. Otherwise, our interception might be bypassed by calls
// through the vtable.
methodFlags(t, clone) |= ACC_PRIVATE;
clone->flags() |= ACC_PRIVATE;
object native = makeNativeIntercept(t, function, true, clone);
GcNativeIntercept* native = makeNativeIntercept(t, function, true, clone);
PROTECT(t, native);
object runtimeData = getMethodRuntimeData(t, m);
GcMethodRuntimeData* runtimeData = getMethodRuntimeData(t, m);
set(t, runtimeData, MethodRuntimeDataNative, native);
runtimeData->setNative(t, native->as<GcNative>(t));
}
} else {
// If we can't find the method, just ignore it, since ProGuard may
// have stripped it out as unused. Otherwise, the code below can
// be uncommented for debugging purposes.
// be enabled for debugging purposes.
// fprintf(stderr, "unable to find %s%s in %s\n",
// name, spec, &byteArrayBody(t, className(t, c), 0));
if (false) {
fprintf(stderr,
"unable to find %s%s in %s\n",
name,
spec,
c->name()->body().begin());
// abort(t);
abort(t);
}
}
}
Finder*
getFinder(Thread* t, const char* name, unsigned nameLength)
Finder* getFinder(Thread* t, const char* name, unsigned nameLength)
{
ACQUIRE(t, t->m->referenceLock);
for (object p = root(t, Machine::VirtualFileFinders);
p; p = finderNext(t, p))
{
if (byteArrayLength(t, finderName(t, p)) == nameLength
and strncmp(reinterpret_cast<const char*>
(&byteArrayBody(t, finderName(t, p), 0)),
name, nameLength))
{
return static_cast<Finder*>(finderFinder(t, p));
for (GcFinder* p = roots(t)->virtualFileFinders(); p; p = p->next()) {
if (p->name()->length() == nameLength
and strncmp(reinterpret_cast<const char*>(p->name()->body().begin()),
name,
nameLength)) {
return static_cast<Finder*>(p->finder());
}
}
object n = makeByteArray(t, nameLength + 1);
memcpy(&byteArrayBody(t, n, 0), name, nameLength);
GcByteArray* n = makeByteArray(t, nameLength + 1);
memcpy(n->body().begin(), name, nameLength);
void* p = t->m->libraries->resolve
(reinterpret_cast<const char*>(&byteArrayBody(t, n, 0)));
void* p = t->m->libraries->resolve(
reinterpret_cast<const char*>(n->body().begin()));
if (p) {
uint8_t* (*function)(unsigned*);
@ -660,10 +706,9 @@ getFinder(Thread* t, const char* name, unsigned nameLength)
uint8_t* data = function(&size);
if (data) {
Finder* f = makeFinder(t->m->system, t->m->heap, data, size);
object finder = makeFinder
(t, f, n, root(t, Machine::VirtualFileFinders));
GcFinder* finder = makeFinder(t, f, n, roots(t)->virtualFileFinders());
setRoot(t, Machine::VirtualFileFinders, finder);
roots(t)->setVirtualFileFinders(t, finder);
return f;
}
@ -672,44 +717,39 @@ getFinder(Thread* t, const char* name, unsigned nameLength)
return 0;
}
object
getDeclaredClasses(Thread* t, object c, bool publicOnly)
object getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
{
object addendum = classAddendum(t, c);
GcClassAddendum* addendum = c->addendum();
if (addendum) {
object table = classAddendumInnerClassTable(t, addendum);
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
if (table) {
PROTECT(t, table);
unsigned count = 0;
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
object reference = arrayBody(t, table, i);
object outer = innerClassReferenceOuter(t, reference);
if (outer and byteArrayEqual(t, outer, className(t, c))
and ((not publicOnly)
or (innerClassReferenceFlags(t, reference) & ACC_PUBLIC)))
{
for (unsigned i = 0; i < table->length(); ++i) {
GcInnerClassReference* reference
= cast<GcInnerClassReference>(t, table->body()[i]);
GcByteArray* outer = reference->outer();
if (outer and byteArrayEqual(t, outer, c->name())
and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) {
++count;
}
}
object result = makeObjectArray(t, type(t, Machine::JclassType), count);
object result = makeObjectArray(t, type(t, GcJclass::Type), count);
PROTECT(t, result);
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
object reference = arrayBody(t, table, i);
object outer = innerClassReferenceOuter(t, reference);
if (outer and byteArrayEqual(t, outer, className(t, c))
and ((not publicOnly)
or (innerClassReferenceFlags(t, reference) & ACC_PUBLIC)))
{
object inner = getJClass
(t, resolveClass
(t, classLoader(t, c),
innerClassReferenceInner(t, arrayBody(t, table, i))));
for (unsigned i = 0; i < table->length(); ++i) {
GcInnerClassReference* reference
= cast<GcInnerClassReference>(t, table->body()[i]);
GcByteArray* outer = reference->outer();
if (outer and byteArrayEqual(t, outer, c->name())
and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) {
object inner
= getJClass(t, resolveClass(t, c->loader(), reference->inner()));
--count;
set(t, result, ArrayBody + (count * BytesPerWord), inner);
reinterpret_cast<GcArray*>(result)->setBodyElement(t, count, inner);
}
}
@ -717,25 +757,22 @@ getDeclaredClasses(Thread* t, object c, bool publicOnly)
}
}
return makeObjectArray(t, type(t, Machine::JclassType), 0);
return makeObjectArray(t, type(t, GcJclass::Type), 0);
}
object
getDeclaringClass(Thread* t, object c)
GcJclass* getDeclaringClass(Thread* t, GcClass* c)
{
object addendum = classAddendum(t, c);
GcClassAddendum* addendum = c->addendum();
if (addendum) {
object table = classAddendumInnerClassTable(t, addendum);
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
if (table) {
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
object reference = arrayBody(t, table, i);
if (innerClassReferenceOuter(t, reference) and strcmp
(&byteArrayBody(t, innerClassReferenceInner(t, reference), 0),
&byteArrayBody(t, className(t, c), 0)) == 0)
{
return getJClass
(t, resolveClass
(t, classLoader(t, c), innerClassReferenceOuter(t, reference)));
for (unsigned i = 0; i < table->length(); ++i) {
GcInnerClassReference* reference
= cast<GcInnerClassReference>(t, table->body()[i]);
if (reference->outer()
and strcmp(reference->inner()->body().begin(),
c->name()->body().begin()) == 0) {
return getJClass(t, resolveClass(t, c->loader(), reference->outer()));
}
}
}
@ -744,26 +781,24 @@ getDeclaringClass(Thread* t, object c)
return 0;
}
unsigned
classModifiers(Thread* t, object c)
unsigned classModifiers(Thread* t, GcClass* c)
{
object addendum = classAddendum(t, c);
GcClassAddendum* addendum = c->addendum();
if (addendum) {
object table = classAddendumInnerClassTable(t, addendum);
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
if (table) {
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
object reference = arrayBody(t, table, i);
if (0 == strcmp
(&byteArrayBody(t, className(t, c), 0),
&byteArrayBody(t, innerClassReferenceInner(t, reference), 0)))
{
return innerClassReferenceFlags(t, reference);
for (unsigned i = 0; i < table->length(); ++i) {
GcInnerClassReference* reference
= cast<GcInnerClassReference>(t, table->body()[i]);
if (0 == strcmp(c->name()->body().begin(),
reference->inner()->body().begin())) {
return reference->flags();
}
}
}
}
return classFlags(t, c);
return c->flags();
}
} // namespace vm

View File

@ -15,6 +15,8 @@
#define __STDC_CONSTANT_MACROS
#endif
#include <new>
#include "stdlib.h"
#include "stdarg.h"
#include "stddef.h"
@ -41,8 +43,8 @@
#define FP_INFINITE 1
#define FP_UNDEF 2
inline int fpclassify(double d) {
inline int fpclassify(double d)
{
switch (_fpclass(d)) {
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
@ -54,7 +56,8 @@ inline int fpclassify(double d) {
return FP_UNDEF;
}
inline int signbit(double d) {
inline int signbit(double d)
{
return _copysign(1.0, d) < 0;
}
@ -140,8 +143,8 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
#define AVIAN_EXPORT __declspec(dllexport)
#define PATH_SEPARATOR ';'
#else // not PLATFORM_WINDOWS
# define AVIAN_EXPORT __attribute__ ((visibility("default"))) \
__attribute__ ((used))
#define AVIAN_EXPORT \
__attribute__((visibility("default"))) __attribute__((used))
#define PATH_SEPARATOR ':'
#endif // not PLATFORM_WINDOWS
@ -198,8 +201,13 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
#define RESOURCE(type, name, release) \
class MAKE_NAME(Resource_) { \
public: \
MAKE_NAME(Resource_)(type name): name(name) { } \
~MAKE_NAME(Resource_)() { release; } \
MAKE_NAME(Resource_)(type name) : name(name) \
{ \
} \
~MAKE_NAME(Resource_)() \
{ \
release; \
} \
\
private: \
type name; \
@ -208,26 +216,22 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
#ifdef _MSC_VER
#pragma warning(disable : 4291)
#endif
inline void* operator new(size_t, void* p) throw() { return p; }
namespace vm {
inline intptr_alias_t&
alias(void* p, unsigned offset)
inline intptr_alias_t& alias(void* p, unsigned offset)
{
return *reinterpret_cast<intptr_alias_t*>(static_cast<uint8_t*>(p) + offset);
}
#ifdef _MSC_VER
inline int
vsnprintf(char* dst, size_t size, const char* format, va_list a)
inline int vsnprintf(char* dst, size_t size, const char* format, va_list a)
{
return vsnprintf_s(dst, size, _TRUNCATE, format, a);
}
inline int
snprintf(char* dst, size_t size, const char* format, ...)
inline int snprintf(char* dst, size_t size, const char* format, ...)
{
va_list a;
va_start(a, format);
@ -236,8 +240,7 @@ snprintf(char* dst, size_t size, const char* format, ...)
return r;
}
inline FILE*
fopen(const char* name, const char* mode)
inline FILE* fopen(const char* name, const char* mode)
{
FILE* file;
if (fopen_s(&file, name, mode) == 0) {
@ -249,14 +252,12 @@ fopen(const char* name, const char* mode)
#else // not _MSC_VER
inline int
vsnprintf(char* dst, size_t size, const char* format, va_list a)
inline int vsnprintf(char* dst, size_t size, const char* format, va_list a)
{
return ::vsnprintf(dst, size, format, a);
}
inline int
snprintf(char* dst, size_t size, const char* format, ...)
inline int snprintf(char* dst, size_t size, const char* format, ...)
{
va_list a;
va_start(a, format);
@ -265,8 +266,7 @@ snprintf(char* dst, size_t size, const char* format, ...)
return r;
}
inline FILE*
fopen(const char* name, const char* mode)
inline FILE* fopen(const char* name, const char* mode)
{
return ::fopen(name, mode);
}
@ -276,102 +276,92 @@ fopen(const char* name, const char* mode)
const unsigned BytesPerWord = sizeof(uintptr_t);
const unsigned BitsPerWord = BytesPerWord * 8;
const uintptr_t PointerMask
= ((~static_cast<uintptr_t>(0)) / BytesPerWord) * BytesPerWord;
const uintptr_t PointerMask = ((~static_cast<uintptr_t>(0)) / BytesPerWord)
* BytesPerWord;
const unsigned LikelyPageSizeInBytes = 4 * 1024;
inline unsigned
pad(unsigned n, unsigned alignment)
inline unsigned pad(unsigned n, unsigned alignment)
{
return (n + (alignment - 1)) & ~(alignment - 1);
}
inline unsigned
pad(unsigned n)
inline unsigned pad(unsigned n)
{
return pad(n, BytesPerWord);
}
inline uintptr_t
padWord(uintptr_t n, uintptr_t alignment)
inline uintptr_t padWord(uintptr_t n, uintptr_t alignment)
{
return (n + (alignment - 1)) & ~(alignment - 1);
}
inline uintptr_t
padWord(uintptr_t n)
inline uintptr_t padWord(uintptr_t n)
{
return padWord(n, BytesPerWord);
}
inline bool fitsInInt8(int64_t v) {
inline bool fitsInInt8(int64_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);
}
inline bool fitsInInt32(int64_t v) {
inline bool fitsInInt32(int64_t v)
{
return v == static_cast<int32_t>(v);
}
template <class T>
inline unsigned
wordOf(unsigned i)
inline unsigned wordOf(unsigned i)
{
return i / (sizeof(T) * 8);
}
inline unsigned
wordOf(unsigned i)
inline unsigned wordOf(unsigned i)
{
return wordOf<uintptr_t>(i);
}
template <class T>
inline unsigned
bitOf(unsigned i)
inline unsigned bitOf(unsigned i)
{
return i % (sizeof(T) * 8);
}
inline unsigned
bitOf(unsigned i)
inline unsigned bitOf(unsigned i)
{
return bitOf<uintptr_t>(i);
}
template <class T>
inline unsigned
indexOf(unsigned word, unsigned bit)
inline unsigned indexOf(unsigned word, unsigned bit)
{
return (word * (sizeof(T) * 8)) + bit;
}
inline unsigned
indexOf(unsigned word, unsigned bit)
inline unsigned indexOf(unsigned word, unsigned bit)
{
return indexOf<uintptr_t>(word, bit);
}
template <class T>
inline void
markBit(T* map, unsigned i)
inline void markBit(T* map, unsigned i)
{
map[wordOf<T>(i)] |= static_cast<T>(1) << bitOf<T>(i);
}
template <class T>
inline void
clearBit(T* map, unsigned i)
inline void clearBit(T* map, unsigned i)
{
map[wordOf<T>(i)] &= ~(static_cast<T>(1) << bitOf<T>(i));
}
template <class T>
inline unsigned
getBit(T* map, unsigned i)
inline unsigned getBit(T* map, unsigned i)
{
return (map[wordOf<T>(i)] & (static_cast<T>(1) << bitOf<T>(i)))
>> bitOf<T>(i);
@ -382,8 +372,7 @@ getBit(T* map, unsigned i)
// a time:
template <class T>
inline void
clearBits(T* map, unsigned bitsPerRecord, unsigned index)
inline void clearBits(T* map, unsigned bitsPerRecord, unsigned index)
{
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
clearBit<T>(map, i);
@ -391,18 +380,19 @@ clearBits(T* map, unsigned bitsPerRecord, unsigned index)
}
template <class T>
inline void
setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
inline void setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
{
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;
}
}
template <class T>
inline unsigned
getBits(T* map, unsigned bitsPerRecord, unsigned index)
inline unsigned getBits(T* map, unsigned bitsPerRecord, unsigned index)
{
unsigned v = 0;
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
@ -413,112 +403,71 @@ getBits(T* map, unsigned bitsPerRecord, unsigned index)
}
template <class T>
inline T&
fieldAtOffset(void* p, unsigned offset)
inline T& fieldAtOffset(void* p, unsigned offset)
{
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
}
template <class T>
inline T*
maskAlignedPointer(T* p)
inline T* maskAlignedPointer(T* p)
{
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
}
inline uint32_t
hash(const char* s)
{
uint32_t h = 0;
for (unsigned i = 0; s[i]; ++i) {
h = (h * 31) + s[i];
}
return h;
}
inline uint32_t
hash(const uint8_t* s, unsigned length)
{
uint32_t h = 0;
for (unsigned i = 0; i < length; ++i) {
h = (h * 31) + s[i];
}
return h;
}
inline uint32_t
hash(const int8_t* s, unsigned length)
{
return hash(reinterpret_cast<const uint8_t*>(s), length);
}
inline uint32_t
hash(const uint16_t* s, unsigned length)
{
uint32_t h = 0;
for (unsigned i = 0; i < length; ++i) {
h = (h * 31) + s[i];
}
return h;
}
inline void
write4(uint8_t* dst, uint32_t v)
inline void write4(uint8_t* dst, uint32_t v)
{
memcpy(dst, &v, 4);
}
inline uint32_t
floatToBits(float f)
inline uint32_t floatToBits(float f)
{
uint32_t bits; memcpy(&bits, &f, 4);
uint32_t bits;
memcpy(&bits, &f, 4);
return bits;
}
inline uint64_t
doubleToBits(double d)
inline uint64_t doubleToBits(double d)
{
uint64_t bits; memcpy(&bits, &d, 8);
uint64_t bits;
memcpy(&bits, &d, 8);
return bits;
}
inline double
bitsToDouble(uint64_t bits)
inline double bitsToDouble(uint64_t bits)
{
double d; memcpy(&d, &bits, 8);
double d;
memcpy(&d, &bits, 8);
return d;
}
inline float
bitsToFloat(uint32_t bits)
inline float bitsToFloat(uint32_t bits)
{
float f; memcpy(&f, &bits, 4);
float f;
memcpy(&f, &bits, 4);
return f;
}
inline int
difference(void* a, void* b)
inline int difference(void* a, void* b)
{
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
}
template <class T>
inline void*
voidPointer(T function)
inline void* voidPointer(T function)
{
void* p;
memcpy(&p, &function, sizeof(void*));
return p;
}
inline void
replace(char a, char b, char* c)
inline void 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
replace(char a, char b, char* dst, const char* src)
inline void replace(char a, char b, char* dst, const char* src)
{
unsigned i = 0;
for (; src[i]; ++i) {
@ -527,8 +476,7 @@ replace(char a, char b, char* dst, const char* src)
dst[i] = 0;
}
inline bool
equal(const void* a, unsigned al, const void* b, unsigned bl)
inline bool equal(const void* a, unsigned al, const void* b, unsigned bl)
{
if (al == bl) {
return memcmp(a, b, al) == 0;

View File

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

View File

@ -30,96 +30,113 @@ const unsigned EntrySignature = 0x02014b50;
const unsigned CentralDirectorySearchStart = 22;
inline uint16_t get2(const uint8_t* p) {
return
(static_cast<uint16_t>(p[1]) << 8) |
(static_cast<uint16_t>(p[0]) );
inline uint16_t get2(const uint8_t* p)
{
return (static_cast<uint16_t>(p[1]) << 8) | (static_cast<uint16_t>(p[0]));
}
inline uint32_t get4(const uint8_t* p) {
return
(static_cast<uint32_t>(p[3]) << 24) |
(static_cast<uint32_t>(p[2]) << 16) |
(static_cast<uint32_t>(p[1]) << 8) |
(static_cast<uint32_t>(p[0]) );
inline uint32_t get4(const uint8_t* p)
{
return (static_cast<uint32_t>(p[3]) << 24)
| (static_cast<uint32_t>(p[2]) << 16)
| (static_cast<uint32_t>(p[1]) << 8) | (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);
}
inline uint16_t compressionMethod(const uint8_t* centralHeader) {
inline uint16_t compressionMethod(const uint8_t* centralHeader)
{
return get2(centralHeader + 10);
}
inline uint32_t fileTime(const uint8_t* centralHeader) {
inline uint32_t fileTime(const uint8_t* centralHeader)
{
return get4(centralHeader + 12);
}
inline uint32_t fileCRC(const uint8_t* centralHeader) {
inline uint32_t fileCRC(const uint8_t* centralHeader)
{
return get4(centralHeader + 16);
}
inline uint32_t compressedSize(const uint8_t* centralHeader) {
inline uint32_t compressedSize(const uint8_t* centralHeader)
{
return get4(centralHeader + 20);
}
inline uint32_t uncompressedSize(const uint8_t* centralHeader) {
inline uint32_t uncompressedSize(const uint8_t* centralHeader)
{
return get4(centralHeader + 24);
}
inline uint16_t fileNameLength(const uint8_t* centralHeader) {
inline uint16_t fileNameLength(const uint8_t* centralHeader)
{
return get2(centralHeader + 28);
}
inline uint16_t extraFieldLength(const uint8_t* centralHeader) {
inline uint16_t extraFieldLength(const uint8_t* centralHeader)
{
return get2(centralHeader + 30);
}
inline uint16_t commentFieldLength(const uint8_t* centralHeader) {
inline uint16_t commentFieldLength(const uint8_t* centralHeader)
{
return get2(centralHeader + 32);
}
inline uint32_t localHeaderOffset(const uint8_t* centralHeader) {
inline uint32_t localHeaderOffset(const uint8_t* centralHeader)
{
return get4(centralHeader + 42);
}
inline uint16_t localFileNameLength(const uint8_t* localHeader) {
inline uint16_t localFileNameLength(const uint8_t* localHeader)
{
return get2(localHeader + 26);
}
inline uint16_t localExtraFieldLength(const uint8_t* localHeader) {
inline uint16_t localExtraFieldLength(const uint8_t* localHeader)
{
return get2(localHeader + 28);
}
inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader) {
inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader)
{
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;
}
inline const uint8_t* fileData(const uint8_t* localHeader) {
return localHeader + LocalHeaderSize + localFileNameLength(localHeader) +
localExtraFieldLength(localHeader);
inline const uint8_t* fileData(const uint8_t* localHeader)
{
return localHeader + LocalHeaderSize + localFileNameLength(localHeader)
+ localExtraFieldLength(localHeader);
}
inline const uint8_t* endOfEntry(const uint8_t* p) {
return p + HeaderSize + fileNameLength(p) + extraFieldLength(p) +
commentFieldLength(p);
inline const uint8_t* endOfEntry(const uint8_t* p)
{
return p + HeaderSize + fileNameLength(p) + extraFieldLength(p)
+ commentFieldLength(p);
}
inline bool
readLine(const uint8_t* base, unsigned total, unsigned* start,
inline bool readLine(const uint8_t* base,
unsigned total,
unsigned* start,
unsigned* length)
{
const uint8_t* p = base + *start;
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;
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;
@ -136,22 +153,26 @@ class Finder {
class Iterator {
public:
Iterator(Finder* finder):
it(finder->iterator()),
current(it->next(&currentSize))
{ }
Iterator(Finder* finder)
: it(finder->iterator()), current(it->next(&currentSize))
{
}
~Iterator() {
~Iterator()
{
it->dispose();
}
bool hasMore() {
if (current) return true;
bool hasMore()
{
if (current)
return true;
current = it->next(&currentSize);
return current != 0;
}
const char* next(unsigned* size) {
const char* next(unsigned* size)
{
if (hasMore()) {
*size = currentSize;
const char* v = current;
@ -173,7 +194,8 @@ class Finder {
unsigned* length,
bool tryDirectory = false) = 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* path() = 0;
virtual void dispose() = 0;

View File

@ -29,8 +29,8 @@ class HeapVisitor {
virtual void root() = 0;
virtual unsigned visitNew(object value) = 0;
virtual void visitOld(object value, unsigned number) = 0;
virtual void push(object parent, unsigned parentNumber,
unsigned childOffset) = 0;
virtual void push(object parent, unsigned parentNumber, unsigned childOffset)
= 0;
virtual void pop() = 0;
};
@ -42,8 +42,7 @@ class HeapWalker {
virtual void dispose() = 0;
};
HeapWalker*
makeHeapWalker(Thread* t, HeapVisitor* v);
HeapWalker* makeHeapWalker(Thread* t, HeapVisitor* v);
} // namespace vm

View File

@ -16,9 +16,10 @@ namespace vm {
class Machine;
class Thread;
struct Object { };
class GcObject;
;
typedef Object* object;
typedef GcObject* object;
typedef uint8_t jboolean;
typedef int8_t jbyte;
@ -33,21 +34,34 @@ typedef jint jsize;
typedef object* jobject;
typedef jobject jclass;
typedef jobject jthrowable;
typedef jobject jstring;
class GcString;
class GcJclass;
class GcThrowable;
class GcBooleanArray;
class GcByteArray;
class GcCharArray;
class GcShortArray;
class GcIntArray;
class GcLongArray;
class GcFloatArray;
class GcDoubleArray;
class GcObjectArray;
typedef GcJclass** jclass;
typedef GcThrowable** jthrowable;
typedef GcString** jstring;
typedef jobject jweak;
typedef jobject jarray;
typedef jarray jbooleanArray;
typedef jarray jbyteArray;
typedef jarray jcharArray;
typedef jarray jshortArray;
typedef jarray jintArray;
typedef jarray jlongArray;
typedef jarray jfloatArray;
typedef jarray jdoubleArray;
typedef jarray jobjectArray;
typedef GcBooleanArray** jbooleanArray;
typedef GcByteArray** jbyteArray;
typedef GcCharArray** jcharArray;
typedef GcShortArray** jshortArray;
typedef GcIntArray** jintArray;
typedef GcLongArray** jlongArray;
typedef GcFloatArray** jfloatArray;
typedef GcDoubleArray** jdoubleArray;
typedef GcObjectArray** jobjectArray;
typedef uintptr_t jfieldID;
typedef uintptr_t jmethodID;

View File

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

View File

@ -22,7 +22,8 @@ const unsigned Padding = 16;
class LzmaAllocator {
public:
LzmaAllocator(avian::util::Allocator* a): a(a) {
LzmaAllocator(avian::util::Allocator* a) : a(a)
{
allocator.Alloc = allocate;
allocator.Free = free;
}
@ -30,15 +31,17 @@ class LzmaAllocator {
ISzAlloc allocator;
avian::util::Allocator* a;
static void* allocate(void* allocator, size_t size) {
uint8_t* p = static_cast<uint8_t*>
(static_cast<LzmaAllocator*>(allocator)->a->allocate(size + Padding));
static void* allocate(void* allocator, size_t size)
{
uint8_t* p = static_cast<uint8_t*>(
static_cast<LzmaAllocator*>(allocator)->a->allocate(size + Padding));
int32_t size32 = size;
memcpy(p, &size32, 4);
return p + Padding;
}
static void free(void* allocator, void* address) {
static void free(void* allocator, void* address)
{
if (address) {
void* p = static_cast<uint8_t*>(address) - Padding;
int32_t size32;

File diff suppressed because it is too large Load Diff

View File

@ -18,28 +18,25 @@
namespace vm {
inline int16_t
codeReadInt16(Thread* t, object code, unsigned& ip)
inline int16_t codeReadInt16(Thread* t UNUSED, GcCode* code, unsigned& ip)
{
uint8_t v1 = codeBody(t, code, ip++);
uint8_t v2 = codeBody(t, code, ip++);
uint8_t v1 = code->body()[ip++];
uint8_t v2 = code->body()[ip++];
return ((v1 << 8) | v2);
}
inline int32_t
codeReadInt32(Thread* t, object code, unsigned& ip)
inline int32_t codeReadInt32(Thread* t UNUSED, GcCode* code, unsigned& ip)
{
uint8_t v1 = codeBody(t, code, ip++);
uint8_t v2 = codeBody(t, code, ip++);
uint8_t v3 = codeBody(t, code, ip++);
uint8_t v4 = codeBody(t, code, ip++);
uint8_t v1 = code->body()[ip++];
uint8_t v2 = code->body()[ip++];
uint8_t v3 = code->body()[ip++];
uint8_t v4 = code->body()[ip++];
return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4);
}
inline bool
isSuperclass(Thread* t, object class_, object base)
inline bool isSuperclass(Thread* t UNUSED, GcClass* class_, GcClass* base)
{
for (object oc = classSuper(t, base); oc; oc = classSuper(t, oc)) {
for (GcClass* oc = base->super(); oc; oc = oc->super()) {
if (oc == class_) {
return true;
}
@ -47,20 +44,17 @@ isSuperclass(Thread* t, object class_, object base)
return false;
}
inline bool
isSpecialMethod(Thread* t, object method, object class_)
inline bool isSpecialMethod(Thread* t, GcMethod* method, GcClass* class_)
{
return (classFlags(t, class_) & ACC_SUPER)
return (class_->flags() & ACC_SUPER)
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, method), 0)) != 0
and isSuperclass(t, methodClass(t, method), class_);
method->name()->body().begin()) != 0
and isSuperclass(t, method->class_(), class_);
}
void
resolveNative(Thread* t, object method);
void resolveNative(Thread* t, GcMethod* method);
int
findLineNumber(Thread* t, object method, unsigned ip);
int findLineNumber(Thread* t, GcMethod* method, unsigned ip);
} // namespace vm

View File

@ -32,6 +32,21 @@ class Slice;
namespace vm {
class GcByteArray;
class GcCode;
class GcClass;
class GcMethod;
class GcMethodAddendum;
class GcIntArray;
class GcContinuation;
class GcThrowable;
class GcThread;
class GcClassAddendum;
class GcClassLoader;
class GcArray;
class GcSingleton;
class GcTriple;
class Processor {
public:
class StackWalker;
@ -45,7 +60,7 @@ class Processor {
public:
virtual void walk(StackVisitor* v) = 0;
virtual object method() = 0;
virtual GcMethod* method() = 0;
virtual int ip() = 0;
@ -54,139 +69,136 @@ class Processor {
class CompilationHandler {
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 Thread*
makeThread(Machine* m, object javaThread, Thread* parent) = 0;
virtual Thread* makeThread(Machine* m, GcThread* javaThread, Thread* parent)
= 0;
virtual object
makeMethod(Thread* t,
virtual GcMethod* makeMethod(Thread* t,
uint8_t vmFlags,
uint8_t returnCode,
uint8_t parameterCount,
uint8_t parameterFootprint,
uint16_t flags,
uint16_t offset,
object name,
object spec,
object addendum,
object class_,
object code) = 0;
GcByteArray* name,
GcByteArray* spec,
GcMethodAddendum* addendum,
GcClass* class_,
GcCode* code) = 0;
virtual object
makeClass(Thread* t,
virtual GcClass* makeClass(Thread* t,
uint16_t flags,
uint16_t vmFlags,
uint16_t fixedSize,
uint8_t arrayElementSize,
uint8_t arrayDimensions,
object objectMask,
object name,
object sourceFile,
object super,
GcClass* arrayElementClass,
GcIntArray* objectMask,
GcByteArray* name,
GcByteArray* sourceFile,
GcClass* super,
object interfaceTable,
object virtualTable,
object fieldTable,
object methodTable,
object addendum,
object staticTable,
object loader,
GcClassAddendum* addendum,
GcSingleton* staticTable,
GcClassLoader* loader,
unsigned vtableLength) = 0;
virtual void
initVtable(Thread* t, object c) = 0;
virtual void initVtable(Thread* t, GcClass* c) = 0;
virtual void
visitObjects(Thread* t, Heap::Visitor* v) = 0;
virtual void visitObjects(Thread* t, Heap::Visitor* v) = 0;
virtual void
walkStack(Thread* t, StackVisitor* v) = 0;
virtual void walkStack(Thread* t, StackVisitor* v) = 0;
virtual int
lineNumber(Thread* t, object method, int ip) = 0;
virtual int lineNumber(Thread* t, GcMethod* method, int ip) = 0;
virtual object*
makeLocalReference(Thread* t, object o) = 0;
virtual object* makeLocalReference(Thread* t, object o) = 0;
virtual void
disposeLocalReference(Thread* t, object* r) = 0;
virtual void disposeLocalReference(Thread* t, object* r) = 0;
virtual bool
pushLocalFrame(Thread* t, unsigned capacity) = 0;
virtual bool pushLocalFrame(Thread* t, unsigned capacity) = 0;
virtual void
popLocalFrame(Thread* t) = 0;
virtual void popLocalFrame(Thread* t) = 0;
virtual object
invokeArray(Thread* t, object method, object this_, object arguments) = 0;
virtual object invokeArray(Thread* t,
GcMethod* method,
object this_,
object arguments) = 0;
virtual object
invokeArray(Thread* t, object method, object this_, const jvalue* arguments)
= 0;
virtual object invokeArray(Thread* t,
GcMethod* method,
object this_,
const jvalue* arguments) = 0;
virtual object
invokeList(Thread* t, object method, object this_, bool indirectObjects,
virtual object invokeList(Thread* t,
GcMethod* method,
object this_,
bool indirectObjects,
va_list arguments) = 0;
virtual object
invokeList(Thread* t, object loader, const char* className,
const char* methodName, const char* methodSpec,
object this_, va_list arguments) = 0;
virtual object invokeList(Thread* t,
GcClassLoader* loader,
const char* className,
const char* methodName,
const char* methodSpec,
object this_,
va_list arguments) = 0;
virtual void
dispose(Thread* t) = 0;
virtual void dispose(Thread* t) = 0;
virtual void
dispose() = 0;
virtual void dispose() = 0;
virtual object
getStackTrace(Thread* t, Thread* target) = 0;
virtual object getStackTrace(Thread* t, Thread* target) = 0;
virtual void initialize(BootImage* image, avian::util::Slice<uint8_t> code)
= 0;
virtual void
addCompilationHandler(CompilationHandler* handler) = 0;
virtual void addCompilationHandler(CompilationHandler* handler) = 0;
virtual void
compileMethod(Thread* t, Zone* zone, object* constants, object* calls,
avian::codegen::DelayedPromise** addresses, object method,
virtual void compileMethod(Thread* t,
Zone* zone,
GcTriple** constants,
GcTriple** calls,
avian::codegen::DelayedPromise** addresses,
GcMethod* method,
OffsetResolver* resolver) = 0;
virtual void
visitRoots(Thread* t, HeapWalker* w) = 0;
virtual void visitRoots(Thread* t, HeapWalker* w) = 0;
virtual void
normalizeVirtualThunks(Thread* t) = 0;
virtual void normalizeVirtualThunks(Thread* t) = 0;
virtual unsigned*
makeCallTable(Thread* t, HeapWalker* w) = 0;
virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) = 0;
virtual void
boot(Thread* t, BootImage* image, uint8_t* code) = 0;
virtual void boot(Thread* t, BootImage* image, uint8_t* code) = 0;
virtual void
callWithCurrentContinuation(Thread* t, object receiver) = 0;
virtual void callWithCurrentContinuation(Thread* t, object receiver) = 0;
virtual void
dynamicWind(Thread* t, object before, object thunk, object after) = 0;
virtual void
feedResultToContinuation(Thread* t, object continuation, object result) = 0;
virtual void
feedExceptionToContinuation(Thread* t, object continuation,
object exception) = 0;
virtual void
walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start)
virtual void dynamicWind(Thread* t, object before, object thunk, object after)
= 0;
object
invoke(Thread* t, object method, object this_, ...)
virtual void feedResultToContinuation(Thread* t,
GcContinuation* continuation,
object result) = 0;
virtual void feedExceptionToContinuation(Thread* t,
GcContinuation* continuation,
GcThrowable* exception) = 0;
virtual void walkContinuationBody(Thread* t,
Heap::Walker* w,
object o,
unsigned start) = 0;
object invoke(Thread* t, GcMethod* method, object this_, ...)
{
va_list a;
va_start(a, this_);
@ -198,15 +210,19 @@ class Processor {
return r;
}
object
invoke(Thread* t, object loader, const char* className,
const char* methodName, const char* methodSpec, object this_, ...)
object invoke(Thread* t,
GcClassLoader* loader,
const char* className,
const char* methodName,
const char* methodSpec,
object this_,
...)
{
va_list a;
va_start(a, this_);
object r = invokeList
(t, loader, className, methodName, methodSpec, this_, a);
object r
= invokeList(t, loader, className, methodName, methodSpec, this_, a);
va_end(a);

View File

@ -11,7 +11,6 @@
#ifndef AVIAN_TARGET_FIELDS_H
#define AVIAN_TARGET_FIELDS_H
#ifdef TARGET_BYTES_PER_WORD
#if (TARGET_BYTES_PER_WORD == 8)
@ -61,4 +60,3 @@
#endif
#endif

View File

@ -17,85 +17,72 @@
namespace vm {
template <class T>
inline T
targetV1(T v)
inline T targetV1(T v)
{
return v;
}
template <class T>
inline T
swapV2(T v)
inline T swapV2(T v)
{
return (((v >> 8) & 0xFF) |
((v << 8)));
return (((v >> 8) & 0xFF) | ((v << 8)));
}
template <class T>
inline T
swapV4(T v)
inline T swapV4(T v)
{
return (((v >> 24) & 0x000000FF) |
((v >> 8) & 0x0000FF00) |
((v << 8) & 0x00FF0000) |
((v << 24)));
return (((v >> 24) & 0x000000FF) | ((v >> 8) & 0x0000FF00)
| ((v << 8) & 0x00FF0000) | ((v << 24)));
}
template <class T>
inline T
swapV8(T v)
inline T swapV8(T v)
{
return (((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) |
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) |
((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(0x000000FF00000000)) |
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) |
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) |
((static_cast<uint64_t>(v) << 56)));
return (((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF))
| ((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00))
| ((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(0x000000FF00000000))
| ((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000))
| ((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000))
| ((static_cast<uint64_t>(v) << 56)));
}
#ifdef TARGET_OPPOSITE_ENDIAN
template <class T>
inline T
targetV2(T v)
inline T targetV2(T v)
{
return swapV2(v);
}
template <class T>
inline T
targetV4(T v)
inline T targetV4(T v)
{
return swapV4(v);
}
template <class T>
inline T
targetV8(T v)
inline T targetV8(T v)
{
return swapV8(v);
}
#else
template <class T>
inline T
targetV2(T v)
inline T targetV2(T v)
{
return v;
}
template <class T>
inline T
targetV4(T v)
inline T targetV4(T v)
{
return v;
}
template <class T>
inline T
targetV8(T v)
inline T targetV8(T v)
{
return v;
}
@ -105,8 +92,7 @@ targetV8(T v)
#if (TARGET_BYTES_PER_WORD == 8)
template <class T>
inline T
targetVW(T v)
inline T targetVW(T v)
{
return targetV8(v);
}
@ -116,15 +102,14 @@ typedef int64_t target_intptr_t;
const unsigned TargetClassFixedSize = 12;
const unsigned TargetClassArrayElementSize = 14;
const unsigned TargetClassVtable = 128;
const unsigned TargetClassVtable = 136;
const unsigned TargetFieldOffset = 12;
#elif(TARGET_BYTES_PER_WORD == 4)
template <class T>
inline T
targetVW(T v)
inline T targetVW(T v)
{
return targetV4(v);
}
@ -134,7 +119,7 @@ typedef int32_t target_intptr_t;
const unsigned TargetClassFixedSize = 8;
const unsigned TargetClassArrayElementSize = 10;
const unsigned TargetClassVtable = 68;
const unsigned TargetClassVtable = 72;
const unsigned TargetFieldOffset = 8;
@ -156,11 +141,10 @@ const target_uintptr_t TargetPointerMask
const unsigned TargetArrayLength = TargetBytesPerWord;
const unsigned TargetArrayBody = TargetBytesPerWord * 2;
inline void
targetMarkBit(target_uintptr_t* map, unsigned i)
inline void targetMarkBit(target_uintptr_t* map, unsigned i)
{
map[wordOf<target_uintptr_t>(i)] |=
targetVW(static_cast<target_uintptr_t>(1) << bitOf<target_uintptr_t>(i));
map[wordOf<target_uintptr_t>(i)] |= targetVW(static_cast<target_uintptr_t>(1)
<< bitOf<target_uintptr_t>(i));
}
} // namespace vm

View File

@ -16,49 +16,58 @@
namespace vm {
object
hashMapFindNode(Thread* t, object map, object key,
GcTriple* hashMapFindNode(Thread* t,
GcHashMap* map,
object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object));
inline object
hashMapFind(Thread* t, object map, object key,
inline object hashMapFind(Thread* t,
GcHashMap* map,
object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
return (n ? tripleSecond(t, n) : 0);
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
return (n ? n->second() : 0);
}
void
hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
void hashMapResize(Thread* t,
GcHashMap* map,
uint32_t (*hash)(Thread*, object),
unsigned size);
void
hashMapInsert(Thread* t, object map, object key, object value,
void hashMapInsert(Thread* t,
GcHashMap* map,
object key,
object value,
uint32_t (*hash)(Thread*, object));
inline bool
hashMapInsertOrReplace(Thread* t, object map, object key, object value,
inline bool hashMapInsertOrReplace(Thread* t,
GcHashMap* map,
object key,
object value,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
if (n == 0) {
hashMapInsert(t, map, key, value, hash);
return true;
} else {
set(t, n, TripleSecond, value);
n->setSecond(t, value);
return false;
}
}
inline bool
hashMapInsertMaybe(Thread* t, object map, object key, object value,
inline bool hashMapInsertMaybe(Thread* t,
GcHashMap* map,
object key,
object value,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
if (n == 0) {
hashMapInsert(t, map, key, value, hash);
return true;
@ -67,53 +76,58 @@ hashMapInsertMaybe(Thread* t, object map, object key, object value,
}
}
object
hashMapRemove(Thread* t, object map, object key,
object hashMapRemove(Thread* t,
GcHashMap* map,
object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object));
object
hashMapIterator(Thread* t, object map);
object hashMapIterator(Thread* t, GcHashMap* map);
object
hashMapIteratorNext(Thread* t, object it);
object hashMapIteratorNext(Thread* t, object it);
void
listAppend(Thread* t, object list, object value);
void listAppend(Thread* t, GcList* list, object value);
object
vectorAppend(Thread* t, object vector, object value);
GcVector* vectorAppend(Thread* t, GcVector* vector, object value);
object
growArray(Thread* t, object array);
object growArray(Thread* t, object array);
object
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
object treeQuery(Thread* t,
GcTreeNode* tree,
intptr_t key,
GcTreeNode* sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b));
object
treeInsert(Thread* t, Zone* zone, object tree, intptr_t key, object value,
object sentinal,
GcTreeNode* treeInsert(Thread* t,
Zone* zone,
GcTreeNode* tree,
intptr_t key,
object value,
GcTreeNode* sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b));
void
treeUpdate(Thread* t, object tree, intptr_t key, object value, object sentinal,
void treeUpdate(Thread* t,
GcTreeNode* tree,
intptr_t key,
object value,
GcTreeNode* sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b));
class HashMapIterator : public Thread::Protector {
public:
HashMapIterator(Thread* t, object map):
Protector(t), map(map), node(0), index(0)
HashMapIterator(Thread* t, GcHashMap* map)
: Protector(t), map(map), node(0), index(0)
{
find();
}
void find() {
object array = hashMapArray(t, map);
void find()
{
GcArray* array = map->array();
if (array) {
for (unsigned i = index; i < arrayLength(t, array); ++i) {
if (arrayBody(t, array, i)) {
node = arrayBody(t, array, i);
for (unsigned i = index; i < array->length(); ++i) {
if (array->body()[i]) {
node = cast<GcTriple>(t, array->body()[i]);
index = i + 1;
return;
}
@ -122,15 +136,17 @@ class HashMapIterator: public Thread::Protector {
node = 0;
}
bool hasMore() {
bool hasMore()
{
return node != 0;
}
object next() {
GcTriple* next()
{
if (node) {
object n = node;
if (tripleThird(t, node)) {
node = tripleThird(t, node);
GcTriple* n = node;
if (node->third()) {
node = cast<GcTriple>(t, node->third());
} else {
find();
}
@ -140,13 +156,14 @@ class HashMapIterator: public Thread::Protector {
}
}
virtual void visit(Heap::Visitor* v) {
virtual void visit(Heap::Visitor* v)
{
v->visit(&map);
v->visit(&node);
}
object map;
object node;
GcHashMap* map;
GcTriple* node;
unsigned index;
};

View File

@ -53,8 +53,7 @@
#define THREAD_STATE_LINK(state) ((state).FIELD(ecx))
#define THREAD_STATE_FRAME(state) ((state).FIELD(ebp))
# define IP_REGISTER(context) \
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
#define STACK_REGISTER(context) \
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
#define THREAD_REGISTER(context) \
@ -84,15 +83,19 @@
#define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
#endif
extern "C" uint64_t
vmNativeCall(void* function, void* stack, unsigned stackSize,
extern "C" uint64_t vmNativeCall(void* function,
void* stack,
unsigned stackSize,
unsigned returnType);
namespace vm {
inline uint64_t
dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
unsigned, unsigned argumentsSize, unsigned returnType)
inline uint64_t dynamicCall(void* function,
uintptr_t* arguments,
uint8_t*,
unsigned,
unsigned argumentsSize,
unsigned 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_FRAME(state) ((state).FIELD(rbp))
# define IP_REGISTER(context) \
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
#define STACK_REGISTER(context) \
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
#define THREAD_REGISTER(context) \
@ -139,26 +141,38 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
extern "C" uint64_t
#ifdef PLATFORM_WINDOWS
vmNativeCall(void* function, void* stack, unsigned stackSize,
vmNativeCall(void* function,
void* stack,
unsigned stackSize,
unsigned returnType);
#else
vmNativeCall(void* function, void* stack, unsigned stackSize,
void* gprTable, void* sseTable, unsigned returnType);
vmNativeCall(void* function,
void* stack,
unsigned stackSize,
void* gprTable,
void* sseTable,
unsigned returnType);
#endif
namespace vm {
#ifdef PLATFORM_WINDOWS
inline uint64_t
dynamicCall(void* function, uint64_t* arguments, UNUSED uint8_t* argumentTypes,
unsigned argumentCount, unsigned, unsigned returnType)
inline uint64_t dynamicCall(void* function,
uint64_t* arguments,
UNUSED uint8_t* argumentTypes,
unsigned argumentCount,
unsigned,
unsigned returnType)
{
return vmNativeCall(function, arguments, argumentCount, returnType);
}
#else
inline uint64_t
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
unsigned argumentCount, unsigned, unsigned returnType)
inline uint64_t dynamicCall(void* function,
uintptr_t* arguments,
uint8_t* argumentTypes,
unsigned argumentCount,
unsigned,
unsigned returnType)
{
const unsigned GprCount = 6;
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),
(sseIndex ? sseTable : 0), returnType);
(sseIndex ? sseTable : 0),
returnType);
}
#endif
@ -206,8 +223,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
namespace vm {
inline void
trap()
inline void trap()
{
#ifdef _MSC_VER
__asm int 3
@ -216,20 +232,17 @@ trap()
#endif
}
inline void
programOrderMemoryBarrier()
inline void programOrderMemoryBarrier()
{
compileTimeMemoryBarrier();
}
inline void
storeStoreMemoryBarrier()
inline void storeStoreMemoryBarrier()
{
programOrderMemoryBarrier();
}
inline void
storeLoadMemoryBarrier()
inline void storeLoadMemoryBarrier()
{
#ifdef _MSC_VER
MemoryBarrier();
@ -240,25 +253,22 @@ storeLoadMemoryBarrier()
#endif // ARCH_x86_64
}
inline void
loadMemoryBarrier()
inline void loadMemoryBarrier()
{
programOrderMemoryBarrier();
}
inline void
syncInstructionCache(const void*, unsigned)
inline void syncInstructionCache(const void*, unsigned)
{
programOrderMemoryBarrier();
}
#ifdef USE_ATOMIC_OPERATIONS
inline bool
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
{
#ifdef _MSC_VER
return old == InterlockedCompareExchange
(reinterpret_cast<LONG*>(p), new_, old);
return old
== InterlockedCompareExchange(reinterpret_cast<LONG*>(p), new_, old);
#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
return __sync_bool_compare_and_swap(p, old, new_);
#else
@ -275,12 +285,11 @@ atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
#define AVIAN_HAS_CAS64
inline bool
atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
inline bool atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
{
#ifdef _MSC_VER
return old == InterlockedCompareExchange64
(reinterpret_cast<LONGLONG*>(p), new_, old);
return old == InterlockedCompareExchange64(
reinterpret_cast<LONGLONG*>(p), new_, old);
#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
return __sync_bool_compare_and_swap(p, old, new_);
#elif defined ARCH_x86_32
@ -308,8 +317,7 @@ atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
#endif
}
inline bool
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
{
#ifdef ARCH_x86_32
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);

View File

@ -13,11 +13,19 @@
#ifdef inflateInit2
#undef inflateInit2
#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
#ifdef deflateInit2
#undef deflateInit2
#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

View File

@ -21,9 +21,9 @@ class Zone : public avian::util::Allocator {
public:
class Segment {
public:
Segment(Segment* next, unsigned size):
next(next), size(size), position(0)
{ }
Segment(Segment* next, unsigned size) : next(next), size(size), position(0)
{
}
Segment* next;
uintptr_t size;
@ -31,19 +31,23 @@ class Zone : public avian::util::Allocator {
uint8_t data[0];
};
Zone(System* s, Allocator* allocator, unsigned minimumFootprint):
s(s),
Zone(System* s, Allocator* allocator, unsigned minimumFootprint)
: s(s),
allocator(allocator),
segment(0),
minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 :
minimumFootprint - sizeof(Segment))
{ }
minimumFootprint(minimumFootprint < sizeof(Segment)
? 0
: minimumFootprint - sizeof(Segment))
{
}
~Zone() {
~Zone()
{
dispose();
}
void dispose() {
void dispose()
{
for (Segment* seg = segment, *next; seg; seg = next) {
next = seg->next;
allocator->free(seg, sizeof(Segment) + seg->size);
@ -52,17 +56,19 @@ class Zone : public avian::util::Allocator {
segment = 0;
}
static unsigned padToPage(unsigned size) {
return (size + (LikelyPageSizeInBytes - 1))
& ~(LikelyPageSizeInBytes - 1);
static unsigned padToPage(unsigned size)
{
return (size + (LikelyPageSizeInBytes - 1)) & ~(LikelyPageSizeInBytes - 1);
}
bool tryEnsure(unsigned space) {
bool tryEnsure(unsigned space)
{
if (segment == 0 or segment->position + space > segment->size) {
unsigned size = padToPage
(avian::util::max
(space, avian::util::max
(minimumFootprint, segment == 0 ? 0 : segment->size * 2))
unsigned size = padToPage(
avian::util::max(
space,
avian::util::max(minimumFootprint,
segment == 0 ? 0 : segment->size * 2))
+ sizeof(Segment));
void* p = allocator->tryAllocate(size);
@ -79,7 +85,8 @@ class Zone : public avian::util::Allocator {
return true;
}
void ensure(unsigned space) {
void ensure(unsigned space)
{
if (segment == 0 or segment->position + space > segment->size) {
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);
if (tryEnsure(size)) {
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);
void* p = tryAllocate(size);
if (p) {
@ -112,7 +121,8 @@ class Zone : public avian::util::Allocator {
}
}
void* peek(unsigned size) {
void* peek(unsigned size)
{
size = pad(size);
Segment* s = segment;
while (s->position < size) {
@ -122,7 +132,8 @@ class Zone : public avian::util::Allocator {
return s->data + (s->position - size);
}
void pop(unsigned size) {
void pop(unsigned size)
{
size = pad(size);
Segment* s = segment;
while (s->position < size) {
@ -135,7 +146,8 @@ class Zone : public avian::util::Allocator {
segment = s;
}
virtual void free(const void*, unsigned) {
virtual void free(const void*, unsigned)
{
// not supported
abort(s);
}

View File

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

View File

@ -14,7 +14,10 @@
// since we aren't linking against libstdc++, we must implement this
// ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); }
extern "C" void __cxa_pure_virtual(void)
{
abort();
}
#ifdef BOOT_IMAGE
@ -27,12 +30,10 @@ extern "C" void __cxa_pure_virtual(void) { abort(); }
#endif
extern "C" {
extern const uint8_t BOOTIMAGE_SYMBOL(start)[];
extern const uint8_t BOOTIMAGE_SYMBOL(end)[];
AVIAN_EXPORT const uint8_t*
bootimageBin(unsigned* size)
AVIAN_EXPORT const uint8_t* bootimageBin(unsigned* size)
{
*size = BOOTIMAGE_SYMBOL(end) - 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(end)[];
AVIAN_EXPORT const uint8_t*
codeimageBin(unsigned* size)
AVIAN_EXPORT const uint8_t* codeimageBin(unsigned* size)
{
*size = CODEIMAGE_SYMBOL(end) - CODEIMAGE_SYMBOL(start);
return CODEIMAGE_SYMBOL(start);
}
}
#undef SYMBOL
@ -63,17 +62,14 @@ extern "C" {
#endif
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[];
AVIAN_EXPORT const uint8_t*
classpathJar(unsigned* size)
AVIAN_EXPORT const uint8_t* classpathJar(unsigned* size)
{
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
}
}
#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(BootHeapOffset) = 1 << (NAME(BootShift) + 1);
inline unsigned
LABEL(codeMapSize)(unsigned codeSize)
inline unsigned LABEL(codeMapSize)(unsigned codeSize)
{
return avian::util::ceilingDivide(codeSize, TargetBitsPerWord) * TargetBytesPerWord;
}
inline unsigned
LABEL(heapMapSize)(unsigned heapSize)
{
return avian::util::ceilingDivide(heapSize, TargetBitsPerWord * TargetBytesPerWord)
return avian::util::ceilingDivide(codeSize, TargetBitsPerWord)
* TargetBytesPerWord;
}
inline object
LABEL(bootObject)(LABEL(uintptr_t)* heap, unsigned offset)
inline unsigned LABEL(heapMapSize)(unsigned heapSize)
{
return avian::util::ceilingDivide(heapSize,
TargetBitsPerWord * TargetBytesPerWord)
* TargetBytesPerWord;
}
inline object LABEL(bootObject)(LABEL(uintptr_t) * heap, unsigned offset)
{
if (offset) {
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,28 +22,28 @@ namespace local {
class MyClasspath : public Classpath {
public:
MyClasspath(Allocator* allocator):
allocator(allocator)
{ }
MyClasspath(Allocator* allocator) : allocator(allocator)
{
}
virtual object
makeJclass(Thread* t, object class_)
virtual GcJclass* makeJclass(Thread* t, GcClass* class_)
{
return vm::makeJclass(t, class_);
}
virtual object
makeString(Thread* t, object array, int32_t offset, int32_t length)
virtual GcString* makeString(Thread* t,
object array,
int32_t offset,
int32_t length)
{
return vm::makeString(t, array, offset, length, 0);
}
virtual object
makeThread(Thread* t, Thread* parent)
virtual GcThread* makeThread(Thread* t, Thread* parent)
{
object group;
GcThreadGroup* group;
if (parent) {
group = threadGroup(t, parent->javaThread);
group = parent->javaThread->group();
} else {
group = makeThreadGroup(t, 0, 0, 0);
}
@ -51,72 +51,79 @@ class MyClasspath : public Classpath {
const unsigned NewState = 0;
const unsigned NormalPriority = 5;
return vm::makeThread
(t, 0, 0, 0, 0, 0, NewState, NormalPriority, 0, 0, 0,
root(t, Machine::AppLoader), 0, 0, group, 0);
return vm::makeThread(t,
0,
0,
0,
0,
0,
NewState,
NormalPriority,
0,
0,
0,
roots(t)->appLoader(),
0,
0,
group,
0);
}
virtual object
makeJMethod(Thread* t, object vmMethod)
virtual object makeJMethod(Thread* t, GcMethod* vmMethod)
{
PROTECT(t, vmMethod);
object jmethod = makeJmethod(t, vmMethod, false);
GcJmethod* jmethod = makeJmethod(t, vmMethod, false);
return byteArrayBody(t, methodName(t, vmMethod), 0) == '<'
? makeJconstructor(t, jmethod) : jmethod;
return vmMethod->name()->body()[0] == '<'
? (object)makeJconstructor(t, jmethod)
: (object)jmethod;
}
virtual object
getVMMethod(Thread* t, object jmethod)
virtual GcMethod* getVMMethod(Thread* t, object jmethod)
{
return objectClass(t, jmethod) == type(t, Machine::JmethodType)
? jmethodVmMethod(t, jmethod)
: jmethodVmMethod(t, jconstructorMethod(t, jmethod));
return objectClass(t, jmethod) == type(t, GcJmethod::Type)
? cast<GcJmethod>(t, jmethod)->vmMethod()
: cast<GcJconstructor>(t, jmethod)->method()->vmMethod();
}
virtual object
makeJField(Thread* t, object vmField)
virtual object makeJField(Thread* t, GcField* vmField)
{
return makeJfield(t, vmField, false);
}
virtual object
getVMField(Thread* t, object jfield)
virtual GcField* getVMField(Thread* t UNUSED, GcJfield* jfield)
{
return jfieldVmField(t, jfield);
return jfield->vmField();
}
virtual void
clearInterrupted(Thread*)
virtual void clearInterrupted(Thread*)
{
// ignore
}
virtual void
runThread(Thread* t)
virtual void runThread(Thread* t)
{
object method = resolveMethod
(t, root(t, Machine::BootLoader), "java/lang/Thread", "run",
GcMethod* method = resolveMethod(t,
roots(t)->bootLoader(),
"java/lang/Thread",
"run",
"(Ljava/lang/Thread;)V");
t->m->processor->invoke(t, method, 0, t->javaThread);
}
virtual void
resolveNative(Thread* t, object method)
virtual void resolveNative(Thread* t, GcMethod* method)
{
vm::resolveNative(t, method);
}
virtual void
interceptMethods(Thread*)
virtual void interceptMethods(Thread*)
{
// ignore
}
virtual void
preBoot(Thread*)
virtual void preBoot(Thread*)
{
// ignore
}
@ -126,64 +133,59 @@ class MyClasspath : public Classpath {
return true;
}
virtual void
boot(Thread*)
virtual void boot(Thread*)
{
// ignore
}
virtual const char*
bootClasspath()
virtual const char* bootClasspath()
{
return AVIAN_CLASSPATH;
}
virtual object
makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
virtual object makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
{
object c = resolveClass
(t, root(t, Machine::BootLoader), "java/nio/DirectByteBuffer");
GcClass* c
= resolveClass(t, roots(t)->bootLoader(), "java/nio/DirectByteBuffer");
PROTECT(t, c);
object instance = makeNew(t, c);
PROTECT(t, instance);
object constructor = resolveMethod(t, c, "<init>", "(JI)V");
GcMethod* constructor = resolveMethod(t, c, "<init>", "(JI)V");
t->m->processor->invoke
(t, constructor, instance, reinterpret_cast<int64_t>(p),
t->m->processor->invoke(t,
constructor,
instance,
reinterpret_cast<int64_t>(p),
static_cast<int32_t>(capacity));
return instance;
}
virtual void*
getDirectBufferAddress(Thread* t, object b)
virtual void* getDirectBufferAddress(Thread* t, object b)
{
PROTECT(t, b);
object field = resolveField(t, objectClass(t, b), "address", "J");
GcField* field = resolveField(t, objectClass(t, b), "address", "J");
return reinterpret_cast<void*>
(fieldAtOffset<int64_t>(b, fieldOffset(t, field)));
return reinterpret_cast<void*>(fieldAtOffset<int64_t>(b, field->offset()));
}
virtual int64_t
getDirectBufferCapacity(Thread* t, object b)
virtual int64_t getDirectBufferCapacity(Thread* t, object b)
{
PROTECT(t, b);
object field = resolveField
(t, objectClass(t, b), "capacity", "I");
GcField* field = resolveField(t, objectClass(t, b), "capacity", "I");
return fieldAtOffset<int32_t>(b, fieldOffset(t, field));
return fieldAtOffset<int32_t>(b, field->offset());
}
virtual bool canTailCall(Thread* t,
object,
object calleeClassName,
object calleeMethodName,
object)
virtual bool canTailCall(Thread* t UNUSED,
GcMethod*,
GcByteArray* calleeClassName,
GcByteArray* calleeMethodName,
GcByteArray*)
{
// we can't tail call System.load[Library] or
// Runtime.load[Library] due to their use of
@ -192,34 +194,30 @@ class MyClasspath : public Classpath {
return (
(strcmp("loadLibrary",
reinterpret_cast<char*>(&byteArrayBody(t, calleeMethodName, 0)))
reinterpret_cast<char*>(calleeMethodName->body().begin()))
and strcmp("load",
reinterpret_cast<char*>(
&byteArrayBody(t, calleeMethodName, 0))))
or (strcmp(
"java/lang/System",
reinterpret_cast<char*>(&byteArrayBody(t, calleeClassName, 0)))
and strcmp("java/lang/Runtime",
reinterpret_cast<char*>(
&byteArrayBody(t, calleeClassName, 0)))));
reinterpret_cast<char*>(calleeMethodName->body().begin())))
or (strcmp("java/lang/System",
reinterpret_cast<char*>(calleeClassName->body().begin()))
and strcmp(
"java/lang/Runtime",
reinterpret_cast<char*>(calleeClassName->body().begin()))));
}
virtual object libraryClassLoader(Thread* t, object caller)
virtual GcClassLoader* libraryClassLoader(Thread* t, GcMethod* caller)
{
return (methodClass(t, caller) == type(t, Machine::ClassLoaderType)
return (caller->class_() == type(t, Gc::ClassLoaderType)
and t->libraryLoadStack)
? t->libraryLoadStack->classLoader
: classLoader(t, methodClass(t, caller));
: caller->class_()->loader();
}
virtual void
shutDown(Thread*)
virtual void shutDown(Thread*)
{
// ignore
}
virtual void
dispose()
virtual void dispose()
{
allocator->free(this, sizeof(*this));
}
@ -227,17 +225,21 @@ class MyClasspath : public Classpath {
Allocator* allocator;
};
void
enumerateThreads(Thread* t, Thread* x, object array, unsigned* index,
void enumerateThreads(Thread* t,
Thread* x,
GcArray* array,
unsigned* index,
unsigned limit)
{
if (*index < limit) {
set(t, array, ArrayBody + (*index * BytesPerWord), x->javaThread);
array->setBodyElement(t, *index, x->javaThread);
++(*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);
}
}
@ -247,8 +249,10 @@ enumerateThreads(Thread* t, Thread* x, object array, unsigned* index,
namespace vm {
Classpath*
makeClasspath(System*, Allocator* allocator, const char*, const char*)
Classpath* makeClasspath(System*,
Allocator* allocator,
const char*,
const char*)
{
return new (allocator->allocate(sizeof(local::MyClasspath)))
local::MyClasspath(allocator);
@ -257,41 +261,36 @@ makeClasspath(System*, Allocator* allocator, const char*, const char*)
} // namespace vm
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Object_toString
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Object_toString(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
unsigned hash = objectHash(t, this_);
object s = makeString
(t, "%s@0x%x",
&byteArrayBody(t, className(t, objectClass(t, this_)), 0),
hash);
GcString* s = makeString(
t, "%s@0x%x", objectClass(t, this_)->name()->body().begin(), hash);
return reinterpret_cast<int64_t>(s);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Object_getVMClass
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Object_getVMClass(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(objectClass(t, reinterpret_cast<object>(arguments[0])));
return reinterpret_cast<int64_t>(
objectClass(t, reinterpret_cast<object>(arguments[0])));
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_Object_wait
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Object_wait(Thread* t, object, uintptr_t* arguments)
{
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);
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_Object_notify
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Object_notify(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
@ -299,8 +298,7 @@ Avian_java_lang_Object_notify
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_Object_notifyAll
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Object_notifyAll(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
@ -308,8 +306,7 @@ Avian_java_lang_Object_notifyAll
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Object_hashCode
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Object_hashCode(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
@ -317,32 +314,34 @@ Avian_java_lang_Object_hashCode
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Object_clone
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Object_clone(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(clone(t, reinterpret_cast<object>(arguments[0])));
return reinterpret_cast<int64_t>(
clone(t, reinterpret_cast<object>(arguments[0])));
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_io_ObjectInputStream_makeInstance
(Thread* t, object, uintptr_t* arguments)
Avian_java_io_ObjectInputStream_makeInstance(Thread* t,
object,
uintptr_t* arguments)
{
object c = reinterpret_cast<object>(arguments[0]);
GcClass* c = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
return reinterpret_cast<int64_t>(make(t, c));
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_avian_LegacyObjectInputStream_makeInstance
(Thread* t, object, uintptr_t* arguments)
Avian_avian_LegacyObjectInputStream_makeInstance(Thread* t,
object,
uintptr_t* arguments)
{
return Avian_java_io_ObjectInputStream_makeInstance(t, NULL, arguments);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_reflect_Field_getPrimitive
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_reflect_Field_getPrimitive(Thread* t,
object,
uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int code = arguments[1];
@ -371,8 +370,9 @@ Avian_java_lang_reflect_Field_getPrimitive
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_reflect_Field_getObject
(Thread*, object, uintptr_t* arguments)
Avian_java_lang_reflect_Field_getObject(Thread*,
object,
uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int offset = arguments[1];
@ -381,13 +381,15 @@ Avian_java_lang_reflect_Field_getObject
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_reflect_Field_setPrimitive
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_reflect_Field_setPrimitive(Thread* t,
object,
uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int code = arguments[1];
int offset = arguments[2];
int64_t value; memcpy(&value, arguments + 3, 8);
int64_t value;
memcpy(&value, arguments + 3, 8);
switch (code) {
case ByteField:
@ -420,118 +422,125 @@ Avian_java_lang_reflect_Field_setPrimitive
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_reflect_Field_setObject
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_reflect_Field_setObject(Thread* t,
object,
uintptr_t* arguments)
{
object instance = reinterpret_cast<object>(arguments[0]);
int offset = arguments[1];
object value = reinterpret_cast<object>(arguments[2]);
set(t, instance, offset, value);
setField(t, instance, offset, value);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_reflect_Constructor_make
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_reflect_Constructor_make(Thread* t,
object,
uintptr_t* arguments)
{
object c = reinterpret_cast<object>(arguments[0]);
GcClass* c = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
return reinterpret_cast<int64_t>(make(t, c));
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_reflect_Method_getCaller
(Thread* t, object, uintptr_t*)
Avian_java_lang_reflect_Method_getCaller(Thread* t, object, uintptr_t*)
{
return reinterpret_cast<int64_t>(getCaller(t, 2));
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_reflect_Method_invoke
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_reflect_Method_invoke(Thread* t,
object,
uintptr_t* arguments)
{
object method = reinterpret_cast<object>(arguments[0]);
GcMethod* method = cast<GcMethod>(t, reinterpret_cast<object>(arguments[0]));
object instance = reinterpret_cast<object>(arguments[1]);
object args = reinterpret_cast<object>(arguments[2]);
THREAD_RESOURCE0(t, {
if (t->exception) {
object exception = t->exception;
t->exception = makeThrowable
(t, Machine::InvocationTargetExceptionType, 0, 0, exception);
GcThrowable* exception = t->exception;
t->exception = makeThrowable(
t, GcInvocationTargetException::Type, 0, 0, exception);
}
});
unsigned returnCode = methodReturnCode(t, method);
unsigned returnCode = method->returnCode();
return reinterpret_cast<int64_t>
(translateInvokeResult
(t, returnCode, t->m->processor->invokeArray(t, method, instance, args)));
return reinterpret_cast<int64_t>(translateInvokeResult(
t, returnCode, t->m->processor->invokeArray(t, method, instance, args)));
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_reflect_Array_getLength
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_reflect_Array_getLength(Thread* t,
object,
uintptr_t* arguments)
{
object array = reinterpret_cast<object>(arguments[0]);
if (LIKELY(array)) {
unsigned elementSize = classArrayElementSize(t, objectClass(t, array));
unsigned elementSize = objectClass(t, array)->arrayElementSize();
if (LIKELY(elementSize)) {
return fieldAtOffset<uintptr_t>(array, BytesPerWord);
} else {
throwNew(t, Machine::IllegalArgumentExceptionType);
throwNew(t, GcIllegalArgumentException::Type);
}
} else {
throwNew(t, Machine::NullPointerExceptionType);
throwNew(t, GcNullPointerException::Type);
}
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_reflect_Array_makeObjectArray
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_reflect_Array_makeObjectArray(Thread* t,
object,
uintptr_t* arguments)
{
object elementType = reinterpret_cast<object>(arguments[0]);
GcJclass* elementType
= cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]));
int length = arguments[1];
return reinterpret_cast<int64_t>
(makeObjectArray(t, jclassVmClass(t, elementType), length));
return reinterpret_cast<int64_t>(
makeObjectArray(t, elementType->vmClass(), length));
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Float_floatToRawIntBits
(Thread*, object, uintptr_t* arguments)
Avian_java_lang_Float_floatToRawIntBits(Thread*,
object,
uintptr_t* arguments)
{
return static_cast<int32_t>(*arguments);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Float_intBitsToFloat
(Thread*, object, uintptr_t* arguments)
Avian_java_lang_Float_intBitsToFloat(Thread*, object, uintptr_t* arguments)
{
return static_cast<int32_t>(*arguments);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Double_doubleToRawLongBits
(Thread*, object, uintptr_t* arguments)
Avian_java_lang_Double_doubleToRawLongBits(Thread*,
object,
uintptr_t* arguments)
{
int64_t v; memcpy(&v, arguments, 8);
int64_t v;
memcpy(&v, arguments, 8);
return v;
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Double_longBitsToDouble
(Thread*, object, uintptr_t* arguments)
Avian_java_lang_Double_longBitsToDouble(Thread*,
object,
uintptr_t* arguments)
{
int64_t v; memcpy(&v, arguments, 8);
int64_t v;
memcpy(&v, arguments, 8);
return v;
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_String_intern
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_String_intern(Thread* t, object, uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
@ -542,22 +551,22 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_System_getVMProperties(Thread* t, object, uintptr_t*)
{
object array
= makeObjectArray(t, type(t, Machine::StringType), t->m->propertyCount);
= makeObjectArray(t, type(t, GcString::Type), t->m->propertyCount);
PROTECT(t, array);
for (unsigned i = 0; i < t->m->propertyCount; ++i) {
object s = makeString(t, "%s", t->m->properties[i]);
set(t, array, ArrayBody + (i * BytesPerWord), s);
GcString* s = makeString(t, "%s", t->m->properties[i]);
reinterpret_cast<GcArray*>(array)->setBodyElement(t, i, s);
}
return reinterpret_cast<int64_t>(array);
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_System_arraycopy
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_System_arraycopy(Thread* t, object, uintptr_t* arguments)
{
arrayCopy(t, reinterpret_cast<object>(arguments[0]),
arrayCopy(t,
reinterpret_cast<object>(arguments[0]),
arguments[1],
reinterpret_cast<object>(arguments[2]),
arguments[3],
@ -565,37 +574,39 @@ Avian_java_lang_System_arraycopy
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_System_identityHashCode
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_System_identityHashCode(Thread* t,
object,
uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[0]);
if (LIKELY(o)) {
return objectHash(t, o);
} else {
throwNew(t, Machine::NullPointerExceptionType);
throwNew(t, GcNullPointerException::Type);
}
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_ClassLoader_getCaller(Thread* t, object, uintptr_t*)
{
return reinterpret_cast<int64_t>(
getJClass(t, methodClass(t, getCaller(t, 2))));
return reinterpret_cast<int64_t>(getJClass(t, getCaller(t, 2)->class_()));
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_ClassLoader_load(Thread* t, object, uintptr_t* arguments)
{
object name = reinterpret_cast<object>(arguments[0]);
GcString* name = cast<GcString>(t, reinterpret_cast<object>(arguments[0]));
Thread::LibraryLoadStack stack(
t,
classLoader(t, jclassVmClass(t, reinterpret_cast<object>(arguments[1]))));
cast<GcJclass>(t, reinterpret_cast<object>(arguments[1]))
->vmClass()
->loader());
bool mapName = arguments[2];
unsigned length = stringLength(t, name);
unsigned length = name->length(t);
THREAD_RUNTIME_ARRAY(t, char, n, length + 1);
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
@ -603,155 +614,159 @@ extern "C" AVIAN_EXPORT void JNICALL
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_Runtime_gc
(Thread* t, object, uintptr_t*)
Avian_java_lang_Runtime_gc(Thread* t, object, uintptr_t*)
{
collect(t, Heap::MajorCollection);
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_Runtime_addShutdownHook
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Runtime_addShutdownHook(Thread* t,
object,
uintptr_t* arguments)
{
object hook = reinterpret_cast<object>(arguments[1]);
PROTECT(t, hook);
ACQUIRE(t, t->m->shutdownLock);
setRoot(t, Machine::ShutdownHooks,
makePair(t, hook, root(t, Machine::ShutdownHooks)));
GcPair* p = makePair(t, hook, roots(t)->shutdownHooks());
// sequence point, for gc (don't recombine statements)
roots(t)->setShutdownHooks(t, p);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Throwable_trace
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Throwable_trace(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>(getTrace(t, arguments[0]));
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Throwable_resolveTrace
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Throwable_resolveTrace(Thread* t,
object,
uintptr_t* arguments)
{
object trace = reinterpret_cast<object>(*arguments);
PROTECT(t, trace);
unsigned length = objectArrayLength(t, trace);
object elementType = type(t, Machine::StackTraceElementType);
GcClass* elementType = type(t, GcStackTraceElement::Type);
object array = makeObjectArray(t, elementType, length);
PROTECT(t, array);
for (unsigned i = 0; i < length; ++i) {
object ste = makeStackTraceElement(t, objectArrayBody(t, trace, i));
set(t, array, ArrayBody + (i * BytesPerWord), ste);
GcStackTraceElement* ste = makeStackTraceElement(
t, cast<GcTraceElement>(t, objectArrayBody(t, trace, i)));
reinterpret_cast<GcArray*>(array)->setBodyElement(t, i, ste);
}
return reinterpret_cast<int64_t>(array);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Thread_currentThread
(Thread* t, object, uintptr_t*)
Avian_java_lang_Thread_currentThread(Thread* t, object, uintptr_t*)
{
return reinterpret_cast<int64_t>(t->javaThread);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Thread_doStart
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Thread_doStart(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(startThread(t, reinterpret_cast<object>(*arguments)));
return reinterpret_cast<int64_t>(
startThread(t, cast<GcThread>(t, reinterpret_cast<object>(*arguments))));
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_Thread_interrupt
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Thread_interrupt(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);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Thread_interrupted
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Thread_interrupted(Thread* t, object, uintptr_t* arguments)
{
int64_t peer; memcpy(&peer, arguments, 8);
int64_t peer;
memcpy(&peer, arguments, 8);
return threadIsInterrupted
(t, reinterpret_cast<Thread*>(peer)->javaThread, true);
return threadIsInterrupted(
t, reinterpret_cast<Thread*>(peer)->javaThread, true);
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Thread_getStackTrace
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Thread_getStackTrace(Thread* t,
object,
uintptr_t* arguments)
{
int64_t peer; memcpy(&peer, arguments, 8);
int64_t peer;
memcpy(&peer, arguments, 8);
if (reinterpret_cast<Thread*>(peer) == t) {
return reinterpret_cast<int64_t>(makeTrace(t));
} else {
return reinterpret_cast<int64_t>
(t->m->processor->getStackTrace(t, reinterpret_cast<Thread*>(peer)));
return reinterpret_cast<int64_t>(
t->m->processor->getStackTrace(t, reinterpret_cast<Thread*>(peer)));
}
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Thread_activeCount
(Thread* t, object, uintptr_t*)
Avian_java_lang_Thread_activeCount(Thread* t, object, uintptr_t*)
{
return t->m->liveCount;
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_java_lang_Thread_enumerate
(Thread* t, object, uintptr_t* arguments)
Avian_java_lang_Thread_enumerate(Thread* t, object, uintptr_t* arguments)
{
object array = reinterpret_cast<object>(*arguments);
GcArray* array = cast<GcArray>(t, reinterpret_cast<object>(*arguments));
ACQUIRE_RAW(t, t->m->stateLock);
unsigned count = min(t->m->liveCount, objectArrayLength(t, array));
unsigned count = min(t->m->liveCount,
objectArrayLength(t, reinterpret_cast<object>(array)));
unsigned index = 0;
local::enumerateThreads(t, t->m->rootThread, array, &index, count);
return count;
}
extern "C" AVIAN_EXPORT void JNICALL
Avian_java_lang_Thread_yield
(Thread* t, object, uintptr_t*)
Avian_java_lang_Thread_yield(Thread* t, object, uintptr_t*)
{
t->m->system->yield();
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_avian_Atomic_getOffset
(Thread* t, object, uintptr_t* arguments)
Avian_avian_Atomic_getOffset(Thread* t, object, uintptr_t* arguments)
{
return fieldOffset
(t, jfieldVmField(t, reinterpret_cast<object>(arguments[0])));
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[0]))
->vmField()
->offset();
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_sun_misc_Unsafe_objectFieldOffset
(Thread* t, object, uintptr_t* arguments)
Avian_sun_misc_Unsafe_objectFieldOffset(Thread* t,
object,
uintptr_t* arguments)
{
return fieldOffset
(t, jfieldVmField(t, reinterpret_cast<object>(arguments[1])));
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[1]))
->vmField()
->offset();
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_avian_Atomic_compareAndSwapObject
(Thread* t, object, uintptr_t* arguments)
Avian_avian_Atomic_compareAndSwapObject(Thread* t,
object,
uintptr_t* arguments)
{
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 update = arguments[4];
bool success = atomicCompareAndSwap
(&fieldAtOffset<uintptr_t>(target, offset), expect, update);
bool success = atomicCompareAndSwap(
&fieldAtOffset<uintptr_t>(target, offset), expect, update);
if (success) {
mark(t, target, offset);
@ -761,60 +776,61 @@ Avian_avian_Atomic_compareAndSwapObject
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_avian_Classes_isAssignableFrom
(Thread* t, object, uintptr_t* arguments)
Avian_avian_Classes_isAssignableFrom(Thread* t,
object,
uintptr_t* arguments)
{
object this_ = reinterpret_cast<object>(arguments[0]);
object that = reinterpret_cast<object>(arguments[1]);
GcClass* this_ = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
GcClass* that = cast<GcClass>(t, reinterpret_cast<object>(arguments[1]));
if (LIKELY(that)) {
return vm::isAssignableFrom(t, this_, that);
} else {
throwNew(t, Machine::NullPointerExceptionType);
throwNew(t, GcNullPointerException::Type);
}
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_avian_Classes_getVMClass
(Thread* t, object, uintptr_t* arguments)
Avian_avian_Classes_getVMClass(Thread* t, object, uintptr_t* arguments)
{
return reinterpret_cast<int64_t>
(objectClass(t, reinterpret_cast<object>(arguments[0])));
return reinterpret_cast<int64_t>(
objectClass(t, reinterpret_cast<object>(arguments[0])));
}
extern "C" AVIAN_EXPORT int64_t JNICALL
Avian_avian_Classes_makeMethod
(Thread* t, object, uintptr_t* arguments)
Avian_avian_Classes_makeMethod(Thread* t, object, uintptr_t* arguments)
{
object method = arrayBody
(t, classMethodTable
(t, jclassVmClass(t, reinterpret_cast<object>(arguments[0]))),
arguments[1]);
GcMethod* method = cast<GcMethod>(
t,
cast<GcArray>(t,
cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]))
->vmClass()
->methodTable())->body()[arguments[1]]);
PROTECT(t, method);
object c = resolveClass
(t, root(t, Machine::BootLoader), "java/lang/reflect/Method");
GcClass* c
= resolveClass(t, roots(t)->bootLoader(), "java/lang/reflect/Method");
PROTECT(t, c);
object instance = makeNew(t, c);
PROTECT(t, instance);
object constructor = resolveMethod(t, c, "<init>", "(Lavian/VMMethod;)V");
GcMethod* constructor = resolveMethod(t, c, "<init>", "(Lavian/VMMethod;)V");
t->m->processor->invoke(t, constructor, instance, method);
if (byteArrayBody(t, methodName(t, method), 0) == '<') {
method = instance;
if (method->name()->body()[0] == '<') {
object oldInstance = instance;
c = resolveClass
(t, root(t, Machine::BootLoader), "java/lang/reflect/Constructor");
c = resolveClass(
t, roots(t)->bootLoader(), "java/lang/reflect/Constructor");
object instance = makeNew(t, c);
object constructor = resolveMethod
(t, c, "<init>", "(Ljava/lang/Method;)V");
GcMethod* constructor
= resolveMethod(t, c, "<init>", "(Ljava/lang/Method;)V");
t->m->processor->invoke(t, constructor, instance, method);
t->m->processor->invoke(t, constructor, instance, oldInstance);
}
return reinterpret_cast<uintptr_t>(instance);

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),
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));
if (registerResources[i].reserved) {
--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));
}
}

View File

@ -38,7 +38,8 @@ class ForkState;
class Block;
template <class T>
List<T>* reverseDestroy(List<T>* cell) {
List<T>* reverseDestroy(List<T>* cell)
{
List<T>* previous = 0;
while (cell) {
List<T>* next = cell->next;
@ -73,7 +74,7 @@ class LogicalCode {
= logicalCode.cloneAndSet(zone, logicalCode.count + more, 0);
for (size_t i = 0; i < logicalCode.count; i++) {
assert((vm::System*)0, logicalCode[i] == newCode[i]);
assertT((vm::System*)0, logicalCode[i] == newCode[i]);
}
logicalCode = newCode;
@ -93,7 +94,9 @@ class LogicalCode {
class Context {
public:
Context(vm::System* system, Assembler* assembler, vm::Zone* zone,
Context(vm::System* system,
Assembler* assembler,
vm::Zone* zone,
Compiler::Client* client);
vm::System* system;
@ -128,12 +131,14 @@ class Context {
ir::TargetInfo targetInfo;
};
inline Aborter* getAborter(Context* c) {
inline Aborter* getAborter(Context* c)
{
return c->system;
}
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);
}

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 bool isBranch() { return false; }
virtual bool allExits() { return false; }
virtual Local* locals() { return localsBefore; }
virtual bool isBranch()
{
return false;
}
virtual bool allExits()
{
return false;
}
virtual Local* locals()
{
return localsBefore;
}
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);
void addReads(Context* c, Value* v, unsigned size,
const SiteMask& lowMask, Value* lowSuccessor,
const SiteMask& highMask, Value* highSuccessor);
void addReads(Context* c,
Value* v,
unsigned size,
const SiteMask& lowMask,
Value* lowSuccessor,
const SiteMask& highMask,
Value* highSuccessor);
void addReads(Context* c, Value* v, unsigned size,
const SiteMask& lowMask, const SiteMask& highMask);
void addReads(Context* c,
Value* v,
unsigned size,
const SiteMask& lowMask,
const SiteMask& highMask);
CodePromise* makeCodePromise(Context* c);
@ -82,7 +98,9 @@ class StubReadPair {
class JunctionState {
public:
JunctionState(unsigned frameFootprint): frameFootprint(frameFootprint) { }
JunctionState(unsigned frameFootprint) : frameFootprint(frameFootprint)
{
}
unsigned frameFootprint;
StubReadPair reads[0];
@ -90,12 +108,19 @@ class JunctionState {
class Link {
public:
Link(Event* predecessor, Link* nextPredecessor, Event* successor,
Link* nextSuccessor, ForkState* forkState):
predecessor(predecessor), nextPredecessor(nextPredecessor),
successor(successor), nextSuccessor(nextSuccessor), forkState(forkState),
Link(Event* predecessor,
Link* nextPredecessor,
Event* successor,
Link* nextSuccessor,
ForkState* forkState)
: predecessor(predecessor),
nextPredecessor(nextPredecessor),
successor(successor),
nextSuccessor(nextSuccessor),
forkState(forkState),
junctionState(0)
{ }
{
}
unsigned countPredecessors();
Link* lastPredecessor();
@ -109,9 +134,12 @@ class Link {
JunctionState* junctionState;
};
Link*
link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor,
Link* nextSuccessor, ForkState* forkState);
Link* link(Context* c,
Event* predecessor,
Link* nextPredecessor,
Event* successor,
Link* nextSuccessor,
ForkState* forkState);
void appendCall(Context* c,
Value* address,
@ -142,12 +170,14 @@ void appendTranslate(Context* c,
Value* first,
Value* result);
void
appendOperation(Context* c, lir::Operation op);
void appendOperation(Context* c, lir::Operation op);
void
appendMemory(Context* c, Value* base, int displacement, Value* index,
unsigned scale, Value* result);
void appendMemory(Context* c,
Value* base,
int displacement,
Value* index,
unsigned scale,
Value* result);
void appendBranch(Context* c,
lir::TernaryOperation op,
@ -161,18 +191,17 @@ void appendJump(Context* c,
bool exit = false,
bool cleanLocals = false);
void
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler);
void appendBoundsCheck(Context* c,
Value* object,
unsigned lengthOffset,
Value* index,
intptr_t handler);
void
appendFrameSite(Context* c, Value* value, int index);
void appendFrameSite(Context* c, Value* value, int index);
void
appendSaveLocals(Context* c);
void appendSaveLocals(Context* c);
void
appendDummy(Context* c);
void appendDummy(Context* c);
void appendBuddy(Context* c, Value* original, Value* buddy);

View File

@ -19,14 +19,15 @@ namespace avian {
namespace codegen {
namespace compiler {
unsigned totalFrameSize(Context* c) {
return c->alignedFrameSize
+ c->arch->frameHeaderSize()
unsigned totalFrameSize(Context* c)
{
return c->alignedFrameSize + c->arch->frameHeaderSize()
+ c->arch->argumentFootprint(c->parameterFootprint);
}
int frameIndex(Context* c, int localIndex) {
assert(c, localIndex >= 0);
int frameIndex(Context* c, int localIndex)
{
assertT(c, localIndex >= 0);
int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1;
@ -36,52 +37,60 @@ int frameIndex(Context* c, int localIndex) {
index -= c->arch->frameFooterSize();
}
assert(c, index >= 0);
assert(c, static_cast<unsigned>(index) < totalFrameSize(c));
assertT(c, index >= 0);
assertT(c, static_cast<unsigned>(index) < totalFrameSize(c));
return index;
}
unsigned frameIndexToOffset(Context* c, unsigned frameIndex) {
assert(c, frameIndex < totalFrameSize(c));
unsigned frameIndexToOffset(Context* c, unsigned frameIndex)
{
assertT(c, frameIndex < totalFrameSize(c));
return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize;
}
unsigned offsetToFrameIndex(Context* c, unsigned offset) {
assert(c,
unsigned offsetToFrameIndex(Context* c, unsigned offset)
{
assertT(c,
static_cast<int>((offset / c->targetInfo.pointerSize)
- c->arch->frameFooterSize()) >= 0);
assert(c,
assertT(c,
((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize())
< totalFrameSize(c));
return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize();
}
unsigned frameBase(Context* c) {
return c->alignedFrameSize
- c->arch->frameReturnAddressSize()
- c->arch->frameFooterSize()
+ c->arch->frameHeaderSize();
unsigned frameBase(Context* c)
{
return c->alignedFrameSize - c->arch->frameReturnAddressSize()
- c->arch->frameFooterSize() + c->arch->frameHeaderSize();
}
FrameIterator::Element::Element(Value* value, unsigned localIndex):
value(value), localIndex(localIndex)
{ }
FrameIterator::Element::Element(Value* value, unsigned localIndex)
: value(value), localIndex(localIndex)
{
}
int FrameIterator::Element::frameIndex(Context* c) {
int FrameIterator::Element::frameIndex(Context* c)
{
return compiler::frameIndex(c, this->localIndex);
}
FrameIterator::FrameIterator(Context* c, Stack* stack, Local* locals,
bool includeEmpty):
stack(stack), locals(locals), localIndex(c->localFootprint - 1),
FrameIterator::FrameIterator(Context* c,
Stack* stack,
Local* locals,
bool includeEmpty)
: stack(stack),
locals(locals),
localIndex(c->localFootprint - 1),
includeEmpty(includeEmpty)
{ }
{
}
bool FrameIterator::hasMore() {
bool FrameIterator::hasMore()
{
if (not includeEmpty) {
while (stack and stack->value == 0) {
stack = stack->next;
@ -95,7 +104,8 @@ bool FrameIterator::hasMore() {
return stack != 0 or localIndex >= 0;
}
FrameIterator::Element FrameIterator::next(Context* c) {
FrameIterator::Element FrameIterator::next(Context* c)
{
Value* v;
unsigned li;
if (stack) {
@ -112,12 +122,11 @@ FrameIterator::Element FrameIterator::next(Context* c) {
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);
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -37,7 +37,9 @@ class FrameIterator {
const unsigned localIndex;
};
FrameIterator(Context* c, Stack* stack, Local* locals,
FrameIterator(Context* c,
Stack* stack,
Local* locals,
bool includeEmpty = false);
bool hasMore();
@ -57,9 +59,10 @@ class Local {
class Stack {
public:
Stack(unsigned index, Value* value, Stack* next):
index(index), value(value), next(next)
{ }
Stack(unsigned index, Value* value, Stack* next)
: index(index), value(value), next(next)
{
}
unsigned index;
Value* value;

View File

@ -23,28 +23,32 @@ LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals)
locals(locals),
machineOffset(0),
/*subroutine(0), */ index(index)
{ }
{
}
LogicalInstruction* LogicalInstruction::next(Context* c) {
LogicalInstruction* LogicalInstruction::next(Context* c)
{
LogicalInstruction* i = this;
for (size_t n = i->index + 1; n < c->logicalCode.count(); ++n) {
i = c->logicalCode[n];
if (i) return i;
if (i)
return i;
}
return 0;
}
unsigned
machineOffset(Context* c, int logicalIp)
unsigned machineOffset(Context* c, int logicalIp)
{
return c->logicalCode[logicalIp]->machineOffset->value();
}
Block::Block(Event* head):
head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
{ }
Block::Block(Event* head)
: 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);
}

View File

@ -26,15 +26,19 @@ class ForkElement {
class ForkState : public Compiler::State {
public:
ForkState(Stack* stack, Local* locals, List<Value*>* saved, Event* predecessor,
unsigned logicalIp):
stack(stack),
ForkState(Stack* stack,
Local* locals,
List<Value*>* saved,
Event* predecessor,
unsigned logicalIp)
: stack(stack),
locals(locals),
saved(saved),
predecessor(predecessor),
logicalIp(logicalIp),
readCount(0)
{ }
{
}
Stack* stack;
Local* locals;

View File

@ -18,15 +18,18 @@ namespace avian {
namespace codegen {
namespace compiler {
CodePromise::CodePromise(Context* c, CodePromise* next):
c(c), offset(0), next(next)
{ }
CodePromise::CodePromise(Context* c, CodePromise* next)
: c(c), offset(0), next(next)
{
}
CodePromise::CodePromise(Context* c, Promise* offset):
c(c), offset(offset), next(0)
{ }
CodePromise::CodePromise(Context* c, Promise* offset)
: c(c), offset(offset), next(0)
{
}
int64_t CodePromise::value() {
int64_t CodePromise::value()
{
if (resolved()) {
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
}
@ -34,43 +37,52 @@ int64_t CodePromise::value() {
abort(c);
}
bool CodePromise::resolved() {
bool CodePromise::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);
}
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);
}
Promise* combinedPromise(Context* c, Promise* low, Promise* high) {
Promise* combinedPromise(Context* c, Promise* low, Promise* 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);
}
class IpPromise : public Promise {
public:
IpPromise(Context* c, int logicalIp):
c(c),
logicalIp(logicalIp)
{ }
IpPromise(Context* c, int logicalIp) : c(c), logicalIp(logicalIp)
{
}
virtual int64_t value() {
virtual int64_t value()
{
if (resolved()) {
return reinterpret_cast<intptr_t>
(c->machineCode + machineOffset(c, logicalIp));
return reinterpret_cast<intptr_t>(c->machineCode
+ machineOffset(c, logicalIp));
}
abort(c);
}
virtual bool resolved() {
virtual bool resolved()
{
return c->machineCode != 0
and c->logicalCode[logicalIp]->machineOffset->resolved();
}
@ -79,16 +91,19 @@ class IpPromise: public Promise {
int logicalIp;
};
Promise* ipPromise(Context* c, int logicalIp) {
Promise* ipPromise(Context* c, int logicalIp)
{
return new (c->zone) IpPromise(c, logicalIp);
}
class PoolPromise : public Promise {
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()) {
return reinterpret_cast<int64_t>(
c->machineCode
@ -99,7 +114,8 @@ class PoolPromise: public Promise {
abort(c);
}
virtual bool resolved() {
virtual bool resolved()
{
return c->machineCode != 0;
}
@ -107,11 +123,11 @@ class PoolPromise: public Promise {
int key;
};
Promise* poolPromise(Context* c, int key) {
Promise* poolPromise(Context* c, int key)
{
return new (c->zone) PoolPromise(c, key);
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -15,7 +15,6 @@ namespace avian {
namespace codegen {
namespace compiler {
class CodePromise : public Promise {
public:
CodePromise(Context* c, CodePromise* next);
@ -33,7 +32,10 @@ class CodePromise: public Promise {
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);

View File

@ -20,43 +20,51 @@ namespace avian {
namespace codegen {
namespace compiler {
SingleRead::SingleRead(const SiteMask& mask, Value* successor)
: next_(0), mask(mask), high_(0), successor_(successor)
{
}
SingleRead::SingleRead(const SiteMask& mask, Value* successor):
next_(0), mask(mask), high_(0), successor_(successor)
{ }
bool SingleRead::intersect(SiteMask* mask, unsigned) {
bool SingleRead::intersect(SiteMask* mask, unsigned)
{
*mask = mask->intersectionWith(this->mask);
return true;
}
Value* SingleRead::high(Context*) {
Value* SingleRead::high(Context*)
{
return high_;
}
Value* SingleRead::successor() {
Value* SingleRead::successor()
{
return successor_;
}
bool SingleRead::valid() {
bool SingleRead::valid()
{
return true;
}
void SingleRead::append(Context* c UNUSED, Read* r) {
assert(c, next_ == 0);
void SingleRead::append(Context* c UNUSED, Read* r)
{
assertT(c, next_ == 0);
next_ = r;
}
Read* SingleRead::next(Context*) {
Read* SingleRead::next(Context*)
{
return next_;
}
MultiRead::MultiRead():
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
{ }
MultiRead::MultiRead()
: 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) {
// short-circuit recursion to avoid poor performance in
// deeply-nested branches
@ -81,11 +89,13 @@ bool MultiRead::intersect(SiteMask* mask, unsigned depth) {
return result;
}
Value* MultiRead::successor() {
Value* MultiRead::successor()
{
return 0;
}
bool MultiRead::valid() {
bool MultiRead::valid()
{
bool result = false;
if (not visited) {
visited = true;
@ -103,7 +113,8 @@ bool MultiRead::valid() {
return result;
}
void MultiRead::append(Context* c, Read* r) {
void MultiRead::append(Context* c, Read* r)
{
List<Read*>* cell = cons<Read*>(c, r, 0);
if (lastRead == 0) {
reads = cell;
@ -112,19 +123,25 @@ void MultiRead::append(Context* c, Read* r) {
}
lastRead = cell;
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
if (false) {
fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
}
lastTarget->item = r;
}
Read* MultiRead::next(Context* c) {
Read* MultiRead::next(Context* c)
{
abort(c);
}
void MultiRead::allocateTarget(Context* c) {
void MultiRead::allocateTarget(Context* c)
{
List<Read*>* cell = cons<Read*>(c, 0, 0);
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
if (false) {
fprintf(stderr, "allocate target for %p: %p\n", this, cell);
}
if (lastTarget) {
lastTarget->next = cell;
@ -134,20 +151,23 @@ void MultiRead::allocateTarget(Context* c) {
lastTarget = cell;
}
Read* MultiRead::nextTarget() {
// fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
Read* MultiRead::nextTarget()
{
if (false) {
fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
}
Read* r = firstTarget->item;
firstTarget = firstTarget->next;
return r;
}
StubRead::StubRead() : next_(0), read(0), visited(false), valid_(true)
{
}
StubRead::StubRead():
next_(0), read(0), visited(false), valid_(true)
{ }
bool StubRead::intersect(SiteMask* mask, unsigned depth) {
bool StubRead::intersect(SiteMask* mask, unsigned depth)
{
if (not visited) {
visited = true;
if (read) {
@ -161,27 +181,31 @@ bool StubRead::intersect(SiteMask* mask, unsigned depth) {
return valid_;
}
Value* StubRead::successor() {
Value* StubRead::successor()
{
return 0;
}
bool StubRead::valid() {
bool StubRead::valid()
{
return valid_;
}
void StubRead::append(Context* c UNUSED, Read* r) {
assert(c, next_ == 0);
void StubRead::append(Context* c UNUSED, Read* r)
{
assertT(c, next_ == 0);
next_ = r;
}
Read* StubRead::next(Context*) {
Read* StubRead::next(Context*)
{
return next_;
}
SingleRead* read(Context* c, const SiteMask& mask, Value* successor) {
assert(c, (mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
SingleRead* read(Context* c, const SiteMask& mask, Value* successor)
{
assertT(c,
(mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
return new (c->zone) SingleRead(mask, successor);
}

View File

@ -22,13 +22,16 @@ class Event;
class Read {
public:
Read():
value(0), event(0), eventNext(0)
{ }
Read() : value(0), event(0), eventNext(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;
@ -43,7 +46,8 @@ class Read {
Read* eventNext;
};
inline bool valid(Read* r) {
inline bool valid(Read* r)
{
return r and r->valid();
}
@ -69,7 +73,6 @@ class SingleRead: public Read {
Value* successor_;
};
class MultiRead : public Read {
public:
MultiRead();
@ -117,7 +120,6 @@ class StubRead: public Read {
SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0);
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -20,27 +20,28 @@ namespace avian {
namespace codegen {
namespace compiler {
RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile):
a(a),
registerFile(registerFile)
{ }
RegisterAllocator::RegisterAllocator(Aborter* a,
const RegisterFile* registerFile)
: a(a), registerFile(registerFile)
{
}
unsigned totalFrameSize(Context* c);
Read* live(Context* c UNUSED, Value* v);
unsigned
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
unsigned resourceCost(Context* c,
Value* v,
Resource* r,
SiteMask mask,
CostCalculator* costCalculator)
{
if (r->reserved or r->freezeCount or r->referenceCount) {
return Target::Impossible;
} else {
unsigned baseCost =
costCalculator ? costCalculator->cost(c, mask) : 0;
unsigned baseCost = costCalculator ? costCalculator->cost(c, mask) : 0;
if (r->value) {
assert(c, r->value->findSite(r->site));
assertT(c, r->value->findSite(r->site));
if (v and r->value->isBuddyOf(v)) {
return baseCost;
@ -55,15 +56,23 @@ resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
}
}
bool
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
unsigned* cost, CostCalculator* costCalculator)
bool pickRegisterTarget(Context* c,
int i,
Value* v,
uint32_t mask,
int* target,
unsigned* cost,
CostCalculator* costCalculator)
{
if ((1 << i) & mask) {
RegisterResource* r = c->registerResources + i;
unsigned myCost = resourceCost
(c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator)
+ Target::MinimumRegisterCost;
unsigned myCost
= resourceCost(
c,
v,
r,
SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex),
costCalculator) + Target::MinimumRegisterCost;
if ((static_cast<uint32_t>(1) << i) == mask) {
*cost = myCost;
@ -76,8 +85,10 @@ pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
return false;
}
int
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
int pickRegisterTarget(Context* c,
Value* v,
uint32_t mask,
unsigned* cost,
CostCalculator* costCalculator)
{
int target = lir::NoRegister;
@ -85,8 +96,8 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
if (mask & c->regFile->generalRegisters.mask) {
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)) {
return i;
}
@ -95,8 +106,8 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
if (mask & c->regFile->floatRegisters.mask) {
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)) {
return i;
}
@ -106,8 +117,9 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
return target;
}
Target
pickRegisterTarget(Context* c, Value* v, uint32_t mask,
Target pickRegisterTarget(Context* c,
Value* v,
uint32_t mask,
CostCalculator* costCalculator)
{
unsigned cost;
@ -115,25 +127,28 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask,
return Target(number, lir::RegisterOperand, cost);
}
unsigned
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator)
unsigned frameCost(Context* c,
Value* v,
int frameIndex,
CostCalculator* costCalculator)
{
return resourceCost
(c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex),
costCalculator)
+ Target::MinimumFrameCost;
return resourceCost(c,
v,
c->frameResources + frameIndex,
SiteMask(1 << lir::MemoryOperand, 0, frameIndex),
costCalculator) + Target::MinimumFrameCost;
}
Target
pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
Target pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
{
Target best;
Value* p = v;
do {
if (p->home >= 0) {
Target mine
(p->home, lir::MemoryOperand, frameCost(c, v, p->home, costCalculator));
Target mine(p->home,
lir::MemoryOperand,
frameCost(c, v, p->home, costCalculator));
if (mine.cost == Target::MinimumFrameCost) {
return mine;
@ -147,8 +162,7 @@ pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
return best;
}
Target
pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
Target pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
{
Target best;
@ -165,14 +179,16 @@ pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
return best;
}
Target
pickTarget(Context* c, Value* value, const SiteMask& mask,
unsigned registerPenalty, Target best,
Target pickTarget(Context* c,
Value* value,
const SiteMask& mask,
unsigned registerPenalty,
Target best,
CostCalculator* costCalculator)
{
if (mask.typeMask & (1 << lir::RegisterOperand)) {
Target mine = pickRegisterTarget
(c, value, mask.registerMask, costCalculator);
Target mine
= pickRegisterTarget(c, value, mask.registerMask, costCalculator);
mine.cost += registerPenalty;
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.frameIndex >= 0) {
Target mine(mask.frameIndex, lir::MemoryOperand,
Target mine(mask.frameIndex,
lir::MemoryOperand,
frameCost(c, value, mask.frameIndex, costCalculator));
if (mine.cost == Target::MinimumFrameCost) {
return mine;
@ -204,13 +221,16 @@ pickTarget(Context* c, Value* value, const SiteMask& mask,
return best;
}
Target
pickTarget(Context* c, Read* read, bool intersectRead,
unsigned registerReserveCount, CostCalculator* costCalculator)
Target pickTarget(Context* c,
Read* read,
bool intersectRead,
unsigned registerReserveCount,
CostCalculator* costCalculator)
{
unsigned registerPenalty
= (c->availableGeneralRegisterCount > registerReserveCount
? 0 : Target::LowRegisterPenalty);
? 0
: Target::LowRegisterPenalty);
Value* value = read->value;
@ -235,8 +255,8 @@ pickTarget(Context* c, Read* read, bool intersectRead,
if (r) {
SiteMask intersection = mask;
if (r->intersect(&intersection)) {
best = pickTarget
(c, value, intersection, registerPenalty, best, costCalculator);
best = pickTarget(
c, value, intersection, registerPenalty, best, costCalculator);
if (best.cost <= Target::MinimumFrameCost) {
return best;
@ -252,14 +272,18 @@ pickTarget(Context* c, Read* read, bool intersectRead,
if (intersectRead) {
if (best.cost == Target::Impossible) {
fprintf(stderr, "mask type %d reg %d frame %d\n",
mask.typeMask, mask.registerMask, mask.frameIndex);
fprintf(stderr,
"mask type %d reg %d frame %d\n",
mask.typeMask,
mask.registerMask,
mask.frameIndex);
abort(c);
}
return best;
}
{ Target mine = pickRegisterTarget(c, value, registerMask, costCalculator);
{
Target mine = pickRegisterTarget(c, value, registerMask, costCalculator);
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) {
return mine;
} else if (mine.cost < best.cost) {
@ -279,13 +304,12 @@ pickTarget(Context* c, Read* read, bool intersectRead,
}
if (best.cost >= Target::StealUniquePenalty
and c->availableGeneralRegisterCount == 0)
{
and c->availableGeneralRegisterCount == 0) {
// there are no free registers left, so moving from memory to
// memory isn't an option - try harder to find an available frame
// site:
best = pickAnyFrameTarget(c, value, costCalculator);
assert(c, best.cost <= 3);
assertT(c, best.cost <= 3);
}
if (best.cost == Target::Impossible) {

View File

@ -33,14 +33,12 @@ class SiteMask;
class Resource;
class Read;
class RegisterAllocator {
public:
Aborter* a;
const RegisterFile* registerFile;
RegisterAllocator(Aborter* a, const RegisterFile* registerFile);
};
class Target {
@ -53,11 +51,14 @@ class Target {
static const unsigned LowRegisterPenalty = 10;
static const unsigned Impossible = 20;
Target(): cost(Impossible) { }
Target() : cost(Impossible)
{
}
Target(int index, lir::OperandType type, unsigned cost):
index(index), type(type), cost(cost)
{ }
Target(int index, lir::OperandType type, unsigned cost)
: index(index), type(type), cost(cost)
{
}
int16_t index;
lir::OperandType type;
@ -69,40 +70,52 @@ class CostCalculator {
virtual unsigned cost(Context* c, SiteMask mask) = 0;
};
unsigned
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
unsigned resourceCost(Context* c,
Value* v,
Resource* r,
SiteMask mask,
CostCalculator* costCalculator);
bool
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
unsigned* cost, CostCalculator* costCalculator = 0);
int
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
bool pickRegisterTarget(Context* c,
int i,
Value* v,
uint32_t mask,
int* target,
unsigned* cost,
CostCalculator* costCalculator = 0);
Target
pickRegisterTarget(Context* c, Value* v, uint32_t mask,
int pickRegisterTarget(Context* c,
Value* v,
uint32_t mask,
unsigned* cost,
CostCalculator* costCalculator = 0);
unsigned
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator);
Target pickRegisterTarget(Context* c,
Value* v,
uint32_t mask,
CostCalculator* costCalculator = 0);
Target
pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
Target
pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
Target
pickTarget(Context* c, Value* value, const SiteMask& mask,
unsigned registerPenalty, Target best,
unsigned frameCost(Context* c,
Value* v,
int frameIndex,
CostCalculator* costCalculator);
Target
pickTarget(Context* c, Read* read, bool intersectRead,
unsigned registerReserveCount, CostCalculator* costCalculator);
Target pickFrameTarget(Context* c, Value* v, 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 codegen

View File

@ -18,160 +18,179 @@ namespace compiler {
const bool DebugResources = false;
void steal(Context* c, Resource* r, Value* thief);
void decrementAvailableGeneralRegisterCount(Context* c) {
assert(c, c->availableGeneralRegisterCount);
void decrementAvailableGeneralRegisterCount(Context* c)
{
assertT(c, c->availableGeneralRegisterCount);
--c->availableGeneralRegisterCount;
if (DebugResources) {
fprintf(stderr, "%d registers available\n",
c->availableGeneralRegisterCount);
fprintf(
stderr, "%d registers available\n", c->availableGeneralRegisterCount);
}
}
void incrementAvailableGeneralRegisterCount(Context* c) {
void incrementAvailableGeneralRegisterCount(Context* c)
{
++c->availableGeneralRegisterCount;
if (DebugResources) {
fprintf(stderr, "%d registers available\n",
c->availableGeneralRegisterCount);
fprintf(
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) {
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);
}
++r->freezeCount;
}
void thawResource(Context* c, Resource* r, Value* v) {
void thawResource(Context* c, Resource* r, Value* v)
{
if (not r->reserved) {
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);
}
assert(c, r->freezeCount);
assertT(c, r->freezeCount);
--r->freezeCount;
}
}
Resource::Resource(bool reserved)
: value(0),
site(0),
previousAcquired(0),
nextAcquired(0),
freezeCount(0),
referenceCount(0),
reserved(reserved)
{
}
Resource::Resource(bool reserved):
value(0), site(0), previousAcquired(0), nextAcquired(0), freezeCount(0),
referenceCount(0), reserved(reserved)
{ }
RegisterResource::RegisterResource(bool reserved) : Resource(reserved)
{
}
RegisterResource::RegisterResource(bool reserved):
Resource(reserved)
{ }
void RegisterResource::freeze(Context* c, Value* v) {
void RegisterResource::freeze(Context* c, Value* v)
{
if (not reserved) {
freezeResource(c, this, v);
if (freezeCount == 1
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
{
and ((1 << index(c)) & c->regFile->generalRegisters.mask)) {
decrementAvailableGeneralRegisterCount(c);
}
}
}
void RegisterResource::thaw(Context* c, Value* v) {
void RegisterResource::thaw(Context* c, Value* v)
{
if (not reserved) {
thawResource(c, this, v);
if (freezeCount == 0
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
{
and ((1 << index(c)) & c->regFile->generalRegisters.mask)) {
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));
}
unsigned RegisterResource::index(Context* c) {
unsigned RegisterResource::index(Context* c)
{
return this - c->registerResources;
}
void RegisterResource::increment(Context* c) {
void RegisterResource::increment(Context* c)
{
if (not this->reserved) {
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);
}
++this->referenceCount;
if (this->referenceCount == 1
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask))
{
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask)) {
decrementAvailableGeneralRegisterCount(c);
}
}
}
void RegisterResource::decrement(Context* c) {
void RegisterResource::decrement(Context* c)
{
if (not this->reserved) {
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);
}
assert(c, this->referenceCount > 0);
assertT(c, this->referenceCount > 0);
--this->referenceCount;
if (this->referenceCount == 0
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask))
{
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask)) {
incrementAvailableGeneralRegisterCount(c);
}
}
}
void FrameResource::freeze(Context* c, Value* v) {
void FrameResource::freeze(Context* c, Value* v)
{
freezeResource(c, this, v);
}
void FrameResource::thaw(Context* c, Value* v) {
void FrameResource::thaw(Context* c, Value* 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));
}
unsigned FrameResource::index(Context* c) {
unsigned FrameResource::index(Context* c)
{
return this - c->frameResources;
}
void acquire(Context* c, Resource* resource, Value* value, Site* site) {
assert(c, value);
assert(c, site);
void acquire(Context* c, Resource* resource, Value* value, Site* site)
{
assertT(c, value);
assertT(c, site);
if (not resource->reserved) {
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);
}
if (resource->value) {
assert(c, resource->value->findSite(resource->site));
assert(c, not value->findSite(resource->site));
assertT(c, resource->value->findSite(resource->site));
assertT(c, not value->findSite(resource->site));
steal(c, resource, value);
}
@ -187,18 +206,23 @@ 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 (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);
}
assert(c, resource->value);
assert(c, resource->site);
assertT(c, resource->value);
assertT(c, resource->site);
assert(c, resource->value->isBuddyOf(value));
assert(c, site == resource->site);
assertT(c, resource->value->isBuddyOf(value));
assertT(c, site == resource->site);
Resource* next = resource->nextAcquired;
if (next) {
@ -211,7 +235,7 @@ void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNU
previous->nextAcquired = next;
resource->previousAcquired = 0;
} else {
assert(c, c->acquiredResources == resource);
assertT(c, c->acquiredResources == resource);
c->acquiredResources = next;
}
@ -220,7 +244,6 @@ void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNU
}
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -21,25 +21,31 @@ namespace avian {
namespace codegen {
namespace compiler {
int intersectFrameIndexes(int a, int b) {
if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex;
if (a == AnyFrameIndex) return b;
if (b == AnyFrameIndex) return a;
if (a == b) return a;
int intersectFrameIndexes(int a, int b)
{
if (a == NoFrameIndex or b == NoFrameIndex)
return NoFrameIndex;
if (a == AnyFrameIndex)
return b;
if (b == AnyFrameIndex)
return a;
if (a == b)
return a;
return NoFrameIndex;
}
SiteMask SiteMask::intersectionWith(const SiteMask& b) {
return SiteMask(typeMask & b.typeMask, registerMask & b.registerMask,
SiteMask SiteMask::intersectionWith(const SiteMask& b)
{
return SiteMask(typeMask & b.typeMask,
registerMask & b.registerMask,
intersectFrameIndexes(frameIndex, b.frameIndex));
}
SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies,
bool includeNextWord):
c(c),
SiteIterator::SiteIterator(Context* c,
Value* v,
bool includeBuddies,
bool includeNextWord)
: c(c),
originalValue(v),
currentValue(v),
includeBuddies(includeBuddies),
@ -47,9 +53,11 @@ SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies,
pass(0),
next_(findNext(&(v->sites))),
previous(0)
{ }
{
}
Site** SiteIterator::findNext(Site** p) {
Site** SiteIterator::findNext(Site** p)
{
while (true) {
if (*p) {
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) {
next_ = findNext(&((*previous)->next));
previous = 0;
@ -91,12 +100,14 @@ bool SiteIterator::hasMore() {
return next_ != 0;
}
Site* SiteIterator::next() {
Site* SiteIterator::next()
{
previous = next_;
return *previous;
}
void SiteIterator::remove(Context* c) {
void SiteIterator::remove(Context* c)
{
(*previous)->release(c, originalValue);
*previous = (*previous)->next;
next_ = findNext(previous);
@ -108,118 +119,135 @@ unsigned Site::registerSize(Context* c)
return c->targetInfo.pointerSize;
}
Site* constantSite(Context* c, Promise* value) {
Site* constantSite(Context* c, Promise* 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));
}
class AddressSite : public Site {
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()) {
return vm::snprintf
(buffer, bufferSize, "address %" LLD, address->value());
return vm::snprintf(
buffer, bufferSize, "address %" LLD, address->value());
} else {
return vm::snprintf(buffer, bufferSize, "address unresolved");
}
}
virtual unsigned copyCost(Context*, Site* s) {
virtual unsigned copyCost(Context*, Site* s)
{
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);
}
virtual bool loneMatch(Context*, const SiteMask&) {
virtual bool loneMatch(Context*, const SiteMask&)
{
return false;
}
virtual bool matchNextWord(Context* c, Site*, unsigned) {
virtual bool matchNextWord(Context* c, Site*, unsigned)
{
abort(c);
}
virtual lir::OperandType type(Context*) {
virtual lir::OperandType type(Context*)
{
return lir::AddressOperand;
}
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
virtual void asAssemblerOperand(Context* c UNUSED,
Site* high UNUSED,
lir::Operand* result)
{
assert(c, high == this);
assertT(c, high == this);
new (result) lir::Address(address);
}
virtual Site* copy(Context* c) {
virtual Site* copy(Context* c)
{
return addressSite(c, address);
}
virtual Site* copyLow(Context* c) {
virtual Site* copyLow(Context* c)
{
abort(c);
}
virtual Site* copyHigh(Context* c) {
virtual Site* copyHigh(Context* c)
{
abort(c);
}
virtual Site* makeNextWord(Context* c, unsigned) {
virtual Site* makeNextWord(Context* c, unsigned)
{
abort(c);
}
virtual SiteMask mask(Context*) {
virtual SiteMask mask(Context*)
{
return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex);
}
virtual SiteMask nextWordMask(Context* c, unsigned) {
virtual SiteMask nextWordMask(Context* c, unsigned)
{
abort(c);
}
Promise* address;
};
Site* addressSite(Context* c, Promise* address) {
Site* addressSite(Context* c, Promise* 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):
mask_(mask), number(number)
{ }
unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize) {
unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize)
{
if (number != lir::NoRegister) {
return vm::snprintf(buffer, bufferSize, "%p register %d", this, number);
} else {
return vm::snprintf(buffer, bufferSize,
"%p register unacquired (mask %d)", this, mask_);
return vm::snprintf(
buffer, bufferSize, "%p register unacquired (mask %d)", this, mask_);
}
}
unsigned RegisterSite::copyCost(Context* c, Site* s) {
assert(c, number != lir::NoRegister);
if (s and
(this == s or
(s->type(c) == lir::RegisterOperand
and (static_cast<RegisterSite*>(s)->mask_ & (1 << number)))))
unsigned RegisterSite::copyCost(Context* c, Site* s)
{
assertT(c, number != lir::NoRegister);
if (s and (this == s
or (s->type(c) == lir::RegisterOperand
and (static_cast<RegisterSite*>(s)->mask_ & (1 << number))))) {
return 0;
} else {
return RegisterCopyCost;
}
}
bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) {
assert(c, number != lir::NoRegister);
bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask)
{
assertT(c, number != lir::NoRegister);
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
return ((static_cast<uint64_t>(1) << number) & mask.registerMask);
@ -228,8 +256,9 @@ bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) {
}
}
bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) {
assert(c, number != lir::NoRegister);
bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask)
{
assertT(c, number != lir::NoRegister);
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
return ((static_cast<uint64_t>(1) << number) == mask.registerMask);
@ -238,8 +267,9 @@ bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) {
}
}
bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
assert(c, number != lir::NoRegister);
bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned)
{
assertT(c, number != lir::NoRegister);
if (s->type(c) != lir::RegisterOperand) {
return false;
@ -248,7 +278,7 @@ bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
RegisterSite* rs = static_cast<RegisterSite*>(s);
unsigned size = rs->registerSize(c);
if (size > c->targetInfo.pointerSize) {
assert(c, number != lir::NoRegister);
assertT(c, number != lir::NoRegister);
return number == rs->number;
} else {
uint32_t mask = c->regFile->generalRegisters.mask;
@ -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;
if (number != lir::NoRegister) {
target = Target(number, lir::RegisterOperand, 0);
@ -271,43 +302,49 @@ void RegisterSite::acquire(Context* c, Value* v) {
number = target.index;
}
void RegisterSite::release(Context* c, Value* v) {
assert(c, number != lir::NoRegister);
void RegisterSite::release(Context* c, Value* v)
{
assertT(c, number != lir::NoRegister);
compiler::release(c, c->registerResources + number, v, this);
}
void RegisterSite::freeze(Context* c, Value* v) {
assert(c, number != lir::NoRegister);
void RegisterSite::freeze(Context* c, Value* v)
{
assertT(c, number != lir::NoRegister);
c->registerResources[number].freeze(c, v);
}
void RegisterSite::thaw(Context* c, Value* v) {
assert(c, number != lir::NoRegister);
void RegisterSite::thaw(Context* c, Value* v)
{
assertT(c, number != lir::NoRegister);
c->registerResources[number].thaw(c, v);
}
bool RegisterSite::frozen(Context* c UNUSED) {
assert(c, number != lir::NoRegister);
bool RegisterSite::frozen(Context* c UNUSED)
{
assertT(c, number != lir::NoRegister);
return c->registerResources[number].freezeCount != 0;
}
lir::OperandType RegisterSite::type(Context*) {
lir::OperandType RegisterSite::type(Context*)
{
return lir::RegisterOperand;
}
void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high,
void RegisterSite::asAssemblerOperand(Context* c UNUSED,
Site* high,
lir::Operand* result)
{
assert(c, number != lir::NoRegister);
assertT(c, number != lir::NoRegister);
int highNumber;
if (high != this) {
highNumber = static_cast<RegisterSite*>(high)->number;
assert(c, highNumber != lir::NoRegister);
assertT(c, highNumber != lir::NoRegister);
} else {
highNumber = lir::NoRegister;
}
@ -315,7 +352,8 @@ void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high,
new (result) lir::Register(number, highNumber);
}
Site* RegisterSite::copy(Context* c) {
Site* RegisterSite::copy(Context* c)
{
uint32_t mask;
if (number != lir::NoRegister) {
@ -327,39 +365,45 @@ Site* RegisterSite::copy(Context* c) {
return freeRegisterSite(c, mask);
}
Site* RegisterSite::copyLow(Context* c) {
Site* RegisterSite::copyLow(Context* c)
{
abort(c);
}
Site* RegisterSite::copyHigh(Context* c) {
Site* RegisterSite::copyHigh(Context* c)
{
abort(c);
}
Site* RegisterSite::makeNextWord(Context* c, unsigned) {
assert(c, number != lir::NoRegister);
assert(c, ((1 << number) & c->regFile->generalRegisters.mask));
Site* RegisterSite::makeNextWord(Context* c, unsigned)
{
assertT(c, number != lir::NoRegister);
assertT(c, ((1 << number) & 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);
}
SiteMask RegisterSite::nextWordMask(Context* c, unsigned) {
assert(c, number != lir::NoRegister);
SiteMask RegisterSite::nextWordMask(Context* c, unsigned)
{
assertT(c, number != lir::NoRegister);
if (registerSize(c) > c->targetInfo.pointerSize) {
return SiteMask
(1 << lir::RegisterOperand, number, NoFrameIndex);
return SiteMask(1 << lir::RegisterOperand, number, NoFrameIndex);
} else {
return SiteMask
(1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex);
return SiteMask(1 << lir::RegisterOperand,
c->regFile->generalRegisters.mask,
NoFrameIndex);
}
}
unsigned RegisterSite::registerSize(Context* c) {
assert(c, number != lir::NoRegister);
unsigned RegisterSite::registerSize(Context* c)
{
assertT(c, number != lir::NoRegister);
if ((1 << number) & c->regFile->floatRegisters.mask) {
return c->arch->floatRegisterSize();
@ -368,70 +412,74 @@ unsigned RegisterSite::registerSize(Context* c) {
}
}
unsigned RegisterSite::registerMask(Context* c UNUSED) {
assert(c, number != lir::NoRegister);
unsigned RegisterSite::registerMask(Context* c UNUSED)
{
assertT(c, number != lir::NoRegister);
return 1 << number;
}
Site* registerSite(Context* c, int number) {
assert(c, number >= 0);
assert(c, (1 << number) & (c->regFile->generalRegisters.mask
Site* registerSite(Context* c, int number)
{
assertT(c, number >= 0);
assertT(c,
(1 << number) & (c->regFile->generalRegisters.mask
| c->regFile->floatRegisters.mask));
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);
}
MemorySite::MemorySite(int base, int offset, int index, unsigned scale):
acquired(false), base(base), offset(offset), index(index), scale(scale)
{ }
MemorySite::MemorySite(int base, int offset, int index, unsigned 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) {
return vm::snprintf(buffer, bufferSize, "memory %d 0x%x %d %d",
base, offset, index, scale);
return vm::snprintf(
buffer, bufferSize, "memory %d 0x%x %d %d", base, offset, index, scale);
} else {
return vm::snprintf(buffer, bufferSize, "memory unacquired");
}
}
unsigned MemorySite::copyCost(Context* c, Site* s) {
assert(c, acquired);
unsigned MemorySite::copyCost(Context* c, Site* s)
{
assertT(c, acquired);
if (s and
(this == s or
(s->type(c) == lir::MemoryOperand
if (s and (this == s or (s->type(c) == lir::MemoryOperand
and static_cast<MemorySite*>(s)->base == base
and static_cast<MemorySite*>(s)->offset == offset
and static_cast<MemorySite*>(s)->index == index
and static_cast<MemorySite*>(s)->scale == scale)))
{
and static_cast<MemorySite*>(s)->scale == scale))) {
return 0;
} else {
return MemoryCopyCost;
}
}
bool MemorySite::conflicts(const SiteMask& mask) {
bool MemorySite::conflicts(const SiteMask& mask)
{
return (mask.typeMask & (1 << lir::RegisterOperand)) != 0
and (((1 << base) & mask.registerMask) == 0
or (index != lir::NoRegister
and ((1 << index) & mask.registerMask) == 0));
}
bool MemorySite::match(Context* c, const SiteMask& mask) {
assert(c, acquired);
bool MemorySite::match(Context* c, const SiteMask& mask)
{
assertT(c, acquired);
if (mask.typeMask & (1 << lir::MemoryOperand)) {
if (mask.frameIndex >= 0) {
if (base == c->arch->stack()) {
assert(c, index == lir::NoRegister);
assertT(c, index == lir::NoRegister);
return static_cast<int>(frameIndexToOffset(c, mask.frameIndex))
== offset;
} else {
@ -445,12 +493,13 @@ bool MemorySite::match(Context* c, const SiteMask& mask) {
}
}
bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
assert(c, acquired);
bool MemorySite::loneMatch(Context* c, const SiteMask& mask)
{
assertT(c, acquired);
if (mask.typeMask & (1 << lir::MemoryOperand)) {
if (base == c->arch->stack()) {
assert(c, index == lir::NoRegister);
assertT(c, index == lir::NoRegister);
if (mask.frameIndex == AnyFrameIndex) {
return false;
@ -462,7 +511,8 @@ bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
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) {
MemorySite* ms = static_cast<MemorySite*>(s);
return ms->base == this->base
@ -480,32 +530,32 @@ 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);
if (index != lir::NoRegister) {
c->registerResources[index].increment(c);
}
if (base == c->arch->stack()) {
assert(c, index == lir::NoRegister);
assert
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
assertT(c, index == lir::NoRegister);
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
compiler::acquire
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
compiler::acquire(
c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
}
acquired = true;
}
void MemorySite::release(Context* c, Value* v) {
void MemorySite::release(Context* c, Value* v)
{
if (base == c->arch->stack()) {
assert(c, index == lir::NoRegister);
assert
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
assertT(c, index == lir::NoRegister);
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
compiler::release
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
compiler::release(
c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
}
c->registerResources[base].decrement(c);
@ -516,7 +566,8 @@ void MemorySite::release(Context* c, Value* v) {
acquired = false;
}
void MemorySite::freeze(Context* c, Value* v) {
void MemorySite::freeze(Context* c, Value* v)
{
if (base == c->arch->stack()) {
c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v);
} else {
@ -527,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()) {
c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v);
} else {
@ -538,20 +590,23 @@ void MemorySite::thaw(Context* c, Value* v) {
}
}
bool MemorySite::frozen(Context* c) {
bool MemorySite::frozen(Context* c)
{
return base == c->arch->stack()
and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0;
}
lir::OperandType MemorySite::type(Context*) {
lir::OperandType MemorySite::type(Context*)
{
return lir::MemoryOperand;
}
void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
void MemorySite::asAssemblerOperand(Context* c UNUSED,
Site* high UNUSED,
lir::Operand* result)
{
// todo: endianness?
assert(c,
assertT(c,
high == this
or (static_cast<MemorySite*>(high)->base == base
and static_cast<MemorySite*>(high)->offset
@ -559,16 +614,18 @@ void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
and static_cast<MemorySite*>(high)->index == index
and static_cast<MemorySite*>(high)->scale == scale));
assert(c, acquired);
assertT(c, acquired);
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);
}
Site* MemorySite::copyHalf(Context* c, bool add) {
Site* MemorySite::copyHalf(Context* c, bool add)
{
if (add) {
return memorySite(
c, base, offset + c->targetInfo.pointerSize, index, scale);
@ -577,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());
}
Site* MemorySite::copyHigh(Context* c) {
Site* MemorySite::copyHigh(Context* c)
{
return copyHalf(c, not c->arch->bigEndian());
}
Site* MemorySite::makeNextWord(Context* c, unsigned index) {
Site* MemorySite::makeNextWord(Context* c, unsigned index)
{
return memorySite(c,
base,
offset + ((index == 1) xor c->arch->bigEndian()
@ -595,16 +655,20 @@ Site* MemorySite::makeNextWord(Context* c, unsigned index) {
scale);
}
SiteMask MemorySite::mask(Context* c) {
return SiteMask(1 << lir::MemoryOperand, 0, (base == c->arch->stack())
SiteMask MemorySite::mask(Context* c)
{
return SiteMask(1 << lir::MemoryOperand,
0,
(base == c->arch->stack())
? static_cast<int>(offsetToFrameIndex(c, offset))
: NoFrameIndex);
}
SiteMask MemorySite::nextWordMask(Context* c, unsigned index) {
SiteMask MemorySite::nextWordMask(Context* c, unsigned index)
{
int frameIndex;
if (base == c->arch->stack()) {
assert(c, this->index == lir::NoRegister);
assertT(c, this->index == lir::NoRegister);
frameIndex = static_cast<int>(offsetToFrameIndex(c, offset))
+ ((index == 1) xor c->arch->bigEndian() ? 1 : -1);
} else {
@ -613,19 +677,28 @@ SiteMask MemorySite::nextWordMask(Context* c, unsigned index) {
return SiteMask(1 << lir::MemoryOperand, 0, frameIndex);
}
bool MemorySite::isVolatile(Context* c) {
bool MemorySite::isVolatile(Context* c)
{
return base != c->arch->stack();
}
MemorySite* memorySite(Context* c, int base, int offset, int index, unsigned scale) {
MemorySite* memorySite(Context* c,
int base,
int offset,
int index,
unsigned scale)
{
return new (c->zone) MemorySite(base, offset, index, scale);
}
MemorySite* frameSite(Context* c, int frameIndex) {
assert(c, frameIndex >= 0);
return memorySite
(c, c->arch->stack(), frameIndexToOffset(c, frameIndex), lir::NoRegister, 0);
MemorySite* frameSite(Context* c, int frameIndex)
{
assertT(c, frameIndex >= 0);
return memorySite(c,
c->arch->stack(),
frameIndexToOffset(c, frameIndex),
lir::NoRegister,
0);
}
} // namespace compiler

View File

@ -30,23 +30,29 @@ const unsigned CopyPenalty = 10;
class SiteMask {
public:
SiteMask(): typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex) { }
SiteMask() : typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex)
{
}
SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex):
typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex)
{ }
SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex)
: typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex)
{
}
SiteMask intersectionWith(const SiteMask& b);
static SiteMask fixedRegisterMask(int number) {
static SiteMask fixedRegisterMask(int number)
{
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);
}
static SiteMask highPart(const OperandMask& mask) {
static SiteMask highPart(const OperandMask& mask)
{
return SiteMask(mask.typeMask, mask.registerMask >> 32, AnyFrameIndex);
}
@ -57,9 +63,14 @@ class SiteMask {
class Site {
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;
@ -71,15 +82,26 @@ class Site {
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;
@ -99,16 +121,24 @@ class Site {
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;
};
class SiteIterator {
public:
SiteIterator(Context* c, Value* v, bool includeBuddies = true,
SiteIterator(Context* c,
Value* v,
bool includeBuddies = true,
bool includeNextWord = true);
Site** findNext(Site** p);
@ -130,43 +160,52 @@ Site* constantSite(Context* c, Promise* value);
Site* constantSite(Context* c, int64_t value);
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 {
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()) {
return vm::snprintf
(buffer, bufferSize, "constant %" LLD, value->value());
return vm::snprintf(buffer, bufferSize, "constant %" LLD, value->value());
} else {
return vm::snprintf(buffer, bufferSize, "constant unresolved");
}
}
virtual unsigned copyCost(Context*, Site* s) {
virtual unsigned copyCost(Context*, Site* s)
{
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);
}
virtual bool loneMatch(Context*, const SiteMask&) {
virtual bool loneMatch(Context*, const SiteMask&)
{
return true;
}
virtual bool matchNextWord(Context* c, Site* s, unsigned) {
virtual bool matchNextWord(Context* c, Site* s, unsigned)
{
return s->type(c) == lir::ConstantOperand;
}
virtual lir::OperandType type(Context*) {
virtual lir::OperandType type(Context*)
{
return lir::ConstantOperand;
}
virtual void asAssemblerOperand(Context* c, Site* high,
lir::Operand* result)
virtual void asAssemblerOperand(Context* c, Site* high, lir::Operand* result)
{
Promise* v = value;
if (high != this) {
@ -175,27 +214,33 @@ class ConstantSite: public Site {
new (result) lir::Constant(v);
}
virtual Site* copy(Context* c) {
virtual Site* copy(Context* c)
{
return constantSite(c, value);
}
virtual Site* copyLow(Context* c) {
virtual Site* copyLow(Context* c)
{
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));
}
virtual Site* makeNextWord(Context* c, unsigned) {
virtual Site* makeNextWord(Context* c, unsigned)
{
abort(c);
}
virtual SiteMask mask(Context*) {
virtual SiteMask mask(Context*)
{
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
}
virtual SiteMask nextWordMask(Context*, unsigned) {
virtual SiteMask nextWordMask(Context*, unsigned)
{
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
}
@ -230,7 +275,8 @@ class RegisterSite: public Site {
virtual lir::OperandType type(Context*);
virtual void asAssemblerOperand(Context* c UNUSED, Site* high,
virtual void asAssemblerOperand(Context* c UNUSED,
Site* high,
lir::Operand* result);
virtual Site* copy(Context* c);
@ -256,7 +302,6 @@ class RegisterSite: public Site {
Site* registerSite(Context* c, int number);
Site* freeRegisterSite(Context* c, uint32_t mask);
class MemorySite : public Site {
public:
MemorySite(int base, int offset, int index, unsigned scale);
@ -285,7 +330,8 @@ class MemorySite: public Site {
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);
virtual Site* copy(Context* c);
@ -311,7 +357,11 @@ class MemorySite: public Site {
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);
} // 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) {
if (s == site) return true;
if (s == site)
return true;
}
return false;
}
bool Value::isBuddyOf(Value* b) {
bool Value::isBuddyOf(Value* b)
{
Value* a = this;
if (a == b) return true;
if (a == b)
return true;
for (Value* p = a->buddy; p != a; p = p->buddy) {
if (p == b) return true;
if (p == b)
return true;
}
return false;
}
void Value::addSite(Context* c, Site* s) {
void Value::addSite(Context* c, Site* s)
{
if (not this->findSite(s)) {
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);
}
s->acquire(c, this);
@ -59,9 +66,9 @@ void Value::addSite(Context* c, Site* s) {
}
}
void Value::grow(Context* c) {
assert(c, this->nextWord == this);
void Value::grow(Context* c)
{
assertT(c, this->nextWord == this);
Value* next = value(c, this->type);
this->nextWord = next;
@ -69,14 +76,15 @@ void Value::grow(Context* c) {
next->wordIndex = 1;
}
void Value::maybeSplit(Context* c) {
void Value::maybeSplit(Context* c)
{
if (this->nextWord == this) {
this->split(c);
}
}
void Value::split(Context* c) {
void Value::split(Context* c)
{
this->grow(c);
for (SiteIterator it(c, this); it.hasMore();) {
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();) {
if (s == it.next()) {
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);
}
it.remove(c);
@ -101,15 +111,17 @@ void Value::removeSite(Context* c, Site* s) {
if (DebugSites) {
fprintf(stderr, "%p has more: %d\n", this, this->hasSite(c));
}
assert(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);
return it.hasMore();
}
bool Value::uniqueSite(Context* c, Site* s) {
bool Value::uniqueSite(Context* c, Site* s)
{
SiteIterator it(c, this);
Site* p UNUSED = it.next();
if (it.hasMore()) {
@ -128,12 +140,13 @@ bool Value::uniqueSite(Context* c, Site* s) {
return false;
}
} else {
assert(c, p == s);
assertT(c, p == s);
return true;
}
}
void Value::clearSites(Context* c) {
void Value::clearSites(Context* c)
{
if (DebugSites) {
fprintf(stderr, "clear sites for %p\n", this);
}
@ -143,9 +156,9 @@ void Value::clearSites(Context* c) {
}
}
#ifndef NDEBUG
bool Value::hasBuddy(Context* c, Value* b) {
bool Value::hasBuddy(Context* c, Value* b)
{
Value* a = this;
if (a == b) {
return true;

View File

@ -63,7 +63,6 @@ class Value : public ir::Value {
#ifndef NDEBUG
bool hasBuddy(Context* c, Value* b);
#endif // not NDEBUG
};
inline bool isFloatValue(ir::Value* a)

View File

@ -13,20 +13,20 @@
namespace avian {
namespace codegen {
unsigned
RegisterMask::maskStart(uint32_t mask)
unsigned RegisterMask::maskStart(uint32_t mask)
{
for (int i = 0; i <= 31; ++i) {
if (mask & (1 << i)) return i;
if (mask & (1 << i))
return i;
}
return 32;
}
unsigned
RegisterMask::maskLimit(uint32_t mask)
unsigned RegisterMask::maskLimit(uint32_t mask)
{
for (int i = 31; i >= 0; --i) {
if (mask & (1 << i)) return i + 1;
if (mask & (1 << i))
return i + 1;
}
return 0;
}

View File

@ -36,7 +36,8 @@ namespace arm {
namespace isa {
// HARDWARE FLAGS
bool vfpSupported() {
bool vfpSupported()
{
// TODO: Use at runtime detection
#if defined(__ARM_PCS_VFP)
// armhf
@ -51,7 +52,10 @@ bool vfpSupported() {
}
} // 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 MyRegisterFileWithFloats(GPR_MASK, FPR_MASK);
@ -59,8 +63,8 @@ const RegisterFile MyRegisterFileWithFloats(GPR_MASK, FPR_MASK);
const unsigned FrameHeaderSize = 1;
const unsigned StackAlignmentInBytes = 8;
const unsigned StackAlignmentInWords
= StackAlignmentInBytes / TargetBytesPerWord;
const unsigned StackAlignmentInWords = StackAlignmentInBytes
/ TargetBytesPerWord;
void resolve(MyBlock*);
@ -74,19 +78,23 @@ using namespace isa;
// END OPERATION COMPILERS
unsigned
argumentFootprint(unsigned footprint)
unsigned argumentFootprint(unsigned footprint)
{
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
}
void
nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
unsigned footprint, void* link, bool,
int targetParameterFootprint UNUSED, void** ip, void** stack)
void nextFrame(ArchitectureContext* con,
uint32_t* start,
unsigned size UNUSED,
unsigned footprint,
void* link,
bool,
int targetParameterFootprint UNUSED,
void** ip,
void** stack)
{
assert(con, *ip >= start);
assert(con, *ip <= start + (size / TargetBytesPerWord));
assertT(con, *ip >= start);
assertT(con, *ip <= start + (size / TargetBytesPerWord));
uint32_t* instruction = static_cast<uint32_t*>(*ip);
@ -125,9 +133,14 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
unsigned value = *instruction & 0xff;
unsigned rotation = (*instruction >> 8) & 0xf;
switch (rotation) {
case 0: offset -= value / TargetBytesPerWord; break;
case 15: offset -= value; break;
default: abort(con);
case 0:
offset -= value / TargetBytesPerWord;
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 {
public:
MyArchitecture(System* system): con(system), referenceCount(0) {
MyArchitecture(System* system) : con(system), referenceCount(0)
{
populateTables(&con);
}
virtual unsigned floatRegisterSize() {
virtual unsigned floatRegisterSize()
{
return vfpSupported() ? 8 : 0;
}
virtual const RegisterFile* registerFile() {
return vfpSupported() ? &MyRegisterFileWithFloats : &MyRegisterFileWithoutFloats;
virtual const RegisterFile* registerFile()
{
return vfpSupported() ? &MyRegisterFileWithFloats
: &MyRegisterFileWithoutFloats;
}
virtual int scratch() {
virtual int scratch()
{
return 5;
}
virtual int stack() {
virtual int stack()
{
return StackRegister;
}
virtual int thread() {
virtual int thread()
{
return ThreadRegister;
}
virtual int returnLow() {
virtual int returnLow()
{
return 0;
}
virtual int returnHigh() {
virtual int returnHigh()
{
return 1;
}
virtual int virtualCallTarget() {
virtual int virtualCallTarget()
{
return 4;
}
virtual int virtualCallIndex() {
virtual int virtualCallIndex()
{
return 3;
}
@ -185,15 +209,18 @@ class MyArchitecture: public Architecture {
return ir::TargetInfo(TargetBytesPerWord);
}
virtual bool bigEndian() {
virtual bool bigEndian()
{
return false;
}
virtual uintptr_t maximumImmediateJump() {
virtual uintptr_t maximumImmediateJump()
{
return 0x1FFFFFF;
}
virtual bool reserved(int register_) {
virtual bool reserved(int register_)
{
switch (register_) {
case LinkRegister:
case StackRegister:
@ -206,15 +233,18 @@ class MyArchitecture: public Architecture {
}
}
virtual unsigned frameFootprint(unsigned footprint) {
virtual unsigned frameFootprint(unsigned footprint)
{
return max(footprint, StackAlignmentInWords);
}
virtual unsigned argumentFootprint(unsigned footprint) {
virtual unsigned argumentFootprint(unsigned footprint)
{
return arm::argumentFootprint(footprint);
}
virtual bool argumentAlignment() {
virtual bool argumentAlignment()
{
#ifdef __APPLE__
return false;
#else
@ -222,7 +252,8 @@ class MyArchitecture: public Architecture {
#endif
}
virtual bool argumentRegisterAlignment() {
virtual bool argumentRegisterAlignment()
{
#ifdef __APPLE__
return false;
#else
@ -230,29 +261,34 @@ class MyArchitecture: public Architecture {
#endif
}
virtual unsigned argumentRegisterCount() {
virtual unsigned argumentRegisterCount()
{
return 4;
}
virtual int argumentRegister(unsigned index) {
assert(&con, index < argumentRegisterCount());
virtual int argumentRegister(unsigned index)
{
assertT(&con, index < argumentRegisterCount());
return index;
}
virtual bool hasLinkRegister() {
virtual bool hasLinkRegister()
{
return true;
}
virtual unsigned stackAlignmentInWords() {
virtual unsigned 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;
return *instruction == static_cast<uint32_t>
(bl(static_cast<uint8_t*>(target)
return *instruction == static_cast<uint32_t>(
bl(static_cast<uint8_t*>(target)
- reinterpret_cast<uint8_t*>(instruction)));
}
@ -265,7 +301,8 @@ class MyArchitecture: public Architecture {
case lir::Jump:
case lir::AlignedCall:
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));
} break;
@ -278,67 +315,90 @@ class MyArchitecture: public Architecture {
= newTarget;
} break;
default: abort(&con);
default:
abort(&con);
}
}
virtual unsigned constantCallSize() {
virtual unsigned constantCallSize()
{
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;
}
virtual unsigned alignFrameSize(unsigned sizeInWords) {
virtual unsigned alignFrameSize(unsigned sizeInWords)
{
return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords)
- FrameHeaderSize;
}
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
void* link, bool mostRecent,
int targetParameterFootprint, void** ip,
virtual void nextFrame(void* start,
unsigned size,
unsigned footprint,
void* link,
bool mostRecent,
int targetParameterFootprint,
void** ip,
void** stack)
{
arm::nextFrame(&con, static_cast<uint32_t*>(start), size, footprint, link,
mostRecent, targetParameterFootprint, ip, stack);
arm::nextFrame(&con,
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;
}
virtual unsigned frameHeaderSize() {
virtual unsigned frameHeaderSize()
{
return FrameHeaderSize;
}
virtual unsigned frameReturnAddressSize() {
virtual unsigned frameReturnAddressSize()
{
return 0;
}
virtual unsigned frameFooterSize() {
virtual unsigned frameFooterSize()
{
return 0;
}
virtual int returnAddressOffset() {
virtual int returnAddressOffset()
{
return -1;
}
virtual int framePointerOffset() {
virtual int framePointerOffset()
{
return 0;
}
virtual bool alwaysCondensed(lir::BinaryOperation) {
virtual bool alwaysCondensed(lir::BinaryOperation)
{
return false;
}
virtual bool alwaysCondensed(lir::TernaryOperation) {
virtual bool alwaysCondensed(lir::TernaryOperation)
{
return false;
}
virtual void plan
(lir::UnaryOperation,
unsigned, OperandMask& aMask,
virtual void plan(lir::UnaryOperation,
unsigned,
OperandMask& aMask,
bool* thunk)
{
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
@ -346,10 +406,11 @@ class MyArchitecture: public Architecture {
*thunk = false;
}
virtual void planSource
(lir::BinaryOperation op,
unsigned aSize, OperandMask& aMask,
unsigned bSize, bool* thunk)
virtual void planSource(lir::BinaryOperation op,
unsigned aSize,
OperandMask& aMask,
unsigned bSize,
bool* thunk)
{
*thunk = false;
aMask.typeMask = ~0;
@ -404,10 +465,11 @@ class MyArchitecture: public Architecture {
}
}
virtual void planDestination
(lir::BinaryOperation op,
unsigned, const OperandMask& aMask,
unsigned, OperandMask& bMask)
virtual void planDestination(lir::BinaryOperation op,
unsigned,
const OperandMask& aMask,
unsigned,
OperandMask& bMask)
{
bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
bMask.registerMask = GPR_MASK64;
@ -443,8 +505,8 @@ class MyArchitecture: public Architecture {
}
}
virtual void planMove
(unsigned, OperandMask& srcMask,
virtual void planMove(unsigned,
OperandMask& srcMask,
OperandMask& tmpMask,
const OperandMask& dstMask)
{
@ -459,20 +521,21 @@ class MyArchitecture: public Architecture {
srcMask.typeMask = 1 << lir::RegisterOperand;
tmpMask.typeMask = 1 << lir::RegisterOperand;
tmpMask.registerMask = GPR_MASK64;
} else if (vfpSupported() &&
dstMask.typeMask & 1 << lir::RegisterOperand &&
dstMask.registerMask & FPR_MASK) {
srcMask.typeMask = tmpMask.typeMask = 1 << lir::RegisterOperand |
1 << lir::MemoryOperand;
} else if (vfpSupported() && dstMask.typeMask & 1 << lir::RegisterOperand
&& dstMask.registerMask & FPR_MASK) {
srcMask.typeMask = tmpMask.typeMask = 1 << lir::RegisterOperand
| 1 << lir::MemoryOperand;
tmpMask.registerMask = ~static_cast<uint64_t>(0);
}
}
virtual void planSource
(lir::TernaryOperation op,
unsigned, OperandMask& aMask,
unsigned bSize, OperandMask& bMask,
unsigned, bool* thunk)
virtual void planSource(lir::TernaryOperation op,
unsigned,
OperandMask& aMask,
unsigned bSize,
OperandMask& bMask,
unsigned,
bool* thunk)
{
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
aMask.registerMask = GPR_MASK64;
@ -486,7 +549,8 @@ class MyArchitecture: public Architecture {
case lir::ShiftLeft:
case lir::ShiftRight:
case lir::UnsignedShiftRight:
if (bSize == 8) aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand);
if (bSize == 8)
aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand);
break;
case lir::Add:
@ -538,11 +602,13 @@ class MyArchitecture: public Architecture {
}
}
virtual void planDestination
(lir::TernaryOperation op,
unsigned, const OperandMask& aMask UNUSED,
unsigned, const OperandMask& bMask,
unsigned, OperandMask& cMask)
virtual void planDestination(lir::TernaryOperation op,
unsigned,
const OperandMask& aMask UNUSED,
unsigned,
const OperandMask& bMask,
unsigned,
OperandMask& cMask)
{
if (isBranch(op)) {
cMask.typeMask = (1 << lir::ConstantOperand);
@ -555,11 +621,13 @@ class MyArchitecture: public Architecture {
virtual Assembler* makeAssembler(Allocator* allocator, Zone* zone);
virtual void acquire() {
virtual void acquire()
{
++referenceCount;
}
virtual void release() {
virtual void release()
{
if (--referenceCount == 0) {
con.s->free(this);
}
@ -571,16 +639,19 @@ class MyArchitecture: public Architecture {
class MyAssembler : public Assembler {
public:
MyAssembler(System* s, Allocator* a, Zone* zone, MyArchitecture* arch):
con(s, a, zone), arch_(arch)
{ }
MyAssembler(System* s, Allocator* a, Zone* zone, MyArchitecture* arch)
: con(s, a, zone), arch_(arch)
{
}
virtual void setClient(Client* client) {
assert(&con, con.client == 0);
virtual void setClient(Client* client)
{
assertT(&con, con.client == 0);
con.client = client;
}
virtual Architecture* arch() {
virtual Architecture* arch()
{
return arch_;
}
@ -590,11 +661,16 @@ class MyAssembler: public Assembler {
lir::Register stack(StackRegister);
lir::Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread);
lir::Constant handlerConstant(new (con.zone) ResolvedPromise(handler));
branchRM(&con, lir::JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit,
branchRM(&con,
lir::JumpIfGreaterOrEqual,
TargetBytesPerWord,
&stack,
&stackLimit,
&handlerConstant);
}
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) {
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset)
{
lir::Register link(LinkRegister);
lir::Memory linkDst(ThreadRegister, ipOffset);
moveRM(&con, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst);
@ -604,7 +680,8 @@ class MyAssembler: public Assembler {
moveRM(&con, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst);
}
virtual void pushFrame(unsigned argumentCount, ...) {
virtual void pushFrame(unsigned argumentCount, ...)
{
struct Argument {
unsigned size;
lir::OperandType type;
@ -612,13 +689,16 @@ class MyAssembler: public Assembler {
};
RUNTIME_ARRAY(Argument, arguments, argumentCount);
va_list a; va_start(a, argumentCount);
va_list a;
va_start(a, argumentCount);
unsigned footprint = 0;
for (unsigned i = 0; i < argumentCount; ++i) {
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*);
footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
TargetBytesPerWord);
}
va_end(a);
@ -630,37 +710,42 @@ class MyAssembler: public Assembler {
lir::Register dst(arch_->argumentRegister(i));
apply(lir::Move,
OperandInfo(
RUNTIME_ARRAY_BODY(arguments)[i].size,
OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size,
RUNTIME_ARRAY_BODY(arguments)[i].type,
RUNTIME_ARRAY_BODY(arguments)[i].operand),
OperandInfo(
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), lir::RegisterOperand, &dst));
OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size,
TargetBytesPerWord),
lir::RegisterOperand,
&dst));
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
TargetBytesPerWord);
} else {
lir::Memory dst(StackRegister, offset * TargetBytesPerWord);
apply(lir::Move,
OperandInfo(
RUNTIME_ARRAY_BODY(arguments)[i].size,
OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size,
RUNTIME_ARRAY_BODY(arguments)[i].type,
RUNTIME_ARRAY_BODY(arguments)[i].operand),
OperandInfo(
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), lir::MemoryOperand, &dst));
OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size,
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;
// larger frames may require multiple subtract/add instructions
// to allocate/deallocate, and nextFrame will need to be taught
// how to handle them:
assert(&con, footprint < 256);
assertT(&con, footprint < 256);
lir::Register stack(StackRegister);
ResolvedPromise footprintPromise(footprint * TargetBytesPerWord);
@ -668,26 +753,34 @@ class MyAssembler: public Assembler {
subC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
lir::Register returnAddress(LinkRegister);
lir::Memory returnAddressDst
(StackRegister, (footprint - 1) * TargetBytesPerWord);
moveRM(&con, TargetBytesPerWord, &returnAddress, TargetBytesPerWord,
lir::Memory returnAddressDst(StackRegister,
(footprint - 1) * TargetBytesPerWord);
moveRM(&con,
TargetBytesPerWord,
&returnAddress,
TargetBytesPerWord,
&returnAddressDst);
}
virtual void adjustFrame(unsigned difference) {
virtual void adjustFrame(unsigned difference)
{
lir::Register stack(StackRegister);
ResolvedPromise differencePromise(difference * TargetBytesPerWord);
lir::Constant differenceConstant(&differencePromise);
subC(&con, TargetBytesPerWord, &differenceConstant, &stack, &stack);
}
virtual void popFrame(unsigned footprint) {
virtual void popFrame(unsigned footprint)
{
footprint += FrameHeaderSize;
lir::Register returnAddress(LinkRegister);
lir::Memory returnAddressSrc
(StackRegister, (footprint - 1) * TargetBytesPerWord);
moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord,
lir::Memory returnAddressSrc(StackRegister,
(footprint - 1) * TargetBytesPerWord);
moveMR(&con,
TargetBytesPerWord,
&returnAddressSrc,
TargetBytesPerWord,
&returnAddress);
lir::Register stack(StackRegister);
@ -701,26 +794,29 @@ class MyAssembler: public Assembler {
int returnAddressSurrogate,
int framePointerSurrogate UNUSED)
{
assert(&con, framePointerSurrogate == lir::NoRegister);
assertT(&con, framePointerSurrogate == lir::NoRegister);
if (TailCalls) {
if (offset) {
footprint += FrameHeaderSize;
lir::Register link(LinkRegister);
lir::Memory returnAddressSrc
(StackRegister, (footprint - 1) * TargetBytesPerWord);
moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord,
lir::Memory returnAddressSrc(StackRegister,
(footprint - 1) * TargetBytesPerWord);
moveMR(&con,
TargetBytesPerWord,
&returnAddressSrc,
TargetBytesPerWord,
&link);
lir::Register stack(StackRegister);
ResolvedPromise footprintPromise
((footprint - offset) * TargetBytesPerWord);
ResolvedPromise footprintPromise((footprint - offset)
* TargetBytesPerWord);
lir::Constant footprintConstant(&footprintPromise);
addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
if (returnAddressSurrogate != lir::NoRegister) {
assert(&con, offset > 0);
assertT(&con, offset > 0);
lir::Register ras(returnAddressSurrogate);
lir::Memory dst(StackRegister, (offset - 1) * TargetBytesPerWord);
@ -739,8 +835,8 @@ class MyAssembler: public Assembler {
{
popFrame(frameFootprint);
assert(&con, argumentFootprint >= StackAlignmentInWords);
assert(&con, (argumentFootprint % StackAlignmentInWords) == 0);
assertT(&con, argumentFootprint >= StackAlignmentInWords);
assertT(&con, (argumentFootprint % StackAlignmentInWords) == 0);
unsigned offset;
if (TailCalls and argumentFootprint > StackAlignmentInWords) {
@ -769,46 +865,52 @@ class MyAssembler: public Assembler {
return_(&con);
}
virtual void apply(lir::Operation op) {
virtual void apply(lir::Operation op)
{
arch_->con.operations[op](&con);
}
virtual void apply(lir::UnaryOperation op, OperandInfo a)
{
arch_->con.unaryOperations[Multimethod::index(op, a.type)]
(&con, a.size, a.operand);
arch_->con.unaryOperations[Multimethod::index(op, a.type)](
&con, a.size, a.operand);
}
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b)
{
arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)]
(&con, a.size, a.operand, b.size, b.operand);
arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)](
&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)) {
assert(&con, a.size == b.size);
assert(&con, c.size == TargetBytesPerWord);
assert(&con, c.type == lir::ConstantOperand);
assertT(&con, a.size == b.size);
assertT(&con, c.size == TargetBytesPerWord);
assertT(&con, c.type == lir::ConstantOperand);
arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)]
(&con, op, a.size, a.operand, b.operand, c.operand);
arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)](
&con, op, a.size, a.operand, b.operand, c.operand);
} else {
assert(&con, b.size == c.size);
assert(&con, b.type == lir::RegisterOperand);
assert(&con, c.type == lir::RegisterOperand);
assertT(&con, b.size == c.size);
assertT(&con, b.type == lir::RegisterOperand);
assertT(&con, c.type == lir::RegisterOperand);
arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)]
(&con, b.size, a.operand, b.operand, c.operand);
arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)](
&con, b.size, a.operand, b.operand, c.operand);
}
}
virtual void setDestination(uint8_t* dst) {
virtual void setDestination(uint8_t* dst)
{
con.result = dst;
}
virtual void write() {
virtual void write()
{
uint8_t* dst = con.result;
unsigned dstOffset = 0;
for (MyBlock* b = con.firstBlock; b; b = b->next) {
@ -828,8 +930,11 @@ class MyAssembler: public Assembler {
unsigned poolSize = 0;
for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) {
if (DebugPool) {
fprintf(stderr, "visit pool offset %p %d in block %p\n",
o, o->offset, b);
fprintf(stderr,
"visit pool offset %p %d in block %p\n",
o,
o->offset,
b);
}
unsigned entry = dstOffset + poolSize;
@ -840,8 +945,8 @@ class MyAssembler: public Assembler {
o->entry->address = dst + entry;
unsigned instruction = o->block->start
+ padding(o->block, o->offset) + o->offset;
unsigned instruction = o->block->start + padding(o->block, o->offset)
+ o->offset;
int32_t v = (entry - 8) - instruction;
expect(&con, v == (v & PoolOffsetMask));
@ -854,8 +959,8 @@ class MyAssembler: public Assembler {
bool jump = needJump(b);
if (jump) {
write4
(dst + dstOffset, isa::b((poolSize + TargetBytesPerWord - 8) >> 2));
write4(dst + dstOffset,
isa::b((poolSize + TargetBytesPerWord - 8) >> 2));
}
dstOffset += poolSize + (jump ? TargetBytesPerWord : 0);
@ -879,20 +984,27 @@ class MyAssembler: public Assembler {
*static_cast<target_uintptr_t*>(e->address) = e->constant->value();
} else {
new (e->constant->listen(sizeof(ConstantPoolListener)))
ConstantPoolListener(con.s, static_cast<target_uintptr_t*>(e->address),
e->callOffset
? dst + e->callOffset->value() + 8
: 0);
ConstantPoolListener(
con.s,
static_cast<target_uintptr_t*>(e->address),
e->callOffset ? dst + e->callOffset->value() + 8 : 0);
}
if (false) {
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);
}
virtual Block* endBlock(bool startNew) {
virtual Block* endBlock(bool startNew)
{
MyBlock* b = con.lastBlock;
b->size = con.code.length() - b->offset;
if (startNew) {
@ -903,7 +1015,8 @@ class MyAssembler: public Assembler {
return b;
}
virtual void endEvent() {
virtual void endEvent()
{
MyBlock* b = con.lastBlock;
unsigned thisEventOffset = con.code.length() - b->offset;
if (b->poolOffsetHead) {
@ -911,18 +1024,24 @@ class MyAssembler: public Assembler {
- b->poolOffsetHead->offset;
if (v > 0 and v != (v & PoolOffsetMask)) {
appendPoolEvent
(&con, b, b->lastEventOffset, b->poolOffsetHead,
appendPoolEvent(&con,
b,
b->lastEventOffset,
b->poolOffsetHead,
b->lastPoolOffsetTail);
if (DebugPool) {
for (PoolOffset* o = b->poolOffsetHead;
o != b->lastPoolOffsetTail->next; o = o->next)
{
o != b->lastPoolOffsetTail->next;
o = o->next) {
fprintf(stderr,
"in endEvent, include %p %d in pool event %p at offset %d "
"in block %p\n",
o, o->offset, b->poolEventTail, b->lastEventOffset, b);
o,
o->offset,
b->poolEventTail,
b->lastEventOffset,
b);
}
}
@ -937,15 +1056,18 @@ class MyAssembler: public Assembler {
b->lastPoolOffsetTail = b->poolOffsetTail;
}
virtual unsigned length() {
virtual unsigned length()
{
return con.code.length();
}
virtual unsigned footerSize() {
virtual unsigned footerSize()
{
return 0;
}
virtual void dispose() {
virtual void dispose()
{
con.code.dispose();
}
@ -953,16 +1075,17 @@ class MyAssembler: public Assembler {
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);
}
} // namespace arm
Architecture*
makeArchitectureArm(System* system, bool)
Architecture* 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

View File

@ -19,13 +19,23 @@ void resolve(MyBlock*);
unsigned padding(MyBlock*, unsigned);
MyBlock::MyBlock(Context* context, unsigned offset):
context(context), next(0), poolOffsetHead(0), poolOffsetTail(0),
lastPoolOffsetTail(0), poolEventHead(0), poolEventTail(0),
lastEventOffset(0), offset(offset), start(~0), size(0)
{ }
MyBlock::MyBlock(Context* context, unsigned offset)
: context(context),
next(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->next = static_cast<MyBlock*>(next);

View File

@ -57,38 +57,52 @@ typedef void (*OperationType)(Context*);
typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*);
typedef void (*BinaryOperationType)
(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*);
typedef void (*TernaryOperationType)
(Context*, unsigned, lir::Operand*, lir::Operand*,
typedef void (*BinaryOperationType)(Context*,
unsigned,
lir::Operand*,
unsigned,
lir::Operand*);
typedef void (*BranchOperationType)
(Context*, lir::TernaryOperation, unsigned, lir::Operand*,
lir::Operand*, lir::Operand*);
typedef void (*TernaryOperationType)(Context*,
unsigned,
lir::Operand*,
lir::Operand*,
lir::Operand*);
typedef void (*BranchOperationType)(Context*,
lir::TernaryOperation,
unsigned,
lir::Operand*,
lir::Operand*,
lir::Operand*);
class ArchitectureContext {
public:
ArchitectureContext(vm::System* s): s(s) { }
ArchitectureContext(vm::System* s) : s(s)
{
}
vm::System* s;
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];
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;
}
inline avian::util::Aborter* getAborter(ArchitectureContext* c) {
inline avian::util::Aborter* getAborter(ArchitectureContext* c)
{
return c->s;
}

View File

@ -25,159 +25,665 @@ const int FPSID = 0x0;
const int FPSCR = 0x1;
const int FPEXC = 0x8;
// 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 };
// INSTRUCTION FORMATS
inline int DATA(int cond, int opcode, int S, int Rn, int Rd, int shift, int Sh, int 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
DATA(int cond, int opcode, int S, int Rn, int Rd, int shift, int Sh, int 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)
{ 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)
{ 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)
{ 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)
{ 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 | 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;}
{
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 | 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
inline int calcU(int imm) { return imm >= 0 ? 1 : 0; }
inline int calcU(int imm)
{
return imm >= 0 ? 1 : 0;
}
// INSTRUCTIONS
// 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 bl(int offset) { return BRANCH(AL, 1, offset); }
inline int bx(int Rm) { return BRANCHX(AL, 0, Rm); }
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 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); }
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 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); }
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); }
inline int b(int offset)
{
return BRANCH(AL, 0, offset);
}
inline int bl(int offset)
{
return BRANCH(AL, 1, offset);
}
inline int bx(int Rm)
{
return BRANCHX(AL, 0, Rm);
}
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 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);
}
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 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);
}
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
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
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 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); }
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 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
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 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); }
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); }
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 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);
}
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
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
inline int fcvtsd(int Sd, int 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); }
inline int fcvtsd(int Sd, int 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
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 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); };
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 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
inline int fmsr(int Sn, int Rd) { 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); }
inline int fmsr(int Sn, int Rd)
{
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
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
inline int fmdrr(int Dm, int Rd, int Rn) { return mcrr(11, 1, Rd, Rn, Dm); }
inline int fmrrd(int Rd, int Rn, int Dm) { return mrrc(11, 1, Rd, Rn, Dm); }
inline int fmdrr(int Dm, int Rd, int Rn)
{
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
inline int SETCOND(int ins, int cond) { return ((ins&0x0fffffff) | (cond<<28)); }
inline int SETS(int ins) { return ins | 1<<20; }
inline int SETCOND(int ins, int cond)
{
return ((ins & 0x0fffffff) | (cond << 28));
}
inline int SETS(int ins)
{
return ins | 1 << 20;
}
// PSEUDO-INSTRUCTIONS
inline int lsl(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSL); }
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); }
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 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); }
inline int lsl(int Rd, int Rm, int Rs)
{
return movsh(Rd, Rm, Rs, LSL);
}
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);
}
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 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:
inline int dmb() { return 0xf57ff05f; }
inline int dmb()
{
return 0xf57ff05f;
}
} // 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 codegen

View File

@ -20,65 +20,78 @@ using namespace util;
unsigned padding(MyBlock*, unsigned);
OffsetPromise::OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace):
con(con), block(block), offset(offset), forTrace(forTrace)
{ }
OffsetPromise::OffsetPromise(Context* con,
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);
}
int64_t OffsetPromise::value() {
assert(con, resolved());
int64_t OffsetPromise::value()
{
assertT(con, resolved());
unsigned o = offset - block->offset;
return block->start + padding
(block, forTrace ? o - vm::TargetBytesPerWord : o) + o;
return block->start
+ padding(block, forTrace ? o - vm::TargetBytesPerWord : o) + o;
}
Promise* offsetPromise(Context* con, bool forTrace) {
return new(con->zone) OffsetPromise(con, con->lastBlock, con->code.length(), forTrace);
Promise* offsetPromise(Context* con, bool 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):
s(s),
instruction(instruction)
{ }
bool OffsetListener::resolve(int64_t value, void** location) {
bool OffsetListener::resolve(int64_t value, void** location)
{
void* p = updateOffset(s, instruction, value);
if (location) *location = p;
if (location)
*location = p;
return false;
}
OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset)
: Task(next), promise(promise), instructionOffset(instructionOffset)
{
}
OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset):
Task(next),
promise(promise),
instructionOffset(instructionOffset)
{ }
void OffsetTask::run(Context* con) {
void OffsetTask::run(Context* con)
{
if (promise->resolved()) {
updateOffset
(con->s, con->result + instructionOffset->value(), promise->value());
updateOffset(
con->s, con->result + instructionOffset->value(), promise->value());
} else {
new (promise->listen(sizeof(OffsetListener)))
OffsetListener(con->s, con->result + instructionOffset->value());
}
}
void appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset) {
con->tasks = new(con->zone) OffsetTask(con->tasks, promise, instructionOffset);
void appendOffsetTask(Context* con,
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;
}
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.
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;
}
ConstantPoolEntry::ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next,
Promise* callOffset):
con(con), constant(constant), next(next), callOffset(callOffset),
ConstantPoolEntry::ConstantPoolEntry(Context* con,
Promise* constant,
ConstantPoolEntry* next,
Promise* callOffset)
: con(con),
constant(constant),
next(next),
callOffset(callOffset),
address(0)
{ }
{
}
int64_t ConstantPoolEntry::value() {
assert(con, resolved());
int64_t ConstantPoolEntry::value()
{
assertT(con, resolved());
return reinterpret_cast<int64_t>(address);
}
bool ConstantPoolEntry::resolved() {
bool ConstantPoolEntry::resolved()
{
return address != 0;
}
ConstantPoolListener::ConstantPoolListener(vm::System* s, vm::target_uintptr_t* address,
uint8_t* returnAddress):
s(s),
address(address),
returnAddress(returnAddress)
{ }
ConstantPoolListener::ConstantPoolListener(vm::System* s,
vm::target_uintptr_t* address,
uint8_t* returnAddress)
: s(s), address(address), returnAddress(returnAddress)
{
}
bool ConstantPoolListener::resolve(int64_t value, void** location) {
bool ConstantPoolListener::resolve(int64_t value, void** location)
{
*address = value;
if (location) {
*location = returnAddress ? static_cast<void*>(returnAddress) : address;
@ -123,32 +145,49 @@ bool ConstantPoolListener::resolve(int64_t value, void** location) {
return true;
}
PoolOffset::PoolOffset(MyBlock* block, ConstantPoolEntry* entry, unsigned offset):
block(block), entry(entry), next(0), offset(offset)
{ }
PoolOffset::PoolOffset(MyBlock* block,
ConstantPoolEntry* entry,
unsigned offset)
: block(block), entry(entry), next(0), offset(offset)
{
}
PoolEvent::PoolEvent(PoolOffset* poolOffsetHead, PoolOffset* poolOffsetTail,
unsigned offset):
poolOffsetHead(poolOffsetHead), poolOffsetTail(poolOffsetTail), next(0),
PoolEvent::PoolEvent(PoolOffset* poolOffsetHead,
PoolOffset* poolOffsetTail,
unsigned offset)
: poolOffsetHead(poolOffsetHead),
poolOffsetTail(poolOffsetTail),
next(0),
offset(offset)
{ }
{
}
void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset) {
void appendConstantPoolEntry(Context* con,
Promise* constant,
Promise* callOffset)
{
if (constant->resolved()) {
// make a copy, since the original might be allocated on the
// stack, and we need our copy to live until assembly is complete
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;
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) {
fprintf(stderr, "add pool offset %p %d to block %p\n",
o, o->offset, con->lastBlock);
fprintf(stderr,
"add pool offset %p %d to block %p\n",
o,
o->offset,
con->lastBlock);
}
if (con->lastBlock->poolOffsetTail) {
@ -159,7 +198,10 @@ void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffse
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)
{
PoolEvent* e = new (con->zone) PoolEvent(head, tail, offset);

View File

@ -31,7 +31,9 @@ const int32_t PoolOffsetMask = 0xFFF;
class Task {
public:
Task(Task* next): next(next) { }
Task(Task* next) : next(next)
{
}
virtual void run(Context* con) = 0;
@ -74,13 +76,17 @@ class OffsetTask: public Task {
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);
class ConstantPoolEntry : public Promise {
public:
ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next,
ConstantPoolEntry(Context* con,
Promise* constant,
ConstantPoolEntry* next,
Promise* callOffset);
virtual int64_t value();
@ -97,7 +103,8 @@ class ConstantPoolEntry: public Promise {
class ConstantPoolListener : public Promise::Listener {
public:
ConstantPoolListener(vm::System* s, vm::target_uintptr_t* address,
ConstantPoolListener(vm::System* s,
vm::target_uintptr_t* address,
uint8_t* returnAddress);
virtual bool resolve(int64_t value, void** location);
@ -119,7 +126,8 @@ class PoolOffset {
class PoolEvent {
public:
PoolEvent(PoolOffset* poolOffsetHead, PoolOffset* poolOffsetTail,
PoolEvent(PoolOffset* poolOffsetHead,
PoolOffset* poolOffsetTail,
unsigned offset);
PoolOffset* poolOffsetHead;
@ -128,9 +136,14 @@ class PoolEvent {
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);
} // namespace arm

View File

@ -25,8 +25,7 @@ unsigned index(ArchitectureContext*,
lir::OperandType operand1,
lir::OperandType operand2)
{
return operation
+ (lir::BinaryOperationCount * operand1)
return operation + (lir::BinaryOperationCount * operand1)
+ (lir::BinaryOperationCount * lir::OperandTypeCount * operand2);
}
@ -34,18 +33,20 @@ unsigned index(ArchitectureContext* con UNUSED,
lir::TernaryOperation operation,
lir::OperandType operand1)
{
assert(con, not isBranch(operation));
assertT(con, not isBranch(operation));
return operation + (lir::NonBranchTernaryOperationCount * operand1);
}
unsigned branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1,
unsigned branchIndex(ArchitectureContext* con UNUSED,
lir::OperandType operand1,
lir::OperandType operand2)
{
return operand1 + (lir::OperandTypeCount * operand2);
}
void populateTables(ArchitectureContext* con) {
void populateTables(ArchitectureContext* con)
{
const lir::OperandType C = lir::ConstantOperand;
const lir::OperandType A = lir::AddressOperand;
const lir::OperandType R = lir::RegisterOperand;

View File

@ -32,7 +32,8 @@ unsigned index(ArchitectureContext* con UNUSED,
lir::TernaryOperation operation,
lir::OperandType operand1);
unsigned branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1,
unsigned branchIndex(ArchitectureContext* con UNUSED,
lir::OperandType operand1,
lir::OperandType operand2);
void populateTables(ArchitectureContext* con);

File diff suppressed because it is too large Load Diff

View File

@ -25,51 +25,87 @@ class Context;
// shortcut functions
inline int newTemp(Context* con) {
inline int newTemp(Context* con)
{
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);
}
inline void freeTemp(Context* con, int r) {
inline void freeTemp(Context* con, int r)
{
con->client->releaseTemporary(r);
}
inline int64_t getValue(lir::Constant* con) {
inline int64_t getValue(lir::Constant* con)
{
return con->value->value();
}
inline lir::Register makeTemp(Context* con) {
inline lir::Register makeTemp(Context* con)
{
lir::Register tmp(newTemp(con));
return tmp;
}
inline lir::Register makeTemp64(Context* con) {
inline lir::Register makeTemp64(Context* con)
{
lir::Register tmp(newTemp(con), newTemp(con));
return 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);
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);
}
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,
unsigned dstSize, lir::Register* dst);
void moveRR(Context* con,
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);
@ -79,142 +115,297 @@ void resolve(MyBlock* b);
void jumpR(Context* con, unsigned size UNUSED, lir::Register* target);
void swapRR(Context* con, unsigned aSize, lir::Register* a,
unsigned bSize, lir::Register* b);
void swapRR(Context* con,
unsigned aSize,
lir::Register* a,
unsigned bSize,
lir::Register* b);
void moveRR(Context* con, unsigned srcSize, lir::Register* src,
unsigned dstSize, lir::Register* dst);
void moveRR(Context* con,
unsigned srcSize,
lir::Register* src,
unsigned dstSize,
lir::Register* dst);
void moveZRR(Context* con, unsigned srcSize, lir::Register* src,
unsigned, lir::Register* dst);
void moveZRR(Context* con,
unsigned srcSize,
lir::Register* src,
unsigned,
lir::Register* dst);
void moveCR(Context* con, unsigned size, lir::Constant* src,
unsigned, lir::Register* dst);
void moveCR(Context* con,
unsigned size,
lir::Constant* src,
unsigned,
lir::Register* dst);
void moveCR2(Context* con, unsigned size, lir::Constant* src,
lir::Register* dst, Promise* callOffset);
void moveCR2(Context* con,
unsigned size,
lir::Constant* src,
lir::Register* dst,
Promise* callOffset);
void moveCR(Context* con, unsigned size, lir::Constant* src,
unsigned, lir::Register* dst);
void moveCR(Context* con,
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,
lir::Register* b, lir::Register* dst);
void addC(Context* con,
unsigned size,
lir::Constant* a,
lir::Register* b,
lir::Register* dst);
void subC(Context* con, unsigned size, lir::Constant* a,
lir::Register* b, lir::Register* dst);
void subC(Context* con,
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,
bool* preserveIndex, bool* release);
int normalize(Context* con,
int offset,
int index,
unsigned scale,
bool* preserveIndex,
bool* release);
void store(Context* con, unsigned size, lir::Register* src,
int base, int offset, int index, unsigned scale, bool preserveIndex);
void store(Context* con,
unsigned size,
lir::Register* src,
int base,
int offset,
int index,
unsigned scale,
bool preserveIndex);
void moveRM(Context* con, unsigned srcSize, lir::Register* src,
unsigned dstSize UNUSED, lir::Memory* dst);
void moveRM(Context* con,
unsigned srcSize,
lir::Register* src,
unsigned dstSize UNUSED,
lir::Memory* dst);
void load(Context* con, unsigned srcSize, int base, int offset, int index,
unsigned scale, unsigned dstSize, lir::Register* dst,
bool preserveIndex, bool signExtend);
void load(Context* con,
unsigned srcSize,
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,
unsigned dstSize, lir::Register* dst);
void moveMR(Context* con,
unsigned srcSize,
lir::Memory* src,
unsigned dstSize,
lir::Register* dst);
void moveZMR(Context* con, unsigned srcSize, lir::Memory* src,
unsigned dstSize, lir::Register* dst);
void moveZMR(Context* con,
unsigned srcSize,
lir::Memory* src,
unsigned dstSize,
lir::Register* dst);
void andR(Context* con, unsigned size, lir::Register* a,
lir::Register* b, lir::Register* dst);
void andR(Context* con,
unsigned size,
lir::Register* a,
lir::Register* b,
lir::Register* dst);
void andC(Context* con, unsigned size, lir::Constant* a,
lir::Register* b, lir::Register* dst);
void andC(Context* con,
unsigned size,
lir::Constant* a,
lir::Register* b,
lir::Register* dst);
void orR(Context* con, unsigned size, lir::Register* a,
lir::Register* b, lir::Register* dst);
void orR(Context* con,
unsigned size,
lir::Register* a,
lir::Register* b,
lir::Register* dst);
void xorR(Context* con, unsigned size, lir::Register* a,
lir::Register* b, lir::Register* dst);
void xorR(Context* con,
unsigned size,
lir::Register* a,
lir::Register* b,
lir::Register* dst);
void moveAR2(Context* con, unsigned srcSize, lir::Address* src,
unsigned dstSize, lir::Register* dst);
void moveAR2(Context* con,
unsigned srcSize,
lir::Address* src,
unsigned dstSize,
lir::Register* dst);
void moveAR(Context* con, unsigned srcSize, lir::Address* src,
unsigned dstSize, lir::Register* dst);
void moveAR(Context* con,
unsigned srcSize,
lir::Address* src,
unsigned dstSize,
lir::Register* dst);
void compareRR(Context* con, unsigned aSize, lir::Register* a,
unsigned bSize UNUSED, lir::Register* b);
void compareRR(Context* con,
unsigned aSize,
lir::Register* a,
unsigned bSize UNUSED,
lir::Register* b);
void compareCR(Context* con, unsigned aSize, lir::Constant* a,
unsigned bSize, lir::Register* b);
void compareCR(Context* con,
unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Register* b);
void compareCM(Context* con, unsigned aSize, lir::Constant* a,
unsigned bSize, lir::Memory* b);
void compareCM(Context* con,
unsigned aSize,
lir::Constant* a,
unsigned bSize,
lir::Memory* b);
void compareRM(Context* con, unsigned aSize, lir::Register* a,
unsigned bSize, lir::Memory* b);
void compareRM(Context* con,
unsigned aSize,
lir::Register* a,
unsigned bSize,
lir::Memory* b);
int32_t
branch(Context* con, lir::TernaryOperation op);
int32_t branch(Context* con, lir::TernaryOperation op);
void conditional(Context* con, int32_t branch, lir::Constant* target);
void branch(Context* con, lir::TernaryOperation op, lir::Constant* target);
void branchLong(Context* con, lir::TernaryOperation op, lir::Operand* al,
lir::Operand* ah, lir::Operand* bl,
lir::Operand* bh, lir::Constant* target,
void branchLong(Context* con,
lir::TernaryOperation op,
lir::Operand* al,
lir::Operand* ah,
lir::Operand* bl,
lir::Operand* bh,
lir::Constant* target,
BinaryOperationType compareSigned,
BinaryOperationType compareUnsigned);
void branchRR(Context* con, lir::TernaryOperation op, unsigned size,
lir::Register* a, lir::Register* b,
void branchRR(Context* con,
lir::TernaryOperation op,
unsigned size,
lir::Register* a,
lir::Register* b,
lir::Constant* target);
void branchCR(Context* con, lir::TernaryOperation op, unsigned size,
lir::Constant* a, lir::Register* b,
void branchCR(Context* con,
lir::TernaryOperation op,
unsigned size,
lir::Constant* a,
lir::Register* b,
lir::Constant* target);
void branchRM(Context* con, lir::TernaryOperation op, unsigned size,
lir::Register* a, lir::Memory* b,
void branchRM(Context* con,
lir::TernaryOperation op,
unsigned size,
lir::Register* a,
lir::Memory* b,
lir::Constant* target);
void branchCM(Context* con, lir::TernaryOperation op, unsigned size,
lir::Constant* a, lir::Memory* b,
void branchCM(Context* con,
lir::TernaryOperation op,
unsigned size,
lir::Constant* a,
lir::Memory* b,
lir::Constant* target);
ShiftMaskPromise*
shiftMaskPromise(Context* con, Promise* base, unsigned shift, int64_t mask);
ShiftMaskPromise* shiftMaskPromise(Context* con,
Promise* base,
unsigned shift,
int64_t mask);
void moveCM(Context* con, unsigned srcSize, lir::Constant* src,
unsigned dstSize, lir::Memory* dst);
void moveCM(Context* con,
unsigned srcSize,
lir::Constant* src,
unsigned dstSize,
lir::Memory* dst);
void negateRR(Context* con, unsigned srcSize, lir::Register* src,
unsigned dstSize UNUSED, lir::Register* dst);
void negateRR(Context* con,
unsigned srcSize,
lir::Register* src,
unsigned dstSize UNUSED,
lir::Register* dst);
void callR(Context* con, unsigned size UNUSED, lir::Register* target);
@ -241,4 +432,3 @@ void storeLoadBarrier(Context*);
} // namespace avian
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H

View File

@ -18,7 +18,6 @@ namespace avian {
namespace codegen {
namespace arm {
const uint64_t MASK_LO32 = 0xffffffff;
const unsigned MASK_LO16 = 0xffff;
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 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;
}
inline int fpr64(int reg) { return reg - N_GPRS; }
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; }
inline int fpr64(int reg)
{
return reg - N_GPRS;
}
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 StackRegister = 13;

View File

@ -11,13 +11,14 @@
#ifndef AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
#define AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
namespace avian {
namespace codegen {
class Multimethod {
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);
}
};
@ -26,4 +27,3 @@ public:
} // namespace avian
#endif // AVIAN_CODEGEN_TARGET_MULTIMETHOD_H

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