mirror of
https://github.com/corda/corda.git
synced 2025-01-21 03:55:00 +00:00
Merge pull request #289 from joshuawarner32/refactor-type-gen
Refactor type generator
This commit is contained in:
commit
a80ac91728
@ -11,7 +11,7 @@
|
||||
package avian;
|
||||
|
||||
public class Addendum {
|
||||
public Object pool;
|
||||
public Singleton pool;
|
||||
public Object annotationTable;
|
||||
public Object signature;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
5
classpath/avian/Code.java
Normal file
5
classpath/avian/Code.java
Normal file
@ -0,0 +1,5 @@
|
||||
package avian;
|
||||
|
||||
abstract class Code {
|
||||
// VM-visible fields in types.def
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)};
|
||||
|
||||
|
@ -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') {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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++;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
57
include/avian/util/hash.h
Normal 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
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
9
makefile
9
makefile
@ -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)
|
||||
|
@ -11,8 +11,7 @@ struct JniConstants {
|
||||
static void init(_JNIEnv* env);
|
||||
};
|
||||
|
||||
void
|
||||
JniConstants::init(_JNIEnv*)
|
||||
void JniConstants::init(_JNIEnv*)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -30,4 +30,3 @@
|
||||
#define AVIAN_ARCH_ARM (3 << 8)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -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(¤tSize))
|
||||
{ }
|
||||
Iterator(Finder* finder)
|
||||
: it(finder->iterator()), current(it->next(¤tSize))
|
||||
{
|
||||
}
|
||||
|
||||
~Iterator() {
|
||||
~Iterator()
|
||||
{
|
||||
it->dispose();
|
||||
}
|
||||
|
||||
bool hasMore() {
|
||||
if (current) return true;
|
||||
bool hasMore()
|
||||
{
|
||||
if (current)
|
||||
return true;
|
||||
current = it->next(¤tSize);
|
||||
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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -27,8 +27,7 @@
|
||||
|
||||
namespace vm {
|
||||
|
||||
void
|
||||
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
|
||||
void populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
|
||||
|
||||
} // namespace vm
|
||||
|
||||
|
@ -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;
|
||||
|
3428
src/avian/machine.h
3428
src/avian/machine.h
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
119
src/avian/util.h
119
src/avian/util.h
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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_);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
18
src/boot.cpp
18
src/boot.cpp
@ -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
|
||||
|
@ -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);
|
||||
|
791
src/builtin.cpp
791
src/builtin.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user