Merge branch 'master' of oss.readytalk.com:/var/local/git/avian

This commit is contained in:
Joel Dice 2010-06-15 18:27:51 -06:00
commit 1b31fb67e1
24 changed files with 807 additions and 611 deletions

6
.gitignore vendored
View File

@ -1,3 +1,7 @@
.gdb_history
build
*~
*~
.classpath
.project
.settings
bin

100
classpath/avian/Utf8.java Normal file
View File

@ -0,0 +1,100 @@
/* Copyright (c) 2010, 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. */
package avian;
import java.io.ByteArrayOutputStream;
public class Utf8 {
public static boolean test(Object data) {
if (!(data instanceof byte[])) return false;
byte[] b = (byte[])data;
for (int i = 0; i < b.length; ++i) {
if (((int)b[i] & 0x080) != 0) return true;
}
return false;
}
public static byte[] encode(char[] s16, int offset, int length) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
for (int i = offset; i < offset+length; ++i) {
char c = s16[i];
if (c == '\u0000') { // null char
buf.write(0);
buf.write(0);
} else if (c < 0x080) { // 1 byte char
buf.write(c);
} else if (c < 0x0800) { // 2 byte char
buf.write(0x0c0 | (c >>> 6));
buf.write(0x080 | (c & 0x03f));
} else { // 3 byte char
buf.write(0x0e0 | ((c >>> 12) & 0x0f));
buf.write(0x080 | ((c >>> 6) & 0x03f));
buf.write(0x080 | (c & 0x03f));
}
}
return buf.toByteArray();
}
public static Object decode(byte[] s8, int offset, int length) {
Object buf = new byte[length];
boolean isMultiByte = false;
int i=offset, j=0;
while (i < offset+length) {
int x = s8[i++];
if ((x & 0x080) == 0x0) { // 1 byte char
if (x == 0) ++i; // 2 byte null char
cram(buf, j++, x);
} else if ((x & 0x0e0) == 0x0c0) { // 2 byte char
if (!isMultiByte) {
buf = widen(buf, j, length-1);
isMultiByte = true;
}
int y = s8[i++];
cram(buf, j++, ((x & 0x1f) << 6) | (y & 0x3f));
} else if ((x & 0x0f0) == 0x0e0) { // 3 byte char
if (!isMultiByte) {
buf = widen(buf, j, length-2);
isMultiByte = true;
}
int y = s8[i++]; int z = s8[i++];
cram(buf, j++, ((x & 0xf) << 12) | ((y & 0x3f) << 6) | (z & 0x3f));
}
}
return trim(buf, j);
}
public static char[] decode16(byte[] s8, int offset, int length) {
Object decoded = decode(s8, offset, length);
if (decoded instanceof char[]) return (char[])decoded;
return (char[])widen(decoded, length, length);
}
private static void cram(Object data, int index, int val) {
if (data instanceof byte[]) ((byte[])data)[index] = (byte)val;
else ((char[])data)[index] = (char)val;
}
private static Object widen(Object data, int length, int capacity) {
byte[] src = (byte[])data;
char[] result = new char[capacity];
for (int i = 0; i < length; ++i) result[i] = (char)((int)src[i] & 0x0ff);
return result;
}
private static Object trim(Object data, int length) {
if (data instanceof byte[]) return data;
if (((char[])data).length == length) return data;
char[] result = new char[length];
System.arraycopy(data, 0, result, 0, length);
return result;
}
}

View File

@ -28,10 +28,11 @@
# define CLOSE _close
# define READ _read
# define WRITE _write
# define STAT _stat
# define STAT _wstat
# define STRUCT_STAT struct _stat
# define MKDIR(path, mode) _mkdir(path)
# define UNLINK _unlink
# define MKDIR(path, mode) _wmkdir(path)
# define UNLINK _wunlink
# define RENAME _wrename
# define OPEN_MASK O_BINARY
# ifdef _MSC_VER
@ -40,10 +41,15 @@
# define S_IRUSR _S_IREAD
# define S_IWUSR _S_IWRITE
# else
# define OPEN _open
# define CREAT _creat
# define OPEN _wopen
# define CREAT _wcreat
# endif
# define GET_CHARS GetStringChars
# define RELEASE_CHARS(path, chars) ReleaseStringChars(path, reinterpret_cast<const jchar*>(chars))
typedef wchar_t char_t;
#else // not PLATFORM_WINDOWS
# include <dirent.h>
@ -59,42 +65,50 @@
# define MKDIR mkdir
# define CREAT creat
# define UNLINK unlink
# define RENAME rename
# define OPEN_MASK 0
# define GET_CHARS GetStringUTFChars
# define RELEASE_CHARS ReleaseStringUTFChars
typedef char char_t;
#endif // not PLATFORM_WINDOWS
inline void* operator new(size_t, void* p) throw() { return p; }
typedef const char_t* string_t;
namespace {
#ifdef _MSC_VER
inline int
OPEN(const char* path, int mask, int mode)
inline int
OPEN(string_t path, int mask, int mode)
{
int fd;
if (_sopen_s(&fd, path, mask, _SH_DENYNO, mode) == 0) {
return fd;
int fd;
if (_wsopen_s(&fd, path, mask, _SH_DENYNO, mode) == 0) {
return fd;
} else {
return -1;
return -1;
}
}
inline int
CREAT(const char* path, int mode)
CREAT(string_t path, int mode)
{
return OPEN(path, _O_CREAT, mode);
}
#endif
inline bool
exists(const char* path)
exists(string_t path)
{
STRUCT_STAT s;
return STAT(path, &s) == 0;
}
inline int
doOpen(JNIEnv* e, const char* path, int mask)
doOpen(JNIEnv* e, string_t path, int mask)
{
int fd = OPEN(path, mask | OPEN_MASK, S_IRUSR | S_IWUSR);
if (fd == -1) {
@ -157,11 +171,11 @@ class Mapping {
};
inline Mapping*
map(JNIEnv* e, const char* path)
map(JNIEnv* e, string_t path)
{
Mapping* result = 0;
HANDLE file = CreateFile(path, FILE_READ_DATA, FILE_SHARE_READ, 0,
OPEN_EXISTING, 0, 0);
HANDLE file = CreateFileW(path, FILE_READ_DATA, FILE_SHARE_READ, 0,
OPEN_EXISTING, 0, 0);
if (file != INVALID_HANDLE_VALUE) {
unsigned size = GetFileSize(file, 0);
if (size != INVALID_FILE_SIZE) {
@ -205,10 +219,10 @@ class Directory {
public:
Directory(): handle(0), findNext(false) { }
virtual const char* next() {
virtual string_t next() {
if (handle and handle != INVALID_HANDLE_VALUE) {
if (findNext) {
if (FindNextFile(handle, &data)) {
if (FindNextFileW(handle, &data)) {
return data.cFileName;
}
} else {
@ -227,7 +241,7 @@ class Directory {
}
HANDLE handle;
WIN32_FIND_DATA data;
WIN32_FIND_DATAW data;
bool findNext;
};
@ -245,7 +259,7 @@ class Mapping {
};
inline Mapping*
map(JNIEnv* e, const char* path)
map(JNIEnv* e, string_t path)
{
Mapping* result = 0;
int fd = open(path, O_RDONLY);
@ -280,6 +294,14 @@ unmap(JNIEnv*, Mapping* mapping)
} // namespace
inline string_t getChars(JNIEnv* e, jstring path) {
return reinterpret_cast<string_t>(e->GET_CHARS(path, 0));
}
inline void releaseChars(JNIEnv* e, jstring path, string_t chars) {
e->RELEASE_CHARS(path, chars);
}
extern "C" JNIEXPORT jstring JNICALL
Java_java_io_File_toCanonicalPath(JNIEnv* /*e*/, jclass, jstring path)
{
@ -297,14 +319,14 @@ Java_java_io_File_toAbsolutePath(JNIEnv* /*e*/, jclass, jstring path)
extern "C" JNIEXPORT jlong JNICALL
Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
STRUCT_STAT s;
int r = STAT(chars, &s);
if (r == 0) {
return s.st_size;
}
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
}
return -1;
@ -313,7 +335,7 @@ Java_java_io_File_length(JNIEnv* e, jclass, jstring path)
extern "C" JNIEXPORT void JNICALL
Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
if (not exists(chars)) {
int r = ::MKDIR(chars, 0700);
@ -321,14 +343,14 @@ Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path)
throwNewErrno(e, "java/io/IOException");
}
}
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
}
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
if (not exists(chars)) {
int fd = CREAT(chars, 0600);
@ -338,38 +360,38 @@ Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path)
doClose(e, fd);
}
}
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
}
}
extern "C" JNIEXPORT void JNICALL
Java_java_io_File_delete(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
int r = UNLINK(chars);
if (r != 0) {
throwNewErrno(e, "java/io/IOException");
}
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
}
}
extern "C" JNIEXPORT jboolean JNICALL
Java_java_io_File_rename(JNIEnv* e, jclass, jstring old, jstring new_)
{
const char* oldChars = e->GetStringUTFChars(old, 0);
const char* newChars = e->GetStringUTFChars(new_, 0);
string_t oldChars = getChars(e, old);
string_t newChars = getChars(e, new_);
if (oldChars) {
bool v;
if (newChars) {
v = rename(oldChars, newChars) == 0;
v = RENAME(oldChars, newChars) == 0;
e->ReleaseStringUTFChars(new_, newChars);
releaseChars(e, new_, newChars);
} else {
v = false;
}
e->ReleaseStringUTFChars(old, oldChars);
releaseChars(e, old, oldChars);
return v;
} else {
return false;
@ -379,12 +401,12 @@ Java_java_io_File_rename(JNIEnv* e, jclass, jstring old, jstring new_)
extern "C" JNIEXPORT jboolean JNICALL
Java_java_io_File_isDirectory(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
STRUCT_STAT s;
int r = STAT(chars, &s);
bool v = (r == 0 and S_ISDIR(s.st_mode));
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
return v;
} else {
return false;
@ -394,12 +416,12 @@ Java_java_io_File_isDirectory(JNIEnv* e, jclass, jstring path)
extern "C" JNIEXPORT jboolean JNICALL
Java_java_io_File_isFile(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
STRUCT_STAT s;
int r = STAT(chars, &s);
bool v = (r == 0 and S_ISREG(s.st_mode));
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
return v;
} else {
return false;
@ -409,10 +431,10 @@ Java_java_io_File_isFile(JNIEnv* e, jclass, jstring path)
extern "C" JNIEXPORT jboolean JNICALL
Java_java_io_File_exists(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
bool v = exists(chars);
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
return v;
} else {
return false;
@ -424,18 +446,19 @@ Java_java_io_File_exists(JNIEnv* e, jclass, jstring path)
extern "C" JNIEXPORT jlong JNICALL
Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
unsigned length = strlen(chars);
unsigned length = wcslen(chars);
unsigned size = length * sizeof(char_t);
RUNTIME_ARRAY(char, buffer, length + 3);
memcpy(RUNTIME_ARRAY_BODY(buffer), chars, length);
memcpy(RUNTIME_ARRAY_BODY(buffer) + length, "\\*", 3);
RUNTIME_ARRAY(char_t, buffer, length + 3);
memcpy(RUNTIME_ARRAY_BODY(buffer), chars, size);
memcpy(RUNTIME_ARRAY_BODY(buffer) + length, L"\\*", 6);
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
Directory* d = new (malloc(sizeof(Directory))) Directory;
d->handle = FindFirstFile(RUNTIME_ARRAY_BODY(buffer), &(d->data));
d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data));
if (d->handle == INVALID_HANDLE_VALUE) {
d->dispose();
d = 0;
@ -451,14 +474,14 @@ extern "C" JNIEXPORT jstring JNICALL
Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle)
{
Directory* d = reinterpret_cast<Directory*>(handle);
while (true) {
const char* s = d->next();
string_t s = d->next();
if (s) {
if (strcmp(s, ".") == 0 || strcmp(s, "..") == 0) {
if (wcscmp(s, L".") == 0 || wcscmp(s, L"..") == 0) {
// skip . or .. and try again
} else {
return e->NewStringUTF(s);
return e->NewString(reinterpret_cast<const jchar*>(s), wcslen(s));
}
} else {
return 0;
@ -477,10 +500,10 @@ Java_java_io_File_closeDir(JNIEnv* , jclass, jlong handle)
extern "C" JNIEXPORT jlong JNICALL
Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
jlong handle = reinterpret_cast<jlong>(opendir(chars));
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
return handle;
} else {
return 0;
@ -522,13 +545,13 @@ Java_java_io_File_closeDir(JNIEnv* , jclass, jlong handle)
extern "C" JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_open(JNIEnv* e, jclass, jstring path)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
int fd = doOpen(e, chars, O_RDONLY);
e->ReleaseStringUTFChars(path, chars);
return fd;
releaseChars(e, path, chars);
return fd;
} else {
return -1;
return -1;
}
}
@ -572,10 +595,10 @@ 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)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
int fd = doOpen(e, chars, O_WRONLY | O_CREAT | O_TRUNC);
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
return fd;
} else {
return -1;
@ -618,7 +641,7 @@ extern "C" JNIEXPORT void JNICALL
Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
jlongArray result)
{
const char* chars = e->GetStringUTFChars(path, 0);
string_t chars = getChars(e, path);
if (chars) {
Mapping* mapping = map(e, chars);
@ -628,7 +651,7 @@ Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
jlong length = (mapping ? mapping->length : 0);
e->SetLongArrayRegion(result, 1, 1, &length);
e->ReleaseStringUTFChars(path, chars);
releaseChars(e, path, chars);
}
}

View File

@ -56,13 +56,15 @@ charsToArray(JNIEnv* e, const char* s)
return a;
}
#ifdef _MSC_VER
inline void
close(int socket)
doClose(int socket)
{
#ifdef PLATFORM_WINDOWS
closesocket(socket);
}
#else
close(socket);
#endif
}
inline jbyteArray
errorString(JNIEnv* e, int n)
@ -428,13 +430,32 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
jint socket,
jbyteArray buffer,
jint offset,
jint length)
jint length,
jboolean blocking)
{
jboolean isCopy;
uint8_t *buf = static_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
int r = ::doRead(socket, buf + offset, length);
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
int r;
if (blocking) {
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
if (buf) {
r = ::doRead(socket, buf, length);
if (r > 0) {
e->SetByteArrayRegion
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
}
free(buf);
} else {
return 0;
}
} else {
jboolean isCopy;
uint8_t* buf = static_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
r = ::doRead(socket, buf + offset, length);
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
}
if (r < 0) {
if (eagain()) {
return 0;
@ -453,13 +474,30 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
jint socket,
jbyteArray buffer,
jint offset,
jint length)
jint length,
jboolean blocking)
{
jboolean isCopy;
uint8_t *buf = static_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
int r = ::doWrite(socket, buf + offset, length);
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
int r;
if (blocking) {
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
if (buf) {
e->GetByteArrayRegion
(buffer, offset, length, reinterpret_cast<jbyte*>(buf));
r = ::doWrite(socket, buf, length);
free(buf);
} else {
return 0;
}
} else {
jboolean isCopy;
uint8_t* buf = static_cast<uint8_t*>
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
r = ::doWrite(socket, buf + offset, length);
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
}
if (r < 0) {
if (eagain()) {
return 0;
@ -492,7 +530,7 @@ Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv *,
jclass,
jint socket)
{
close(socket);
doClose(socket);
}
namespace {
@ -526,9 +564,9 @@ class Pipe {
}
void dispose() {
if (listener_ >= 0) ::close(listener_);
if (reader_ >= 0) ::close(reader_);
if (writer_ >= 0) ::close(writer_);
if (listener_ >= 0) ::doClose(listener_);
if (reader_ >= 0) ::doClose(reader_);
if (writer_ >= 0) ::doClose(writer_);
}
bool connected() {
@ -579,8 +617,8 @@ class Pipe {
}
void dispose() {
::close(pipe[0]);
::close(pipe[1]);
::doClose(pipe[0]);
::doClose(pipe[1]);
open_ = false;
}
@ -742,9 +780,9 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
if (FD_ISSET(s->control.writer(), &(s->write)) or
FD_ISSET(s->control.writer(), &(s->except)))
{
unsigned socket = s->control.writer();
FD_CLR(socket, &(s->write));
FD_CLR(socket, &(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);

View File

@ -0,0 +1,16 @@
/* Copyright (c) 2010, 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. */
package java.io;
public interface Externalizable {
public void readExternal(ObjectInput in);
public void writeExternal(ObjectOutput out);
}

View File

@ -10,6 +10,8 @@
package java.io;
import avian.Utf8;
public class InputStreamReader extends Reader {
private final InputStream in;
@ -31,10 +33,14 @@ public class InputStreamReader extends Reader {
public int read(char[] b, int offset, int length) throws IOException {
byte[] buffer = new byte[length];
int c = in.read(buffer);
for (int i = 0; i < c; ++i) {
b[i + offset] = (char) buffer[i];
}
return c;
if (c <= 0) return c;
char[] buffer16 = Utf8.decode16(buffer, 0, c);
System.arraycopy(buffer16, 0, b, offset, buffer16.length);
return buffer16.length;
}
public void close() throws IOException {

View File

@ -0,0 +1,21 @@
/* Copyright (c) 2010, 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. */
package java.io;
public interface ObjectInput {
public int available();
public void close();
public void read();
public void read(byte[] b);
public void read(byte[] b, int off, int len);
public Object readObject();
public long skip(long n);
}

View File

@ -0,0 +1,20 @@
/* Copyright (c) 2010, 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. */
package java.io;
public interface ObjectOutput {
public void close();
public void flush();
public void write(byte[] b);
public void write(byte[] b, int off, int len);
public void write(int b);
public void writeObject(Object obj);
}

View File

@ -10,6 +10,8 @@
package java.io;
import avian.Utf8;
public class OutputStreamWriter extends Writer {
private final OutputStream out;
@ -18,11 +20,7 @@ public class OutputStreamWriter extends Writer {
}
public void write(char[] b, int offset, int length) throws IOException {
byte[] buffer = new byte[length];
for (int i = 0; i < length; ++i) {
buffer[i] = (byte) b[i + offset];
}
out.write(buffer);
out.write(Utf8.encode(b, offset, length));
}
public void flush() throws IOException {

View File

@ -15,8 +15,8 @@ import java.util.regex.Pattern;
import java.util.Comparator;
import java.util.Formatter;
import java.util.Locale;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import avian.Utf8;
public final class String
implements Comparable<String>, CharSequence, Serializable
@ -112,7 +112,7 @@ public final class String
(offset + " < 0 or " + offset + " + " + length + " > " + l);
}
if(!copy && isUTF8(data)) copy = true;
if(!copy && Utf8.test(data)) copy = true;
if (copy) {
Object c;
@ -120,7 +120,7 @@ public final class String
c = new char[length];
System.arraycopy(data, offset, c, 0, length);
} else {
c = decodeUTF8((byte[])data, offset, length);
c = Utf8.decode((byte[])data, offset, length);
if(c instanceof char[]) length = ((char[])c).length;
}
@ -134,85 +134,6 @@ public final class String
}
}
private static boolean isUTF8(Object data) {
if(!(data instanceof byte[])) return false;
byte[] b = (byte[])data;
for(int i = 0; i < b.length; ++i) {
if(((int)b[i] & 0x080) != 0) return true;
}
return false;
}
private static byte[] encodeUTF8(char[] s16, int offset, int length) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
for(int i = offset; i < offset+length; ++i) {
char c = s16[i];
if(c == '\u0000') { // null char
buf.write(0);
buf.write(0);
} else if(c < 0x080) { // 1 byte char
buf.write(c);
} else if(c < 0x0800) { // 2 byte char
buf.write(0x0c0 | (c >>> 6));
buf.write(0x080 | (c & 0x03f));
} else { // 3 byte char
buf.write(0x0e0 | ((c >>> 12) & 0x0f));
buf.write(0x080 | ((c >>> 6) & 0x03f));
buf.write(0x080 | (c & 0x03f));
}
}
return buf.toByteArray();
}
private static void decodeUTF8_insert(Object data, int index, int val) {
if(data instanceof byte[]) ((byte[])data)[index] = (byte)val;
else ((char[])data)[index] = (char)val;
}
private static Object decodeUTF8_widen(Object data, int length, int capacity) {
byte[] src = (byte[])data;
char[] result = new char[capacity];
for(int i = 0; i < length; ++i) result[i] = (char)((int)src[i] & 0x0ff);
return result;
}
private static Object decodeUTF8_trim(Object data, int length) {
if(data instanceof byte[]) return data;
if(((char[])data).length == length) return data;
char[] result = new char[length];
System.arraycopy(data, 0, result, 0, length);
return result;
}
private static Object decodeUTF8(byte[] s8, int offset, int length) {
Object buf = new byte[length];
boolean isMultiByte = false;
int i=offset, j=0;
while(i < offset+length) {
int x = s8[i++];
if((x & 0x080) == 0x0) { // 1 byte char
if(x == 0) ++i; // 2 byte null char
decodeUTF8_insert(buf, j++, x);
} else if((x & 0x0e0) == 0x0c0) { // 2 byte char
if(!isMultiByte) {
buf = decodeUTF8_widen(buf, j, length-1);
isMultiByte = true;
}
int y = s8[i++];
decodeUTF8_insert(buf, j++, ((x & 0x1f) << 6) | (y & 0x3f));
} else if((x & 0x0f0) == 0x0e0) { // 3 byte char
if(!isMultiByte) {
buf = decodeUTF8_widen(buf, j, length-2);
isMultiByte = true;
}
int y = s8[i++]; int z = s8[i++];
decodeUTF8_insert(buf, j++, ((x & 0xf) << 12) | ((y & 0x3f) << 6) | (z & 0x3f));
}
}
return decodeUTF8_trim(buf, j);
}
public String toString() {
return this;
}
@ -494,7 +415,7 @@ public final class String
getBytes(0, length, b, 0);
return b;
}
return encodeUTF8((char[])data, offset, length);
return Utf8.encode((char[])data, offset, length);
}
public byte[] getBytes(String format)

View File

@ -15,6 +15,7 @@ import java.nio.ByteBuffer;
public abstract class SelectableChannel implements Channel {
private SelectionKey key;
private boolean open = true;
abstract int socketFD();
@ -30,12 +31,11 @@ public abstract class SelectableChannel implements Channel {
}
public boolean isOpen() {
return key != null;
return open;
}
public void close() throws IOException {
if (key != null) {
key = null;
}
open = false;
key = null;
}
}

View File

@ -92,7 +92,7 @@ public class SocketChannel extends SelectableChannel
byte[] array = b.array();
if (array == null) throw new NullPointerException();
int r = natRead(socket, array, b.arrayOffset() + b.position(), b.remaining());
int r = natRead(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking);
if (r > 0) {
b.position(b.position() + r);
}
@ -108,7 +108,7 @@ public class SocketChannel extends SelectableChannel
byte[] array = b.array();
if (array == null) throw new NullPointerException();
int w = natWrite(socket, array, b.arrayOffset() + b.position(), b.remaining());
int w = natWrite(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking);
if (w > 0) {
b.position(b.position() + w);
}
@ -139,9 +139,9 @@ public class SocketChannel extends SelectableChannel
throws IOException;
private static native boolean natFinishConnect(int socket)
throws IOException;
private static native int natRead(int socket, byte[] buffer, int offset, int length)
private static native int natRead(int socket, byte[] buffer, int offset, int length, boolean blocking)
throws IOException;
private static native int natWrite(int socket, byte[] buffer, int offset, int length)
private static native int natWrite(int socket, byte[] buffer, int offset, int length, boolean blocking)
throws IOException;
private static native void natThrowWriteError(int socket) throws IOException;
private static native void natCloseSocket(int socket);

View File

@ -3,7 +3,7 @@ MAKEFLAGS = -s
name = avian
version = 0.3
build-arch := $(shell uname -m | sed 's/^i.86$$/i386/')
build-arch := $(shell uname -m | sed 's/^i.86$$/i386/' | sed 's/^arm.*$$/arm/')
ifeq (Power,$(filter Power,$(build-arch)))
build-arch = powerpc
endif
@ -145,19 +145,8 @@ ifeq ($(arch),powerpc)
pointer-size = 4
endif
ifeq ($(arch),arm)
lflags := -L/opt/crosstool/gcc-4.1.0-glibc-2.3.2/arm-unknown-linux-gnu/arm-unknown-linux-gnu/lib -L$(root)/arm/lib $(lflags)
cflags := -I/opt/crosstool/gcc-4.1.0-glibc-2.3.2/arm-unknown-linux-gnu/arm-unknown-linux-gnu/include -I$(root)/arm/include $(cflags)
asm = arm
object-arch = arm
object-format = elf32-littlearm
pointer-size = 4
cxx = arm-unknown-linux-gnu-g++
cc = arm-unknown-linux-gnu-gcc
ar = arm-unknown-linux-gnu-ar
ranlib = arm-unknown-linux-gnu-ranlib
objcopy = arm-unknown-linux-gnu-objcopy
strip = arm-unknown-linux-gnu-strip
endif
ifeq ($(platform),darwin)
@ -223,8 +212,8 @@ ifeq ($(platform),windows)
endif
ifeq ($(arch),x86_64)
cxx = x86_64-w64-mingw32-g++
cc = x86_64-w64-mingw32-gcc
cxx = x86_64-w64-mingw32-g++ $(mflag)
cc = x86_64-w64-mingw32-gcc $(mflag)
dlltool = x86_64-w64-mingw32-dlltool
ar = x86_64-w64-mingw32-ar
ranlib = x86_64-w64-mingw32-ranlib
@ -277,6 +266,7 @@ ifdef msvc
ld = "$(msvc)/BIN/link.exe"
mt = "mt.exe"
cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \
-DUSE_ATOMIC_OPERATIONS \
-Fd$(native-build)/$(name).pdb -I"$(zlib)/include" -I$(src) \
-I"$(native-build)" -I"$(windows-java-home)/include" \
-I"$(windows-java-home)/include/win32"

View File

@ -11,6 +11,14 @@
#ifndef ARCH_H
#define ARCH_H
#ifdef _MSC_VER
# include "windows.h"
# pragma push_macro("assert")
# include "intrin.h"
# pragma pop_macro("assert")
# undef interface
#endif
#include "common.h"
extern "C" void NO_RETURN

View File

@ -14,9 +14,9 @@
#include "types.h"
#include "common.h"
#define IP_REGISTER(context) (context->uc_mcontext.gregs[15])
#define STACK_REGISTER(context) (context->uc_mcontext.gregs[13])
#define THREAD_REGISTER(context) (context->uc_mcontext.gregs[12])
#define IP_REGISTER(context) (context->uc_mcontext.arm_pc)
#define STACK_REGISTER(context) (context->uc_mcontext.arm_sp)
#define THREAD_REGISTER(context) (context->uc_mcontext.arm_ip)
extern "C" uint64_t
vmNativeCall(void* function, unsigned stackTotal, void* memoryTable,
@ -60,16 +60,32 @@ syncInstructionCache(const void* start UNUSED, unsigned size UNUSED)
asm("nop");
}
typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
inline bool
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
{
int r = __kernel_cmpxchg(static_cast<int>(old), static_cast<int>(new_), reinterpret_cast<int*>(p));
return (!r ? true : false);
}
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,
unsigned argumentCount, unsigned argumentsSize UNUSED,
unsigned returnType UNUSED)
{
const unsigned GprCount = 4;
uintptr_t gprTable[GprCount];
unsigned gprIndex = 0;
uintptr_t stack[argumentsSize / BytesPerWord];
uintptr_t stack[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding
unsigned stackIndex = 0;
unsigned ai = 0;
@ -77,15 +93,18 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
switch (argumentTypes[ati]) {
case DOUBLE_TYPE:
case INT64_TYPE: {
if (gprIndex + (8 / BytesPerWord) <= GprCount) {
if (gprIndex + (8 / BytesPerWord) <= GprCount) { // pass argument on registers
if (gprIndex & 1) { // 8-byte alignment
memset(gprTable + gprIndex, 0, 4); // probably not necessary, but for good luck
++gprIndex;
}
memcpy(gprTable + gprIndex, arguments + ai, 8);
gprIndex += 8 / BytesPerWord;
} else if (gprIndex == GprCount-1) { // split between last GPR and stack
memcpy(gprTable + gprIndex, arguments + ai, 4);
++gprIndex;
memcpy(stack + stackIndex, arguments + ai + 4, 4);
++stackIndex;
} else {
} else { // pass argument on stack
if (stackIndex & 1) { // 8-byte alignment
memset(stack + stackIndex, 0, 4); // probably not necessary, but for good luck
++stackIndex;
}
memcpy(stack + stackIndex, arguments + ai, 8);
stackIndex += 8 / BytesPerWord;
}

View File

@ -42,6 +42,7 @@
#define EM_386 3
#define EM_X86_64 62
#define EM_ARM 40
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
@ -352,6 +353,8 @@ MAKE_NAME(writeElf, BITS_PER_WORD, Object)
machine = EM_X86_64;
} else if (strcmp(architecture, "i386") == 0) {
machine = EM_386;
} else if (strcmp(architecture, "arm") == 0) {
machine = EM_ARM;
} else {
fprintf(stderr, "unsupported architecture: %s\n", architecture);
return false;

View File

@ -73,7 +73,8 @@ writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName,
success = writeElf64Object
(data, size, out, startName, endName, architecture, alignment,
writable, executable);
} else if (strcmp("i386", architecture) == 0) {
} else if (strcmp("i386", architecture) == 0 ||
strcmp("arm", architecture) == 0) {
found = true;
success = writeElf32Object
(data, size, out, startName, endName, architecture, alignment,

View File

@ -118,9 +118,6 @@ inline void
pushDouble(Thread* t, double v)
{
uint64_t w = doubleToBits(v);
#ifdef __arm__
w = w << 32 | w >> 32;
#endif
pushLong(t, w);
}
@ -175,9 +172,6 @@ inline double
popDouble(Thread* t)
{
uint64_t v = popLong(t);
#ifdef __arm__
v = v << 32 | v >> 32;
#endif
return bitsToDouble(v);
}
@ -569,15 +563,6 @@ pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect)
break;
case DoubleField:
#ifdef __arm__
result = result << 32 | result >> 32;
if (DebugRun) {
fprintf(stderr, "result: %"LLD"\n", result);
}
pushLong(t, result);
break;
#endif
case LongField:
if (DebugRun) {
fprintf(stderr, "result: %"LLD"\n", result);
@ -629,15 +614,6 @@ marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count,
break;
case DOUBLE_TYPE:
#ifdef __arm__
{
uint64_t v = peekLong(t, sp);
v = v << 32 | v >> 32;
memcpy(args + offset, &v, 8);
offset += (8 / BytesPerWord);
sp += 2;
} break;
#endif
case INT64_TYPE: {
uint64_t v = peekLong(t, sp);
memcpy(args + offset, &v, 8);

View File

@ -13,12 +13,13 @@
#include "util.h"
#include "processor.h"
#include "constants.h"
#include "processor.h"
using namespace vm;
namespace {
namespace local {
const uintptr_t InterfaceMethodID
= (static_cast<uintptr_t>(1) << (BitsPerWord - 1));
@ -118,7 +119,7 @@ GetEnv(Machine* m, Thread** t, jint version)
}
}
jsize JNICALL
jint JNICALL
GetVersion(Thread* t)
{
ENTER(t, Thread::ActiveState);
@ -160,7 +161,7 @@ GetStringUTFLength(Thread* t, jstring s)
{
ENTER(t, Thread::ActiveState);
return stringLength(t, *s);
return stringUTFLength(t, *s);
}
const char* JNICALL
@ -168,9 +169,10 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
{
ENTER(t, Thread::ActiveState);
int length = stringUTFLength(t, *s);
char* chars = static_cast<char*>
(t->m->heap->allocate(stringLength(t, *s) + 1));
stringChars(t, *s, chars);
(t->m->heap->allocate(length + 1));
stringUTFChars(t, *s, chars, length);
if (isCopy) *isCopy = true;
return chars;
@ -1907,6 +1909,8 @@ append(char** p, const char* value, unsigned length, char tail)
}
}
} // namespace local
} // namespace
namespace vm {
@ -1927,170 +1931,171 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
{
memset(vmTable, 0, sizeof(JavaVMVTable));
vmTable->DestroyJavaVM = DestroyJavaVM;
vmTable->AttachCurrentThread = AttachCurrentThread;
vmTable->AttachCurrentThreadAsDaemon = AttachCurrentThreadAsDaemon;
vmTable->DetachCurrentThread = DetachCurrentThread;
vmTable->GetEnv = GetEnv;
vmTable->DestroyJavaVM = local::DestroyJavaVM;
vmTable->AttachCurrentThread = local::AttachCurrentThread;
vmTable->AttachCurrentThreadAsDaemon = local::AttachCurrentThreadAsDaemon;
vmTable->DetachCurrentThread = local::DetachCurrentThread;
vmTable->GetEnv = local::GetEnv;
memset(envTable, 0, sizeof(JNIEnvVTable));
envTable->GetVersion = ::GetVersion;
envTable->GetStringLength = ::GetStringLength;
envTable->GetStringChars = ::GetStringChars;
envTable->ReleaseStringChars = ::ReleaseStringChars;
envTable->GetStringUTFLength = ::GetStringUTFLength;
envTable->GetStringUTFChars = ::GetStringUTFChars;
envTable->ReleaseStringUTFChars = ::ReleaseStringUTFChars;
envTable->GetArrayLength = ::GetArrayLength;
envTable->NewString = ::NewString;
envTable->NewStringUTF = ::NewStringUTF;
envTable->FindClass = ::FindClass;
envTable->ThrowNew = ::ThrowNew;
envTable->ExceptionCheck = ::ExceptionCheck;
envTable->NewDirectByteBuffer = ::NewDirectByteBuffer;
envTable->GetDirectBufferAddress = ::GetDirectBufferAddress;
envTable->GetDirectBufferCapacity = ::GetDirectBufferCapacity;
envTable->DeleteLocalRef = ::DeleteLocalRef;
envTable->GetObjectClass = ::GetObjectClass;
envTable->IsInstanceOf = ::IsInstanceOf;
envTable->GetFieldID = ::GetFieldID;
envTable->GetMethodID = ::GetMethodID;
envTable->GetStaticMethodID = ::GetStaticMethodID;
envTable->NewObject = ::NewObject;
envTable->NewObjectV = ::NewObjectV;
envTable->CallObjectMethodV = ::CallObjectMethodV;
envTable->CallObjectMethod = ::CallObjectMethod;
envTable->CallBooleanMethodV = ::CallBooleanMethodV;
envTable->CallBooleanMethod = ::CallBooleanMethod;
envTable->CallByteMethodV = ::CallByteMethodV;
envTable->CallByteMethod = ::CallByteMethod;
envTable->CallCharMethodV = ::CallCharMethodV;
envTable->CallCharMethod = ::CallCharMethod;
envTable->CallShortMethodV = ::CallShortMethodV;
envTable->CallShortMethod = ::CallShortMethod;
envTable->CallIntMethodV = ::CallIntMethodV;
envTable->CallIntMethod = ::CallIntMethod;
envTable->CallLongMethodV = ::CallLongMethodV;
envTable->CallLongMethod = ::CallLongMethod;
envTable->CallFloatMethodV = ::CallFloatMethodV;
envTable->CallFloatMethod = ::CallFloatMethod;
envTable->CallDoubleMethodV = ::CallDoubleMethodV;
envTable->CallDoubleMethod = ::CallDoubleMethod;
envTable->CallVoidMethodV = ::CallVoidMethodV;
envTable->CallVoidMethod = ::CallVoidMethod;
envTable->CallStaticObjectMethodV = ::CallStaticObjectMethodV;
envTable->CallStaticObjectMethod = ::CallStaticObjectMethod;
envTable->CallStaticBooleanMethodV = ::CallStaticBooleanMethodV;
envTable->CallStaticBooleanMethod = ::CallStaticBooleanMethod;
envTable->CallStaticByteMethodV = ::CallStaticByteMethodV;
envTable->CallStaticByteMethod = ::CallStaticByteMethod;
envTable->CallStaticCharMethodV = ::CallStaticCharMethodV;
envTable->CallStaticCharMethod = ::CallStaticCharMethod;
envTable->CallStaticShortMethodV = ::CallStaticShortMethodV;
envTable->CallStaticShortMethod = ::CallStaticShortMethod;
envTable->CallStaticIntMethodV = ::CallStaticIntMethodV;
envTable->CallStaticIntMethod = ::CallStaticIntMethod;
envTable->CallStaticLongMethodV = ::CallStaticLongMethodV;
envTable->CallStaticLongMethod = ::CallStaticLongMethod;
envTable->CallStaticFloatMethodV = ::CallStaticFloatMethodV;
envTable->CallStaticFloatMethod = ::CallStaticFloatMethod;
envTable->CallStaticDoubleMethodV = ::CallStaticDoubleMethodV;
envTable->CallStaticDoubleMethod = ::CallStaticDoubleMethod;
envTable->CallStaticVoidMethodV = ::CallStaticVoidMethodV;
envTable->CallStaticVoidMethod = ::CallStaticVoidMethod;
envTable->GetStaticFieldID = ::GetStaticFieldID;
envTable->GetObjectField = ::GetObjectField;
envTable->GetBooleanField = ::GetBooleanField;
envTable->GetByteField = ::GetByteField;
envTable->GetCharField = ::GetCharField;
envTable->GetShortField = ::GetShortField;
envTable->GetIntField = ::GetIntField;
envTable->GetLongField = ::GetLongField;
envTable->GetFloatField = ::GetFloatField;
envTable->GetDoubleField = ::GetDoubleField;
envTable->SetObjectField = ::SetObjectField;
envTable->SetBooleanField = ::SetBooleanField;
envTable->SetByteField = ::SetByteField;
envTable->SetCharField = ::SetCharField;
envTable->SetShortField = ::SetShortField;
envTable->SetIntField = ::SetIntField;
envTable->SetLongField = ::SetLongField;
envTable->SetFloatField = ::SetFloatField;
envTable->SetDoubleField = ::SetDoubleField;
envTable->GetStaticObjectField = ::GetStaticObjectField;
envTable->GetStaticBooleanField = ::GetStaticBooleanField;
envTable->GetStaticByteField = ::GetStaticByteField;
envTable->GetStaticCharField = ::GetStaticCharField;
envTable->GetStaticShortField = ::GetStaticShortField;
envTable->GetStaticIntField = ::GetStaticIntField;
envTable->GetStaticLongField = ::GetStaticLongField;
envTable->GetStaticFloatField = ::GetStaticFloatField;
envTable->GetStaticDoubleField = ::GetStaticDoubleField;
envTable->SetStaticObjectField = ::SetStaticObjectField;
envTable->SetStaticBooleanField = ::SetStaticBooleanField;
envTable->SetStaticByteField = ::SetStaticByteField;
envTable->SetStaticCharField = ::SetStaticCharField;
envTable->SetStaticShortField = ::SetStaticShortField;
envTable->SetStaticIntField = ::SetStaticIntField;
envTable->SetStaticLongField = ::SetStaticLongField;
envTable->SetStaticFloatField = ::SetStaticFloatField;
envTable->SetStaticDoubleField = ::SetStaticDoubleField;
envTable->NewGlobalRef = ::NewGlobalRef;
envTable->NewWeakGlobalRef = ::NewGlobalRef;
envTable->DeleteGlobalRef = ::DeleteGlobalRef;
envTable->ExceptionOccurred = ::ExceptionOccurred;
envTable->ExceptionDescribe = ::ExceptionDescribe;
envTable->ExceptionClear = ::ExceptionClear;
envTable->NewObjectArray = ::NewObjectArray;
envTable->GetObjectArrayElement = ::GetObjectArrayElement;
envTable->SetObjectArrayElement = ::SetObjectArrayElement;
envTable->NewBooleanArray = ::NewBooleanArray;
envTable->NewByteArray = ::NewByteArray;
envTable->NewCharArray = ::NewCharArray;
envTable->NewShortArray = ::NewShortArray;
envTable->NewIntArray = ::NewIntArray;
envTable->NewLongArray = ::NewLongArray;
envTable->NewFloatArray = ::NewFloatArray;
envTable->NewDoubleArray = ::NewDoubleArray;
envTable->GetBooleanArrayElements = ::GetBooleanArrayElements;
envTable->GetByteArrayElements = ::GetByteArrayElements;
envTable->GetCharArrayElements = ::GetCharArrayElements;
envTable->GetShortArrayElements = ::GetShortArrayElements;
envTable->GetIntArrayElements = ::GetIntArrayElements;
envTable->GetLongArrayElements = ::GetLongArrayElements;
envTable->GetFloatArrayElements = ::GetFloatArrayElements;
envTable->GetDoubleArrayElements = ::GetDoubleArrayElements;
envTable->ReleaseBooleanArrayElements = ::ReleaseBooleanArrayElements;
envTable->ReleaseByteArrayElements = ::ReleaseByteArrayElements;
envTable->ReleaseCharArrayElements = ::ReleaseCharArrayElements;
envTable->ReleaseShortArrayElements = ::ReleaseShortArrayElements;
envTable->ReleaseIntArrayElements = ::ReleaseIntArrayElements;
envTable->ReleaseLongArrayElements = ::ReleaseLongArrayElements;
envTable->ReleaseFloatArrayElements = ::ReleaseFloatArrayElements;
envTable->ReleaseDoubleArrayElements = ::ReleaseDoubleArrayElements;
envTable->GetBooleanArrayRegion = ::GetBooleanArrayRegion;
envTable->GetByteArrayRegion = ::GetByteArrayRegion;
envTable->GetCharArrayRegion = ::GetCharArrayRegion;
envTable->GetShortArrayRegion = ::GetShortArrayRegion;
envTable->GetIntArrayRegion = ::GetIntArrayRegion;
envTable->GetLongArrayRegion = ::GetLongArrayRegion;
envTable->GetFloatArrayRegion = ::GetFloatArrayRegion;
envTable->GetDoubleArrayRegion = ::GetDoubleArrayRegion;
envTable->SetBooleanArrayRegion = ::SetBooleanArrayRegion;
envTable->SetByteArrayRegion = ::SetByteArrayRegion;
envTable->SetCharArrayRegion = ::SetCharArrayRegion;
envTable->SetShortArrayRegion = ::SetShortArrayRegion;
envTable->SetIntArrayRegion = ::SetIntArrayRegion;
envTable->SetLongArrayRegion = ::SetLongArrayRegion;
envTable->SetFloatArrayRegion = ::SetFloatArrayRegion;
envTable->SetDoubleArrayRegion = ::SetDoubleArrayRegion;
envTable->GetPrimitiveArrayCritical = ::GetPrimitiveArrayCritical;
envTable->ReleasePrimitiveArrayCritical = ::ReleasePrimitiveArrayCritical;
envTable->MonitorEnter = MonitorEnter;
envTable->MonitorExit = MonitorExit;
envTable->GetJavaVM = ::GetJavaVM;
envTable->IsSameObject = ::IsSameObject;
envTable->GetVersion = local::GetVersion;
envTable->GetStringLength = local::GetStringLength;
envTable->GetStringChars = local::GetStringChars;
envTable->ReleaseStringChars = local::ReleaseStringChars;
envTable->GetStringUTFLength = local::GetStringUTFLength;
envTable->GetStringUTFChars = local::GetStringUTFChars;
envTable->ReleaseStringUTFChars = local::ReleaseStringUTFChars;
envTable->GetArrayLength = local::GetArrayLength;
envTable->NewString = local::NewString;
envTable->NewStringUTF = local::NewStringUTF;
envTable->FindClass = local::FindClass;
envTable->ThrowNew = local::ThrowNew;
envTable->ExceptionCheck = local::ExceptionCheck;
envTable->NewDirectByteBuffer = local::NewDirectByteBuffer;
envTable->GetDirectBufferAddress = local::GetDirectBufferAddress;
envTable->GetDirectBufferCapacity = local::GetDirectBufferCapacity;
envTable->DeleteLocalRef = local::DeleteLocalRef;
envTable->GetObjectClass = local::GetObjectClass;
envTable->IsInstanceOf = local::IsInstanceOf;
envTable->GetFieldID = local::GetFieldID;
envTable->GetMethodID = local::GetMethodID;
envTable->GetStaticMethodID = local::GetStaticMethodID;
envTable->NewObject = local::NewObject;
envTable->NewObjectV = local::NewObjectV;
envTable->CallObjectMethodV = local::CallObjectMethodV;
envTable->CallObjectMethod = local::CallObjectMethod;
envTable->CallBooleanMethodV = local::CallBooleanMethodV;
envTable->CallBooleanMethod = local::CallBooleanMethod;
envTable->CallByteMethodV = local::CallByteMethodV;
envTable->CallByteMethod = local::CallByteMethod;
envTable->CallCharMethodV = local::CallCharMethodV;
envTable->CallCharMethod = local::CallCharMethod;
envTable->CallShortMethodV = local::CallShortMethodV;
envTable->CallShortMethod = local::CallShortMethod;
envTable->CallIntMethodV = local::CallIntMethodV;
envTable->CallIntMethod = local::CallIntMethod;
envTable->CallLongMethodV = local::CallLongMethodV;
envTable->CallLongMethod = local::CallLongMethod;
envTable->CallFloatMethodV = local::CallFloatMethodV;
envTable->CallFloatMethod = local::CallFloatMethod;
envTable->CallDoubleMethodV = local::CallDoubleMethodV;
envTable->CallDoubleMethod = local::CallDoubleMethod;
envTable->CallVoidMethodV = local::CallVoidMethodV;
envTable->CallVoidMethod = local::CallVoidMethod;
envTable->CallStaticObjectMethodV = local::CallStaticObjectMethodV;
envTable->CallStaticObjectMethod = local::CallStaticObjectMethod;
envTable->CallStaticBooleanMethodV = local::CallStaticBooleanMethodV;
envTable->CallStaticBooleanMethod = local::CallStaticBooleanMethod;
envTable->CallStaticByteMethodV = local::CallStaticByteMethodV;
envTable->CallStaticByteMethod = local::CallStaticByteMethod;
envTable->CallStaticCharMethodV = local::CallStaticCharMethodV;
envTable->CallStaticCharMethod = local::CallStaticCharMethod;
envTable->CallStaticShortMethodV = local::CallStaticShortMethodV;
envTable->CallStaticShortMethod = local::CallStaticShortMethod;
envTable->CallStaticIntMethodV = local::CallStaticIntMethodV;
envTable->CallStaticIntMethod = local::CallStaticIntMethod;
envTable->CallStaticLongMethodV = local::CallStaticLongMethodV;
envTable->CallStaticLongMethod = local::CallStaticLongMethod;
envTable->CallStaticFloatMethodV = local::CallStaticFloatMethodV;
envTable->CallStaticFloatMethod = local::CallStaticFloatMethod;
envTable->CallStaticDoubleMethodV = local::CallStaticDoubleMethodV;
envTable->CallStaticDoubleMethod = local::CallStaticDoubleMethod;
envTable->CallStaticVoidMethodV = local::CallStaticVoidMethodV;
envTable->CallStaticVoidMethod = local::CallStaticVoidMethod;
envTable->GetStaticFieldID = local::GetStaticFieldID;
envTable->GetObjectField = local::GetObjectField;
envTable->GetBooleanField = local::GetBooleanField;
envTable->GetByteField = local::GetByteField;
envTable->GetCharField = local::GetCharField;
envTable->GetShortField = local::GetShortField;
envTable->GetIntField = local::GetIntField;
envTable->GetLongField = local::GetLongField;
envTable->GetFloatField = local::GetFloatField;
envTable->GetDoubleField = local::GetDoubleField;
envTable->SetObjectField = local::SetObjectField;
envTable->SetBooleanField = local::SetBooleanField;
envTable->SetByteField = local::SetByteField;
envTable->SetCharField = local::SetCharField;
envTable->SetShortField = local::SetShortField;
envTable->SetIntField = local::SetIntField;
envTable->SetLongField = local::SetLongField;
envTable->SetFloatField = local::SetFloatField;
envTable->SetDoubleField = local::SetDoubleField;
envTable->GetStaticObjectField = local::GetStaticObjectField;
envTable->GetStaticBooleanField = local::GetStaticBooleanField;
envTable->GetStaticByteField = local::GetStaticByteField;
envTable->GetStaticCharField = local::GetStaticCharField;
envTable->GetStaticShortField = local::GetStaticShortField;
envTable->GetStaticIntField = local::GetStaticIntField;
envTable->GetStaticLongField = local::GetStaticLongField;
envTable->GetStaticFloatField = local::GetStaticFloatField;
envTable->GetStaticDoubleField = local::GetStaticDoubleField;
envTable->SetStaticObjectField = local::SetStaticObjectField;
envTable->SetStaticBooleanField = local::SetStaticBooleanField;
envTable->SetStaticByteField = local::SetStaticByteField;
envTable->SetStaticCharField = local::SetStaticCharField;
envTable->SetStaticShortField = local::SetStaticShortField;
envTable->SetStaticIntField = local::SetStaticIntField;
envTable->SetStaticLongField = local::SetStaticLongField;
envTable->SetStaticFloatField = local::SetStaticFloatField;
envTable->SetStaticDoubleField = local::SetStaticDoubleField;
envTable->NewGlobalRef = local::NewGlobalRef;
envTable->NewWeakGlobalRef = local::NewGlobalRef;
envTable->DeleteGlobalRef = local::DeleteGlobalRef;
envTable->ExceptionOccurred = local::ExceptionOccurred;
envTable->ExceptionDescribe = local::ExceptionDescribe;
envTable->ExceptionClear = local::ExceptionClear;
envTable->NewObjectArray = local::NewObjectArray;
envTable->GetObjectArrayElement = local::GetObjectArrayElement;
envTable->SetObjectArrayElement = local::SetObjectArrayElement;
envTable->NewBooleanArray = local::NewBooleanArray;
envTable->NewByteArray = local::NewByteArray;
envTable->NewCharArray = local::NewCharArray;
envTable->NewShortArray = local::NewShortArray;
envTable->NewIntArray = local::NewIntArray;
envTable->NewLongArray = local::NewLongArray;
envTable->NewFloatArray = local::NewFloatArray;
envTable->NewDoubleArray = local::NewDoubleArray;
envTable->GetBooleanArrayElements = local::GetBooleanArrayElements;
envTable->GetByteArrayElements = local::GetByteArrayElements;
envTable->GetCharArrayElements = local::GetCharArrayElements;
envTable->GetShortArrayElements = local::GetShortArrayElements;
envTable->GetIntArrayElements = local::GetIntArrayElements;
envTable->GetLongArrayElements = local::GetLongArrayElements;
envTable->GetFloatArrayElements = local::GetFloatArrayElements;
envTable->GetDoubleArrayElements = local::GetDoubleArrayElements;
envTable->ReleaseBooleanArrayElements = local::ReleaseBooleanArrayElements;
envTable->ReleaseByteArrayElements = local::ReleaseByteArrayElements;
envTable->ReleaseCharArrayElements = local::ReleaseCharArrayElements;
envTable->ReleaseShortArrayElements = local::ReleaseShortArrayElements;
envTable->ReleaseIntArrayElements = local::ReleaseIntArrayElements;
envTable->ReleaseLongArrayElements = local::ReleaseLongArrayElements;
envTable->ReleaseFloatArrayElements = local::ReleaseFloatArrayElements;
envTable->ReleaseDoubleArrayElements = local::ReleaseDoubleArrayElements;
envTable->GetBooleanArrayRegion = local::GetBooleanArrayRegion;
envTable->GetByteArrayRegion = local::GetByteArrayRegion;
envTable->GetCharArrayRegion = local::GetCharArrayRegion;
envTable->GetShortArrayRegion = local::GetShortArrayRegion;
envTable->GetIntArrayRegion = local::GetIntArrayRegion;
envTable->GetLongArrayRegion = local::GetLongArrayRegion;
envTable->GetFloatArrayRegion = local::GetFloatArrayRegion;
envTable->GetDoubleArrayRegion = local::GetDoubleArrayRegion;
envTable->SetBooleanArrayRegion = local::SetBooleanArrayRegion;
envTable->SetByteArrayRegion = local::SetByteArrayRegion;
envTable->SetCharArrayRegion = local::SetCharArrayRegion;
envTable->SetShortArrayRegion = local::SetShortArrayRegion;
envTable->SetIntArrayRegion = local::SetIntArrayRegion;
envTable->SetLongArrayRegion = local::SetLongArrayRegion;
envTable->SetFloatArrayRegion = local::SetFloatArrayRegion;
envTable->SetDoubleArrayRegion = local::SetDoubleArrayRegion;
envTable->GetPrimitiveArrayCritical = local::GetPrimitiveArrayCritical;
envTable->ReleasePrimitiveArrayCritical
= local::ReleasePrimitiveArrayCritical;
envTable->MonitorEnter = local::MonitorEnter;
envTable->MonitorExit = local::MonitorExit;
envTable->GetJavaVM = local::GetJavaVM;
envTable->IsSameObject = local::IsSameObject;
}
} // namespace vm
@ -2112,7 +2117,7 @@ JNI_GetDefaultJavaVMInitArgs(void*)
extern "C" JNIEXPORT jint JNICALL
JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
{
JavaVMInitArgs* a = static_cast<JavaVMInitArgs*>(args);
local::JavaVMInitArgs* a = static_cast<local::JavaVMInitArgs*>(args);
unsigned heapLimit = 0;
const char* bootLibrary = 0;
@ -2128,7 +2133,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
if (strncmp(a->options[i].optionString, "-X", 2) == 0) {
const char* p = a->options[i].optionString + 2;
if (strncmp(p, "mx", 2) == 0) {
heapLimit = parseSize(p + 2);
heapLimit = local::parseSize(p + 2);
} else if (strncmp(p, BOOTCLASSPATH_PREPEND_OPTION ":",
sizeof(BOOTCLASSPATH_PREPEND_OPTION)) == 0)
{
@ -2175,10 +2180,11 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
RUNTIME_ARRAY(char, classpathBuffer, classpathBufferSize);
char* classpathPointer = RUNTIME_ARRAY_BODY(classpathBuffer);
append(&classpathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR);
append(&classpathPointer, bootClasspath, bcpl, PATH_SEPARATOR);
append(&classpathPointer, bootClasspathAppend, bcpal, PATH_SEPARATOR);
append(&classpathPointer, classpath, cpl, 0);
local::append
(&classpathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR);
local::append(&classpathPointer, bootClasspath, bcpl, PATH_SEPARATOR);
local::append(&classpathPointer, bootClasspathAppend, bcpal, PATH_SEPARATOR);
local::append(&classpathPointer, classpath, cpl, 0);
System* s = makeSystem(crashDumpDirectory);
Heap* h = makeHeap(s, heapLimit);

View File

@ -2690,6 +2690,30 @@ makeString(Thread* t, const char* format, ...)
return makeString(t, s, 0, byteArrayLength(t, s) - 1, 0);
}
int
stringUTFLength(Thread* t, object string) {
int length = 0;
if (stringLength(t, string)) {
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType)) {
length = stringLength(t, string);
} else {
for (unsigned i = 0; i < stringLength(t, string); ++i) {
uint16_t c = charArrayBody(t, data, stringOffset(t, string) + i);
if (!c) length += 1; // null char (was 2 bytes in Java)
else if (c < 0x80) length += 1; // ASCII char
else if (c < 0x800) length += 2; // two-byte char
else length += 3; // three-byte char
}
}
}
return length;
}
void
stringChars(Thread* t, object string, char* chars)
{
@ -2730,6 +2754,42 @@ stringChars(Thread* t, object string, uint16_t* chars)
chars[stringLength(t, string)] = 0;
}
void
stringUTFChars(Thread* t, object string, char* chars, unsigned length UNUSED)
{
assert(t, static_cast<unsigned>(stringUTFLength(t, string)) == length);
if (stringLength(t, string)) {
object data = stringData(t, string);
if (objectClass(t, data)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
memcpy(chars,
&byteArrayBody(t, data, stringOffset(t, string)),
stringLength(t, string));
chars[stringLength(t, string)] = 0;
} else {
int j = 0;
for (unsigned i = 0; i < stringLength(t, string); ++i) {
uint16_t c = charArrayBody(t, data, stringOffset(t, string) + i);
if(!c) { // null char
chars[j++] = 0;
} else if (c < 0x80) { // ASCII char
chars[j++] = static_cast<char>(c);
} else if (c < 0x800) { // two-byte char
chars[j++] = static_cast<char>(0x0c0 | (c >> 6));
chars[j++] = static_cast<char>(0x080 | (c & 0x03f));
} else { // three-byte char
chars[j++] = static_cast<char>(0x0e0 | ((c >> 12) & 0x0f));
chars[j++] = static_cast<char>(0x080 | ((c >> 6) & 0x03f));
chars[j++] = static_cast<char>(0x080 | (c & 0x03f));
}
}
chars[j] = 0;
}
}
}
bool
isAssignableFrom(Thread* t, object a, object b)
{

View File

@ -1901,12 +1901,18 @@ makeByteArray(Thread* t, const char* format, ...);
object
makeString(Thread* t, const char* format, ...);
int
stringUTFLength(Thread* t, object string);
void
stringChars(Thread* t, object string, char* chars);
void
stringChars(Thread* t, object string, uint16_t* chars);
void
stringUTFChars(Thread* t, object string, char* chars, unsigned length);
bool
isAssignableFrom(Thread* t, object a, object b);

View File

@ -93,6 +93,8 @@ pathOfExecutable(System* s, const char** retBuf, unsigned* size)
CFBundleRef bundle = CFBundleGetMainBundle();
CFURLRef url = CFBundleCopyExecutableURL(bundle);
CFStringRef path = CFURLCopyPath(url);
path = CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault,
path, CFSTR(""));
CFIndex pathSize = CFStringGetMaximumSizeOfFileSystemRepresentation(path);
char* buffer = reinterpret_cast<char*>(allocate(s, pathSize));
if (CFStringGetFileSystemRepresentation(path, buffer, pathSize)) {

View File

@ -20,29 +20,6 @@ using namespace vm;
namespace {
namespace field {
// BITFIELD MASKS
const int64_t MASK_LO32 = 0x0ffffffff;
const int MASK_LO16 = 0x0ffff;
const int MASK_LO8 = 0x0ff;
// BITFIELD EXTRACTORS
inline int lo32(int64_t i) { return (int)(i & MASK_LO32); }
inline int hi32(int64_t i) { return lo32(i >> 32); }
inline int lo16(int64_t i) { return (int)(i & MASK_LO16); }
inline int hi16(int64_t i) { return lo16(i >> 16); }
inline int lo8(int64_t i) { return (int)(i & MASK_LO8); }
inline int hi8(int64_t i) { return lo8(i >> 8); }
inline int ha16(int32_t i) {
return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff;
}
inline int unha16(int32_t high, int32_t low) {
return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low;
}
}
namespace isa {
// INSTRUCTION FORMATS
inline int D(int op, int rt, int ra, int d) { return op<<26|rt<<21|ra<<16|(d & 0xFFFF); }
@ -155,6 +132,24 @@ inline int cmpwi(int ra, int i) { return cmpi(0, ra, i); }
inline int cmplwi(int ra, int i) { return cmpli(0, ra, i); }
}
const int64_t MASK_LO32 = 0x0ffffffff;
const int MASK_LO16 = 0x0ffff;
const int MASK_LO8 = 0x0ff;
inline int lo32(int64_t i) { return (int)(i & MASK_LO32); }
inline int hi32(int64_t i) { return lo32(i >> 32); }
inline int lo16(int64_t i) { return (int)(i & MASK_LO16); }
inline int hi16(int64_t i) { return lo16(i >> 16); }
inline int lo8(int64_t i) { return (int)(i & MASK_LO8); }
inline int hi8(int64_t i) { return lo8(i >> 8); }
inline int ha16(int32_t i) {
return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff;
}
inline int unha16(int32_t high, int32_t low) {
return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low;
}
inline bool
isInt16(intptr_t v)
{
@ -445,100 +440,94 @@ branchIndex(ArchitectureContext* c UNUSED, OperandType operand1,
// BEGIN OPERATION COMPILERS
using namespace field;
using namespace isa;
typedef Assembler::Register Reg;
typedef Assembler::Constant Const;
inline void issue(Context* con, int code) { con->code.append4(code); }
inline int getTemp(Context* con) { return con->client->acquireTemporary(); }
inline void emit(Context* con, int code) { con->code.append4(code); }
inline int newTemp(Context* con) { return con->client->acquireTemporary(); }
inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); }
inline int64_t getVal(Const* c) { return c->value->value(); }
inline int R(Reg* r) { return r->low; }
inline int H(Reg* r) { return r->high; }
inline int64_t getValue(Assembler::Constant* c) { return c->value->value(); }
void shiftLeftR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t)
void shiftLeftR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t)
{
if(size == 8) {
Reg Tmp(getTemp(con), getTemp(con)); Reg* tmp = &Tmp;
issue(con, subfic(H(tmp), R(a), 32));
issue(con, slw(H(t), H(b), R(a)));
issue(con, srw(R(tmp), R(b), H(tmp)));
issue(con, or_(H(t), H(t), R(tmp)));
issue(con, addi(H(tmp), R(a), -32));
issue(con, slw(R(tmp), R(b), H(tmp)));
issue(con, or_(H(t), H(t), R(tmp)));
freeTemp(con, H(tmp)); freeTemp(con, R(tmp));
Assembler::Register Tmp(newTemp(con), newTemp(con)); Assembler::Register* tmp = &Tmp;
emit(con, subfic(tmp->high, a->low, 32));
emit(con, slw(t->high, b->high, a->low));
emit(con, srw(tmp->low, b->low, tmp->high));
emit(con, or_(t->high, t->high, tmp->low));
emit(con, addi(tmp->high, a->low, -32));
emit(con, slw(tmp->low, b->low, tmp->high));
emit(con, or_(t->high, t->high, tmp->low));
freeTemp(con, tmp->high); freeTemp(con, tmp->low);
}
issue(con, slw(R(t), R(b), R(a)));
emit(con, slw(t->low, b->low, a->low));
}
void shiftLeftC(Context* con, unsigned size, Const* a, Reg* b, Reg* t)
void shiftLeftC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t)
{
int sh = getVal(a);
int sh = getValue(a);
if (size == 8) {
if (sh < 32) {
issue(con, rlwinm(H(t),H(b),sh,0,31-sh));
issue(con, rlwimi(H(t),R(b),sh,32-sh,31));
emit(con, rlwinm(t->high,b->high,sh,0,31-sh));
emit(con, rlwimi(t->high,b->low,sh,32-sh,31));
} else {
issue(con, rlwinm(H(t),R(b),sh-32,0,63-sh));
issue(con, li(R(t),0));
emit(con, rlwinm(t->high,b->low,sh-32,0,63-sh));
emit(con, li(t->low,0));
}
}
issue(con, slwi(R(t), R(b), sh));
emit(con, slwi(t->low, b->low, sh));
}
void shiftRightR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t)
void shiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t)
{
if(size == 8) {
Reg Tmp(getTemp(con), getTemp(con)); Reg* tmp = &Tmp;
issue(con, subfic(H(tmp), R(a), 32));
issue(con, srw(R(t), R(b), R(a)));
issue(con, slw(R(tmp), H(b), H(tmp)));
issue(con, or_(R(t), R(t), R(tmp)));
issue(con, addic(H(tmp), R(a), -32));
issue(con, sraw(R(tmp), H(b), H(tmp)));
issue(con, ble(8));
issue(con, ori(R(t), R(tmp), 0));
issue(con, sraw(H(t), H(b), R(a)));
freeTemp(con, H(tmp)); freeTemp(con, R(tmp));
Assembler::Register Tmp(newTemp(con), newTemp(con)); Assembler::Register* tmp = &Tmp;
emit(con, subfic(tmp->high, a->low, 32));
emit(con, srw(t->low, b->low, a->low));
emit(con, slw(tmp->low, b->high, tmp->high));
emit(con, or_(t->low, t->low, tmp->low));
emit(con, addic(tmp->high, a->low, -32));
emit(con, sraw(tmp->low, b->high, tmp->high));
emit(con, ble(8));
emit(con, ori(t->low, tmp->low, 0));
emit(con, sraw(t->high, b->high, a->low));
freeTemp(con, tmp->high); freeTemp(con, tmp->low);
} else {
issue(con, sraw(R(t), R(b), R(a)));
emit(con, sraw(t->low, b->low, a->low));
}
}
void shiftRightC(Context* con, unsigned size, Const* a, Reg* b, Reg* t)
void shiftRightC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t)
{
int sh = getVal(a);
int sh = getValue(a);
if(size == 8) {
if (sh < 32) {
issue(con, rlwinm(R(t),R(b),32-sh,sh,31));
issue(con, rlwimi(R(t),H(b),32-sh,0,sh-1));
issue(con, srawi(H(t),H(b),sh));
emit(con, rlwinm(t->low,b->low,32-sh,sh,31));
emit(con, rlwimi(t->low,b->high,32-sh,0,sh-1));
emit(con, srawi(t->high,b->high,sh));
} else {
issue(con, srawi(H(t),H(b),31));
issue(con, srawi(R(t),H(b),sh-32));
emit(con, srawi(t->high,b->high,31));
emit(con, srawi(t->low,b->high,sh-32));
}
} else {
issue(con, srawi(R(t), R(b), sh));
emit(con, srawi(t->low, b->low, sh));
}
}
void unsignedShiftRightR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t)
void unsignedShiftRightR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t)
{
issue(con, srw(R(t), R(b), R(a)));
emit(con, srw(t->low, b->low, a->low));
if(size == 8) {
Reg Tmp(getTemp(con), getTemp(con)); Reg* tmp = &Tmp;
issue(con, subfic(H(tmp), R(a), 32));
issue(con, slw(R(tmp), H(b), H(tmp)));
issue(con, or_(R(t), R(t), R(tmp)));
issue(con, addi(H(tmp), R(a), -32));
issue(con, srw(R(tmp), H(b), H(tmp)));
issue(con, or_(R(t), R(t), R(tmp)));
issue(con, srw(H(t), H(b), R(a)));
freeTemp(con, H(tmp)); freeTemp(con, R(tmp));
Assembler::Register Tmp(newTemp(con), newTemp(con)); Assembler::Register* tmp = &Tmp;
emit(con, subfic(tmp->high, a->low, 32));
emit(con, slw(tmp->low, b->high, tmp->high));
emit(con, or_(t->low, t->low, tmp->low));
emit(con, addi(tmp->high, a->low, -32));
emit(con, srw(tmp->low, b->high, tmp->high));
emit(con, or_(t->low, t->low, tmp->low));
emit(con, srw(t->high, b->high, a->low));
freeTemp(con, tmp->high); freeTemp(con, tmp->low);
}
}
@ -546,24 +535,24 @@ void
moveRR(Context* c, unsigned srcSize, Assembler::Register* src,
unsigned dstSize, Assembler::Register* dst);
void unsignedShiftRightC(Context* con, unsigned size, Const* a, Reg* b, Reg* t)
void unsignedShiftRightC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t)
{
int sh = getVal(a);
int sh = getValue(a);
if (size == 8) {
if (sh == 32) {
Assembler::Register high(b->high);
moveRR(con, 4, &high, 4, t);
issue(con, li(H(t),0));
emit(con, li(t->high,0));
} else if (sh < 32) {
issue(con, srwi(R(t), R(b), sh));
issue(con, rlwimi(R(t),H(b),32-sh,0,sh-1));
issue(con, rlwinm(H(t),H(b),32-sh,sh,31));
emit(con, srwi(t->low, b->low, sh));
emit(con, rlwimi(t->low,b->high,32-sh,0,sh-1));
emit(con, rlwinm(t->high,b->high,32-sh,sh,31));
} else {
issue(con, rlwinm(R(t),H(b),64-sh,sh-32,31));
issue(con, li(H(t),0));
emit(con, rlwinm(t->low,b->high,64-sh,sh-32,31));
emit(con, li(t->high,0));
}
} else {
issue(con, srwi(R(t), R(b), sh));
emit(con, srwi(t->low, b->low, sh));
}
}
@ -683,8 +672,8 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* target)
{
assert(c, size == BytesPerWord);
issue(c, mtctr(target->low));
issue(c, bctr());
emit(c, mtctr(target->low));
emit(c, bctr());
}
void
@ -707,18 +696,18 @@ moveRR(Context* c, unsigned srcSize, Assembler::Register* src,
{
switch (srcSize) {
case 1:
issue(c, extsb(dst->low, src->low));
emit(c, extsb(dst->low, src->low));
break;
case 2:
issue(c, extsh(dst->low, src->low));
emit(c, extsh(dst->low, src->low));
break;
case 4:
case 8:
if (srcSize == 4 and dstSize == 8) {
moveRR(c, 4, src, 4, dst);
issue(c, srawi(dst->high, src->low, 31));
emit(c, srawi(dst->high, src->low, 31));
} else if (srcSize == 8 and dstSize == 8) {
Assembler::Register srcHigh(src->high);
Assembler::Register dstHigh(dst->high);
@ -735,7 +724,7 @@ moveRR(Context* c, unsigned srcSize, Assembler::Register* src,
moveRR(c, 4, &srcHigh, 4, &dstHigh);
}
} else if (src->low != dst->low) {
issue(c, mr(dst->low, src->low));
emit(c, mr(dst->low, src->low));
}
break;
@ -749,7 +738,7 @@ moveZRR(Context* c, unsigned srcSize, Assembler::Register* src,
{
switch (srcSize) {
case 2:
issue(c, andi(dst->low, src->low, 0xFFFF));
emit(c, andi(dst->low, src->low, 0xFFFF));
break;
default: abort(c);
@ -764,16 +753,16 @@ moveCR2(Context* c, unsigned, Assembler::Constant* src,
if (src->value->resolved()) {
int32_t v = src->value->value();
if (isInt16(v)) {
issue(c, li(dst->low, v));
emit(c, li(dst->low, v));
} else {
issue(c, lis(dst->low, v >> 16));
issue(c, ori(dst->low, dst->low, v));
emit(c, lis(dst->low, v >> 16));
emit(c, ori(dst->low, dst->low, v));
}
} else {
appendImmediateTask
(c, src->value, offset(c), BytesPerWord, promiseOffset, false);
issue(c, lis(dst->low, 0));
issue(c, ori(dst->low, dst->low, 0));
emit(c, lis(dst->low, 0));
emit(c, ori(dst->low, dst->low, 0));
}
} else {
abort(c); // todo
@ -787,38 +776,38 @@ moveCR(Context* c, unsigned srcSize, Assembler::Constant* src,
moveCR2(c, srcSize, src, dstSize, dst, 0);
}
void addR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t) {
void addR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) {
if(size == 8) {
issue(con, addc(R(t), R(a), R(b)));
issue(con, adde(H(t), H(a), H(b)));
emit(con, addc(t->low, a->low, b->low));
emit(con, adde(t->high, a->high, b->high));
} else {
issue(con, add(R(t), R(a), R(b)));
emit(con, add(t->low, a->low, b->low));
}
}
void addC(Context* con, unsigned size, Const* a, Reg* b, Reg* t) {
void addC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) {
assert(con, size == BytesPerWord);
int32_t i = getVal(a);
int32_t i = getValue(a);
if(i) {
issue(con, addi(R(t), R(b), lo16(i)));
emit(con, addi(t->low, b->low, lo16(i)));
if(not isInt16(i))
issue(con, addis(R(t), R(t), hi16(i) + carry16(i)));
emit(con, addis(t->low, t->low, hi16(i) + carry16(i)));
} else {
moveRR(con, size, b, size, t);
}
}
void subR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t) {
void subR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) {
if(size == 8) {
issue(con, subfc(R(t), R(a), R(b)));
issue(con, subfe(H(t), H(a), H(b)));
emit(con, subfc(t->low, a->low, b->low));
emit(con, subfe(t->high, a->high, b->high));
} else {
issue(con, subf(R(t), R(a), R(b)));
emit(con, subf(t->low, a->low, b->low));
}
}
void subC(Context* c, unsigned size, Const* a, Reg* b, Reg* t) {
void subC(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* t) {
assert(c, size == BytesPerWord);
ResolvedPromise promise(- a->value->value());
@ -826,7 +815,7 @@ void subC(Context* c, unsigned size, Const* a, Reg* b, Reg* t) {
addC(c, size, &constant, b, t);
}
void multiplyR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t) {
void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) {
if(size == 8) {
bool useTemporaries = b->low == t->low;
int tmpLow;
@ -839,28 +828,28 @@ void multiplyR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t) {
tmpHigh = t->high;
}
issue(con, mullw(tmpHigh, H(a), R(b)));
issue(con, mullw(tmpLow, R(a), H(b)));
issue(con, add(H(t), tmpHigh, tmpLow));
issue(con, mulhwu(tmpLow, R(a), R(b)));
issue(con, add(H(t), H(t), tmpLow));
issue(con, mullw(R(t), R(a), R(b)));
emit(con, mullw(tmpHigh, a->high, b->low));
emit(con, mullw(tmpLow, a->low, b->high));
emit(con, add(t->high, tmpHigh, tmpLow));
emit(con, mulhwu(tmpLow, a->low, b->low));
emit(con, add(t->high, t->high, tmpLow));
emit(con, mullw(t->low, a->low, b->low));
if (useTemporaries) {
con->client->releaseTemporary(tmpLow);
con->client->releaseTemporary(tmpHigh);
}
} else {
issue(con, mullw(R(t), R(a), R(b)));
emit(con, mullw(t->low, a->low, b->low));
}
}
void divideR(Context* con, unsigned size UNUSED, Reg* a, Reg* b, Reg* t) {
void divideR(Context* con, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) {
assert(con, size == 4);
issue(con, divw(R(t), R(b), R(a)));
emit(con, divw(t->low, b->low, a->low));
}
void remainderR(Context* con, unsigned size, Reg* a, Reg* b, Reg* t) {
void remainderR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) {
bool useTemporary = b->low == t->low;
Assembler::Register tmp(t->low);
if (useTemporary) {
@ -935,15 +924,15 @@ store(Context* c, unsigned size, Assembler::Register* src,
switch (size) {
case 1:
issue(c, stbx(src->low, base, normalized));
emit(c, stbx(src->low, base, normalized));
break;
case 2:
issue(c, sthx(src->low, base, normalized));
emit(c, sthx(src->low, base, normalized));
break;
case 4:
issue(c, stwx(src->low, base, normalized));
emit(c, stwx(src->low, base, normalized));
break;
case 8: {
@ -959,15 +948,15 @@ store(Context* c, unsigned size, Assembler::Register* src,
} else {
switch (size) {
case 1:
issue(c, stb(src->low, base, offset));
emit(c, stb(src->low, base, offset));
break;
case 2:
issue(c, sth(src->low, base, offset));
emit(c, sth(src->low, base, offset));
break;
case 4:
issue(c, stw(src->low, base, offset));
emit(c, stw(src->low, base, offset));
break;
case 8: {
@ -998,12 +987,12 @@ moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, Assembler::Register* src,
assert(c, dstSize == BytesPerWord);
if (dst->index == NoRegister) {
issue(c, stwu(src->low, dst->base, dst->offset));
emit(c, stwu(src->low, dst->base, dst->offset));
} else {
assert(c, dst->offset == 0);
assert(c, dst->scale == 1);
issue(c, stwux(src->low, dst->base, dst->index));
emit(c, stwux(src->low, dst->base, dst->index));
}
}
@ -1019,17 +1008,17 @@ load(Context* c, unsigned srcSize, int base, int offset, int index,
switch (srcSize) {
case 1:
issue(c, lbzx(dst->low, base, normalized));
emit(c, lbzx(dst->low, base, normalized));
if (signExtend) {
issue(c, extsb(dst->low, dst->low));
emit(c, extsb(dst->low, dst->low));
}
break;
case 2:
if (signExtend) {
issue(c, lhax(dst->low, base, normalized));
emit(c, lhax(dst->low, base, normalized));
} else {
issue(c, lhzx(dst->low, base, normalized));
emit(c, lhzx(dst->low, base, normalized));
}
break;
@ -1043,7 +1032,7 @@ load(Context* c, unsigned srcSize, int base, int offset, int index,
load(c, 4, base, 0, normalized, 1, 4, &dstHigh, preserveIndex, false);
load(c, 4, base, 4, normalized, 1, 4, dst, preserveIndex, false);
} else {
issue(c, lwzx(dst->low, base, normalized));
emit(c, lwzx(dst->low, base, normalized));
}
} break;
@ -1054,22 +1043,22 @@ load(Context* c, unsigned srcSize, int base, int offset, int index,
} else {
switch (srcSize) {
case 1:
issue(c, lbz(dst->low, base, offset));
emit(c, lbz(dst->low, base, offset));
if (signExtend) {
issue(c, extsb(dst->low, dst->low));
emit(c, extsb(dst->low, dst->low));
}
break;
case 2:
if (signExtend) {
issue(c, lha(dst->low, base, offset));
emit(c, lha(dst->low, base, offset));
} else {
issue(c, lha(dst->low, base, offset));
emit(c, lha(dst->low, base, offset));
}
break;
case 4:
issue(c, lwz(dst->low, base, offset));
emit(c, lwz(dst->low, base, offset));
break;
case 8: {
@ -1078,7 +1067,7 @@ load(Context* c, unsigned srcSize, int base, int offset, int index,
load(c, 4, base, offset, NoRegister, 1, 4, &dstHigh, false, false);
load(c, 4, base, offset + 4, NoRegister, 1, 4, dst, false, false);
} else {
issue(c, lwzx(dst->low, base, offset));
emit(c, lwzx(dst->low, base, offset));
}
} break;
@ -1103,19 +1092,6 @@ moveZMR(Context* c, unsigned srcSize, Assembler::Memory* src,
dstSize, dst, true, false);
}
// void moveCR3(Context* con, unsigned aSize, Const* a, unsigned tSize, Reg* t) {
// int64_t i = getVal(a);
// if(tSize == 8) {
// int64_t j;
// if(aSize == 8) j = i; // 64-bit const -> load high bits into high register
// else j = 0; // 32-bit const -> clear high register
// issue(con, lis(H(t), hi16(hi32(j))));
// issue(con, ori(H(t), H(t), lo16(hi32(j))));
// }
// issue(con, lis(R(t), hi16(i)));
// issue(con, ori(R(t), R(t), lo16(i)));
// }
void
andR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b, Assembler::Register* dst)
@ -1128,7 +1104,7 @@ andR(Context* c, unsigned size, Assembler::Register* a,
andR(c, 4, a, b, dst);
andR(c, 4, &ah, &bh, &dh);
} else {
issue(c, and_(dst->low, a->low, b->low));
emit(c, and_(dst->low, a->low, b->low));
}
}
@ -1181,9 +1157,9 @@ andC(Context* c, unsigned size, Assembler::Constant* a,
// the topmost or bottommost 16 bits are zero.
if ((v32 >> 16) == 0) {
issue(c, andi(dst->low, b->low, v32));
emit(c, andi(dst->low, b->low, v32));
} else if ((v32 & 0xFFFF) == 0) {
issue(c, andis(dst->low, b->low, v32 >> 16));
emit(c, andis(dst->low, b->low, v32 >> 16));
} else {
bool useTemporary = b->low == dst->low;
Assembler::Register tmp(dst->low);
@ -1206,12 +1182,12 @@ andC(Context* c, unsigned size, Assembler::Constant* a,
if (state) {
if (start != 0 or end != 31) {
issue(c, rlwinm(dst->low, b->low, 0, 31 - end, 31 - start));
emit(c, rlwinm(dst->low, b->low, 0, 31 - end, 31 - start));
} else {
moveRR(c, 4, b, 4, dst);
}
} else {
issue(c, li(dst->low, 0));
emit(c, li(dst->low, 0));
}
}
}
@ -1228,7 +1204,7 @@ orR(Context* c, unsigned size, Assembler::Register* a,
orR(c, 4, a, b, dst);
orR(c, 4, &ah, &bh, &dh);
} else {
issue(c, or_(dst->low, a->low, b->low));
emit(c, or_(dst->low, a->low, b->low));
}
}
@ -1251,9 +1227,9 @@ orC(Context* c, unsigned size, Assembler::Constant* a,
orC(c, 4, &al, b, dst);
orC(c, 4, &ah, &bh, &dh);
} else {
issue(c, ori(b->low, dst->low, v));
emit(c, ori(b->low, dst->low, v));
if (v >> 16) {
issue(c, oris(dst->low, dst->low, v >> 16));
emit(c, oris(dst->low, dst->low, v >> 16));
}
}
}
@ -1270,7 +1246,7 @@ xorR(Context* c, unsigned size, Assembler::Register* a,
xorR(c, 4, a, b, dst);
xorR(c, 4, &ah, &bh, &dh);
} else {
issue(c, xor_(dst->low, a->low, b->low));
emit(c, xor_(dst->low, a->low, b->low));
}
}
@ -1294,10 +1270,10 @@ xorC(Context* c, unsigned size, Assembler::Constant* a,
xorC(c, 4, &ah, &bh, &dh);
} else {
if (v >> 16) {
issue(c, xoris(b->low, dst->low, v >> 16));
issue(c, xori(dst->low, dst->low, v));
emit(c, xoris(b->low, dst->low, v >> 16));
emit(c, xori(dst->low, dst->low, v));
} else {
issue(c, xori(b->low, dst->low, v));
emit(c, xori(b->low, dst->low, v));
}
}
}
@ -1313,7 +1289,7 @@ moveAR2(Context* c, unsigned srcSize UNUSED, Assembler::Address* src,
appendImmediateTask
(c, src->address, offset(c), BytesPerWord, promiseOffset, true);
issue(c, lis(dst->low, 0));
emit(c, lis(dst->low, 0));
moveMR(c, dstSize, &memory, dstSize, dst);
}
@ -1330,7 +1306,7 @@ compareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
{
assert(c, aSize == 4 and bSize == 4);
issue(c, cmpw(b->low, a->low));
emit(c, cmpw(b->low, a->low));
}
void
@ -1340,7 +1316,7 @@ compareCR(Context* c, unsigned aSize, Assembler::Constant* a,
assert(c, aSize == 4 and bSize == 4);
if (a->value->resolved() and isInt16(a->value->value())) {
issue(c, cmpwi(b->low, a->value->value()));
emit(c, cmpwi(b->low, a->value->value()));
} else {
Assembler::Register tmp(c->client->acquireTemporary());
moveCR(c, aSize, a, bSize, &tmp);
@ -1379,7 +1355,7 @@ compareUnsignedRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
{
assert(c, aSize == 4 and bSize == 4);
issue(c, cmplw(b->low, a->low));
emit(c, cmplw(b->low, a->low));
}
void
@ -1389,7 +1365,7 @@ compareUnsignedCR(Context* c, unsigned aSize, Assembler::Constant* a,
assert(c, aSize == 4 and bSize == 4);
if (a->value->resolved() and (a->value->value() >> 16) == 0) {
issue(c, cmplwi(b->low, a->value->value()));
emit(c, cmplwi(b->low, a->value->value()));
} else {
Assembler::Register tmp(c->client->acquireTemporary());
moveCR(c, aSize, a, bSize, &tmp);
@ -1429,7 +1405,7 @@ void
conditional(Context* c, int32_t branch, Assembler::Constant* target)
{
appendOffsetTask(c, target->value, offset(c), true);
issue(c, branch);
emit(c, branch);
}
void
@ -1452,7 +1428,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al,
switch (op) {
case JumpIfEqual:
next = c->code.length();
issue(c, bne(0));
emit(c, bne(0));
compareSigned(c, 4, al, 4, bl);
conditional(c, beq(0), target);
@ -1469,7 +1445,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al,
conditional(c, blt(0), target);
next = c->code.length();
issue(c, bgt(0));
emit(c, bgt(0));
compareUnsigned(c, 4, al, 4, bl);
conditional(c, blt(0), target);
@ -1479,7 +1455,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al,
conditional(c, bgt(0), target);
next = c->code.length();
issue(c, blt(0));
emit(c, blt(0));
compareUnsigned(c, 4, al, 4, bl);
conditional(c, bgt(0), target);
@ -1489,7 +1465,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al,
conditional(c, blt(0), target);
next = c->code.length();
issue(c, bgt(0));
emit(c, bgt(0));
compareUnsigned(c, 4, al, 4, bl);
conditional(c, ble(0), target);
@ -1499,7 +1475,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al,
conditional(c, bgt(0), target);
next = c->code.length();
issue(c, blt(0));
emit(c, blt(0));
compareUnsigned(c, 4, al, 4, bl);
conditional(c, bge(0), target);
@ -1621,10 +1597,10 @@ negateRR(Context* c, unsigned srcSize, Assembler::Register* src,
if (srcSize == 8) {
Assembler::Register dstHigh(dst->high);
issue(c, subfic(dst->low, src->low, 0));
issue(c, subfze(dst->high, src->high));
emit(c, subfic(dst->low, src->low, 0));
emit(c, subfze(dst->high, src->high));
} else {
issue(c, neg(dst->low, src->low));
emit(c, neg(dst->low, src->low));
}
}
@ -1633,8 +1609,8 @@ callR(Context* c, unsigned size UNUSED, Assembler::Register* target)
{
assert(c, size == BytesPerWord);
issue(c, mtctr(target->low));
issue(c, bctrl());
emit(c, mtctr(target->low));
emit(c, bctrl());
}
void
@ -1643,7 +1619,7 @@ callC(Context* c, unsigned size UNUSED, Assembler::Constant* target)
assert(c, size == BytesPerWord);
appendOffsetTask(c, target->value, offset(c), false);
issue(c, bl(0));
emit(c, bl(0));
}
void
@ -1696,7 +1672,7 @@ jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target)
assert(c, size == BytesPerWord);
appendOffsetTask(c, target->value, offset(c), false);
issue(c, b(0));
emit(c, b(0));
}
void
@ -1705,7 +1681,7 @@ jumpIfEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* target)
assert(c, size == BytesPerWord);
appendOffsetTask(c, target->value, offset(c), true);
issue(c, beq(0));
emit(c, beq(0));
}
void
@ -1714,7 +1690,7 @@ jumpIfNotEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* target)
assert(c, size == BytesPerWord);
appendOffsetTask(c, target->value, offset(c), true);
issue(c, bne(0));
emit(c, bne(0));
}
void
@ -1723,7 +1699,7 @@ jumpIfGreaterC(Context* c, unsigned size UNUSED, Assembler::Constant* target)
assert(c, size == BytesPerWord);
appendOffsetTask(c, target->value, offset(c), true);
issue(c, bgt(0));
emit(c, bgt(0));
}
void
@ -1733,7 +1709,7 @@ jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED,
assert(c, size == BytesPerWord);
appendOffsetTask(c, target->value, offset(c), true);
issue(c, bge(0));
emit(c, bge(0));
}
void
@ -1742,7 +1718,7 @@ jumpIfLessC(Context* c, unsigned size UNUSED, Assembler::Constant* target)
assert(c, size == BytesPerWord);
appendOffsetTask(c, target->value, offset(c), true);
issue(c, blt(0));
emit(c, blt(0));
}
void
@ -1752,19 +1728,19 @@ jumpIfLessOrEqualC(Context* c, unsigned size UNUSED,
assert(c, size == BytesPerWord);
appendOffsetTask(c, target->value, offset(c), true);
issue(c, ble(0));
emit(c, ble(0));
}
void
return_(Context* c)
{
issue(c, blr());
emit(c, blr());
}
void
memoryBarrier(Context* c)
{
issue(c, sync(0));
emit(c, sync(0));
}
// END OPERATION COMPILERS
@ -2268,7 +2244,7 @@ class MyAssembler: public Assembler {
virtual void allocateFrame(unsigned footprint) {
Register returnAddress(0);
issue(&c, mflr(returnAddress.low));
emit(&c, mflr(returnAddress.low));
Memory returnAddressDst(StackRegister, 8);
moveRM(&c, BytesPerWord, &returnAddress, BytesPerWord, &returnAddressDst);
@ -2296,7 +2272,7 @@ class MyAssembler: public Assembler {
Memory returnAddressSrc(StackRegister, 8);
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &returnAddress);
issue(&c, mtlr(returnAddress.low));
emit(&c, mtlr(returnAddress.low));
}
virtual void popFrameForTailCall(unsigned footprint,
@ -2310,7 +2286,7 @@ class MyAssembler: public Assembler {
Memory returnAddressSrc(StackRegister, 8 + (footprint * BytesPerWord));
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &tmp);
issue(&c, mtlr(tmp.low));
emit(&c, mtlr(tmp.low));
Memory stackSrc(StackRegister, footprint * BytesPerWord);
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp);

View File

@ -199,7 +199,8 @@ inline bool
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
{
#ifdef _MSC_VER
InterlockedCompareExchange(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
@ -218,7 +219,8 @@ inline bool
atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
{
#ifdef _MSC_VER
InterlockedCompareExchange64(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_);
#else