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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -17,25 +17,25 @@
#include "jni-util.h" #include "jni-util.h"
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
# include <winsock2.h> #include <winsock2.h>
# include <ws2tcpip.h> #include <ws2tcpip.h>
# include <errno.h> #include <errno.h>
# ifdef _MSC_VER #ifdef _MSC_VER
# define snprintf sprintf_s #define snprintf sprintf_s
# else
# include <unistd.h>
# endif
#else #else
# include <unistd.h> #include <unistd.h>
# include <fcntl.h> #endif
# include <errno.h> #else
# include <netdb.h> #include <unistd.h>
# include <sys/select.h> #include <fcntl.h>
# include <arpa/inet.h> #include <errno.h>
# include <netinet/in.h> #include <netdb.h>
# include <netinet/ip.h> #include <sys/select.h>
# include <netinet/tcp.h> #include <arpa/inet.h>
# include <sys/socket.h> #include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#endif #endif
#define java_nio_channels_SelectionKey_OP_READ 1L #define java_nio_channels_SelectionKey_OP_READ 1L
@ -47,12 +47,14 @@
typedef int socklen_t; typedef int socklen_t;
#endif #endif
inline void* operator new(size_t, void* p) throw() { return p; } inline void* operator new(size_t, void* p) throw()
{
return p;
}
namespace { namespace {
inline jbyteArray inline jbyteArray charsToArray(JNIEnv* e, const char* s)
charsToArray(JNIEnv* e, const char* s)
{ {
unsigned length = strlen(s); unsigned length = strlen(s);
jbyteArray a = e->NewByteArray(length + 1); jbyteArray a = e->NewByteArray(length + 1);
@ -60,8 +62,7 @@ charsToArray(JNIEnv* e, const char* s)
return a; return a;
} }
inline void inline void doClose(int socket)
doClose(int socket)
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
closesocket(socket); closesocket(socket);
@ -70,8 +71,7 @@ doClose(int socket)
#endif #endif
} }
inline jbyteArray inline jbyteArray errorString(JNIEnv* e, int n)
errorString(JNIEnv* e, int n)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
const unsigned size = 128; const unsigned size = 128;
@ -83,8 +83,7 @@ errorString(JNIEnv* e, int n)
#endif #endif
} }
inline jbyteArray inline jbyteArray socketErrorString(JNIEnv* e, int n)
socketErrorString(JNIEnv* e, int n)
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
const unsigned size = 64; const unsigned size = 64;
@ -96,8 +95,7 @@ socketErrorString(JNIEnv* e, int n)
#endif #endif
} }
inline jbyteArray inline jbyteArray errorString(JNIEnv* e)
errorString(JNIEnv* e)
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
const unsigned size = 64; const unsigned size = 64;
@ -109,8 +107,7 @@ errorString(JNIEnv* e)
#endif #endif
} }
void void throwIOException(JNIEnv* e, const char* s)
throwIOException(JNIEnv* e, const char* s)
{ {
throwNew(e, "java/io/IOException", s); throwNew(e, "java/io/IOException", s);
} }
@ -128,20 +125,17 @@ void throwIOException(JNIEnv* e, jbyteArray a)
} }
} }
void void throwIOException(JNIEnv* e)
throwIOException(JNIEnv* e)
{ {
throwIOException(e, errorString(e)); throwIOException(e, errorString(e));
} }
void void throwSocketException(JNIEnv* e, const char* s)
throwSocketException(JNIEnv* e, const char* s)
{ {
throwNew(e, "java/net/SocketException", s); throwNew(e, "java/net/SocketException", s);
} }
void void throwSocketException(JNIEnv* e, jbyteArray a)
throwSocketException(JNIEnv* e, jbyteArray a)
{ {
size_t length = e->GetArrayLength(a); size_t length = e->GetArrayLength(a);
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length)); uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
@ -154,8 +148,7 @@ throwSocketException(JNIEnv* e, jbyteArray a)
} }
} }
void void throwSocketException(JNIEnv* e)
throwSocketException(JNIEnv* e)
{ {
throwSocketException(e, errorString(e)); throwSocketException(e, errorString(e));
} }
@ -168,41 +161,36 @@ void init(sockaddr_in* address, jint host, jint port)
address->sin_addr.s_addr = htonl(host); address->sin_addr.s_addr = htonl(host);
} }
inline bool inline bool einProgress(int error)
einProgress(int error)
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
return error == WSAEINPROGRESS return error == WSAEINPROGRESS or error == WSAEWOULDBLOCK;
or error == WSAEWOULDBLOCK;
#else #else
return error == EINPROGRESS; return error == EINPROGRESS;
#endif #endif
} }
inline bool inline bool einProgress()
einProgress()
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
return WSAGetLastError() == WSAEINPROGRESS return WSAGetLastError() == WSAEINPROGRESS
or WSAGetLastError() == WSAEWOULDBLOCK; or WSAGetLastError() == WSAEWOULDBLOCK;
#else #else
return errno == EINPROGRESS; return errno == EINPROGRESS;
#endif #endif
} }
inline bool inline bool eagain()
eagain()
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
return WSAGetLastError() == WSAEINPROGRESS return WSAGetLastError() == WSAEINPROGRESS
or WSAGetLastError() == WSAEWOULDBLOCK; or WSAGetLastError() == WSAEWOULDBLOCK;
#else #else
return errno == EAGAIN; return errno == EAGAIN;
#endif #endif
} }
bool bool setBlocking(JNIEnv* e, int d, bool blocking)
setBlocking(JNIEnv* e, int d, bool blocking)
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
u_long a = (blocking ? 0 : 1); u_long a = (blocking ? 0 : 1);
@ -212,9 +200,10 @@ setBlocking(JNIEnv* e, int d, bool blocking)
return false; return false;
} }
#else #else
int r = fcntl(d, F_SETFL, (blocking int r = fcntl(d,
? (fcntl(d, F_GETFL) & (~O_NONBLOCK)) F_SETFL,
: (fcntl(d, F_GETFL) | O_NONBLOCK))); (blocking ? (fcntl(d, F_GETFL) & (~O_NONBLOCK))
: (fcntl(d, F_GETFL) | O_NONBLOCK)));
if (r < 0) { if (r < 0) {
throwIOException(e); throwIOException(e);
return false; return false;
@ -223,12 +212,11 @@ setBlocking(JNIEnv* e, int d, bool blocking)
return true; return true;
} }
bool bool setTcpNoDelay(JNIEnv* e, int d, bool on)
setTcpNoDelay(JNIEnv* e, int d, bool on)
{ {
int flag = on; int flag = on;
int r = setsockopt int r = setsockopt(
(d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&flag), sizeof(int)); d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&flag), sizeof(int));
if (r < 0) { if (r < 0) {
throwSocketException(e); throwSocketException(e);
return false; return false;
@ -236,12 +224,15 @@ setTcpNoDelay(JNIEnv* e, int d, bool on)
return true; return true;
} }
void void doBind(JNIEnv* e, int s, sockaddr_in* address)
doBind(JNIEnv* e, int s, sockaddr_in* address)
{ {
{ int opt = 1; {
int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR, int opt = 1;
reinterpret_cast<char*>(&opt), sizeof(int)); int r = ::setsockopt(s,
SOL_SOCKET,
SO_REUSEADDR,
reinterpret_cast<char*>(&opt),
sizeof(int));
if (r != 0) { if (r != 0) {
throwIOException(e); throwIOException(e);
return; return;
@ -249,9 +240,13 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
} }
#ifdef SO_NOSIGPIPE #ifdef SO_NOSIGPIPE
{ int opt = 1; {
int r = ::setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, int opt = 1;
reinterpret_cast<char*>(&opt), sizeof(int)); int r = ::setsockopt(s,
SOL_SOCKET,
SO_NOSIGPIPE,
reinterpret_cast<char*>(&opt),
sizeof(int));
if (r != 0) { if (r != 0) {
throwIOException(e); throwIOException(e);
return; return;
@ -259,8 +254,9 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
} }
#endif #endif
{ int r = ::bind {
(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in)); int r
= ::bind(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
if (r != 0) { if (r != 0) {
throwIOException(e); throwIOException(e);
return; return;
@ -268,8 +264,7 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
} }
} }
void void doListen(JNIEnv* e, int s)
doListen(JNIEnv* e, int s)
{ {
int r = ::listen(s, 100); int r = ::listen(s, 100);
if (r != 0) { if (r != 0) {
@ -277,13 +272,12 @@ doListen(JNIEnv* e, int s)
} }
} }
void void doFinishConnect(JNIEnv* e, int socket)
doFinishConnect(JNIEnv* e, int socket)
{ {
int error; int error;
socklen_t size = sizeof(int); socklen_t size = sizeof(int);
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR, int r = getsockopt(
reinterpret_cast<char*>(&error), &size); socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
if (r != 0 or size != sizeof(int)) { if (r != 0 or size != sizeof(int)) {
throwIOException(e); throwIOException(e);
@ -292,11 +286,10 @@ doFinishConnect(JNIEnv* e, int socket)
} }
} }
bool bool doConnect(JNIEnv* e, int s, sockaddr_in* address)
doConnect(JNIEnv* e, int s, sockaddr_in* address)
{ {
int r = ::connect(s, reinterpret_cast<sockaddr*>(address), int r
sizeof(sockaddr_in)); = ::connect(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
if (r == 0) { if (r == 0) {
return true; return true;
} else if (not einProgress()) { } else if (not einProgress()) {
@ -307,8 +300,7 @@ doConnect(JNIEnv* e, int s, sockaddr_in* address)
} }
} }
int int doAccept(JNIEnv* e, int s)
doAccept(JNIEnv* e, int s)
{ {
sockaddr address; sockaddr address;
socklen_t length = sizeof(address); socklen_t length = sizeof(address);
@ -321,8 +313,7 @@ doAccept(JNIEnv* e, int s)
return -1; return -1;
} }
int int doRead(int fd, void* buffer, size_t count)
doRead(int fd, void* buffer, size_t count)
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
return recv(fd, static_cast<char*>(buffer), count, 0); return recv(fd, static_cast<char*>(buffer), count, 0);
@ -331,16 +322,15 @@ doRead(int fd, void* buffer, size_t count)
#endif #endif
} }
int int doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
{ {
sockaddr address; sockaddr address;
socklen_t length = sizeof(address); socklen_t length = sizeof(address);
int r = recvfrom int r = recvfrom(fd, static_cast<char*>(buffer), count, 0, &address, &length);
(fd, static_cast<char*>(buffer), count, 0, &address, &length);
if (r > 0) { if (r > 0) {
sockaddr_in a; memcpy(&a, &address, length); sockaddr_in a;
memcpy(&a, &address, length);
*host = ntohl(a.sin_addr.s_addr); *host = ntohl(a.sin_addr.s_addr);
*port = ntohs(a.sin_port); *port = ntohs(a.sin_port);
} else { } else {
@ -351,8 +341,7 @@ doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
return r; return r;
} }
int int doWrite(int fd, const void* buffer, size_t count)
doWrite(int fd, const void* buffer, size_t count)
{ {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
return send(fd, static_cast<const char*>(buffer), count, 0); return send(fd, static_cast<const char*>(buffer), count, 0);
@ -382,11 +371,12 @@ int makeSocket(JNIEnv* e, int type = SOCK_STREAM, int protocol = IPPROTO_TCP)
return s; return s;
} }
} // namespace <anonymous> } // namespace <anonymous>
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_ServerSocketChannel_natDoAccept(JNIEnv *e, jclass, jint socket) Java_java_nio_channels_ServerSocketChannel_natDoAccept(JNIEnv* e,
jclass,
jint socket)
{ {
return ::doAccept(e, socket); return ::doAccept(e, socket);
} }
@ -432,29 +422,29 @@ extern "C" JNIEXPORT void JNICALL
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv *e, Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv* e,
jclass, jclass,
jint socket, jint socket,
jboolean blocking) jboolean blocking)
{ {
setBlocking(e, socket, blocking); setBlocking(e, socket, blocking);
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e, Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e,
jclass c, jclass c,
jint socket, jint socket,
jboolean blocking) jboolean blocking)
{ {
return Java_java_nio_channels_SocketChannel_configureBlocking return Java_java_nio_channels_SocketChannel_configureBlocking(
(e, c, socket, blocking); e, c, socket, blocking);
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv *e, Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv* e,
jclass, jclass,
jint socket, jint socket,
jboolean on) jboolean on)
{ {
setTcpNoDelay(e, socket, on); setTcpNoDelay(e, socket, on);
} }
@ -498,21 +488,21 @@ extern "C" JNIEXPORT jboolean JNICALL
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv *e, Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv* e,
jclass, jclass,
jint socket) jint socket)
{ {
doFinishConnect(e, socket); doFinishConnect(e, socket);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e, Java_java_nio_channels_SocketChannel_natRead(JNIEnv* e,
jclass, jclass,
jint socket, jint socket,
jbyteArray buffer, jbyteArray buffer,
jint offset, jint offset,
jint length, jint length,
jboolean blocking) jboolean blocking)
{ {
int r; int r;
if (blocking) { if (blocking) {
@ -520,8 +510,7 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
if (buf) { if (buf) {
r = ::doRead(socket, buf, length); r = ::doRead(socket, buf, length);
if (r > 0) { if (r > 0) {
e->SetByteArrayRegion e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
} }
free(buf); free(buf);
} else { } else {
@ -529,8 +518,8 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
} }
} else { } else {
jboolean isCopy; jboolean isCopy;
uint8_t* buf = static_cast<uint8_t*> uint8_t* buf
(e->GetPrimitiveArrayCritical(buffer, &isCopy)); = static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
r = ::doRead(socket, buf + offset, length); r = ::doRead(socket, buf + offset, length);
@ -550,14 +539,14 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e, Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
jclass, jclass,
jint socket, jint socket,
jbyteArray buffer, jbyteArray buffer,
jint offset, jint offset,
jint length, jint length,
jboolean blocking, jboolean blocking,
jintArray address) jintArray address)
{ {
int r; int r;
int32_t host; int32_t host;
@ -567,8 +556,7 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
if (buf) { if (buf) {
r = ::doRecv(socket, buf, length, &host, &port); r = ::doRecv(socket, buf, length, &host, &port);
if (r > 0) { if (r > 0) {
e->SetByteArrayRegion e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
} }
free(buf); free(buf);
} else { } else {
@ -576,8 +564,8 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
} }
} else { } else {
jboolean isCopy; jboolean isCopy;
uint8_t* buf = static_cast<uint8_t*> uint8_t* buf
(e->GetPrimitiveArrayCritical(buffer, &isCopy)); = static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
r = ::doRecv(socket, buf + offset, length, &host, &port); r = ::doRecv(socket, buf + offset, length, &host, &port);
@ -593,28 +581,30 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
} else if (r == 0) { } else if (r == 0) {
return -1; return -1;
} else { } else {
jint jhost = host; e->SetIntArrayRegion(address, 0, 1, &jhost); jint jhost = host;
jint jport = port; e->SetIntArrayRegion(address, 1, 1, &jport); e->SetIntArrayRegion(address, 0, 1, &jhost);
jint jport = port;
e->SetIntArrayRegion(address, 1, 1, &jport);
} }
return r; return r;
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e, Java_java_nio_channels_SocketChannel_natWrite(JNIEnv* e,
jclass, jclass,
jint socket, jint socket,
jbyteArray buffer, jbyteArray buffer,
jint offset, jint offset,
jint length, jint length,
jboolean blocking) jboolean blocking)
{ {
int r; int r;
if (blocking) { if (blocking) {
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length)); uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
if (buf) { if (buf) {
e->GetByteArrayRegion e->GetByteArrayRegion(
(buffer, offset, length, reinterpret_cast<jbyte*>(buf)); buffer, offset, length, reinterpret_cast<jbyte*>(buf));
r = ::doWrite(socket, buf, length); r = ::doWrite(socket, buf, length);
free(buf); free(buf);
} else { } else {
@ -622,8 +612,8 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
} }
} else { } else {
jboolean isCopy; jboolean isCopy;
uint8_t* buf = static_cast<uint8_t*> uint8_t* buf
(e->GetPrimitiveArrayCritical(buffer, &isCopy)); = static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
r = ::doWrite(socket, buf + offset, length); r = ::doWrite(socket, buf + offset, length);
@ -641,16 +631,16 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_DatagramChannel_write(JNIEnv* e, Java_java_nio_channels_DatagramChannel_write(JNIEnv* e,
jclass c, jclass c,
jint socket, jint socket,
jbyteArray buffer, jbyteArray buffer,
jint offset, jint offset,
jint length, jint length,
jboolean blocking) jboolean blocking)
{ {
return Java_java_nio_channels_SocketChannel_natWrite return Java_java_nio_channels_SocketChannel_natWrite(
(e, c, socket, buffer, offset, length, blocking); e, c, socket, buffer, offset, length, blocking);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
@ -699,14 +689,14 @@ extern "C" JNIEXPORT jint JNICALL
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e, Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv* e,
jclass, jclass,
jint socket) jint socket)
{ {
int error; int error;
socklen_t size = sizeof(int); socklen_t size = sizeof(int);
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR, int r = getsockopt(
reinterpret_cast<char*>(&error), &size); socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
if (r != 0 or size != sizeof(int)) { if (r != 0 or size != sizeof(int)) {
throwIOException(e); throwIOException(e);
} else if (error != 0) { } else if (error != 0) {
@ -715,17 +705,15 @@ Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e,
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv *, Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv*,
jclass, jclass,
jint socket) jint socket)
{ {
doClose(socket); doClose(socket);
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_DatagramChannel_close(JNIEnv *, Java_java_nio_channels_DatagramChannel_close(JNIEnv*, jclass, jint socket)
jclass,
jint socket)
{ {
doClose(socket); doClose(socket);
} }
@ -739,69 +727,85 @@ class Pipe {
// pipe descriptors or others. Thus, to implement // pipe descriptors or others. Thus, to implement
// Selector.wakeup(), we make a socket connection via the loopback // Selector.wakeup(), we make a socket connection via the loopback
// interface and use it as a pipe. // interface and use it as a pipe.
Pipe(JNIEnv* e): connected_(false), listener_(-1), reader_(-1), writer_(-1) { Pipe(JNIEnv* e) : connected_(false), listener_(-1), reader_(-1), writer_(-1)
{
sockaddr_in address; sockaddr_in address;
address.sin_family = AF_INET; address.sin_family = AF_INET;
address.sin_port = 0; address.sin_port = 0;
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //INADDR_LOOPBACK; address.sin_addr.s_addr = inet_addr("127.0.0.1"); // INADDR_LOOPBACK;
listener_ = makeSocket(e); listener_ = makeSocket(e);
if (e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
setBlocking(e, listener_, false); setBlocking(e, listener_, false);
::doBind(e, listener_, &address); ::doBind(e, listener_, &address);
if (e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
::doListen(e, listener_); ::doListen(e, listener_);
if (e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
socklen_t length = sizeof(sockaddr_in); socklen_t length = sizeof(sockaddr_in);
int r = getsockname(listener_, reinterpret_cast<sockaddr*>(&address), int r = getsockname(
&length); listener_, reinterpret_cast<sockaddr*>(&address), &length);
if (r) { if (r) {
throwIOException(e); throwIOException(e);
return; return;
} }
writer_ = makeSocket(e); writer_ = makeSocket(e);
if (e->ExceptionCheck()) return; if (e->ExceptionCheck())
return;
setBlocking(e, writer_, true); setBlocking(e, writer_, true);
connected_ = ::doConnect(e, writer_, &address); connected_ = ::doConnect(e, writer_, &address);
} }
void dispose() { void dispose()
if (listener_ >= 0) ::doClose(listener_); {
if (reader_ >= 0) ::doClose(reader_); if (listener_ >= 0)
if (writer_ >= 0) ::doClose(writer_); ::doClose(listener_);
if (reader_ >= 0)
::doClose(reader_);
if (writer_ >= 0)
::doClose(writer_);
} }
bool connected() { bool connected()
{
return connected_; return connected_;
} }
void setConnected(bool v) { void setConnected(bool v)
{
connected_ = v; connected_ = v;
} }
int listener() { int listener()
{
return listener_; return listener_;
} }
void setListener(int v) { void setListener(int v)
{
listener_ = v; listener_ = v;
} }
int reader() { int reader()
{
return reader_; return reader_;
} }
void setReader(int v) { void setReader(int v)
{
reader_ = v; reader_ = v;
} }
int writer() { int writer()
{
return writer_; return writer_;
} }
@ -811,7 +815,8 @@ class Pipe {
int reader_; int reader_;
int writer_; int writer_;
#else #else
Pipe(JNIEnv* e) { Pipe(JNIEnv* e)
{
if (::pipe(pipe) != 0) { if (::pipe(pipe) != 0) {
throwIOException(e); throwIOException(e);
return; return;
@ -824,21 +829,25 @@ class Pipe {
open_ = true; open_ = true;
} }
void dispose() { void dispose()
{
::doClose(pipe[0]); ::doClose(pipe[0]);
::doClose(pipe[1]); ::doClose(pipe[1]);
open_ = false; open_ = false;
} }
bool connected() { bool connected()
{
return open_; return open_;
} }
int reader() { int reader()
{
return pipe[0]; return pipe[0];
} }
int writer() { int writer()
{
return pipe[1]; return pipe[1];
} }
@ -853,18 +862,21 @@ struct SelectorState {
fd_set write; fd_set write;
fd_set except; fd_set except;
Pipe control; Pipe control;
SelectorState(JNIEnv* e) : control(e) { } SelectorState(JNIEnv* e) : control(e)
{
}
}; };
} // namespace } // namespace
extern "C" JNIEXPORT jlong JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass) Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass)
{ {
void *mem = malloc(sizeof(SelectorState)); void* mem = malloc(sizeof(SelectorState));
if (mem) { if (mem) {
SelectorState *s = new (mem) SelectorState(e); SelectorState* s = new (mem) SelectorState(e);
if (e->ExceptionCheck()) return 0; if (e->ExceptionCheck())
return 0;
if (s) { if (s) {
FD_ZERO(&(s->read)); FD_ZERO(&(s->read));
@ -878,7 +890,9 @@ Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass)
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv *e, jclass, jlong state) Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv* e,
jclass,
jlong state)
{ {
SelectorState* s = reinterpret_cast<SelectorState*>(state); SelectorState* s = reinterpret_cast<SelectorState*>(state);
if (s->control.connected()) { if (s->control.connected()) {
@ -891,7 +905,7 @@ Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv *e, jclass, jlong state)
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_SocketSelector_natClose(JNIEnv *, jclass, jlong state) Java_java_nio_channels_SocketSelector_natClose(JNIEnv*, jclass, jlong state)
{ {
SelectorState* s = reinterpret_cast<SelectorState*>(state); SelectorState* s = reinterpret_cast<SelectorState*>(state);
s->control.dispose(); s->control.dispose();
@ -899,9 +913,10 @@ Java_java_nio_channels_SocketSelector_natClose(JNIEnv *, jclass, jlong state)
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv *, jclass, Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv*,
jint socket, jclass,
jlong state) jint socket,
jlong state)
{ {
SelectorState* s = reinterpret_cast<SelectorState*>(state); SelectorState* s = reinterpret_cast<SelectorState*>(state);
FD_CLR(static_cast<unsigned>(socket), &(s->read)); FD_CLR(static_cast<unsigned>(socket), &(s->read));
@ -910,27 +925,30 @@ Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv *, jclass,
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *, Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(
jclass, JNIEnv*,
jint socket, jclass,
jint interest, jint socket,
jlong state, jint interest,
jint max) jlong state,
jint max)
{ {
SelectorState* s = reinterpret_cast<SelectorState*>(state); SelectorState* s = reinterpret_cast<SelectorState*>(state);
if (interest & (java_nio_channels_SelectionKey_OP_READ | if (interest & (java_nio_channels_SelectionKey_OP_READ
java_nio_channels_SelectionKey_OP_ACCEPT)) { | java_nio_channels_SelectionKey_OP_ACCEPT)) {
FD_SET(static_cast<unsigned>(socket), &(s->read)); FD_SET(static_cast<unsigned>(socket), &(s->read));
if (max < socket) max = socket; if (max < socket)
max = socket;
} else { } else {
FD_CLR(static_cast<unsigned>(socket), &(s->read)); FD_CLR(static_cast<unsigned>(socket), &(s->read));
} }
if (interest & (java_nio_channels_SelectionKey_OP_WRITE | if (interest & (java_nio_channels_SelectionKey_OP_WRITE
java_nio_channels_SelectionKey_OP_CONNECT)) { | java_nio_channels_SelectionKey_OP_CONNECT)) {
FD_SET(static_cast<unsigned>(socket), &(s->write)); FD_SET(static_cast<unsigned>(socket), &(s->write));
FD_SET(static_cast<unsigned>(socket), &(s->except)); FD_SET(static_cast<unsigned>(socket), &(s->except));
if (max < socket) max = socket; if (max < socket)
max = socket;
} else { } else {
FD_CLR(static_cast<unsigned>(socket), &(s->write)); FD_CLR(static_cast<unsigned>(socket), &(s->write));
} }
@ -938,30 +956,34 @@ Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *,
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass, Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv* e,
jlong state, jclass,
jint max, jlong state,
jlong interval) jint max,
jlong interval)
{ {
SelectorState* s = reinterpret_cast<SelectorState*>(state); SelectorState* s = reinterpret_cast<SelectorState*>(state);
if (s->control.reader() >= 0) { if (s->control.reader() >= 0) {
int socket = s->control.reader(); int socket = s->control.reader();
FD_SET(static_cast<unsigned>(socket), &(s->read)); FD_SET(static_cast<unsigned>(socket), &(s->read));
if (max < socket) max = socket; if (max < socket)
max = socket;
} }
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
if (s->control.listener() >= 0) { if (s->control.listener() >= 0) {
int socket = s->control.listener(); int socket = s->control.listener();
FD_SET(static_cast<unsigned>(socket), &(s->read)); FD_SET(static_cast<unsigned>(socket), &(s->read));
if (max < socket) max = socket; if (max < socket)
max = socket;
} }
if (not s->control.connected()) { if (not s->control.connected()) {
int socket = s->control.writer(); int socket = s->control.writer();
FD_SET(static_cast<unsigned>(socket), &(s->write)); FD_SET(static_cast<unsigned>(socket), &(s->write));
FD_SET(static_cast<unsigned>(socket), &(s->except)); FD_SET(static_cast<unsigned>(socket), &(s->except));
if (max < socket) max = socket; if (max < socket)
max = socket;
} }
#endif #endif
@ -986,17 +1008,16 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
} }
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
if (FD_ISSET(s->control.writer(), &(s->write)) or if (FD_ISSET(s->control.writer(), &(s->write))
FD_ISSET(s->control.writer(), &(s->except))) or FD_ISSET(s->control.writer(), &(s->except))) {
{
int socket = s->control.writer(); int socket = s->control.writer();
FD_CLR(static_cast<unsigned>(socket), &(s->write)); FD_CLR(static_cast<unsigned>(socket), &(s->write));
FD_CLR(static_cast<unsigned>(socket), &(s->except)); FD_CLR(static_cast<unsigned>(socket), &(s->except));
int error; int error;
socklen_t size = sizeof(int); socklen_t size = sizeof(int);
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR, int r = getsockopt(
reinterpret_cast<char*>(&error), &size); socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
if (r != 0 or size != sizeof(int)) { if (r != 0 or size != sizeof(int)) {
throwIOException(e); throwIOException(e);
} else if (error != 0) { } else if (error != 0) {
@ -1005,9 +1026,8 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
s->control.setConnected(true); s->control.setConnected(true);
} }
if (s->control.listener() >= 0 and if (s->control.listener() >= 0
FD_ISSET(s->control.listener(), &(s->read))) and FD_ISSET(s->control.listener(), &(s->read))) {
{
FD_CLR(static_cast<unsigned>(s->control.listener()), &(s->read)); FD_CLR(static_cast<unsigned>(s->control.listener()), &(s->read));
s->control.setReader(::doAccept(e, s->control.listener())); s->control.setReader(::doAccept(e, s->control.listener()));
@ -1015,9 +1035,7 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
} }
#endif #endif
if (s->control.reader() >= 0 and if (s->control.reader() >= 0 and FD_ISSET(s->control.reader(), &(s->read))) {
FD_ISSET(s->control.reader(), &(s->read)))
{
FD_CLR(static_cast<unsigned>(s->control.reader()), &(s->read)); FD_CLR(static_cast<unsigned>(s->control.reader()), &(s->read));
char c; char c;
@ -1034,10 +1052,11 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass, Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv*,
jint socket, jclass,
jint interest, jint socket,
jlong state) jint interest,
jlong state)
{ {
SelectorState* s = reinterpret_cast<SelectorState*>(state); SelectorState* s = reinterpret_cast<SelectorState*>(state);
jint ready = 0; jint ready = 0;
@ -1065,9 +1084,8 @@ Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass,
return ready; return ready;
} }
extern "C" JNIEXPORT jboolean JNICALL extern "C" JNIEXPORT jboolean JNICALL
Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv *, jclass) Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv*, jclass)
{ {
union { union {
uint32_t i; uint32_t i;

View File

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

View File

@ -16,8 +16,7 @@ namespace {
#if (!defined PLATFORM_WINDOWS) || (defined _MSC_VER) #if (!defined PLATFORM_WINDOWS) || (defined _MSC_VER)
void void removeNewline(char* s)
removeNewline(char* s)
{ {
for (; s; ++s) { for (; s; ++s) {
if (*s == '\n') { if (*s == '\n') {
@ -29,10 +28,10 @@ removeNewline(char* s)
#endif #endif
} // namespace } // namespace
extern "C" JNIEXPORT jstring JNICALL extern "C" JNIEXPORT jstring JNICALL
Java_java_util_Date_toString(JNIEnv* e, jclass c UNUSED, jlong when) Java_java_util_Date_toString(JNIEnv* e, jclass c UNUSED, jlong when)
{ {
const unsigned BufferSize UNUSED = 27; const unsigned BufferSize UNUSED = 27;
@ -40,13 +39,13 @@ Java_java_util_Date_toString(JNIEnv* e, jclass c UNUSED, jlong when)
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
e->MonitorEnter(c); e->MonitorEnter(c);
# ifdef _MSC_VER #ifdef _MSC_VER
char buffer[BufferSize]; char buffer[BufferSize];
ctime_s(buffer, BufferSize, &time); ctime_s(buffer, BufferSize, &time);
removeNewline(buffer); removeNewline(buffer);
# else #else
char* buffer = ctime(&time); char* buffer = ctime(&time);
# endif #endif
jstring r = e->NewStringUTF(buffer); jstring r = e->NewStringUTF(buffer);
e->MonitorExit(c); e->MonitorExit(c);
return r; return r;

View File

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

View File

@ -20,19 +20,18 @@
#undef JNIEXPORT #undef JNIEXPORT
#if (defined __MINGW32__) || (defined _MSC_VER) #if (defined __MINGW32__) || (defined _MSC_VER)
# define PLATFORM_WINDOWS #define PLATFORM_WINDOWS
# define PATH_SEPARATOR ';' #define PATH_SEPARATOR ';'
# define JNIEXPORT __declspec(dllexport) #define JNIEXPORT __declspec(dllexport)
#else // not (defined __MINGW32__) || (defined _MSC_VER) #else // not (defined __MINGW32__) || (defined _MSC_VER)
# define PLATFORM_POSIX #define PLATFORM_POSIX
# define PATH_SEPARATOR ':' #define PATH_SEPARATOR ':'
# define JNIEXPORT __attribute__ ((visibility("default"))) \ #define JNIEXPORT __attribute__((visibility("default"))) __attribute__((used))
__attribute__ ((used)) #endif // not (defined __MINGW32__) || (defined _MSC_VER)
#endif // not (defined __MINGW32__) || (defined _MSC_VER)
#ifdef _MSC_VER #ifdef _MSC_VER
# define UNUSED #define UNUSED
typedef char int8_t; typedef char int8_t;
typedef unsigned char uint8_t; typedef unsigned char uint8_t;
@ -43,38 +42,37 @@ typedef unsigned int uint32_t;
typedef __int64 int64_t; typedef __int64 int64_t;
typedef unsigned __int64 uint64_t; typedef unsigned __int64 uint64_t;
# define INT32_MAX 2147483647 #define INT32_MAX 2147483647
# define not ! #define not!
# define or || #define or ||
# define and && #define and &&
# define xor ^ #define xor ^
# ifdef _M_IX86 #ifdef _M_IX86
# define ARCH_x86_32 #define ARCH_x86_32
# elif defined _M_X64 #elif defined _M_X64
# define ARCH_x86_64 #define ARCH_x86_64
# endif #endif
#else // not _MSC_VER #else // not _MSC_VER
# define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused))
# include "stdint.h" #include "stdint.h"
# include "errno.h" #include "errno.h"
# ifdef __i386__ #ifdef __i386__
# define ARCH_x86_32 #define ARCH_x86_32
# elif defined __x86_64__ #elif defined __x86_64__
# define ARCH_x86_64 #define ARCH_x86_64
# elif defined __arm__ #elif defined __arm__
# define ARCH_arm #define ARCH_arm
# endif #endif
#endif // not _MSC_VER #endif // not _MSC_VER
inline void inline void throwNew(JNIEnv* e, const char* class_, const char* message, ...)
throwNew(JNIEnv* e, const char* class_, const char* message, ...)
{ {
jclass c = e->FindClass(class_); jclass c = e->FindClass(class_);
if (c) { if (c) {
@ -99,8 +97,7 @@ throwNew(JNIEnv* e, const char* class_, const char* message, ...)
} }
} }
inline void inline void throwNewErrno(JNIEnv* e, const char* class_)
throwNewErrno(JNIEnv* e, const char* class_)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
const unsigned size = 128; const unsigned size = 128;
@ -112,8 +109,7 @@ throwNewErrno(JNIEnv* e, const char* class_)
#endif #endif
} }
inline void* inline void* allocate(JNIEnv* e, unsigned size)
allocate(JNIEnv* e, unsigned size)
{ {
void* p = malloc(size); void* p = malloc(size);
if (p == 0) { if (p == 0) {
@ -122,4 +118,4 @@ allocate(JNIEnv* e, unsigned size)
return p; return p;
} }
#endif//JNI_UTIL #endif // JNI_UTIL

View File

@ -19,166 +19,183 @@ namespace avian {
namespace classpath { namespace classpath {
namespace sockets { namespace sockets {
int last_socket_error() { int last_socket_error()
{
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
int error = WSAGetLastError(); int error = WSAGetLastError();
#else #else
int error = errno; int error = errno;
#endif #endif
return error; return error;
} }
void init(JNIEnv* ONLY_ON_WINDOWS(e))
void init(JNIEnv* ONLY_ON_WINDOWS(e)) { {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
static bool wsaInitialized = false; static bool wsaInitialized = false;
if (not wsaInitialized) { if (not wsaInitialized) {
WSADATA data; WSADATA data;
int r = WSAStartup(MAKEWORD(2, 2), &data); int r = WSAStartup(MAKEWORD(2, 2), &data);
if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) { if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) {
throwNew(e, "java/io/IOException", "WSAStartup failed"); throwNew(e, "java/io/IOException", "WSAStartup failed");
} else { } else {
wsaInitialized = true; wsaInitialized = true;
} }
} }
#endif #endif
} }
SOCKET create(JNIEnv* e) { SOCKET create(JNIEnv* e)
SOCKET sock; {
if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) { SOCKET sock;
char buf[255]; if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
sprintf(buf, "Can't create a socket. System error: %d", last_socket_error()); char buf[255];
throwNew(e, "java/io/IOException", buf); sprintf(
return 0; // This doesn't matter cause we have risen an exception buf, "Can't create a socket. System error: %d", last_socket_error());
} throwNew(e, "java/io/IOException", buf);
return sock; 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; sockaddr_in adr;
adr.sin_family = AF_INET;
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
adr.sin_addr.S_un.S_addr = htonl(addr); adr.sin_addr.S_un.S_addr = htonl(addr);
#else #else
adr.sin_addr.s_addr = htonl(addr); adr.sin_addr.s_addr = htonl(addr);
#endif #endif
adr.sin_port = htons (port); adr.sin_port = htons(port);
if (SOCKET_ERROR == ::connect(sock, (sockaddr* )&adr, sizeof(adr))) if (SOCKET_ERROR == ::connect(sock, (sockaddr*)&adr, sizeof(adr))) {
{ char buf[255];
char buf[255]; sprintf(
sprintf(buf, "Can't connect a socket. System error: %d", last_socket_error()); buf, "Can't connect a socket. System error: %d", last_socket_error());
throwNew(e, "java/io/IOException", buf); throwNew(e, "java/io/IOException", buf);
return; return;
} }
} }
void bind(JNIEnv* e, SOCKET sock, long addr, short port) { void bind(JNIEnv* e, SOCKET sock, long addr, short port)
sockaddr_in adr; {
adr.sin_family = AF_INET; sockaddr_in adr;
adr.sin_family = AF_INET;
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
adr.sin_addr.S_un.S_addr = htonl(addr); adr.sin_addr.S_un.S_addr = htonl(addr);
#else #else
adr.sin_addr.s_addr = htonl(addr); adr.sin_addr.s_addr = htonl(addr);
#endif #endif
adr.sin_port = htons (port); adr.sin_port = htons(port);
if (SOCKET_ERROR == ::bind(sock, (sockaddr* )&adr, sizeof(adr))) if (SOCKET_ERROR == ::bind(sock, (sockaddr*)&adr, sizeof(adr))) {
{ char buf[255];
char buf[255]; sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error());
sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error()); throwNew(e, "java/io/IOException", buf);
throwNew(e, "java/io/IOException", buf); return;
return; }
}
} }
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); sockaddr_in adr;
if (INVALID_SOCKET == client_socket) { SOCKET client_socket = ::accept(sock, (sockaddr*)&adr, NULL);
char buf[255]; if (INVALID_SOCKET == client_socket) {
sprintf(buf, "Can't accept the incoming connection. System error: %d", last_socket_error()); char buf[255];
throwNew(e, "java/io/IOException", buf); sprintf(buf,
return INVALID_SOCKET; "Can't accept the incoming connection. System error: %d",
} last_socket_error());
throwNew(e, "java/io/IOException", buf);
return INVALID_SOCKET;
}
if (client_addr != NULL) { if (client_addr != NULL) {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
*client_addr = ntohl(adr.sin_addr.S_un.S_addr); *client_addr = ntohl(adr.sin_addr.S_un.S_addr);
#else #else
*client_addr = ntohl(adr.sin_addr.s_addr); *client_addr = ntohl(adr.sin_addr.s_addr);
#endif #endif
} }
if (client_port != NULL) { if (client_port != NULL) {
*client_port = ntohs (adr.sin_port); *client_port = ntohs(adr.sin_port);
} }
return client_socket; return client_socket;
} }
void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size) { void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size)
if (SOCKET_ERROR == ::send(sock, buff_ptr, buff_size, 0)) { {
char buf[255]; if (SOCKET_ERROR == ::send(sock, buff_ptr, buff_size, 0)) {
sprintf(buf, "Can't send data through the socket. System error: %d", last_socket_error()); char buf[255];
throwNew(e, "java/io/IOException", buf); sprintf(buf,
return; "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) { int length = ::recv(sock, buff_ptr, buff_size, 0);
char buf[255]; if (SOCKET_ERROR == length) {
sprintf(buf, "Can't receive data through the socket. System error: %d", last_socket_error()); char buf[255];
throwNew(e, "java/io/IOException", buf); sprintf(buf,
return 0; // This doesn't matter cause we have risen an exception "Can't receive data through the socket. System error: %d",
} last_socket_error());
return length; 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]; if (SOCKET_ERROR == ::closesocket(sock)) {
sprintf(buf, "Can't close the socket. System error: %d", last_socket_error()); char buf[255];
throwNew(e, "java/io/IOException", buf); 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 (SOCKET_ERROR == ::shutdown(sock, SD_BOTH)) {
if (errcode != ENOTCONN) { int errcode = last_socket_error();
char buf[255]; if (errcode != ENOTCONN) {
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode); char buf[255];
throwNew(e, "java/io/IOException", buf); sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
} throwNew(e, "java/io/IOException", buf);
} }
}
} }
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 (SOCKET_ERROR == ::shutdown(sock, SD_RECEIVE)) {
if (errcode != ENOTCONN) { int errcode = last_socket_error();
char buf[255]; if (errcode != ENOTCONN) {
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode); char buf[255];
throwNew(e, "java/io/IOException", buf); sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
} throwNew(e, "java/io/IOException", buf);
} }
} }
void close_output(JNIEnv* e, SOCKET sock) {
if (SOCKET_ERROR == ::shutdown(sock, SD_SEND)) {
int errcode = last_socket_error();
if (errcode != ENOTCONN) {
char buf[255];
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
throwNew(e, "java/io/IOException", buf);
}
}
} }
void close_output(JNIEnv* e, SOCKET sock)
{
if (SOCKET_ERROR == ::shutdown(sock, SD_SEND)) {
int errcode = last_socket_error();
if (errcode != ENOTCONN) {
char buf[255];
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
throwNew(e, "java/io/IOException", buf);
}
}
}
} }
} }
} }

View File

@ -8,7 +8,6 @@
There is NO WARRANTY for this software. See license.txt for There is NO WARRANTY for this software. See license.txt for
details. */ details. */
/* /*
* This file represents a simple cross-platform JNI sockets API * This file represents a simple cross-platform JNI sockets API
* It is used from different classes of the default Avian classpath * It is used from different classes of the default Avian classpath
@ -22,28 +21,28 @@
#include "jni-util.h" #include "jni-util.h"
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
# include <winsock2.h> #include <winsock2.h>
# define ONLY_ON_WINDOWS(x) x #define ONLY_ON_WINDOWS(x) x
# ifndef ENOTCONN #ifndef ENOTCONN
# define ENOTCONN WSAENOTCONN #define ENOTCONN WSAENOTCONN
# endif #endif
#else #else
# include <netdb.h> #include <netdb.h>
# include <sys/socket.h> #include <sys/socket.h>
# include <netinet/in.h> #include <netinet/in.h>
# include <unistd.h> #include <unistd.h>
# define ONLY_ON_WINDOWS(x) #define ONLY_ON_WINDOWS(x)
# define SOCKET int #define SOCKET int
# define INVALID_SOCKET -1 #define INVALID_SOCKET -1
# define SOCKET_ERROR -1 #define SOCKET_ERROR -1
# define closesocket(x) close(x) #define closesocket(x) close(x)
# define SD_RECEIVE SHUT_RD #define SD_RECEIVE SHUT_RD
# define SD_SEND SHUT_WR #define SD_SEND SHUT_WR
# define SD_BOTH SHUT_RDWR #define SD_BOTH SHUT_RDWR
#endif #endif
@ -69,7 +68,6 @@ void abort(JNIEnv* e, SOCKET sock);
void close(JNIEnv* e, SOCKET sock); void close(JNIEnv* e, SOCKET sock);
void close_input(JNIEnv* e, SOCKET sock); void close_input(JNIEnv* e, SOCKET sock);
void close_output(JNIEnv* e, SOCKET sock); void close_output(JNIEnv* e, SOCKET sock);
} }
} }
} }

View File

@ -30,116 +30,126 @@ class Assembler;
class RegisterFile; class RegisterFile;
class OperandMask { class OperandMask {
public: public:
uint8_t typeMask; uint8_t typeMask;
uint64_t registerMask; uint64_t registerMask;
OperandMask(uint8_t typeMask, uint64_t registerMask): OperandMask(uint8_t typeMask, uint64_t registerMask)
typeMask(typeMask), : typeMask(typeMask), registerMask(registerMask)
registerMask(registerMask) {
{ } }
OperandMask(): OperandMask() : typeMask(~0), registerMask(~static_cast<uint64_t>(0))
typeMask(~0), {
registerMask(~static_cast<uint64_t>(0)) }
{ }
}; };
class Architecture { class Architecture {
public: public:
virtual unsigned floatRegisterSize() = 0; virtual unsigned floatRegisterSize() = 0;
virtual const RegisterFile* registerFile() = 0; virtual const RegisterFile* registerFile() = 0;
virtual int scratch() = 0; virtual int scratch() = 0;
virtual int stack() = 0; virtual int stack() = 0;
virtual int thread() = 0; virtual int thread() = 0;
virtual int returnLow() = 0; virtual int returnLow() = 0;
virtual int returnHigh() = 0; virtual int returnHigh() = 0;
virtual int virtualCallTarget() = 0; virtual int virtualCallTarget() = 0;
virtual int virtualCallIndex() = 0; virtual int virtualCallIndex() = 0;
virtual ir::TargetInfo targetInfo() = 0; virtual ir::TargetInfo targetInfo() = 0;
virtual bool bigEndian() = 0; virtual bool bigEndian() = 0;
virtual uintptr_t maximumImmediateJump() = 0; virtual uintptr_t maximumImmediateJump() = 0;
virtual bool alwaysCondensed(lir::BinaryOperation op) = 0; virtual bool alwaysCondensed(lir::BinaryOperation op) = 0;
virtual bool alwaysCondensed(lir::TernaryOperation op) = 0; virtual bool alwaysCondensed(lir::TernaryOperation op) = 0;
virtual bool reserved(int register_) = 0; virtual bool reserved(int register_) = 0;
virtual unsigned frameFootprint(unsigned footprint) = 0; virtual unsigned frameFootprint(unsigned footprint) = 0;
virtual unsigned argumentFootprint(unsigned footprint) = 0; virtual unsigned argumentFootprint(unsigned footprint) = 0;
virtual bool argumentAlignment() = 0; virtual bool argumentAlignment() = 0;
virtual bool argumentRegisterAlignment() = 0; virtual bool argumentRegisterAlignment() = 0;
virtual unsigned argumentRegisterCount() = 0; virtual unsigned argumentRegisterCount() = 0;
virtual int argumentRegister(unsigned index) = 0; virtual int argumentRegister(unsigned index) = 0;
virtual bool hasLinkRegister() = 0; virtual bool hasLinkRegister() = 0;
virtual unsigned stackAlignmentInWords() = 0; virtual unsigned stackAlignmentInWords() = 0;
virtual bool matchCall(void* returnAddress, void* target) = 0; virtual bool matchCall(void* returnAddress, void* target) = 0;
virtual void updateCall(lir::UnaryOperation op, void* returnAddress, virtual void updateCall(lir::UnaryOperation op,
void* newTarget) = 0; void* returnAddress,
void* newTarget) = 0;
virtual void setConstant(void* dst, uint64_t constant) = 0; virtual void setConstant(void* dst, uint64_t constant) = 0;
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0; virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
virtual void nextFrame(void* start, unsigned size, unsigned footprint, virtual void nextFrame(void* start,
void* link, bool mostRecent, unsigned size,
int targetParameterFootprint, void** ip, unsigned footprint,
void** stack) = 0; void* link,
virtual void* frameIp(void* stack) = 0; bool mostRecent,
virtual unsigned frameHeaderSize() = 0; int targetParameterFootprint,
virtual unsigned frameReturnAddressSize() = 0; void** ip,
virtual unsigned frameFooterSize() = 0; void** stack) = 0;
virtual int returnAddressOffset() = 0; virtual void* frameIp(void* stack) = 0;
virtual int framePointerOffset() = 0; virtual unsigned frameHeaderSize() = 0;
virtual unsigned frameReturnAddressSize() = 0;
virtual unsigned frameFooterSize() = 0;
virtual int returnAddressOffset() = 0;
virtual int framePointerOffset() = 0;
virtual void plan virtual void plan(lir::UnaryOperation op,
(lir::UnaryOperation op, unsigned aSize,
unsigned aSize, OperandMask& aMask, OperandMask& aMask,
bool* thunk) = 0; bool* thunk) = 0;
virtual void planSource virtual void planSource(lir::BinaryOperation op,
(lir::BinaryOperation op, unsigned aSize,
unsigned aSize, OperandMask& aMask, OperandMask& aMask,
unsigned bSize, bool* thunk) = 0; unsigned bSize,
bool* thunk) = 0;
virtual void planDestination virtual void planDestination(lir::BinaryOperation op,
(lir::BinaryOperation op, unsigned aSize,
unsigned aSize, const OperandMask& aMask, const OperandMask& aMask,
unsigned bSize, OperandMask& bMask) = 0; unsigned bSize,
OperandMask& bMask) = 0;
virtual void planMove virtual void planMove(unsigned size,
(unsigned size, OperandMask& src, OperandMask& src,
OperandMask& tmp, OperandMask& tmp,
const OperandMask& dst) = 0; const OperandMask& dst) = 0;
virtual void planSource virtual void planSource(lir::TernaryOperation op,
(lir::TernaryOperation op, unsigned aSize,
unsigned aSize, OperandMask& aMask, OperandMask& aMask,
unsigned bSize, OperandMask& bMask, unsigned bSize,
unsigned cSize, bool* thunk) = 0; OperandMask& bMask,
unsigned cSize,
bool* thunk) = 0;
virtual void planDestination virtual void planDestination(lir::TernaryOperation op,
(lir::TernaryOperation op, unsigned aSize,
unsigned aSize, const OperandMask& aMask, const OperandMask& aMask,
unsigned bSize, const OperandMask& bMask, unsigned bSize,
unsigned cSize, OperandMask& cMask) = 0; const OperandMask& bMask,
unsigned cSize,
OperandMask& cMask) = 0;
virtual Assembler* makeAssembler(util::Allocator*, vm::Zone*) = 0; virtual Assembler* makeAssembler(util::Allocator*, vm::Zone*) = 0;
virtual void acquire() = 0; virtual void acquire() = 0;
virtual void release() = 0; virtual void release() = 0;
}; };
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_ARCHITECTURE_H #endif // AVIAN_CODEGEN_ARCHITECTURE_H

View File

@ -23,16 +23,17 @@ namespace codegen {
class Architecture; class Architecture;
class OperandInfo { class OperandInfo {
public: public:
const unsigned size; const unsigned size;
const lir::OperandType type; const lir::OperandType type;
lir::Operand* const operand; lir::Operand* const operand;
inline OperandInfo(unsigned size, lir::OperandType type, lir::Operand* operand): inline OperandInfo(unsigned size,
size(size), lir::OperandType type,
type(type), lir::Operand* operand)
operand(operand) : size(size), type(type), operand(operand)
{ } {
}
}; };
#ifdef AVIAN_TAILS #ifdef AVIAN_TAILS
@ -49,11 +50,9 @@ const bool UseFramePointer = false;
class Assembler { class Assembler {
public: public:
class Client { class Client {
public: public:
virtual int acquireTemporary virtual int acquireTemporary(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
virtual void releaseTemporary(int r) = 0; virtual void releaseTemporary(int r) = 0;
virtual void save(int r) = 0; virtual void save(int r) = 0;
@ -75,20 +74,23 @@ class Assembler {
virtual void allocateFrame(unsigned footprint) = 0; virtual void allocateFrame(unsigned footprint) = 0;
virtual void adjustFrame(unsigned difference) = 0; virtual void adjustFrame(unsigned difference) = 0;
virtual void popFrame(unsigned footprint) = 0; virtual void popFrame(unsigned footprint) = 0;
virtual void popFrameForTailCall(unsigned footprint, int offset, virtual void popFrameForTailCall(unsigned footprint,
int offset,
int returnAddressSurrogate, int returnAddressSurrogate,
int framePointerSurrogate) = 0; int framePointerSurrogate) = 0;
virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint, virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint,
unsigned argumentFootprint) unsigned argumentFootprint) = 0;
= 0;
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint, virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
unsigned stackOffsetFromThread) unsigned stackOffsetFromThread)
= 0; = 0;
virtual void apply(lir::Operation op) = 0; virtual void apply(lir::Operation op) = 0;
virtual void apply(lir::UnaryOperation op, OperandInfo a) = 0; virtual void apply(lir::UnaryOperation op, OperandInfo a) = 0;
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) = 0; virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) = 0;
virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c) = 0; virtual void apply(lir::TernaryOperation op,
OperandInfo a,
OperandInfo b,
OperandInfo c) = 0;
virtual void setDestination(uint8_t* dst) = 0; virtual void setDestination(uint8_t* dst) = 0;
@ -107,7 +109,7 @@ class Assembler {
virtual void dispose() = 0; virtual void dispose() = 0;
}; };
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_ASSEMBLER_H #endif // AVIAN_CODEGEN_ASSEMBLER_H

View File

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

View File

@ -17,71 +17,67 @@ class Promise;
namespace lir { namespace lir {
enum Operation { enum Operation {
#define LIR_OP_0(x) x, #define LIR_OP_0(x) x,
#define LIR_OP_1(x) #define LIR_OP_1(x)
#define LIR_OP_2(x) #define LIR_OP_2(x)
#define LIR_OP_3(x) #define LIR_OP_3(x)
#include "lir-ops.inc.cpp" #include "lir-ops.inc.cpp"
#undef LIR_OP_0 #undef LIR_OP_0
#undef LIR_OP_1 #undef LIR_OP_1
#undef LIR_OP_2 #undef LIR_OP_2
#undef LIR_OP_3 #undef LIR_OP_3
}; };
const unsigned OperationCount = Trap + 1; const unsigned OperationCount = Trap + 1;
enum UnaryOperation { enum UnaryOperation {
#define LIR_OP_0(x) #define LIR_OP_0(x)
#define LIR_OP_1(x) x, #define LIR_OP_1(x) x,
#define LIR_OP_2(x) #define LIR_OP_2(x)
#define LIR_OP_3(x) #define LIR_OP_3(x)
#include "lir-ops.inc.cpp" #include "lir-ops.inc.cpp"
#undef LIR_OP_0 #undef LIR_OP_0
#undef LIR_OP_1 #undef LIR_OP_1
#undef LIR_OP_2 #undef LIR_OP_2
#undef LIR_OP_3 #undef LIR_OP_3
NoUnaryOperation = -1 NoUnaryOperation = -1
}; };
const unsigned UnaryOperationCount = AlignedJump + 1; const unsigned UnaryOperationCount = AlignedJump + 1;
enum BinaryOperation { enum BinaryOperation {
#define LIR_OP_0(x) #define LIR_OP_0(x)
#define LIR_OP_1(x) #define LIR_OP_1(x)
#define LIR_OP_2(x) x, #define LIR_OP_2(x) x,
#define LIR_OP_3(x) #define LIR_OP_3(x)
#include "lir-ops.inc.cpp" #include "lir-ops.inc.cpp"
#undef LIR_OP_0 #undef LIR_OP_0
#undef LIR_OP_1 #undef LIR_OP_1
#undef LIR_OP_2 #undef LIR_OP_2
#undef LIR_OP_3 #undef LIR_OP_3
NoBinaryOperation = -1 NoBinaryOperation = -1
}; };
const unsigned BinaryOperationCount = Absolute + 1; const unsigned BinaryOperationCount = Absolute + 1;
enum TernaryOperation { enum TernaryOperation {
#define LIR_OP_0(x) #define LIR_OP_0(x)
#define LIR_OP_1(x) #define LIR_OP_1(x)
#define LIR_OP_2(x) #define LIR_OP_2(x)
#define LIR_OP_3(x) x, #define LIR_OP_3(x) x,
#include "lir-ops.inc.cpp" #include "lir-ops.inc.cpp"
#undef LIR_OP_0 #undef LIR_OP_0
#undef LIR_OP_1 #undef LIR_OP_1
#undef LIR_OP_2 #undef LIR_OP_2
#undef LIR_OP_3 #undef LIR_OP_3
NoTernaryOperation = -1 NoTernaryOperation = -1
}; };
const unsigned TernaryOperationCount const unsigned TernaryOperationCount = JumpIfFloatGreaterOrEqualOrUnordered + 1;
= JumpIfFloatGreaterOrEqualOrUnordered + 1;
const unsigned NonBranchTernaryOperationCount = FloatMin + 1; const unsigned NonBranchTernaryOperationCount = FloatMin + 1;
const unsigned BranchOperationCount const unsigned BranchOperationCount = JumpIfFloatGreaterOrEqualOrUnordered
= JumpIfFloatGreaterOrEqualOrUnordered - FloatMin; - FloatMin;
enum OperandType { enum OperandType {
ConstantOperand, ConstantOperand,
@ -90,72 +86,84 @@ enum OperandType {
MemoryOperand MemoryOperand
}; };
enum ValueType { enum ValueType { ValueGeneral, ValueFloat };
ValueGeneral,
ValueFloat
};
const unsigned OperandTypeCount = MemoryOperand + 1; const unsigned OperandTypeCount = MemoryOperand + 1;
const int NoRegister = -1; const int NoRegister = -1;
inline bool isBranch(lir::TernaryOperation op) { inline bool isBranch(lir::TernaryOperation op)
{
return op > FloatMin; return op > FloatMin;
} }
inline bool isFloatBranch(lir::TernaryOperation op) { inline bool isFloatBranch(lir::TernaryOperation op)
{
return op > JumpIfNotEqual; return op > JumpIfNotEqual;
} }
inline bool isGeneralBranch(lir::TernaryOperation op) { inline bool isGeneralBranch(lir::TernaryOperation op)
{
return isBranch(op) && !isFloatBranch(op); return isBranch(op) && !isFloatBranch(op);
} }
inline bool isGeneralBinaryOp(lir::TernaryOperation op) { inline bool isGeneralBinaryOp(lir::TernaryOperation op)
{
return op < FloatAdd; return op < FloatAdd;
} }
inline bool isFloatBinaryOp(lir::TernaryOperation op) { inline bool isFloatBinaryOp(lir::TernaryOperation op)
{
return op >= FloatAdd && op <= FloatMin; return op >= FloatAdd && op <= FloatMin;
} }
inline bool isGeneralUnaryOp(lir::BinaryOperation op) { inline bool isGeneralUnaryOp(lir::BinaryOperation op)
{
return op == Negate || op == Absolute; return op == Negate || op == Absolute;
} }
inline bool isFloatUnaryOp(lir::BinaryOperation op) { inline bool isFloatUnaryOp(lir::BinaryOperation op)
{
return op == FloatNegate || op == FloatSquareRoot || op == FloatAbsolute; return op == FloatNegate || op == FloatSquareRoot || op == FloatAbsolute;
} }
class Operand { }; class Operand {
};
class Constant: public Operand { class Constant : public Operand {
public: public:
Constant(Promise* value): value(value) { } Constant(Promise* value) : value(value)
{
}
Promise* value; Promise* value;
}; };
class Address: public Operand { class Address : public Operand {
public: public:
Address(Promise* address): address(address) { } Address(Promise* address) : address(address)
{
}
Promise* address; Promise* address;
}; };
class Register: public Operand { class Register : public Operand {
public: public:
Register(int low, int high = NoRegister): low(low), high(high) { } Register(int low, int high = NoRegister) : low(low), high(high)
{
}
int low; int low;
int high; int high;
}; };
class Memory: public Operand { class Memory : public Operand {
public: public:
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1): Memory(int base, int offset, int index = NoRegister, unsigned scale = 1)
base(base), offset(offset), index(index), scale(scale) : base(base), offset(offset), index(index), scale(scale)
{ } {
}
int base; int base;
int offset; int offset;
@ -163,8 +171,8 @@ class Memory: public Operand {
unsigned scale; unsigned scale;
}; };
} // namespace lir } // namespace lir
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_LIR_H #endif // AVIAN_CODEGEN_LIR_H

View File

@ -29,35 +29,45 @@ class Promise {
virtual int64_t value() = 0; virtual int64_t value() = 0;
virtual bool resolved() = 0; virtual bool resolved() = 0;
virtual Listener* listen(unsigned) { return 0; } virtual Listener* listen(unsigned)
{
return 0;
}
}; };
class ResolvedPromise: public Promise { class ResolvedPromise : public Promise {
public: public:
ResolvedPromise(int64_t value): value_(value) { } ResolvedPromise(int64_t value) : value_(value)
{
}
virtual int64_t value() { virtual int64_t value()
{
return value_; return value_;
} }
virtual bool resolved() { virtual bool resolved()
{
return true; return true;
} }
int64_t value_; int64_t value_;
}; };
class ShiftMaskPromise: public Promise { class ShiftMaskPromise : public Promise {
public: public:
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask): ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask)
base(base), shift(shift), mask(mask) : base(base), shift(shift), mask(mask)
{ } {
}
virtual int64_t value() { virtual int64_t value()
{
return (base->value() >> shift) & mask; return (base->value() >> shift) & mask;
} }
virtual bool resolved() { virtual bool resolved()
{
return base->resolved(); return base->resolved();
} }
@ -66,17 +76,19 @@ class ShiftMaskPromise: public Promise {
int64_t mask; int64_t mask;
}; };
class CombinedPromise: public Promise { class CombinedPromise : public Promise {
public: public:
CombinedPromise(Promise* low, Promise* high): CombinedPromise(Promise* low, Promise* high) : low(low), high(high)
low(low), high(high) {
{ } }
virtual int64_t value() { virtual int64_t value()
{
return low->value() | (high->value() << 32); return low->value() | (high->value() << 32);
} }
virtual bool resolved() { virtual bool resolved()
{
return low->resolved() and high->resolved(); return low->resolved() and high->resolved();
} }
@ -84,17 +96,19 @@ class CombinedPromise: public Promise {
Promise* high; Promise* high;
}; };
class OffsetPromise: public Promise { class OffsetPromise : public Promise {
public: public:
OffsetPromise(Promise* base, int64_t offset): OffsetPromise(Promise* base, int64_t offset) : base(base), offset(offset)
base(base), offset(offset) {
{ } }
virtual int64_t value() { virtual int64_t value()
{
return base->value() + offset; return base->value() + offset;
} }
virtual bool resolved() { virtual bool resolved()
{
return base->resolved(); return base->resolved();
} }
@ -102,21 +116,25 @@ class OffsetPromise: public Promise {
int64_t offset; int64_t offset;
}; };
class ListenPromise: public Promise { class ListenPromise : public Promise {
public: public:
ListenPromise(vm::System* s, util::Allocator* allocator) ListenPromise(vm::System* s, util::Allocator* allocator)
: s(s), allocator(allocator), listener(0) : s(s), allocator(allocator), listener(0)
{ } {
}
virtual int64_t value() { virtual int64_t value()
{
abort(s); abort(s);
} }
virtual bool resolved() { virtual bool resolved()
{
return false; return false;
} }
virtual Listener* listen(unsigned sizeInBytes) { virtual Listener* listen(unsigned sizeInBytes)
{
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes)); Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener; l->next = listener;
listener = l; listener = l;
@ -129,24 +147,28 @@ class ListenPromise: public Promise {
Promise* promise; Promise* promise;
}; };
class DelayedPromise: public ListenPromise { class DelayedPromise : public ListenPromise {
public: public:
DelayedPromise(vm::System* s, DelayedPromise(vm::System* s,
util::Allocator* allocator, util::Allocator* allocator,
Promise* basis, Promise* basis,
DelayedPromise* next) DelayedPromise* next)
: ListenPromise(s, allocator), basis(basis), next(next) : ListenPromise(s, allocator), basis(basis), next(next)
{ } {
}
virtual int64_t value() { virtual int64_t value()
{
abort(s); abort(s);
} }
virtual bool resolved() { virtual bool resolved()
{
return false; return false;
} }
virtual Listener* listen(unsigned sizeInBytes) { virtual Listener* listen(unsigned sizeInBytes)
{
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes)); Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener; l->next = listener;
listener = l; listener = l;
@ -157,7 +179,7 @@ class DelayedPromise: public ListenPromise {
DelayedPromise* next; DelayedPromise* next;
}; };
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_PROMISE_H #endif // AVIAN_CODEGEN_PROMISE_H

View File

@ -17,7 +17,7 @@ namespace avian {
namespace codegen { namespace codegen {
class RegisterMask { class RegisterMask {
public: public:
uint32_t mask; uint32_t mask;
uint8_t start; uint8_t start;
uint8_t limit; uint8_t limit;
@ -25,49 +25,52 @@ public:
static unsigned maskStart(uint32_t mask); static unsigned maskStart(uint32_t mask);
static unsigned maskLimit(uint32_t mask); static unsigned maskLimit(uint32_t mask);
inline RegisterMask(uint32_t mask): inline RegisterMask(uint32_t mask)
mask(mask), : mask(mask), start(maskStart(mask)), limit(maskLimit(mask))
start(maskStart(mask)), {
limit(maskLimit(mask)) }
{ }
}; };
class RegisterFile { class RegisterFile {
public: public:
RegisterMask allRegisters; RegisterMask allRegisters;
RegisterMask generalRegisters; RegisterMask generalRegisters;
RegisterMask floatRegisters; RegisterMask floatRegisters;
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask): inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask)
allRegisters(generalRegisterMask | floatRegisterMask), : allRegisters(generalRegisterMask | floatRegisterMask),
generalRegisters(generalRegisterMask), generalRegisters(generalRegisterMask),
floatRegisters(floatRegisterMask) floatRegisters(floatRegisterMask)
{ } {
}
}; };
class RegisterIterator { class RegisterIterator {
public: public:
int index; int index;
const RegisterMask& mask; const RegisterMask& mask;
inline RegisterIterator(const RegisterMask& mask): inline RegisterIterator(const RegisterMask& mask)
index(mask.start), : index(mask.start), mask(mask)
mask(mask) {} {
}
inline bool hasNext() { inline bool hasNext()
{
return index < mask.limit; return index < mask.limit;
} }
inline int next() { inline int next()
{
int r = index; int r = index;
do { do {
index++; index++;
} while(index < mask.limit && !(mask.mask & (1 << index))); } while (index < mask.limit && !(mask.mask & (1 << index)));
return r; return r;
} }
}; };
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_REGISTERS_H #endif // AVIAN_CODEGEN_REGISTERS_H

View File

@ -47,8 +47,8 @@ uint64_t intToFloat(int32_t a);
uint64_t longToDouble(int64_t a); uint64_t longToDouble(int64_t a);
uint64_t longToFloat(int64_t a); uint64_t longToFloat(int64_t a);
} // namespace runtime } // namespace runtime
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_RUNTIME_H #endif // AVIAN_CODEGEN_RUNTIME_H

View File

@ -20,12 +20,13 @@ namespace codegen {
class Architecture; class Architecture;
Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures); Architecture* makeArchitectureNative(vm::System* system,
bool useNativeFeatures);
Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures); Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures);
Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures); Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures);
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_TARGETS_H #endif // AVIAN_CODEGEN_TARGETS_H

View File

@ -24,17 +24,9 @@ const unsigned FixieTenureThreshold = TenureThreshold + 2;
class Heap : public avian::util::Allocator { class Heap : public avian::util::Allocator {
public: public:
enum CollectionType { enum CollectionType { MinorCollection, MajorCollection };
MinorCollection,
MajorCollection
};
enum Status { enum Status { Null, Reachable, Unreachable, Tenured };
Null,
Reachable,
Unreachable,
Tenured
};
class Visitor { class Visitor {
public: public:
@ -62,7 +54,8 @@ class Heap : public avian::util::Allocator {
virtual unsigned remaining() = 0; virtual unsigned remaining() = 0;
virtual unsigned limit() = 0; virtual unsigned limit() = 0;
virtual bool limitExceeded(int pendingAllocation = 0) = 0; virtual bool limitExceeded(int pendingAllocation = 0) = 0;
virtual void collect(CollectionType type, unsigned footprint, virtual void collect(CollectionType type,
unsigned footprint,
int pendingAllocation) = 0; int pendingAllocation) = 0;
virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) = 0; virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) = 0;
virtual void* allocateFixed(avian::util::Allocator* allocator, virtual void* allocateFixed(avian::util::Allocator* allocator,
@ -74,6 +67,13 @@ class Heap : public avian::util::Allocator {
virtual void mark(void* p, unsigned offset, unsigned count) = 0; virtual void mark(void* p, unsigned offset, unsigned count) = 0;
virtual void pad(void* p) = 0; virtual void pad(void* p) = 0;
virtual void* follow(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 void postVisit() = 0;
virtual Status status(void* p) = 0; virtual Status status(void* p) = 0;
virtual CollectionType collectionType() = 0; virtual CollectionType collectionType() = 0;
@ -83,6 +83,6 @@ class Heap : public avian::util::Allocator {
Heap* makeHeap(System* system, unsigned limit); Heap* makeHeap(System* system, unsigned limit);
} // namespace vm } // namespace vm
#endif//HEAP_H #endif // HEAP_H

View File

@ -21,7 +21,8 @@ namespace system {
// order to trigger the crash dump logic. // order to trigger the crash dump logic.
NO_RETURN void crash(); NO_RETURN void crash();
// Registrar for unix-like "signals" (implemented with structured exceptions on windows). // Registrar for unix-like "signals" (implemented with structured exceptions on
// windows).
// TODO: remove dependence on generated code having a well-known "thread" // TODO: remove dependence on generated code having a well-known "thread"
// register. Use a thread-local variable instead. // register. Use a thread-local variable instead.
class SignalRegistrar { class SignalRegistrar {
@ -40,7 +41,6 @@ class SignalRegistrar {
// "Segmentation fault" exceptions (mostly null pointer dereference, but // "Segmentation fault" exceptions (mostly null pointer dereference, but
// generally access to any non-mapped memory) // generally access to any non-mapped memory)
SegFault, SegFault,
DivideByZero, DivideByZero,
}; };
@ -72,11 +72,10 @@ class SignalRegistrar {
struct Data; struct Data;
private: private:
Data* data; Data* data;
}; };
} // namespace system } // namespace system
} // namespace avian } // namespace avian
#endif #endif

View File

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

View File

@ -23,16 +23,17 @@ namespace avian {
namespace tools { namespace tools {
class OutputStream { class OutputStream {
public: public:
virtual void writeChunk(const void* data, size_t size) = 0; virtual void writeChunk(const void* data, size_t size) = 0;
virtual void write(uint8_t byte); virtual void write(uint8_t byte);
virtual void writeRepeat(uint8_t byte, size_t size); virtual void writeRepeat(uint8_t byte, size_t size);
}; };
class FileOutputStream : public OutputStream { class FileOutputStream : public OutputStream {
private: private:
FILE* file; FILE* file;
public:
public:
FileOutputStream(const char* name); FileOutputStream(const char* name);
~FileOutputStream(); ~FileOutputStream();
@ -43,20 +44,22 @@ public:
}; };
class SymbolInfo { class SymbolInfo {
public: public:
unsigned addr; unsigned addr;
util::String name; util::String name;
inline SymbolInfo(uint64_t addr, const util::String& name): inline SymbolInfo(uint64_t addr, const util::String& name)
addr(addr), : addr(addr), name(name)
name(name) {} {
}
inline SymbolInfo(): inline SymbolInfo() : name("")
name("") {} {
}
}; };
class Buffer { class Buffer {
public: public:
size_t capacity; size_t capacity;
size_t length; size_t length;
uint8_t* data; uint8_t* data;
@ -69,7 +72,7 @@ public:
}; };
class StringTable : public Buffer { class StringTable : public Buffer {
public: public:
unsigned add(util::String str); unsigned add(util::String str);
}; };
@ -103,7 +106,7 @@ class DynamicArray : public util::Slice<T> {
}; };
class PlatformInfo { class PlatformInfo {
public: public:
enum Format { enum Format {
Elf = AVIAN_FORMAT_ELF, Elf = AVIAN_FORMAT_ELF,
Pe = AVIAN_FORMAT_PE, Pe = AVIAN_FORMAT_PE,
@ -124,33 +127,31 @@ public:
static Format formatFromString(const char* format); static Format formatFromString(const char* format);
static Architecture archFromString(const char* arch); static Architecture archFromString(const char* arch);
inline PlatformInfo(Format format, Architecture arch): inline PlatformInfo(Format format, Architecture arch)
format(format), : format(format), arch(arch)
arch(arch) {} {
}
inline bool operator == (const PlatformInfo& other) { inline bool operator==(const PlatformInfo& other)
{
return format == other.format && arch == other.arch; return format == other.format && arch == other.arch;
} }
}; };
class Platform { class Platform {
private: private:
Platform* next; Platform* next;
static Platform* first; static Platform* first;
public:
public:
PlatformInfo info; PlatformInfo info;
inline Platform(PlatformInfo info): inline Platform(PlatformInfo info) : next(first), info(info)
next(first),
info(info)
{ {
first = this; first = this;
} }
enum AccessFlags { enum AccessFlags { Writable = 1 << 0, Executable = 1 << 1 };
Writable = 1 << 0,
Executable = 1 << 1
};
virtual bool writeObject(OutputStream* out, virtual bool writeObject(OutputStream* out,
util::Slice<SymbolInfo> symbols, util::Slice<SymbolInfo> symbols,
@ -161,9 +162,8 @@ public:
static Platform* getPlatform(PlatformInfo info); static Platform* getPlatform(PlatformInfo info);
}; };
} // namespace tools } // namespace tools
} // namespace avian } // namespace avian
#endif #endif

View File

@ -19,7 +19,7 @@ namespace avian {
namespace util { namespace util {
class Aborter { class Aborter {
public: public:
virtual void NO_RETURN abort() = 0; virtual void NO_RETURN abort() = 0;
}; };
@ -28,29 +28,32 @@ inline Aborter* getAborter(Aborter* a)
return a; return a;
} }
template<class T> template <class T>
inline void NO_RETURN abort(T t) { inline void NO_RETURN abort(T t)
{
getAborter(t)->abort(); getAborter(t)->abort();
::abort(); ::abort();
} }
template<class T> template <class T>
inline void expect(T t, bool v) { inline void expect(T t, bool v)
if(UNLIKELY(!v)) { {
if (UNLIKELY(!v)) {
abort(t); abort(t);
} }
} }
#ifdef NDEBUG #ifdef NDEBUG
#define assert(t, v) #define assertT(t, v)
#else #else
template<class T> template <class T>
inline void assert(T t, bool v) { inline void assertT(T t, bool v)
{
expect(t, v); expect(t, v);
} }
#endif #endif
} // namespace util } // namespace util
} // namespace avian } // namespace avian
#endif // AVIAN_UTIL_ABORT_H #endif // AVIAN_UTIL_ABORT_H

View File

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

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

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

View File

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

View File

@ -17,40 +17,51 @@
namespace avian { namespace avian {
namespace util { namespace util {
inline unsigned max(unsigned a, unsigned b) { inline unsigned max(unsigned a, unsigned b)
{
return (a > b ? a : b); return (a > b ? a : b);
} }
inline unsigned min(unsigned a, unsigned b) { inline unsigned min(unsigned a, unsigned b)
{
return (a < b ? a : b); return (a < b ? a : b);
} }
inline unsigned avg(unsigned a, unsigned b) { inline unsigned avg(unsigned a, unsigned b)
{
return (a + b) / 2; return (a + b) / 2;
} }
inline unsigned ceilingDivide(unsigned n, unsigned d) { inline unsigned ceilingDivide(unsigned n, unsigned d)
{
return (n + d - 1) / d; return (n + d - 1) / d;
} }
inline bool powerOfTwo(unsigned n) { inline bool powerOfTwo(unsigned n)
for (; n > 2; n >>= 1) if (n & 1) return false; {
for (; n > 2; n >>= 1)
if (n & 1)
return false;
return true; return true;
} }
inline unsigned nextPowerOfTwo(unsigned n) { inline unsigned nextPowerOfTwo(unsigned n)
{
unsigned r = 1; unsigned r = 1;
while (r < n) r <<= 1; while (r < n)
r <<= 1;
return r; return r;
} }
inline unsigned log(unsigned n) { inline unsigned log(unsigned n)
{
unsigned r = 0; unsigned r = 0;
for (unsigned i = 1; i < n; ++r) i <<= 1; for (unsigned i = 1; i < n; ++r)
i <<= 1;
return r; return r;
} }
} // namespace util } // namespace util
} // namespace avian } // namespace avian
#endif // AVIAN_UTIL_MATH_H #endif // AVIAN_UTIL_MATH_H

View File

@ -16,25 +16,26 @@
template <class T> template <class T>
class RuntimeArray { class RuntimeArray {
public: public:
RuntimeArray(unsigned size): RuntimeArray(unsigned size) : body(static_cast<T*>(malloc(size * sizeof(T))))
body(static_cast<T*>(malloc(size * sizeof(T)))) {
{ } }
~RuntimeArray() { ~RuntimeArray()
{
free(body); free(body);
} }
T* body; T* body;
}; };
# define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size); #define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size);
# define RUNTIME_ARRAY_BODY(name) name.body #define RUNTIME_ARRAY_BODY(name) name.body
#else // not _MSC_VER #else // not _MSC_VER
# define RUNTIME_ARRAY(type, name, size) type name##_body[size]; #define RUNTIME_ARRAY(type, name, size) type name##_body[size];
# define RUNTIME_ARRAY_BODY(name) name##_body #define RUNTIME_ARRAY_BODY(name) name##_body
#endif #endif
#endif // AVIAN_UTIL_RUNTIME_ARRAY_H #endif // AVIAN_UTIL_RUNTIME_ARRAY_H

View File

@ -18,6 +18,19 @@
namespace avian { namespace avian {
namespace util { 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> template <class T>
class Slice { class Slice {
public: 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; 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) static Slice<T> alloc(Allocator* a, size_t count)
{ {
return Slice<T>((T*)a->allocate(sizeof(T) * count), count); return Slice<T>((T*)a->allocate(sizeof(T) * count), count);

View File

@ -22,19 +22,23 @@ class AbstractStream {
virtual void handleError() = 0; virtual void handleError() = 0;
}; };
AbstractStream(Client* client, unsigned size): AbstractStream(Client* client, unsigned size)
client(client), size(size), position_(0) : client(client), size(size), position_(0)
{ } {
}
unsigned position() { unsigned position()
{
return position_; return position_;
} }
void setPosition(unsigned p) { void setPosition(unsigned p)
{
position_ = p; position_ = p;
} }
void skip(unsigned size) { void skip(unsigned size)
{
if (size > this->size - position_) { if (size > this->size - position_) {
client->handleError(); client->handleError();
} else { } else {
@ -42,7 +46,8 @@ class AbstractStream {
} }
} }
void read(uint8_t* dst, unsigned size) { void read(uint8_t* dst, unsigned size)
{
if (size > this->size - position_) { if (size > this->size - position_) {
memset(dst, 0, size); memset(dst, 0, size);
@ -53,35 +58,41 @@ class AbstractStream {
} }
} }
uint8_t read1() { uint8_t read1()
{
uint8_t v; uint8_t v;
read(&v, 1); read(&v, 1);
return v; return v;
} }
uint16_t read2() { uint16_t read2()
{
uint16_t a = read1(); uint16_t a = read1();
uint16_t b = read1(); uint16_t b = read1();
return (a << 8) | b; return (a << 8) | b;
} }
uint32_t read4() { uint32_t read4()
{
uint32_t a = read2(); uint32_t a = read2();
uint32_t b = read2(); uint32_t b = read2();
return (a << 16) | b; return (a << 16) | b;
} }
uint64_t read8() { uint64_t read8()
{
uint64_t a = read4(); uint64_t a = read4();
uint64_t b = read4(); uint64_t b = read4();
return (a << 32) | b; return (a << 32) | b;
} }
uint32_t readFloat() { uint32_t readFloat()
{
return read4(); return read4();
} }
uint64_t readDouble() { uint64_t readDouble()
{
return read8(); return read8();
} }
@ -94,20 +105,22 @@ class AbstractStream {
unsigned position_; unsigned position_;
}; };
class Stream: public AbstractStream { class Stream : public AbstractStream {
public: public:
Stream(Client* client, const uint8_t* data, unsigned size): Stream(Client* client, const uint8_t* data, unsigned size)
AbstractStream(client, size), data(data) : AbstractStream(client, size), data(data)
{ } {
}
private: private:
virtual void copy(uint8_t* dst, unsigned offset, unsigned size) { virtual void copy(uint8_t* dst, unsigned offset, unsigned size)
{
memcpy(dst, data + offset, size); memcpy(dst, data + offset, size);
} }
const uint8_t* data; const uint8_t* data;
}; };
} // namespace vm } // namespace vm
#endif//STREAM_H #endif // STREAM_H

View File

@ -17,38 +17,43 @@ namespace avian {
namespace util { namespace util {
class String { class String {
public: public:
const char* text; const char* text;
size_t length; size_t length;
String(const char* text): String(const char* text) : text(text), length(strlen(text))
text(text), {
length(strlen(text)) {} }
inline String(const char* text, size_t length): inline String(const char* text, size_t length) : text(text), length(length)
text(text), {
length(length) {} }
}; };
class Tokenizer { class Tokenizer {
public: public:
Tokenizer(const char* s, char delimiter)
: s(s), limit(0), delimiter(delimiter)
{
}
Tokenizer(const char* s, char delimiter): Tokenizer(String str, char delimiter)
s(s), limit(0), delimiter(delimiter) : s(str.text), limit(str.text + str.length), delimiter(delimiter)
{ } {
}
Tokenizer(String str, char delimiter): bool hasMore()
s(str.text), limit(str.text + str.length), delimiter(delimiter) {
{ } while (s != limit and *s == delimiter)
++s;
bool hasMore() {
while (s != limit and *s == delimiter) ++s;
return s != limit and *s != 0; return s != limit and *s != 0;
} }
String next() { String next()
{
const char* p = s; const char* p = s;
while (s != limit and *s and *s != delimiter) ++s; while (s != limit and *s and *s != delimiter)
++s;
return String(p, s - p); return String(p, s - p);
} }
@ -57,7 +62,7 @@ class Tokenizer {
char delimiter; char delimiter;
}; };
} // namespace util } // namespace util
} // namespace avain } // namespace avain
#endif//AVIAN_UTIL_STRING_H #endif // AVIAN_UTIL_STRING_H

View File

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

View File

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

View File

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

View File

@ -12,39 +12,41 @@
#define ARCH_H #define ARCH_H
#ifdef _MSC_VER #ifdef _MSC_VER
# include "windows.h" #include "windows.h"
# pragma push_macro("assert") #pragma push_macro("assert")
# include "intrin.h" #include "intrin.h"
# pragma pop_macro("assert") #pragma pop_macro("assert")
# undef interface #undef interface
#endif #endif
#include "avian/common.h" #include "avian/common.h"
extern "C" void NO_RETURN extern "C" void NO_RETURN vmJump(void* address,
vmJump(void* address, void* frame, void* stack, void* thread, void* frame,
uintptr_t returnLow, uintptr_t returnHigh); void* stack,
void* thread,
uintptr_t returnLow,
uintptr_t returnHigh);
namespace vm { namespace vm {
inline void inline void compileTimeMemoryBarrier()
compileTimeMemoryBarrier()
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
_ReadWriteBarrier(); _ReadWriteBarrier();
#else #else
__asm__ __volatile__("": : :"memory"); __asm__ __volatile__("" : : : "memory");
#endif #endif
} }
} // namespace vm } // namespace vm
#if (defined ARCH_x86_32) || (defined ARCH_x86_64) #if (defined ARCH_x86_32) || (defined ARCH_x86_64)
# include "x86.h" #include "x86.h"
#elif defined ARCH_arm #elif defined ARCH_arm
# include "arm.h" #include "arm.h"
#else #else
# error unsupported architecture #error unsupported architecture
#endif #endif
#endif//ARCH_H #endif // ARCH_H

View File

@ -16,61 +16,62 @@
#include <avian/util/runtime-array.h> #include <avian/util/runtime-array.h>
#ifdef __APPLE__ #ifdef __APPLE__
# include "libkern/OSAtomic.h" #include "libkern/OSAtomic.h"
# include "libkern/OSCacheControl.h" #include "libkern/OSCacheControl.h"
# include "mach/mach_types.h" #include "mach/mach_types.h"
# include "mach/thread_act.h" #include "mach/thread_act.h"
# include "mach/thread_status.h" #include "mach/thread_status.h"
# define THREAD_STATE ARM_THREAD_STATE #define THREAD_STATE ARM_THREAD_STATE
# define THREAD_STATE_TYPE arm_thread_state_t #define THREAD_STATE_TYPE arm_thread_state_t
# define THREAD_STATE_COUNT ARM_THREAD_STATE_COUNT #define THREAD_STATE_COUNT ARM_THREAD_STATE_COUNT
# if __DARWIN_UNIX03 && defined(_STRUCT_ARM_EXCEPTION_STATE) #if __DARWIN_UNIX03 && defined(_STRUCT_ARM_EXCEPTION_STATE)
# define FIELD(x) __##x #define FIELD(x) __##x
# else
# define FIELD(x) x
# endif
# define THREAD_STATE_IP(state) ((state).FIELD(pc))
# define THREAD_STATE_STACK(state) ((state).FIELD(sp))
# define THREAD_STATE_THREAD(state) ((state).FIELD(r[8]))
# define THREAD_STATE_LINK(state) ((state).FIELD(lr))
# define IP_REGISTER(context) \
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
# define STACK_REGISTER(context) \
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
# define THREAD_REGISTER(context) \
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
# define LINK_REGISTER(context) \
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
#elif (defined __QNX__)
# include "arm/smpxchg.h"
# include "sys/mman.h"
# define IP_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_PC])
# define STACK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_SP])
# define THREAD_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_IP])
# define LINK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_LR])
#else #else
# define IP_REGISTER(context) (context->uc_mcontext.arm_pc) #define FIELD(x) x
# define STACK_REGISTER(context) (context->uc_mcontext.arm_sp) #endif
# define THREAD_REGISTER(context) (context->uc_mcontext.arm_ip)
# define LINK_REGISTER(context) (context->uc_mcontext.arm_lr) #define THREAD_STATE_IP(state) ((state).FIELD(pc))
#define THREAD_STATE_STACK(state) ((state).FIELD(sp))
#define THREAD_STATE_THREAD(state) ((state).FIELD(r[8]))
#define THREAD_STATE_LINK(state) ((state).FIELD(lr))
#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
#define STACK_REGISTER(context) \
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
#define THREAD_REGISTER(context) \
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
#define LINK_REGISTER(context) \
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
#elif(defined __QNX__)
#include "arm/smpxchg.h"
#include "sys/mman.h"
#define IP_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_PC])
#define STACK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_SP])
#define THREAD_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_IP])
#define LINK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_LR])
#else
#define IP_REGISTER(context) (context->uc_mcontext.arm_pc)
#define STACK_REGISTER(context) (context->uc_mcontext.arm_sp)
#define THREAD_REGISTER(context) (context->uc_mcontext.arm_ip)
#define LINK_REGISTER(context) (context->uc_mcontext.arm_lr)
#endif #endif
#define VA_LIST(x) (&(x)) #define VA_LIST(x) (&(x))
extern "C" uint64_t extern "C" uint64_t vmNativeCall(void* function,
vmNativeCall(void* function, unsigned stackTotal, void* memoryTable, unsigned stackTotal,
unsigned memoryCount, void* gprTable, void* vfpTable, void* memoryTable,
unsigned returnType); unsigned memoryCount,
void* gprTable,
void* vfpTable,
unsigned returnType);
namespace vm { namespace vm {
inline void inline void trap()
trap()
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
__debugbreak(); __debugbreak();
@ -86,23 +87,21 @@ trap()
// performant choice. // performant choice.
#ifndef _MSC_VER #ifndef _MSC_VER
inline void inline void memoryBarrier()
memoryBarrier()
{ {
#ifdef __APPLE__ #ifdef __APPLE__
OSMemoryBarrier(); OSMemoryBarrier();
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1) #elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
return __sync_synchronize(); return __sync_synchronize();
#elif (! defined AVIAN_ASSUME_ARMV6) #elif(!defined AVIAN_ASSUME_ARMV6)
__asm__ __volatile__ ("dmb" : : : "memory"); __asm__ __volatile__("dmb" : : : "memory");
#else #else
__asm__ __volatile__ ("" : : : "memory"); __asm__ __volatile__("" : : : "memory");
#endif #endif
} }
#endif #endif
inline void inline void storeStoreMemoryBarrier()
storeStoreMemoryBarrier()
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
_ReadWriteBarrier(); _ReadWriteBarrier();
@ -111,8 +110,7 @@ storeStoreMemoryBarrier()
#endif #endif
} }
inline void inline void storeLoadMemoryBarrier()
storeLoadMemoryBarrier()
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
MemoryBarrier(); MemoryBarrier();
@ -121,8 +119,7 @@ storeLoadMemoryBarrier()
#endif #endif
} }
inline void inline void loadMemoryBarrier()
loadMemoryBarrier()
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
_ReadWriteBarrier(); _ReadWriteBarrier();
@ -135,52 +132,54 @@ loadMemoryBarrier()
#if defined(__ANDROID__) #if defined(__ANDROID__)
// http://code.google.com/p/android/issues/detail?id=1803 // http://code.google.com/p/android/issues/detail?id=1803
extern "C" void __clear_cache (void *beg __attribute__((__unused__)), void *end __attribute__((__unused__))); extern "C" void __clear_cache(void* beg __attribute__((__unused__)),
void* end __attribute__((__unused__)));
#endif #endif
inline void inline void syncInstructionCache(const void* start, unsigned size)
syncInstructionCache(const void* start, unsigned size)
{ {
#ifdef __APPLE__ #ifdef __APPLE__
sys_icache_invalidate(const_cast<void*>(start), size); sys_icache_invalidate(const_cast<void*>(start), size);
#elif (defined __QNX__) #elif(defined __QNX__)
msync(const_cast<void*>(start), size, MS_INVALIDATE_ICACHE); msync(const_cast<void*>(start), size, MS_INVALIDATE_ICACHE);
#else #else
__clear_cache __clear_cache(
(const_cast<void*>(start), const_cast<void*>(start),
const_cast<uint8_t*>(static_cast<const uint8_t*>(start) + size)); const_cast<uint8_t*>(static_cast<const uint8_t*>(start) + size));
#endif #endif
} }
#endif // AVIAN_AOT_ONLY #endif // AVIAN_AOT_ONLY
#ifndef __APPLE__ #ifndef __APPLE__
typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); typedef int(__kernel_cmpxchg_t)(int oldval, int newval, int* ptr);
# define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) #define __kernel_cmpxchg (*(__kernel_cmpxchg_t*)0xffff0fc0)
#endif #endif
inline bool inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
{ {
#ifdef __APPLE__ #ifdef __APPLE__
return OSAtomicCompareAndSwap32Barrier(old, new_, reinterpret_cast<int32_t*>(p)); return OSAtomicCompareAndSwap32Barrier(
#elif (defined __QNX__) old, new_, reinterpret_cast<int32_t*>(p));
#elif(defined __QNX__)
return old == _smp_cmpxchg(p, old, new_); return old == _smp_cmpxchg(p, old, new_);
#else #else
int r = __kernel_cmpxchg(static_cast<int>(old), static_cast<int>(new_), reinterpret_cast<int*>(p)); int r = __kernel_cmpxchg(
static_cast<int>(old), static_cast<int>(new_), reinterpret_cast<int*>(p));
return (!r ? true : false); return (!r ? true : false);
#endif #endif
} }
inline bool inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
{ {
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_); return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
} }
inline uint64_t inline uint64_t dynamicCall(void* function,
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, uintptr_t* arguments,
unsigned argumentCount, unsigned argumentsSize UNUSED, uint8_t* argumentTypes,
unsigned returnType) unsigned argumentCount,
unsigned argumentsSize UNUSED,
unsigned returnType)
{ {
#ifdef __APPLE__ #ifdef __APPLE__
const unsigned Alignment = 1; const unsigned Alignment = 1;
@ -197,34 +196,37 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
unsigned vfpIndex = 0; unsigned vfpIndex = 0;
unsigned vfpBackfillIndex UNUSED = 0; unsigned vfpBackfillIndex UNUSED = 0;
RUNTIME_ARRAY(uintptr_t, stack, (argumentCount * 8) / BytesPerWord); // is > argumentSize to account for padding RUNTIME_ARRAY(uintptr_t,
stack,
(argumentCount * 8)
/ BytesPerWord); // is > argumentSize to account for padding
unsigned stackIndex = 0; unsigned stackIndex = 0;
unsigned ai = 0; unsigned ai = 0;
for (unsigned ati = 0; ati < argumentCount; ++ ati) { for (unsigned ati = 0; ati < argumentCount; ++ati) {
switch (argumentTypes[ati]) { switch (argumentTypes[ati]) {
case DOUBLE_TYPE: case DOUBLE_TYPE:
#if defined(__ARM_PCS_VFP) #if defined(__ARM_PCS_VFP)
{ {
if (vfpIndex + Alignment <= VfpCount) { if (vfpIndex + Alignment <= VfpCount) {
if (vfpIndex % Alignment) { if (vfpIndex % Alignment) {
vfpBackfillIndex = vfpIndex; vfpBackfillIndex = vfpIndex;
++ vfpIndex; ++vfpIndex;
}
memcpy(vfpTable + vfpIndex, arguments + ai, 8);
vfpIndex += 8 / BytesPerWord;
} else {
vfpIndex = VfpCount;
if (stackIndex % Alignment) {
++ stackIndex;
}
memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8);
stackIndex += 8 / BytesPerWord;
} }
ai += 8 / BytesPerWord;
} break; memcpy(vfpTable + vfpIndex, arguments + ai, 8);
vfpIndex += 8 / BytesPerWord;
} else {
vfpIndex = VfpCount;
if (stackIndex % Alignment) {
++stackIndex;
}
memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8);
stackIndex += 8 / BytesPerWord;
}
ai += 8 / BytesPerWord;
} break;
case FLOAT_TYPE: case FLOAT_TYPE:
if (vfpBackfillIndex) { if (vfpBackfillIndex) {
@ -235,15 +237,13 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
} else { } else {
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai]; RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
} }
++ ai; ++ai;
break; break;
#endif #endif
case INT64_TYPE: { case INT64_TYPE: {
if (gprIndex + Alignment <= GprCount) { // pass argument in register(s) if (gprIndex + Alignment <= GprCount) { // pass argument in register(s)
if (Alignment == 1 if (Alignment == 1 and BytesPerWord < 8
and BytesPerWord < 8 and gprIndex + Alignment == GprCount) {
and gprIndex + Alignment == GprCount)
{
gprTable[gprIndex++] = arguments[ai]; gprTable[gprIndex++] = arguments[ai];
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1]; RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1];
} else { } else {
@ -254,7 +254,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
memcpy(gprTable + gprIndex, arguments + ai, 8); memcpy(gprTable + gprIndex, arguments + ai, 8);
gprIndex += 8 / BytesPerWord; gprIndex += 8 / BytesPerWord;
} }
} else { // pass argument on stack } else { // pass argument on stack
gprIndex = GprCount; gprIndex = GprCount;
if (stackIndex % Alignment) { if (stackIndex % Alignment) {
++stackIndex; ++stackIndex;
@ -272,27 +272,30 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
} else { } else {
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai]; RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
} }
++ ai; ++ai;
} break; } break;
} }
} }
if (gprIndex < GprCount) { // pad since assembly loads all GPRs if (gprIndex < GprCount) { // pad since assembly loads all GPRs
memset(gprTable + gprIndex, 0, (GprCount-gprIndex)*4); memset(gprTable + gprIndex, 0, (GprCount - gprIndex) * 4);
gprIndex = GprCount; gprIndex = GprCount;
} }
if (vfpIndex < VfpCount) { if (vfpIndex < VfpCount) {
memset(vfpTable + vfpIndex, 0, (VfpCount-vfpIndex)*4); memset(vfpTable + vfpIndex, 0, (VfpCount - vfpIndex) * 4);
vfpIndex = VfpCount; vfpIndex = VfpCount;
} }
unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2); unsigned stackSize = stackIndex * BytesPerWord + ((stackIndex & 1) << 2);
return vmNativeCall return vmNativeCall(function,
(function, stackSize, RUNTIME_ARRAY_BODY(stack), stackIndex * BytesPerWord, stackSize,
(gprIndex ? gprTable : 0), RUNTIME_ARRAY_BODY(stack),
(vfpIndex ? vfpTable : 0), returnType); stackIndex * BytesPerWord,
(gprIndex ? gprTable : 0),
(vfpIndex ? vfpTable : 0),
returnType);
} }
} // namespace vm } // namespace vm
#endif // ARM_H #endif // ARM_H

View File

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

View File

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

View File

@ -12,9 +12,11 @@
#define AVIAN_COMMON_H #define AVIAN_COMMON_H
#ifndef __STDC_CONSTANT_MACROS #ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS
#endif #endif
#include <new>
#include "stdlib.h" #include "stdlib.h"
#include "stdarg.h" #include "stdarg.h"
#include "stddef.h" #include "stddef.h"
@ -29,11 +31,11 @@
#include <stdint.h> #include <stdint.h>
#ifdef linux #ifdef linux
# undef linux #undef linux
#endif #endif
// don't complain about using 'this' in member initializers: // don't complain about using 'this' in member initializers:
# pragma warning(disable:4355) #pragma warning(disable : 4355)
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
@ -41,193 +43,195 @@
#define FP_INFINITE 1 #define FP_INFINITE 1
#define FP_UNDEF 2 #define FP_UNDEF 2
inline int fpclassify(double d) { inline int fpclassify(double d)
{
switch(_fpclass(d)) { switch (_fpclass(d)) {
case _FPCLASS_SNAN: case _FPCLASS_SNAN:
case _FPCLASS_QNAN: case _FPCLASS_QNAN:
return FP_NAN; return FP_NAN;
case _FPCLASS_PINF: case _FPCLASS_PINF:
case _FPCLASS_NINF: case _FPCLASS_NINF:
return FP_INFINITE; return FP_INFINITE;
} }
return FP_UNDEF; return FP_UNDEF;
} }
inline int signbit(double d) { inline int signbit(double d)
return _copysign(1.0, d) < 0; {
return _copysign(1.0, d) < 0;
} }
# define not ! #define not!
# define or || #define or ||
# define and && #define and &&
# define xor ^ #define xor ^
# define LIKELY(v) v #define LIKELY(v) v
# define UNLIKELY(v) v #define UNLIKELY(v) v
# define UNUSED #define UNUSED
# define NO_RETURN __declspec(noreturn) #define NO_RETURN __declspec(noreturn)
# define PACKED #define PACKED
# define PLATFORM_WINDOWS #define PLATFORM_WINDOWS
# ifdef _M_IX86 #ifdef _M_IX86
typedef int32_t intptr_t; typedef int32_t intptr_t;
typedef uint32_t uintptr_t; typedef uint32_t uintptr_t;
# define ARCH_x86_32 #define ARCH_x86_32
# define BYTES_PER_WORD 4 #define BYTES_PER_WORD 4
# elif defined _M_X64 #elif defined _M_X64
typedef int64_t intptr_t; typedef int64_t intptr_t;
typedef uint64_t uintptr_t; typedef uint64_t uintptr_t;
# define ARCH_x86_64 #define ARCH_x86_64
# define BYTES_PER_WORD 8 #define BYTES_PER_WORD 8
# elif defined _M_ARM_FP #elif defined _M_ARM_FP
typedef int32_t intptr_t; typedef int32_t intptr_t;
typedef uint32_t uintptr_t; typedef uint32_t uintptr_t;
# define ARCH_arm #define ARCH_arm
# define BYTES_PER_WORD 4 #define BYTES_PER_WORD 4
# else #else
# error "unsupported architecture" #error "unsupported architecture"
# endif #endif
namespace vm { namespace vm {
typedef intptr_t intptr_alias_t; typedef intptr_t intptr_alias_t;
} // namespace vm } // namespace vm
#else // not _MSC_VER #else // not _MSC_VER
# include <stdint.h> #include <stdint.h>
# define BYTES_PER_WORD __SIZEOF_POINTER__ #define BYTES_PER_WORD __SIZEOF_POINTER__
# define LIKELY(v) __builtin_expect((v) != 0, true) #define LIKELY(v) __builtin_expect((v) != 0, true)
# define UNLIKELY(v) __builtin_expect((v) != 0, false) #define UNLIKELY(v) __builtin_expect((v) != 0, false)
# define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused))
# define NO_RETURN __attribute__((noreturn)) #define NO_RETURN __attribute__((noreturn))
# define PACKED __attribute__((packed)) #define PACKED __attribute__((packed))
# ifdef __MINGW32__ #ifdef __MINGW32__
# define PLATFORM_WINDOWS #define PLATFORM_WINDOWS
# endif #endif
# ifdef __i386__ #ifdef __i386__
# define ARCH_x86_32 #define ARCH_x86_32
# elif defined __x86_64__ #elif defined __x86_64__
# define ARCH_x86_64 #define ARCH_x86_64
# elif defined __arm__ #elif defined __arm__
# define ARCH_arm #define ARCH_arm
# else #else
# error "unsupported architecture" #error "unsupported architecture"
# endif #endif
namespace vm { namespace vm {
typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t; typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
} // namespace vm } // namespace vm
#endif // not _MSC_VER #endif // not _MSC_VER
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
# define AVIAN_EXPORT __declspec(dllexport) #define AVIAN_EXPORT __declspec(dllexport)
# define PATH_SEPARATOR ';' #define PATH_SEPARATOR ';'
#else // not PLATFORM_WINDOWS #else // not PLATFORM_WINDOWS
# define AVIAN_EXPORT __attribute__ ((visibility("default"))) \ #define AVIAN_EXPORT \
__attribute__ ((used)) __attribute__((visibility("default"))) __attribute__((used))
# define PATH_SEPARATOR ':' #define PATH_SEPARATOR ':'
#endif // not PLATFORM_WINDOWS #endif // not PLATFORM_WINDOWS
#if (defined ARCH_x86_32) || (defined ARCH_arm) #if (defined ARCH_x86_32) || (defined ARCH_arm)
# define LD "ld" #define LD "ld"
# if (defined _MSC_VER) || ((defined __MINGW32__) && __GNUC__ >= 4) #if (defined _MSC_VER) || ((defined __MINGW32__) && __GNUC__ >= 4)
# define LLD "I64d" #define LLD "I64d"
# else
# define LLD "lld"
# endif
# ifdef __APPLE__
# define ULD "lu"
# define LX "lx"
# else
# define LX "x"
# define ULD "u"
# endif
#elif defined ARCH_x86_64
# define LD "ld"
# define LX "lx"
# if (defined _MSC_VER) || (defined __MINGW32__)
# define LLD "I64d"
# define ULD "I64x"
# else
# ifdef __APPLE__
# define LLD "lld"
# else
# define LLD "ld"
# endif
# define ULD "lu"
# endif
#else #else
# error "Unsupported architecture" #define LLD "lld"
#endif
#ifdef __APPLE__
#define ULD "lu"
#define LX "lx"
#else
#define LX "x"
#define ULD "u"
#endif
#elif defined ARCH_x86_64
#define LD "ld"
#define LX "lx"
#if (defined _MSC_VER) || (defined __MINGW32__)
#define LLD "I64d"
#define ULD "I64x"
#else
#ifdef __APPLE__
#define LLD "lld"
#else
#define LLD "ld"
#endif
#define ULD "lu"
#endif
#else
#error "Unsupported architecture"
#endif #endif
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
# define SO_PREFIX "" #define SO_PREFIX ""
#else #else
# define SO_PREFIX "lib" #define SO_PREFIX "lib"
#endif #endif
#ifdef __APPLE__ #ifdef __APPLE__
# define SO_SUFFIX ".dylib" #define SO_SUFFIX ".dylib"
#elif defined PLATFORM_WINDOWS #elif defined PLATFORM_WINDOWS
# define SO_SUFFIX ".dll" #define SO_SUFFIX ".dll"
#else #else
# define SO_SUFFIX ".so" #define SO_SUFFIX ".so"
#endif #endif
#define MACRO_XY(X, Y) X##Y #define MACRO_XY(X, Y) X##Y
#define MACRO_MakeNameXY(FX, LINE) MACRO_XY(FX, LINE) #define MACRO_MakeNameXY(FX, LINE) MACRO_XY(FX, LINE)
#define MAKE_NAME(FX) MACRO_MakeNameXY(FX, __LINE__) #define MAKE_NAME(FX) MACRO_MakeNameXY(FX, __LINE__)
#define RESOURCE(type, name, release) \ #define RESOURCE(type, name, release) \
class MAKE_NAME(Resource_) { \ class MAKE_NAME(Resource_) { \
public: \ public: \
MAKE_NAME(Resource_)(type name): name(name) { } \ MAKE_NAME(Resource_)(type name) : name(name) \
~MAKE_NAME(Resource_)() { release; } \ { \
\ } \
private: \ ~MAKE_NAME(Resource_)() \
type name; \ { \
release; \
} \
\
private: \
type name; \
} MAKE_NAME(resource_)(name); } MAKE_NAME(resource_)(name);
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning( disable : 4291 ) #pragma warning(disable : 4291)
#endif #endif
inline void* operator new(size_t, void* p) throw() { return p; }
namespace vm { namespace vm {
inline intptr_alias_t& inline intptr_alias_t& alias(void* p, unsigned offset)
alias(void* p, unsigned offset)
{ {
return *reinterpret_cast<intptr_alias_t*>(static_cast<uint8_t*>(p) + offset); return *reinterpret_cast<intptr_alias_t*>(static_cast<uint8_t*>(p) + offset);
} }
#ifdef _MSC_VER #ifdef _MSC_VER
inline int inline int vsnprintf(char* dst, size_t size, const char* format, va_list a)
vsnprintf(char* dst, size_t size, const char* format, va_list a)
{ {
return vsnprintf_s(dst, size, _TRUNCATE, format, a); return vsnprintf_s(dst, size, _TRUNCATE, format, a);
} }
inline int inline int snprintf(char* dst, size_t size, const char* format, ...)
snprintf(char* dst, size_t size, const char* format, ...)
{ {
va_list a; va_list a;
va_start(a, format); va_start(a, format);
@ -236,8 +240,7 @@ snprintf(char* dst, size_t size, const char* format, ...)
return r; return r;
} }
inline FILE* inline FILE* fopen(const char* name, const char* mode)
fopen(const char* name, const char* mode)
{ {
FILE* file; FILE* file;
if (fopen_s(&file, name, mode) == 0) { if (fopen_s(&file, name, mode) == 0) {
@ -247,16 +250,14 @@ fopen(const char* name, const char* mode)
} }
} }
#else // not _MSC_VER #else // not _MSC_VER
inline int inline int vsnprintf(char* dst, size_t size, const char* format, va_list a)
vsnprintf(char* dst, size_t size, const char* format, va_list a)
{ {
return ::vsnprintf(dst, size, format, a); return ::vsnprintf(dst, size, format, a);
} }
inline int inline int snprintf(char* dst, size_t size, const char* format, ...)
snprintf(char* dst, size_t size, const char* format, ...)
{ {
va_list a; va_list a;
va_start(a, format); va_start(a, format);
@ -265,116 +266,105 @@ snprintf(char* dst, size_t size, const char* format, ...)
return r; return r;
} }
inline FILE* inline FILE* fopen(const char* name, const char* mode)
fopen(const char* name, const char* mode)
{ {
return ::fopen(name, mode); return ::fopen(name, mode);
} }
#endif // not _MSC_VER #endif // not _MSC_VER
const unsigned BytesPerWord = sizeof(uintptr_t); const unsigned BytesPerWord = sizeof(uintptr_t);
const unsigned BitsPerWord = BytesPerWord * 8; const unsigned BitsPerWord = BytesPerWord * 8;
const uintptr_t PointerMask const uintptr_t PointerMask = ((~static_cast<uintptr_t>(0)) / BytesPerWord)
= ((~static_cast<uintptr_t>(0)) / BytesPerWord) * BytesPerWord; * BytesPerWord;
const unsigned LikelyPageSizeInBytes = 4 * 1024; const unsigned LikelyPageSizeInBytes = 4 * 1024;
inline unsigned inline unsigned pad(unsigned n, unsigned alignment)
pad(unsigned n, unsigned alignment)
{ {
return (n + (alignment - 1)) & ~(alignment - 1); return (n + (alignment - 1)) & ~(alignment - 1);
} }
inline unsigned inline unsigned pad(unsigned n)
pad(unsigned n)
{ {
return pad(n, BytesPerWord); return pad(n, BytesPerWord);
} }
inline uintptr_t inline uintptr_t padWord(uintptr_t n, uintptr_t alignment)
padWord(uintptr_t n, uintptr_t alignment)
{ {
return (n + (alignment - 1)) & ~(alignment - 1); return (n + (alignment - 1)) & ~(alignment - 1);
} }
inline uintptr_t inline uintptr_t padWord(uintptr_t n)
padWord(uintptr_t n)
{ {
return padWord(n, BytesPerWord); return padWord(n, BytesPerWord);
} }
inline bool fitsInInt8(int64_t v) { inline bool fitsInInt8(int64_t v)
{
return v == static_cast<int8_t>(v); return v == static_cast<int8_t>(v);
} }
inline bool fitsInInt16(int64_t v) { inline bool fitsInInt16(int64_t v)
{
return v == static_cast<int16_t>(v); return v == static_cast<int16_t>(v);
} }
inline bool fitsInInt32(int64_t v) { inline bool fitsInInt32(int64_t v)
{
return v == static_cast<int32_t>(v); return v == static_cast<int32_t>(v);
} }
template <class T> template <class T>
inline unsigned inline unsigned wordOf(unsigned i)
wordOf(unsigned i)
{ {
return i / (sizeof(T) * 8); return i / (sizeof(T) * 8);
} }
inline unsigned inline unsigned wordOf(unsigned i)
wordOf(unsigned i)
{ {
return wordOf<uintptr_t>(i); return wordOf<uintptr_t>(i);
} }
template <class T> template <class T>
inline unsigned inline unsigned bitOf(unsigned i)
bitOf(unsigned i)
{ {
return i % (sizeof(T) * 8); return i % (sizeof(T) * 8);
} }
inline unsigned inline unsigned bitOf(unsigned i)
bitOf(unsigned i)
{ {
return bitOf<uintptr_t>(i); return bitOf<uintptr_t>(i);
} }
template <class T> template <class T>
inline unsigned inline unsigned indexOf(unsigned word, unsigned bit)
indexOf(unsigned word, unsigned bit)
{ {
return (word * (sizeof(T) * 8)) + bit; return (word * (sizeof(T) * 8)) + bit;
} }
inline unsigned inline unsigned indexOf(unsigned word, unsigned bit)
indexOf(unsigned word, unsigned bit)
{ {
return indexOf<uintptr_t>(word, bit); return indexOf<uintptr_t>(word, bit);
} }
template <class T> template <class T>
inline void inline void markBit(T* map, unsigned i)
markBit(T* map, unsigned i)
{ {
map[wordOf<T>(i)] |= static_cast<T>(1) << bitOf<T>(i); map[wordOf<T>(i)] |= static_cast<T>(1) << bitOf<T>(i);
} }
template <class T> template <class T>
inline void inline void clearBit(T* map, unsigned i)
clearBit(T* map, unsigned i)
{ {
map[wordOf<T>(i)] &= ~(static_cast<T>(1) << bitOf<T>(i)); map[wordOf<T>(i)] &= ~(static_cast<T>(1) << bitOf<T>(i));
} }
template <class T> template <class T>
inline unsigned inline unsigned getBit(T* map, unsigned i)
getBit(T* map, unsigned i)
{ {
return (map[wordOf<T>(i)] & (static_cast<T>(1) << bitOf<T>(i))) return (map[wordOf<T>(i)] & (static_cast<T>(1) << bitOf<T>(i)))
>> bitOf<T>(i); >> bitOf<T>(i);
} }
// todo: the following (clearBits, setBits, and getBits) could be made // todo: the following (clearBits, setBits, and getBits) could be made
@ -382,8 +372,7 @@ getBit(T* map, unsigned i)
// a time: // a time:
template <class T> template <class T>
inline void inline void clearBits(T* map, unsigned bitsPerRecord, unsigned index)
clearBits(T* map, unsigned bitsPerRecord, unsigned index)
{ {
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) { for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
clearBit<T>(map, i); clearBit<T>(map, i);
@ -391,18 +380,19 @@ clearBits(T* map, unsigned bitsPerRecord, unsigned index)
} }
template <class T> template <class T>
inline void inline void setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
{ {
for (int i = index + bitsPerRecord - 1; i >= index; --i) { for (int i = index + bitsPerRecord - 1; i >= index; --i) {
if (v & 1) markBit<T>(map, i); else clearBit<T>(map, i); if (v & 1)
markBit<T>(map, i);
else
clearBit<T>(map, i);
v >>= 1; v >>= 1;
} }
} }
template <class T> template <class T>
inline unsigned inline unsigned getBits(T* map, unsigned bitsPerRecord, unsigned index)
getBits(T* map, unsigned bitsPerRecord, unsigned index)
{ {
unsigned v = 0; unsigned v = 0;
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) { for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
@ -413,122 +403,80 @@ getBits(T* map, unsigned bitsPerRecord, unsigned index)
} }
template <class T> template <class T>
inline T& inline T& fieldAtOffset(void* p, unsigned offset)
fieldAtOffset(void* p, unsigned offset)
{ {
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset); return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
} }
template <class T> template <class T>
inline T* inline T* maskAlignedPointer(T* p)
maskAlignedPointer(T* p)
{ {
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask); return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
} }
inline uint32_t inline void write4(uint8_t* dst, uint32_t v)
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)
{ {
memcpy(dst, &v, 4); memcpy(dst, &v, 4);
} }
inline uint32_t inline uint32_t floatToBits(float f)
floatToBits(float f)
{ {
uint32_t bits; memcpy(&bits, &f, 4); uint32_t bits;
memcpy(&bits, &f, 4);
return bits; return bits;
} }
inline uint64_t inline uint64_t doubleToBits(double d)
doubleToBits(double d)
{ {
uint64_t bits; memcpy(&bits, &d, 8); uint64_t bits;
memcpy(&bits, &d, 8);
return bits; return bits;
} }
inline double inline double bitsToDouble(uint64_t bits)
bitsToDouble(uint64_t bits)
{ {
double d; memcpy(&d, &bits, 8); double d;
memcpy(&d, &bits, 8);
return d; return d;
} }
inline float inline float bitsToFloat(uint32_t bits)
bitsToFloat(uint32_t bits)
{ {
float f; memcpy(&f, &bits, 4); float f;
memcpy(&f, &bits, 4);
return f; return f;
} }
inline int inline int difference(void* a, void* b)
difference(void* a, void* b)
{ {
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b); return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
} }
template <class T> template <class T>
inline void* inline void* voidPointer(T function)
voidPointer(T function)
{ {
void* p; void* p;
memcpy(&p, &function, sizeof(void*)); memcpy(&p, &function, sizeof(void*));
return p; return p;
} }
inline void inline void replace(char a, char b, char* c)
replace(char a, char b, char* c)
{ {
for (; *c; ++c) if (*c == a) *c = b; for (; *c; ++c)
if (*c == a)
*c = b;
} }
inline void inline void replace(char a, char b, char* dst, const char* src)
replace(char a, char b, char* dst, const char* src)
{ {
unsigned i = 0; unsigned i = 0;
for (; src[i]; ++ i) { for (; src[i]; ++i) {
dst[i] = src[i] == a ? b : src[i]; dst[i] = src[i] == a ? b : src[i];
} }
dst[i] = 0; dst[i] = 0;
} }
inline bool inline bool equal(const void* a, unsigned al, const void* b, unsigned bl)
equal(const void* a, unsigned al, const void* b, unsigned bl)
{ {
if (al == bl) { if (al == bl) {
return memcmp(a, b, al) == 0; return memcmp(a, b, al) == 0;
@ -537,6 +485,6 @@ equal(const void* a, unsigned al, const void* b, unsigned bl)
} }
} }
} // namespace vm } // namespace vm
#endif // AVIAN_COMMON_H #endif // AVIAN_COMMON_H

View File

@ -248,35 +248,35 @@ enum Constant {
CONSTANT_Utf8 = 1 CONSTANT_Utf8 = 1
}; };
const unsigned ACC_PUBLIC = 1 << 0; const unsigned ACC_PUBLIC = 1 << 0;
const unsigned ACC_PRIVATE = 1 << 1; const unsigned ACC_PRIVATE = 1 << 1;
const unsigned ACC_PROTECTED = 1 << 2; const unsigned ACC_PROTECTED = 1 << 2;
const unsigned ACC_STATIC = 1 << 3; const unsigned ACC_STATIC = 1 << 3;
const unsigned ACC_FINAL = 1 << 4; const unsigned ACC_FINAL = 1 << 4;
const unsigned ACC_SUPER = 1 << 5; const unsigned ACC_SUPER = 1 << 5;
const unsigned ACC_SYNCHRONIZED = ACC_SUPER; const unsigned ACC_SYNCHRONIZED = ACC_SUPER;
const unsigned ACC_VOLATILE = 1 << 6; const unsigned ACC_VOLATILE = 1 << 6;
const unsigned ACC_TRANSIENT = 1 << 7; const unsigned ACC_TRANSIENT = 1 << 7;
const unsigned ACC_NATIVE = 1 << 8; const unsigned ACC_NATIVE = 1 << 8;
const unsigned ACC_INTERFACE = 1 << 9; const unsigned ACC_INTERFACE = 1 << 9;
const unsigned ACC_ABSTRACT = 1 << 10; const unsigned ACC_ABSTRACT = 1 << 10;
const unsigned ACC_STRICT = 1 << 11; const unsigned ACC_STRICT = 1 << 11;
const int AVIAN_JNI_COMMIT = 1; const int AVIAN_JNI_COMMIT = 1;
const int AVIAN_JNI_ABORT = 2; const int AVIAN_JNI_ABORT = 2;
const int AVIAN_JNI_OK = 0; const int AVIAN_JNI_OK = 0;
const int AVIAN_JNI_ERR = -1; const int AVIAN_JNI_ERR = -1;
const int AVIAN_JNI_EDETACHED = -2; const int AVIAN_JNI_EDETACHED = -2;
const int AVIAN_JNI_EVERSION = -3; const int AVIAN_JNI_EVERSION = -3;
const int AVIAN_JNI_ENOMEM = -4; const int AVIAN_JNI_ENOMEM = -4;
const int AVIAN_JNI_EEXIST = -5; const int AVIAN_JNI_EEXIST = -5;
const int AVIAN_JNI_EINVAL = -6; const int AVIAN_JNI_EINVAL = -6;
const int AVIAN_JNI_VERSION_1_1 = 0x00010001; const int AVIAN_JNI_VERSION_1_1 = 0x00010001;
const int AVIAN_JNI_VERSION_1_2 = 0x00010002; const int AVIAN_JNI_VERSION_1_2 = 0x00010002;
const int AVIAN_JNI_VERSION_1_4 = 0x00010004; const int AVIAN_JNI_VERSION_1_4 = 0x00010004;
} // namespace vm } // namespace vm
#endif//CONSTANTS_H #endif // CONSTANTS_H

View File

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

View File

@ -30,96 +30,113 @@ const unsigned EntrySignature = 0x02014b50;
const unsigned CentralDirectorySearchStart = 22; const unsigned CentralDirectorySearchStart = 22;
inline uint16_t get2(const uint8_t* p) { inline uint16_t get2(const uint8_t* p)
return {
(static_cast<uint16_t>(p[1]) << 8) | return (static_cast<uint16_t>(p[1]) << 8) | (static_cast<uint16_t>(p[0]));
(static_cast<uint16_t>(p[0]) );
} }
inline uint32_t get4(const uint8_t* p) { inline uint32_t get4(const uint8_t* p)
return {
(static_cast<uint32_t>(p[3]) << 24) | return (static_cast<uint32_t>(p[3]) << 24)
(static_cast<uint32_t>(p[2]) << 16) | | (static_cast<uint32_t>(p[2]) << 16)
(static_cast<uint32_t>(p[1]) << 8) | | (static_cast<uint32_t>(p[1]) << 8) | (static_cast<uint32_t>(p[0]));
(static_cast<uint32_t>(p[0]) );
} }
inline uint32_t signature(const uint8_t* p) { inline uint32_t signature(const uint8_t* p)
{
return get4(p); return get4(p);
} }
inline uint16_t compressionMethod(const uint8_t* centralHeader) { inline uint16_t compressionMethod(const uint8_t* centralHeader)
{
return get2(centralHeader + 10); return get2(centralHeader + 10);
} }
inline uint32_t fileTime(const uint8_t* centralHeader) { inline uint32_t fileTime(const uint8_t* centralHeader)
{
return get4(centralHeader + 12); return get4(centralHeader + 12);
} }
inline uint32_t fileCRC(const uint8_t* centralHeader) { inline uint32_t fileCRC(const uint8_t* centralHeader)
{
return get4(centralHeader + 16); return get4(centralHeader + 16);
} }
inline uint32_t compressedSize(const uint8_t* centralHeader) { inline uint32_t compressedSize(const uint8_t* centralHeader)
{
return get4(centralHeader + 20); return get4(centralHeader + 20);
} }
inline uint32_t uncompressedSize(const uint8_t* centralHeader) { inline uint32_t uncompressedSize(const uint8_t* centralHeader)
{
return get4(centralHeader + 24); return get4(centralHeader + 24);
} }
inline uint16_t fileNameLength(const uint8_t* centralHeader) { inline uint16_t fileNameLength(const uint8_t* centralHeader)
{
return get2(centralHeader + 28); return get2(centralHeader + 28);
} }
inline uint16_t extraFieldLength(const uint8_t* centralHeader) { inline uint16_t extraFieldLength(const uint8_t* centralHeader)
{
return get2(centralHeader + 30); return get2(centralHeader + 30);
} }
inline uint16_t commentFieldLength(const uint8_t* centralHeader) { inline uint16_t commentFieldLength(const uint8_t* centralHeader)
{
return get2(centralHeader + 32); return get2(centralHeader + 32);
} }
inline uint32_t localHeaderOffset(const uint8_t* centralHeader) { inline uint32_t localHeaderOffset(const uint8_t* centralHeader)
{
return get4(centralHeader + 42); return get4(centralHeader + 42);
} }
inline uint16_t localFileNameLength(const uint8_t* localHeader) { inline uint16_t localFileNameLength(const uint8_t* localHeader)
{
return get2(localHeader + 26); return get2(localHeader + 26);
} }
inline uint16_t localExtraFieldLength(const uint8_t* localHeader) { inline uint16_t localExtraFieldLength(const uint8_t* localHeader)
{
return get2(localHeader + 28); return get2(localHeader + 28);
} }
inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader) { inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader)
{
return get4(centralHeader + 16); return get4(centralHeader + 16);
} }
inline const uint8_t* fileName(const uint8_t* centralHeader) { inline const uint8_t* fileName(const uint8_t* centralHeader)
{
return centralHeader + 46; return centralHeader + 46;
} }
inline const uint8_t* fileData(const uint8_t* localHeader) { inline const uint8_t* fileData(const uint8_t* localHeader)
return localHeader + LocalHeaderSize + localFileNameLength(localHeader) + {
localExtraFieldLength(localHeader); return localHeader + LocalHeaderSize + localFileNameLength(localHeader)
+ localExtraFieldLength(localHeader);
} }
inline const uint8_t* endOfEntry(const uint8_t* p) { inline const uint8_t* endOfEntry(const uint8_t* p)
return p + HeaderSize + fileNameLength(p) + extraFieldLength(p) + {
commentFieldLength(p); return p + HeaderSize + fileNameLength(p) + extraFieldLength(p)
+ commentFieldLength(p);
} }
inline bool inline bool readLine(const uint8_t* base,
readLine(const uint8_t* base, unsigned total, unsigned* start, unsigned total,
unsigned* length) unsigned* start,
unsigned* length)
{ {
const uint8_t* p = base + *start; const uint8_t* p = base + *start;
const uint8_t* end = base + total; const uint8_t* end = base + total;
while (p != end and (*p == '\n' or *p == '\r')) ++ p; while (p != end and (*p == '\n' or *p == '\r'))
++p;
*start = p - base; *start = p - base;
while (p != end and not (*p == '\n' or *p == '\r')) ++ p; while (p != end and not(*p == '\n' or *p == '\r'))
++p;
*length = (p - base) - *start; *length = (p - base) - *start;
@ -136,22 +153,26 @@ class Finder {
class Iterator { class Iterator {
public: public:
Iterator(Finder* finder): Iterator(Finder* finder)
it(finder->iterator()), : it(finder->iterator()), current(it->next(&currentSize))
current(it->next(&currentSize)) {
{ } }
~Iterator() { ~Iterator()
{
it->dispose(); it->dispose();
} }
bool hasMore() { bool hasMore()
if (current) return true; {
if (current)
return true;
current = it->next(&currentSize); current = it->next(&currentSize);
return current != 0; return current != 0;
} }
const char* next(unsigned* size) { const char* next(unsigned* size)
{
if (hasMore()) { if (hasMore()) {
*size = currentSize; *size = currentSize;
const char* v = current; const char* v = current;
@ -173,7 +194,8 @@ class Finder {
unsigned* length, unsigned* length,
bool tryDirectory = false) = 0; bool tryDirectory = false) = 0;
virtual const char* urlPrefix(const char* name) = 0; virtual const char* urlPrefix(const char* name) = 0;
virtual const char* nextUrlPrefix(const char* name, void *&finderElementPtr) = 0; virtual const char* nextUrlPrefix(const char* name, void*& finderElementPtr)
= 0;
virtual const char* sourceUrl(const char* name) = 0; virtual const char* sourceUrl(const char* name) = 0;
virtual const char* path() = 0; virtual const char* path() = 0;
virtual void dispose() = 0; virtual void dispose() = 0;
@ -189,6 +211,6 @@ Finder* makeFinder(System* s,
const uint8_t* jarData, const uint8_t* jarData,
unsigned jarLength); unsigned jarLength);
} // namespace vm } // namespace vm
#endif//FINDER_H #endif // FINDER_H

View File

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

View File

@ -16,9 +16,10 @@ namespace vm {
class Machine; class Machine;
class Thread; class Thread;
struct Object { }; class GcObject;
;
typedef Object* object; typedef GcObject* object;
typedef uint8_t jboolean; typedef uint8_t jboolean;
typedef int8_t jbyte; typedef int8_t jbyte;
@ -33,37 +34,50 @@ typedef jint jsize;
typedef object* jobject; typedef object* jobject;
typedef jobject jclass; class GcString;
typedef jobject jthrowable; class GcJclass;
typedef jobject jstring; 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 jweak;
typedef jobject jarray; typedef jobject jarray;
typedef jarray jbooleanArray; typedef GcBooleanArray** jbooleanArray;
typedef jarray jbyteArray; typedef GcByteArray** jbyteArray;
typedef jarray jcharArray; typedef GcCharArray** jcharArray;
typedef jarray jshortArray; typedef GcShortArray** jshortArray;
typedef jarray jintArray; typedef GcIntArray** jintArray;
typedef jarray jlongArray; typedef GcLongArray** jlongArray;
typedef jarray jfloatArray; typedef GcFloatArray** jfloatArray;
typedef jarray jdoubleArray; typedef GcDoubleArray** jdoubleArray;
typedef jarray jobjectArray; typedef GcObjectArray** jobjectArray;
typedef uintptr_t jfieldID; typedef uintptr_t jfieldID;
typedef uintptr_t jmethodID; typedef uintptr_t jmethodID;
union jvalue { union jvalue {
jboolean z; jboolean z;
jbyte b; jbyte b;
jchar c; jchar c;
jshort s; jshort s;
jint i; jint i;
jlong j; jlong j;
jfloat f; jfloat f;
jdouble d; jdouble d;
jobject l; jobject l;
}; };
} // namespace vm } // namespace vm
#endif // JAVA_COMMON_H #endif // JAVA_COMMON_H

View File

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

View File

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

View File

@ -33,6 +33,6 @@ uint8_t* encodeLZMA(System* s,
unsigned inSize, unsigned inSize,
unsigned* outSize); unsigned* outSize);
} // namespace vm } // namespace vm
#endif // LZMA_H #endif // LZMA_H

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -11,9 +11,8 @@
#ifndef AVIAN_TARGET_FIELDS_H #ifndef AVIAN_TARGET_FIELDS_H
#define AVIAN_TARGET_FIELDS_H #define AVIAN_TARGET_FIELDS_H
#ifdef TARGET_BYTES_PER_WORD #ifdef TARGET_BYTES_PER_WORD
# if (TARGET_BYTES_PER_WORD == 8) #if (TARGET_BYTES_PER_WORD == 8)
#define TARGET_THREAD_EXCEPTION 80 #define TARGET_THREAD_EXCEPTION 80
#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2264 #define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2264
@ -33,7 +32,7 @@
#define TARGET_THREAD_THUNKTABLE 2328 #define TARGET_THREAD_THUNKTABLE 2328
#define TARGET_THREAD_STACKLIMIT 2376 #define TARGET_THREAD_STACKLIMIT 2376
# elif (TARGET_BYTES_PER_WORD == 4) #elif(TARGET_BYTES_PER_WORD == 4)
#define TARGET_THREAD_EXCEPTION 44 #define TARGET_THREAD_EXCEPTION 44
#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2168 #define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2168
@ -53,12 +52,11 @@
#define TARGET_THREAD_THUNKTABLE 2200 #define TARGET_THREAD_THUNKTABLE 2200
#define TARGET_THREAD_STACKLIMIT 2224 #define TARGET_THREAD_STACKLIMIT 2224
# else
# error
# endif
#else #else
# error #error
#endif
#else
#error
#endif #endif
#endif #endif

View File

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

View File

@ -20,4 +20,4 @@
#define DOUBLE_TYPE 6 #define DOUBLE_TYPE 6
#define POINTER_TYPE 7 #define POINTER_TYPE 7
#endif//TYPES_H #endif // TYPES_H

View File

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

View File

@ -15,150 +15,164 @@
#include "avian/common.h" #include "avian/common.h"
#ifdef _MSC_VER #ifdef _MSC_VER
# include "windows.h" #include "windows.h"
# pragma push_macro("assert") #pragma push_macro("assert")
# include "intrin.h" #include "intrin.h"
# pragma pop_macro("assert") #pragma pop_macro("assert")
# undef interface #undef interface
#endif #endif
#if (defined ARCH_x86_32) || (defined PLATFORM_WINDOWS) #if (defined ARCH_x86_32) || (defined PLATFORM_WINDOWS)
# define VA_LIST(x) (&(x)) #define VA_LIST(x) (&(x))
#else #else
# define VA_LIST(x) (x) #define VA_LIST(x) (x)
#endif #endif
#ifdef __APPLE__ #ifdef __APPLE__
# include "mach/mach_types.h" #include "mach/mach_types.h"
# include "mach/thread_act.h" #include "mach/thread_act.h"
# include "mach/thread_status.h" #include "mach/thread_status.h"
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32) #if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
# define FIELD(x) __##x #define FIELD(x) __##x
# else #else
# define FIELD(x) x #define FIELD(x) x
# endif #endif
#endif #endif
#ifdef ARCH_x86_32 #ifdef ARCH_x86_32
# ifdef __APPLE__ #ifdef __APPLE__
# define THREAD_STATE x86_THREAD_STATE32 #define THREAD_STATE x86_THREAD_STATE32
# define THREAD_STATE_TYPE x86_thread_state32_t #define THREAD_STATE_TYPE x86_thread_state32_t
# define THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT #define THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
# define THREAD_STATE_IP(state) ((state).FIELD(eip)) #define THREAD_STATE_IP(state) ((state).FIELD(eip))
# define THREAD_STATE_STACK(state) ((state).FIELD(esp)) #define THREAD_STATE_STACK(state) ((state).FIELD(esp))
# define THREAD_STATE_THREAD(state) ((state).FIELD(ebx)) #define THREAD_STATE_THREAD(state) ((state).FIELD(ebx))
# define THREAD_STATE_LINK(state) ((state).FIELD(ecx)) #define THREAD_STATE_LINK(state) ((state).FIELD(ecx))
# define THREAD_STATE_FRAME(state) ((state).FIELD(ebp)) #define THREAD_STATE_FRAME(state) ((state).FIELD(ebp))
# define IP_REGISTER(context) \ #define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss)) #define STACK_REGISTER(context) \
# define STACK_REGISTER(context) \
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss)) THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
# define THREAD_REGISTER(context) \ #define THREAD_REGISTER(context) \
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss)) THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
# define LINK_REGISTER(context) \ #define LINK_REGISTER(context) \
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss)) THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
# define FRAME_REGISTER(context) \ #define FRAME_REGISTER(context) \
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss)) THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
# elif (defined __QNX__) #elif(defined __QNX__)
# define IP_REGISTER(context) (context->uc_mcontext.cpu.eip) #define IP_REGISTER(context) (context->uc_mcontext.cpu.eip)
# define STACK_REGISTER(context) (context->uc_mcontext.cpu.esp) #define STACK_REGISTER(context) (context->uc_mcontext.cpu.esp)
# define THREAD_REGISTER(context) (context->uc_mcontext.cpu.ebx) #define THREAD_REGISTER(context) (context->uc_mcontext.cpu.ebx)
# define LINK_REGISTER(context) (context->uc_mcontext.cpu.ecx) #define LINK_REGISTER(context) (context->uc_mcontext.cpu.ecx)
# define FRAME_REGISTER(context) (context->uc_mcontext.cpu.ebp) #define FRAME_REGISTER(context) (context->uc_mcontext.cpu.ebp)
# elif (defined __FreeBSD__) #elif(defined __FreeBSD__)
# define IP_REGISTER(context) (context->uc_mcontext.mc_eip) #define IP_REGISTER(context) (context->uc_mcontext.mc_eip)
# define STACK_REGISTER(context) (context->uc_mcontext.mc_esp) #define STACK_REGISTER(context) (context->uc_mcontext.mc_esp)
# define THREAD_REGISTER(context) (context->uc_mcontext.mc_ebx) #define THREAD_REGISTER(context) (context->uc_mcontext.mc_ebx)
# define LINK_REGISTER(context) (context->uc_mcontext.mc_ecx) #define LINK_REGISTER(context) (context->uc_mcontext.mc_ecx)
# define FRAME_REGISTER(context) (context->uc_mcontext.mc_ebp) #define FRAME_REGISTER(context) (context->uc_mcontext.mc_ebp)
# else #else
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP]) #define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP]) #define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX]) #define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX])
# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_ECX]) #define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_ECX])
# define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP]) #define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
# endif #endif
extern "C" uint64_t extern "C" uint64_t vmNativeCall(void* function,
vmNativeCall(void* function, void* stack, unsigned stackSize, void* stack,
unsigned returnType); unsigned stackSize,
unsigned returnType);
namespace vm { namespace vm {
inline uint64_t inline uint64_t dynamicCall(void* function,
dynamicCall(void* function, uintptr_t* arguments, uint8_t*, uintptr_t* arguments,
unsigned, unsigned argumentsSize, unsigned returnType) uint8_t*,
unsigned,
unsigned argumentsSize,
unsigned returnType)
{ {
return vmNativeCall(function, arguments, argumentsSize, returnType); return vmNativeCall(function, arguments, argumentsSize, returnType);
} }
} // namespace vm } // namespace vm
#elif defined ARCH_x86_64 #elif defined ARCH_x86_64
# ifdef __APPLE__ #ifdef __APPLE__
# define THREAD_STATE x86_THREAD_STATE64 #define THREAD_STATE x86_THREAD_STATE64
# define THREAD_STATE_TYPE x86_thread_state64_t #define THREAD_STATE_TYPE x86_thread_state64_t
# define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT #define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
# define THREAD_STATE_IP(state) ((state).FIELD(rip)) #define THREAD_STATE_IP(state) ((state).FIELD(rip))
# define THREAD_STATE_STACK(state) ((state).FIELD(rsp)) #define THREAD_STATE_STACK(state) ((state).FIELD(rsp))
# define THREAD_STATE_THREAD(state) ((state).FIELD(rbx)) #define THREAD_STATE_THREAD(state) ((state).FIELD(rbx))
# define THREAD_STATE_LINK(state) ((state).FIELD(rcx)) #define THREAD_STATE_LINK(state) ((state).FIELD(rcx))
# define THREAD_STATE_FRAME(state) ((state).FIELD(rbp)) #define THREAD_STATE_FRAME(state) ((state).FIELD(rbp))
# define IP_REGISTER(context) \ #define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss)) #define STACK_REGISTER(context) \
# define STACK_REGISTER(context) \
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss)) THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
# define THREAD_REGISTER(context) \ #define THREAD_REGISTER(context) \
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss)) THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
# define LINK_REGISTER(context) \ #define LINK_REGISTER(context) \
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss)) THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
# define FRAME_REGISTER(context) \ #define FRAME_REGISTER(context) \
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss)) THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
# elif (defined __FreeBSD__) #elif(defined __FreeBSD__)
# define IP_REGISTER(context) (context->uc_mcontext.mc_rip) #define IP_REGISTER(context) (context->uc_mcontext.mc_rip)
# define STACK_REGISTER(context) (context->uc_mcontext.mc_rsp) #define STACK_REGISTER(context) (context->uc_mcontext.mc_rsp)
# define THREAD_REGISTER(context) (context->uc_mcontext.mc_rbx) #define THREAD_REGISTER(context) (context->uc_mcontext.mc_rbx)
# define LINK_REGISTER(context) (context->uc_mcontext.mc_rcx) #define LINK_REGISTER(context) (context->uc_mcontext.mc_rcx)
# define FRAME_REGISTER(context) (context->uc_mcontext.mc_rbp) #define FRAME_REGISTER(context) (context->uc_mcontext.mc_rbp)
# else #else
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP]) #define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP]) #define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX]) #define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_RCX]) #define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_RCX])
# define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP]) #define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP])
# endif #endif
extern "C" uint64_t extern "C" uint64_t
# ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
vmNativeCall(void* function, void* stack, unsigned stackSize, vmNativeCall(void* function,
unsigned returnType); void* stack,
# else unsigned stackSize,
vmNativeCall(void* function, void* stack, unsigned stackSize, unsigned returnType);
void* gprTable, void* sseTable, unsigned returnType); #else
# endif vmNativeCall(void* function,
void* stack,
unsigned stackSize,
void* gprTable,
void* sseTable,
unsigned returnType);
#endif
namespace vm { namespace vm {
# ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
inline uint64_t inline uint64_t dynamicCall(void* function,
dynamicCall(void* function, uint64_t* arguments, UNUSED uint8_t* argumentTypes, uint64_t* arguments,
unsigned argumentCount, unsigned, unsigned returnType) UNUSED uint8_t* argumentTypes,
unsigned argumentCount,
unsigned,
unsigned returnType)
{ {
return vmNativeCall(function, arguments, argumentCount, returnType); return vmNativeCall(function, arguments, argumentCount, returnType);
} }
# else #else
inline uint64_t inline uint64_t dynamicCall(void* function,
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, uintptr_t* arguments,
unsigned argumentCount, unsigned, unsigned returnType) uint8_t* argumentTypes,
unsigned argumentCount,
unsigned,
unsigned returnType)
{ {
const unsigned GprCount = 6; const unsigned GprCount = 6;
uint64_t gprTable[GprCount]; uint64_t gprTable[GprCount];
@ -192,22 +206,24 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
} }
} }
return vmNativeCall(function, stack, stackIndex * BytesPerWord, return vmNativeCall(function,
stack,
stackIndex * BytesPerWord,
(gprIndex ? gprTable : 0), (gprIndex ? gprTable : 0),
(sseIndex ? sseTable : 0), returnType); (sseIndex ? sseTable : 0),
returnType);
} }
#endif #endif
} // namespace vm } // namespace vm
#else #else
# error unsupported architecture #error unsupported architecture
#endif #endif
namespace vm { namespace vm {
inline void inline void trap()
trap()
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
__asm int 3 __asm int 3
@ -216,50 +232,44 @@ trap()
#endif #endif
} }
inline void inline void programOrderMemoryBarrier()
programOrderMemoryBarrier()
{ {
compileTimeMemoryBarrier(); compileTimeMemoryBarrier();
} }
inline void inline void storeStoreMemoryBarrier()
storeStoreMemoryBarrier()
{ {
programOrderMemoryBarrier(); programOrderMemoryBarrier();
} }
inline void inline void storeLoadMemoryBarrier()
storeLoadMemoryBarrier()
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
MemoryBarrier(); MemoryBarrier();
#elif defined ARCH_x86_32 #elif defined ARCH_x86_32
__asm__ __volatile__("lock; addl $0,0(%%esp)": : :"memory"); __asm__ __volatile__("lock; addl $0,0(%%esp)" : : : "memory");
#elif defined ARCH_x86_64 #elif defined ARCH_x86_64
__asm__ __volatile__("mfence": : :"memory"); __asm__ __volatile__("mfence" : : : "memory");
#endif // ARCH_x86_64 #endif // ARCH_x86_64
} }
inline void inline void loadMemoryBarrier()
loadMemoryBarrier()
{ {
programOrderMemoryBarrier(); programOrderMemoryBarrier();
} }
inline void inline void syncInstructionCache(const void*, unsigned)
syncInstructionCache(const void*, unsigned)
{ {
programOrderMemoryBarrier(); programOrderMemoryBarrier();
} }
#ifdef USE_ATOMIC_OPERATIONS #ifdef USE_ATOMIC_OPERATIONS
inline bool inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
return old == InterlockedCompareExchange return old
(reinterpret_cast<LONG*>(p), new_, old); == InterlockedCompareExchange(reinterpret_cast<LONG*>(p), new_, old);
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1) #elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
return __sync_bool_compare_and_swap(p, old, new_); return __sync_bool_compare_and_swap(p, old, new_);
#else #else
uint8_t result; uint8_t result;
@ -275,13 +285,12 @@ atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
#define AVIAN_HAS_CAS64 #define AVIAN_HAS_CAS64
inline bool inline bool atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
return old == InterlockedCompareExchange64 return old == InterlockedCompareExchange64(
(reinterpret_cast<LONGLONG*>(p), new_, old); reinterpret_cast<LONGLONG*>(p), new_, old);
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1) #elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
return __sync_bool_compare_and_swap(p, old, new_); return __sync_bool_compare_and_swap(p, old, new_);
#elif defined ARCH_x86_32 #elif defined ARCH_x86_32
uint8_t result; uint8_t result;
@ -308,17 +317,16 @@ atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
#endif #endif
} }
inline bool inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
{ {
#ifdef ARCH_x86_32 #ifdef ARCH_x86_32
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_); return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
#elif defined ARCH_x86_64 #elif defined ARCH_x86_64
return atomicCompareAndSwap64(reinterpret_cast<uint64_t*>(p), old, new_); return atomicCompareAndSwap64(reinterpret_cast<uint64_t*>(p), old, new_);
#endif // ARCH_x86_64 #endif // ARCH_x86_64
} }
#endif // USE_ATOMIC_OPERATIONS #endif // USE_ATOMIC_OPERATIONS
} // namespace vm } // namespace vm
#endif//X86_H #endif // X86_H

View File

@ -13,11 +13,19 @@
#ifdef inflateInit2 #ifdef inflateInit2
#undef inflateInit2 #undef inflateInit2
#define inflateInit2(strm, windowBits) \ #define inflateInit2(strm, windowBits) \
inflateInit2_((strm), (windowBits), ZLIB_VERSION, static_cast<int>(sizeof(z_stream))) inflateInit2_( \
(strm), (windowBits), ZLIB_VERSION, static_cast<int>(sizeof(z_stream)))
#endif #endif
#ifdef deflateInit2 #ifdef deflateInit2
#undef deflateInit2 #undef deflateInit2
#define deflateInit2(strm, level, windowBits) \ #define deflateInit2(strm, level, windowBits) \
deflateInit2_((strm), (level), Z_DEFLATED, (windowBits), 8, Z_DEFAULT_STRATEGY, ZLIB_VERSION, static_cast<int>(sizeof(z_stream))) deflateInit2_((strm), \
(level), \
Z_DEFLATED, \
(windowBits), \
8, \
Z_DEFAULT_STRATEGY, \
ZLIB_VERSION, \
static_cast<int>(sizeof(z_stream)))
#endif #endif

View File

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

View File

@ -12,26 +12,23 @@
#ifdef BOOT_JAVAHOME #ifdef BOOT_JAVAHOME
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) #if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
# define SYMBOL(x) binary_javahome_jar_##x #define SYMBOL(x) binary_javahome_jar_##x
#else #else
# define SYMBOL(x) _binary_javahome_jar_##x #define SYMBOL(x) _binary_javahome_jar_##x
#endif #endif
extern "C" { extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[];
extern const uint8_t SYMBOL(start)[]; AVIAN_EXPORT const uint8_t* javahomeJar(unsigned* size)
extern const uint8_t SYMBOL(end)[]; {
*size = SYMBOL(end) - SYMBOL(start);
AVIAN_EXPORT const uint8_t* return SYMBOL(start);
javahomeJar(unsigned* size) }
{
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
}
} }
#undef SYMBOL #undef SYMBOL
#endif//BOOT_JAVAHOME #endif // BOOT_JAVAHOME

View File

@ -14,68 +14,64 @@
// since we aren't linking against libstdc++, we must implement this // since we aren't linking against libstdc++, we must implement this
// ourselves: // ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); } extern "C" void __cxa_pure_virtual(void)
{
abort();
}
#ifdef BOOT_IMAGE #ifdef BOOT_IMAGE
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) #if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
# define BOOTIMAGE_SYMBOL(x) binary_bootimage_bin_##x #define BOOTIMAGE_SYMBOL(x) binary_bootimage_bin_##x
# define CODEIMAGE_SYMBOL(x) binary_codeimage_bin_##x #define CODEIMAGE_SYMBOL(x) binary_codeimage_bin_##x
#else #else
# define BOOTIMAGE_SYMBOL(x) _binary_bootimage_bin_##x #define BOOTIMAGE_SYMBOL(x) _binary_bootimage_bin_##x
# define CODEIMAGE_SYMBOL(x) _binary_codeimage_bin_##x #define CODEIMAGE_SYMBOL(x) _binary_codeimage_bin_##x
#endif #endif
extern "C" { extern "C" {
extern const uint8_t BOOTIMAGE_SYMBOL(start)[];
extern const uint8_t BOOTIMAGE_SYMBOL(end)[];
extern const uint8_t BOOTIMAGE_SYMBOL(start)[]; AVIAN_EXPORT const uint8_t* bootimageBin(unsigned* size)
extern const uint8_t BOOTIMAGE_SYMBOL(end)[]; {
*size = BOOTIMAGE_SYMBOL(end) - BOOTIMAGE_SYMBOL(start);
return BOOTIMAGE_SYMBOL(start);
}
AVIAN_EXPORT const uint8_t* extern const uint8_t CODEIMAGE_SYMBOL(start)[];
bootimageBin(unsigned* size) extern const uint8_t CODEIMAGE_SYMBOL(end)[];
{
*size = BOOTIMAGE_SYMBOL(end) - BOOTIMAGE_SYMBOL(start);
return BOOTIMAGE_SYMBOL(start);
}
extern const uint8_t CODEIMAGE_SYMBOL(start)[];
extern const uint8_t CODEIMAGE_SYMBOL(end)[];
AVIAN_EXPORT const uint8_t*
codeimageBin(unsigned* size)
{
*size = CODEIMAGE_SYMBOL(end) - CODEIMAGE_SYMBOL(start);
return CODEIMAGE_SYMBOL(start);
}
AVIAN_EXPORT const uint8_t* codeimageBin(unsigned* size)
{
*size = CODEIMAGE_SYMBOL(end) - CODEIMAGE_SYMBOL(start);
return CODEIMAGE_SYMBOL(start);
}
} }
#undef SYMBOL #undef SYMBOL
#endif//BOOT_IMAGE #endif // BOOT_IMAGE
#ifdef BOOT_CLASSPATH #ifdef BOOT_CLASSPATH
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) #if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
# define SYMBOL(x) binary_classpath_jar_##x #define SYMBOL(x) binary_classpath_jar_##x
#else #else
# define SYMBOL(x) _binary_classpath_jar_##x #define SYMBOL(x) _binary_classpath_jar_##x
#endif #endif
extern "C" { extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[];
extern const uint8_t SYMBOL(start)[]; AVIAN_EXPORT const uint8_t* classpathJar(unsigned* size)
extern const uint8_t SYMBOL(end)[]; {
*size = SYMBOL(end) - SYMBOL(start);
AVIAN_EXPORT const uint8_t* return SYMBOL(start);
classpathJar(unsigned* size) }
{
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
}
} }
#undef SYMBOL #undef SYMBOL
#endif//BOOT_CLASSPATH #endif // BOOT_CLASSPATH

View File

@ -1,6 +1,6 @@
#ifndef FIELD #ifndef FIELD
# define FIELD(name) #define FIELD(name)
# define FIELD_DEFINED #define FIELD_DEFINED
#endif #endif
FIELD(magic) FIELD(magic)
@ -23,13 +23,13 @@ FIELD(methodTreeSentinal)
FIELD(virtualThunks) FIELD(virtualThunks)
#ifdef FIELD_DEFINED #ifdef FIELD_DEFINED
# undef FIELD #undef FIELD
# undef FIELD_DEFINED #undef FIELD_DEFINED
#endif #endif
#ifndef THUNK_FIELD #ifndef THUNK_FIELD
# define THUNK_FIELD(name) #define THUNK_FIELD(name)
# define THUNK_FIELD_DEFINED #define THUNK_FIELD_DEFINED
#endif #endif
THUNK_FIELD(default_); THUNK_FIELD(default_);
@ -40,6 +40,6 @@ THUNK_FIELD(stackOverflow);
THUNK_FIELD(table); THUNK_FIELD(table);
#ifdef THUNK_FIELD_DEFINED #ifdef THUNK_FIELD_DEFINED
# undef THUNK_FIELD #undef THUNK_FIELD
# undef THUNK_FIELD_DEFINED #undef THUNK_FIELD_DEFINED
#endif #endif

View File

@ -1,26 +1,25 @@
const unsigned NAME(BootMask) = (~static_cast<unsigned>(0)) const unsigned NAME(BootMask) = (~static_cast<unsigned>(0))
/ NAME(BytesPerWord); / NAME(BytesPerWord);
const unsigned NAME(BootShift) = 32 - avian::util::log(NAME(BytesPerWord)); const unsigned NAME(BootShift) = 32 - avian::util::log(NAME(BytesPerWord));
const unsigned NAME(BootFlatConstant) = 1 << NAME(BootShift); const unsigned NAME(BootFlatConstant) = 1 << NAME(BootShift);
const unsigned NAME(BootHeapOffset) = 1 << (NAME(BootShift) + 1); const unsigned NAME(BootHeapOffset) = 1 << (NAME(BootShift) + 1);
inline unsigned inline unsigned LABEL(codeMapSize)(unsigned codeSize)
LABEL(codeMapSize)(unsigned codeSize)
{ {
return avian::util::ceilingDivide(codeSize, TargetBitsPerWord) * TargetBytesPerWord; return avian::util::ceilingDivide(codeSize, TargetBitsPerWord)
* TargetBytesPerWord;
} }
inline unsigned inline unsigned LABEL(heapMapSize)(unsigned heapSize)
LABEL(heapMapSize)(unsigned heapSize)
{ {
return avian::util::ceilingDivide(heapSize, TargetBitsPerWord * TargetBytesPerWord) return avian::util::ceilingDivide(heapSize,
* TargetBytesPerWord; TargetBitsPerWord * TargetBytesPerWord)
* TargetBytesPerWord;
} }
inline object inline object LABEL(bootObject)(LABEL(uintptr_t) * heap, unsigned offset)
LABEL(bootObject)(LABEL(uintptr_t)* heap, unsigned offset)
{ {
if (offset) { if (offset) {
return reinterpret_cast<object>(heap + offset - 1); return reinterpret_cast<object>(heap + offset - 1);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -53,18 +53,22 @@ Context::Context(vm::System* system,
- regFile->generalRegisters.start), - regFile->generalRegisters.start),
targetInfo(arch->targetInfo()) targetInfo(arch->targetInfo())
{ {
for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) { for (unsigned i = regFile->generalRegisters.start;
i < regFile->generalRegisters.limit;
++i) {
new (registerResources + i) RegisterResource(arch->reserved(i)); new (registerResources + i) RegisterResource(arch->reserved(i));
if (registerResources[i].reserved) { if (registerResources[i].reserved) {
-- availableGeneralRegisterCount; --availableGeneralRegisterCount;
} }
} }
for (unsigned i = regFile->floatRegisters.start; i < regFile->floatRegisters.limit; ++i) { for (unsigned i = regFile->floatRegisters.start;
i < regFile->floatRegisters.limit;
++i) {
new (registerResources + i) RegisterResource(arch->reserved(i)); new (registerResources + i) RegisterResource(arch->reserved(i));
} }
} }
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian

View File

@ -37,8 +37,9 @@ class ConstantPoolNode;
class ForkState; class ForkState;
class Block; class Block;
template<class T> template <class T>
List<T>* reverseDestroy(List<T>* cell) { List<T>* reverseDestroy(List<T>* cell)
{
List<T>* previous = 0; List<T>* previous = 0;
while (cell) { while (cell) {
List<T>* next = cell->next; List<T>* next = cell->next;
@ -73,7 +74,7 @@ class LogicalCode {
= logicalCode.cloneAndSet(zone, logicalCode.count + more, 0); = logicalCode.cloneAndSet(zone, logicalCode.count + more, 0);
for (size_t i = 0; i < logicalCode.count; i++) { 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; logicalCode = newCode;
@ -93,7 +94,9 @@ class LogicalCode {
class Context { class Context {
public: public:
Context(vm::System* system, Assembler* assembler, vm::Zone* zone, Context(vm::System* system,
Assembler* assembler,
vm::Zone* zone,
Compiler::Client* client); Compiler::Client* client);
vm::System* system; vm::System* system;
@ -128,17 +131,19 @@ class Context {
ir::TargetInfo targetInfo; ir::TargetInfo targetInfo;
}; };
inline Aborter* getAborter(Context* c) { inline Aborter* getAborter(Context* c)
{
return c->system; return c->system;
} }
template<class T> template <class T>
List<T>* cons(Context* c, const T& value, List<T>* next) { List<T>* cons(Context* c, const T& value, List<T>* next)
{
return new (c->zone) List<T>(value, next); return new (c->zone) List<T>(value, next);
} }
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_CONTEXT_H #endif // AVIAN_CODEGEN_COMPILER_CONTEXT_H

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -19,14 +19,15 @@ namespace avian {
namespace codegen { namespace codegen {
namespace compiler { namespace compiler {
unsigned totalFrameSize(Context* c) { unsigned totalFrameSize(Context* c)
return c->alignedFrameSize {
+ c->arch->frameHeaderSize() return c->alignedFrameSize + c->arch->frameHeaderSize()
+ c->arch->argumentFootprint(c->parameterFootprint); + c->arch->argumentFootprint(c->parameterFootprint);
} }
int frameIndex(Context* c, int localIndex) { int frameIndex(Context* c, int localIndex)
assert(c, localIndex >= 0); {
assertT(c, localIndex >= 0);
int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1; int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1;
@ -36,66 +37,75 @@ int frameIndex(Context* c, int localIndex) {
index -= c->arch->frameFooterSize(); index -= c->arch->frameFooterSize();
} }
assert(c, index >= 0); assertT(c, index >= 0);
assert(c, static_cast<unsigned>(index) < totalFrameSize(c)); assertT(c, static_cast<unsigned>(index) < totalFrameSize(c));
return index; return index;
} }
unsigned frameIndexToOffset(Context* c, unsigned frameIndex) { unsigned frameIndexToOffset(Context* c, unsigned frameIndex)
assert(c, frameIndex < totalFrameSize(c)); {
assertT(c, frameIndex < totalFrameSize(c));
return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize; return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize;
} }
unsigned offsetToFrameIndex(Context* c, unsigned offset) { unsigned offsetToFrameIndex(Context* c, unsigned offset)
assert(c, {
static_cast<int>((offset / c->targetInfo.pointerSize) assertT(c,
- c->arch->frameFooterSize()) >= 0); static_cast<int>((offset / c->targetInfo.pointerSize)
assert(c, - c->arch->frameFooterSize()) >= 0);
((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize()) assertT(c,
< totalFrameSize(c)); ((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize())
< totalFrameSize(c));
return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize(); return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize();
} }
unsigned frameBase(Context* c) { unsigned frameBase(Context* c)
return c->alignedFrameSize {
- c->arch->frameReturnAddressSize() return c->alignedFrameSize - c->arch->frameReturnAddressSize()
- c->arch->frameFooterSize() - c->arch->frameFooterSize() + c->arch->frameHeaderSize();
+ c->arch->frameHeaderSize();
} }
FrameIterator::Element::Element(Value* value, unsigned localIndex): FrameIterator::Element::Element(Value* value, unsigned localIndex)
value(value), localIndex(localIndex) : value(value), localIndex(localIndex)
{ } {
}
int FrameIterator::Element::frameIndex(Context* c)
int FrameIterator::Element::frameIndex(Context* c) { {
return compiler::frameIndex(c, this->localIndex); return compiler::frameIndex(c, this->localIndex);
} }
FrameIterator::FrameIterator(Context* c, Stack* stack, Local* locals, FrameIterator::FrameIterator(Context* c,
bool includeEmpty): Stack* stack,
stack(stack), locals(locals), localIndex(c->localFootprint - 1), Local* locals,
includeEmpty(includeEmpty) bool includeEmpty)
{ } : stack(stack),
locals(locals),
localIndex(c->localFootprint - 1),
includeEmpty(includeEmpty)
{
}
bool FrameIterator::hasMore() { bool FrameIterator::hasMore()
{
if (not includeEmpty) { if (not includeEmpty) {
while (stack and stack->value == 0) { while (stack and stack->value == 0) {
stack = stack->next; stack = stack->next;
} }
while (localIndex >= 0 and locals[localIndex].value == 0) { while (localIndex >= 0 and locals[localIndex].value == 0) {
-- localIndex; --localIndex;
} }
} }
return stack != 0 or localIndex >= 0; return stack != 0 or localIndex >= 0;
} }
FrameIterator::Element FrameIterator::next(Context* c) { FrameIterator::Element FrameIterator::next(Context* c)
{
Value* v; Value* v;
unsigned li; unsigned li;
if (stack) { if (stack) {
@ -107,17 +117,16 @@ FrameIterator::Element FrameIterator::next(Context* c) {
Local* l = locals + localIndex; Local* l = locals + localIndex;
v = l->value; v = l->value;
li = localIndex; li = localIndex;
-- localIndex; --localIndex;
} }
return Element(v, li); return Element(v, li);
} }
Stack* stack(Context* c, Value* value, Stack* next) { Stack* stack(Context* c, Value* value, Stack* next)
return new(c->zone) Stack(next ? next->index + 1 : 0, value, next); {
return new (c->zone) Stack(next ? next->index + 1 : 0, value, next);
} }
} // namespace compiler
} // namespace codegen
} // namespace compiler } // namespace avian
} // namespace codegen
} // namespace avian

View File

@ -37,7 +37,9 @@ class FrameIterator {
const unsigned localIndex; const unsigned localIndex;
}; };
FrameIterator(Context* c, Stack* stack, Local* locals, FrameIterator(Context* c,
Stack* stack,
Local* locals,
bool includeEmpty = false); bool includeEmpty = false);
bool hasMore(); bool hasMore();
@ -57,9 +59,10 @@ class Local {
class Stack { class Stack {
public: public:
Stack(unsigned index, Value* value, Stack* next): Stack(unsigned index, Value* value, Stack* next)
index(index), value(value), next(next) : index(index), value(value), next(next)
{ } {
}
unsigned index; unsigned index;
Value* value; Value* value;
@ -68,8 +71,8 @@ class Stack {
Stack* stack(Context* c, Value* value, Stack* next); Stack* stack(Context* c, Value* value, Stack* next);
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_FRAME_H #endif // AVIAN_CODEGEN_COMPILER_FRAME_H

View File

@ -23,31 +23,35 @@ LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals)
locals(locals), locals(locals),
machineOffset(0), machineOffset(0),
/*subroutine(0), */ index(index) /*subroutine(0), */ index(index)
{ } {
}
LogicalInstruction* LogicalInstruction::next(Context* c) { LogicalInstruction* LogicalInstruction::next(Context* c)
{
LogicalInstruction* i = this; LogicalInstruction* i = this;
for (size_t n = i->index + 1; n < c->logicalCode.count(); ++n) { for (size_t n = i->index + 1; n < c->logicalCode.count(); ++n) {
i = c->logicalCode[n]; i = c->logicalCode[n];
if (i) return i; if (i)
return i;
} }
return 0; return 0;
} }
unsigned unsigned machineOffset(Context* c, int logicalIp)
machineOffset(Context* c, int logicalIp)
{ {
return c->logicalCode[logicalIp]->machineOffset->value(); return c->logicalCode[logicalIp]->machineOffset->value();
} }
Block::Block(Event* head): Block::Block(Event* head)
head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0) : head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
{ } {
Block* block(Context* c, Event* head) {
return new(c->zone) Block(head);
} }
} // namespace compiler Block* block(Context* c, Event* head)
} // namespace codegen {
} // namespace avian return new (c->zone) Block(head);
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -24,17 +24,21 @@ class ForkElement {
bool local; bool local;
}; };
class ForkState: public Compiler::State { class ForkState : public Compiler::State {
public: public:
ForkState(Stack* stack, Local* locals, List<Value*>* saved, Event* predecessor, ForkState(Stack* stack,
unsigned logicalIp): Local* locals,
stack(stack), List<Value*>* saved,
locals(locals), Event* predecessor,
saved(saved), unsigned logicalIp)
predecessor(predecessor), : stack(stack),
logicalIp(logicalIp), locals(locals),
readCount(0) saved(saved),
{ } predecessor(predecessor),
logicalIp(logicalIp),
readCount(0)
{
}
Stack* stack; Stack* stack;
Local* locals; Local* locals;
@ -75,8 +79,8 @@ Block* block(Context* c, Event* head);
unsigned machineOffset(Context* c, int logicalIp); unsigned machineOffset(Context* c, int logicalIp);
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_IR_H #endif // AVIAN_CODEGEN_COMPILER_IR_H

View File

@ -18,15 +18,18 @@ namespace avian {
namespace codegen { namespace codegen {
namespace compiler { namespace compiler {
CodePromise::CodePromise(Context* c, CodePromise* next): CodePromise::CodePromise(Context* c, CodePromise* next)
c(c), offset(0), next(next) : c(c), offset(0), next(next)
{ } {
}
CodePromise::CodePromise(Context* c, Promise* offset): CodePromise::CodePromise(Context* c, Promise* offset)
c(c), offset(offset), next(0) : c(c), offset(offset), next(0)
{ } {
}
int64_t CodePromise::value() { int64_t CodePromise::value()
{
if (resolved()) { if (resolved()) {
return reinterpret_cast<intptr_t>(c->machineCode + offset->value()); return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
} }
@ -34,61 +37,73 @@ int64_t CodePromise::value() {
abort(c); abort(c);
} }
bool CodePromise::resolved() { bool CodePromise::resolved()
{
return c->machineCode != 0 and offset and offset->resolved(); return c->machineCode != 0 and offset and offset->resolved();
} }
CodePromise* codePromise(Context* c, Promise* offset) { CodePromise* codePromise(Context* c, Promise* offset)
{
return new (c->zone) CodePromise(c, offset); return new (c->zone) CodePromise(c, offset);
} }
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { Promise* shiftMaskPromise(Context* c,
Promise* base,
unsigned shift,
int64_t mask)
{
return new (c->zone) ShiftMaskPromise(base, shift, mask); return new (c->zone) ShiftMaskPromise(base, shift, mask);
} }
Promise* combinedPromise(Context* c, Promise* low, Promise* high) { Promise* combinedPromise(Context* c, Promise* low, Promise* high)
{
return new (c->zone) CombinedPromise(low, high); return new (c->zone) CombinedPromise(low, high);
} }
Promise* resolvedPromise(Context* c, int64_t value) { Promise* resolvedPromise(Context* c, int64_t value)
{
return new (c->zone) ResolvedPromise(value); return new (c->zone) ResolvedPromise(value);
} }
class IpPromise: public Promise { class IpPromise : public Promise {
public: public:
IpPromise(Context* c, int logicalIp): IpPromise(Context* c, int logicalIp) : c(c), logicalIp(logicalIp)
c(c), {
logicalIp(logicalIp) }
{ }
virtual int64_t value() { virtual int64_t value()
{
if (resolved()) { if (resolved()) {
return reinterpret_cast<intptr_t> return reinterpret_cast<intptr_t>(c->machineCode
(c->machineCode + machineOffset(c, logicalIp)); + machineOffset(c, logicalIp));
} }
abort(c); abort(c);
} }
virtual bool resolved() { virtual bool resolved()
{
return c->machineCode != 0 return c->machineCode != 0
and c->logicalCode[logicalIp]->machineOffset->resolved(); and c->logicalCode[logicalIp]->machineOffset->resolved();
} }
Context* c; Context* c;
int logicalIp; int logicalIp;
}; };
Promise* ipPromise(Context* c, int logicalIp) { Promise* ipPromise(Context* c, int logicalIp)
{
return new (c->zone) IpPromise(c, logicalIp); return new (c->zone) IpPromise(c, logicalIp);
} }
class PoolPromise : public Promise {
class PoolPromise: public Promise {
public: public:
PoolPromise(Context* c, int key): c(c), key(key) { } PoolPromise(Context* c, int key) : c(c), key(key)
{
}
virtual int64_t value() { virtual int64_t value()
{
if (resolved()) { if (resolved()) {
return reinterpret_cast<int64_t>( return reinterpret_cast<int64_t>(
c->machineCode c->machineCode
@ -99,7 +114,8 @@ class PoolPromise: public Promise {
abort(c); abort(c);
} }
virtual bool resolved() { virtual bool resolved()
{
return c->machineCode != 0; return c->machineCode != 0;
} }
@ -107,11 +123,11 @@ class PoolPromise: public Promise {
int key; int key;
}; };
Promise* poolPromise(Context* c, int key) { Promise* poolPromise(Context* c, int key)
return new(c->zone) PoolPromise(c, key); {
return new (c->zone) PoolPromise(c, key);
} }
} // namespace compiler
} // namespace compiler } // namespace codegen
} // namespace codegen } // namespace avian
} // namespace avian

View File

@ -15,8 +15,7 @@ namespace avian {
namespace codegen { namespace codegen {
namespace compiler { namespace compiler {
class CodePromise : public Promise {
class CodePromise: public Promise {
public: public:
CodePromise(Context* c, CodePromise* next); CodePromise(Context* c, CodePromise* next);
@ -33,7 +32,10 @@ class CodePromise: public Promise {
CodePromise* codePromise(Context* c, Promise* offset); CodePromise* codePromise(Context* c, Promise* offset);
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask); Promise* shiftMaskPromise(Context* c,
Promise* base,
unsigned shift,
int64_t mask);
Promise* combinedPromise(Context* c, Promise* low, Promise* high); Promise* combinedPromise(Context* c, Promise* low, Promise* high);
@ -43,8 +45,8 @@ Promise* ipPromise(Context* c, int logicalIp);
Promise* poolPromise(Context* c, int key); Promise* poolPromise(Context* c, int key);
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_PROMISE_H #endif // AVIAN_CODEGEN_COMPILER_PROMISE_H

View File

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

View File

@ -22,13 +22,16 @@ class Event;
class Read { class Read {
public: public:
Read(): Read() : value(0), event(0), eventNext(0)
value(0), event(0), eventNext(0) {
{ } }
virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0; virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0;
virtual Value* high(Context* c) { abort(c); } virtual Value* high(Context* c)
{
abort(c);
}
virtual Value* successor() = 0; virtual Value* successor() = 0;
@ -43,11 +46,12 @@ class Read {
Read* eventNext; Read* eventNext;
}; };
inline bool valid(Read* r) { inline bool valid(Read* r)
{
return r and r->valid(); return r and r->valid();
} }
class SingleRead: public Read { class SingleRead : public Read {
public: public:
SingleRead(const SiteMask& mask, Value* successor); SingleRead(const SiteMask& mask, Value* successor);
@ -69,8 +73,7 @@ class SingleRead: public Read {
Value* successor_; Value* successor_;
}; };
class MultiRead : public Read {
class MultiRead: public Read {
public: public:
MultiRead(); MultiRead();
@ -95,7 +98,7 @@ class MultiRead: public Read {
bool visited; bool visited;
}; };
class StubRead: public Read { class StubRead : public Read {
public: public:
StubRead(); StubRead();
@ -117,9 +120,8 @@ class StubRead: public Read {
SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0); SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0);
} // namespace compiler
} // namespace codegen
} // namespace avian
} // namespace compiler #endif // AVIAN_CODEGEN_COMPILER_READ_H
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_READ_H

View File

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

View File

@ -20,7 +20,7 @@ namespace avian {
namespace util { namespace util {
class Aborter; class Aborter;
} // namespace util } // namespace util
namespace codegen { namespace codegen {
namespace compiler { namespace compiler {
@ -33,14 +33,12 @@ class SiteMask;
class Resource; class Resource;
class Read; class Read;
class RegisterAllocator { class RegisterAllocator {
public: public:
Aborter* a; Aborter* a;
const RegisterFile* registerFile; const RegisterFile* registerFile;
RegisterAllocator(Aborter* a, const RegisterFile* registerFile); RegisterAllocator(Aborter* a, const RegisterFile* registerFile);
}; };
class Target { class Target {
@ -53,11 +51,14 @@ class Target {
static const unsigned LowRegisterPenalty = 10; static const unsigned LowRegisterPenalty = 10;
static const unsigned Impossible = 20; static const unsigned Impossible = 20;
Target(): cost(Impossible) { } Target() : cost(Impossible)
{
}
Target(int index, lir::OperandType type, unsigned cost): Target(int index, lir::OperandType type, unsigned cost)
index(index), type(type), cost(cost) : index(index), type(type), cost(cost)
{ } {
}
int16_t index; int16_t index;
lir::OperandType type; lir::OperandType type;
@ -69,43 +70,55 @@ class CostCalculator {
virtual unsigned cost(Context* c, SiteMask mask) = 0; virtual unsigned cost(Context* c, SiteMask mask) = 0;
}; };
unsigned unsigned resourceCost(Context* c,
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask, Value* v,
CostCalculator* costCalculator); Resource* r,
SiteMask mask,
CostCalculator* costCalculator);
bool pickRegisterTarget(Context* c,
int i,
Value* v,
uint32_t mask,
int* target,
unsigned* cost,
CostCalculator* costCalculator = 0);
bool int pickRegisterTarget(Context* c,
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target, Value* v,
unsigned* cost, CostCalculator* costCalculator = 0); uint32_t mask,
unsigned* cost,
CostCalculator* costCalculator = 0);
int Target pickRegisterTarget(Context* c,
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost, Value* v,
CostCalculator* costCalculator = 0); uint32_t mask,
CostCalculator* costCalculator = 0);
Target unsigned frameCost(Context* c,
pickRegisterTarget(Context* c, Value* v, uint32_t mask, Value* v,
CostCalculator* costCalculator = 0); int frameIndex,
CostCalculator* costCalculator);
unsigned Target pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator);
Target Target pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
Target Target pickTarget(Context* c,
pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator); Value* value,
const SiteMask& mask,
unsigned registerPenalty,
Target best,
CostCalculator* costCalculator);
Target Target pickTarget(Context* c,
pickTarget(Context* c, Value* value, const SiteMask& mask, Read* read,
unsigned registerPenalty, Target best, bool intersectRead,
CostCalculator* costCalculator); unsigned registerReserveCount,
CostCalculator* costCalculator);
Target } // namespace regalloc
pickTarget(Context* c, Read* read, bool intersectRead, } // namespace codegen
unsigned registerReserveCount, CostCalculator* costCalculator); } // namespace avian
} // namespace regalloc #endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H

View File

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

View File

@ -38,7 +38,7 @@ class Resource {
bool reserved; bool reserved;
}; };
class RegisterResource: public Resource { class RegisterResource : public Resource {
public: public:
RegisterResource(bool reserved); RegisterResource(bool reserved);
@ -55,7 +55,7 @@ class RegisterResource: public Resource {
void decrement(Context*); void decrement(Context*);
}; };
class FrameResource: public Resource { class FrameResource : public Resource {
public: public:
virtual void freeze(Context*, Value*); virtual void freeze(Context*, Value*);
@ -70,8 +70,8 @@ void acquire(Context* c, Resource* resource, Value* value, Site* site);
void release(Context* c, Resource* resource, Value* value, Site* site); void release(Context* c, Resource* resource, Value* value, Site* site);
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_RESOURCE_H #endif // AVIAN_CODEGEN_COMPILER_RESOURCE_H

View File

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

View File

@ -30,23 +30,29 @@ const unsigned CopyPenalty = 10;
class SiteMask { class SiteMask {
public: public:
SiteMask(): typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex) { } SiteMask() : typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex)
{
}
SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex): SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex)
typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex) : typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex)
{ } {
}
SiteMask intersectionWith(const SiteMask& b); SiteMask intersectionWith(const SiteMask& b);
static SiteMask fixedRegisterMask(int number) { static SiteMask fixedRegisterMask(int number)
{
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex); return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
} }
static SiteMask lowPart(const OperandMask& mask) { static SiteMask lowPart(const OperandMask& mask)
{
return SiteMask(mask.typeMask, mask.registerMask, AnyFrameIndex); return SiteMask(mask.typeMask, mask.registerMask, AnyFrameIndex);
} }
static SiteMask highPart(const OperandMask& mask) { static SiteMask highPart(const OperandMask& mask)
{
return SiteMask(mask.typeMask, mask.registerMask >> 32, AnyFrameIndex); return SiteMask(mask.typeMask, mask.registerMask >> 32, AnyFrameIndex);
} }
@ -57,9 +63,14 @@ class SiteMask {
class Site { class Site {
public: public:
Site(): next(0) { } Site() : next(0)
{
}
virtual Site* readTarget(Context*, Read*) { return this; } virtual Site* readTarget(Context*, Read*)
{
return this;
}
virtual unsigned toString(Context*, char*, unsigned) = 0; virtual unsigned toString(Context*, char*, unsigned) = 0;
@ -71,15 +82,26 @@ class Site {
virtual bool matchNextWord(Context*, Site*, unsigned) = 0; virtual bool matchNextWord(Context*, Site*, unsigned) = 0;
virtual void acquire(Context*, Value*) { } virtual void acquire(Context*, Value*)
{
}
virtual void release(Context*, Value*) { } virtual void release(Context*, Value*)
{
}
virtual void freeze(Context*, Value*) { } virtual void freeze(Context*, Value*)
{
}
virtual void thaw(Context*, Value*) { } virtual void thaw(Context*, Value*)
{
}
virtual bool frozen(Context*) { return false; } virtual bool frozen(Context*)
{
return false;
}
virtual lir::OperandType type(Context*) = 0; virtual lir::OperandType type(Context*) = 0;
@ -99,16 +121,24 @@ class Site {
virtual unsigned registerSize(Context*); virtual unsigned registerSize(Context*);
virtual unsigned registerMask(Context*) { return 0; } virtual unsigned registerMask(Context*)
{
return 0;
}
virtual bool isVolatile(Context*) { return false; } virtual bool isVolatile(Context*)
{
return false;
}
Site* next; Site* next;
}; };
class SiteIterator { class SiteIterator {
public: public:
SiteIterator(Context* c, Value* v, bool includeBuddies = true, SiteIterator(Context* c,
Value* v,
bool includeBuddies = true,
bool includeNextWord = true); bool includeNextWord = true);
Site** findNext(Site** p); Site** findNext(Site** p);
@ -130,43 +160,52 @@ Site* constantSite(Context* c, Promise* value);
Site* constantSite(Context* c, int64_t value); Site* constantSite(Context* c, int64_t value);
Promise* combinedPromise(Context* c, Promise* low, Promise* high); Promise* combinedPromise(Context* c, Promise* low, Promise* high);
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask); Promise* shiftMaskPromise(Context* c,
Promise* base,
unsigned shift,
int64_t mask);
class ConstantSite: public Site { class ConstantSite : public Site {
public: public:
ConstantSite(Promise* value): value(value) { } ConstantSite(Promise* value) : value(value)
{
}
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { virtual unsigned toString(Context*, char* buffer, unsigned bufferSize)
{
if (value->resolved()) { if (value->resolved()) {
return vm::snprintf return vm::snprintf(buffer, bufferSize, "constant %" LLD, value->value());
(buffer, bufferSize, "constant %" LLD, value->value());
} else { } else {
return vm::snprintf(buffer, bufferSize, "constant unresolved"); return vm::snprintf(buffer, bufferSize, "constant unresolved");
} }
} }
virtual unsigned copyCost(Context*, Site* s) { virtual unsigned copyCost(Context*, Site* s)
{
return (s == this ? 0 : ConstantCopyCost); return (s == this ? 0 : ConstantCopyCost);
} }
virtual bool match(Context*, const SiteMask& mask) { virtual bool match(Context*, const SiteMask& mask)
{
return mask.typeMask & (1 << lir::ConstantOperand); return mask.typeMask & (1 << lir::ConstantOperand);
} }
virtual bool loneMatch(Context*, const SiteMask&) { virtual bool loneMatch(Context*, const SiteMask&)
{
return true; return true;
} }
virtual bool matchNextWord(Context* c, Site* s, unsigned) { virtual bool matchNextWord(Context* c, Site* s, unsigned)
{
return s->type(c) == lir::ConstantOperand; return s->type(c) == lir::ConstantOperand;
} }
virtual lir::OperandType type(Context*) { virtual lir::OperandType type(Context*)
{
return lir::ConstantOperand; return lir::ConstantOperand;
} }
virtual void asAssemblerOperand(Context* c, Site* high, virtual void asAssemblerOperand(Context* c, Site* high, lir::Operand* result)
lir::Operand* result)
{ {
Promise* v = value; Promise* v = value;
if (high != this) { if (high != this) {
@ -175,27 +214,33 @@ class ConstantSite: public Site {
new (result) lir::Constant(v); new (result) lir::Constant(v);
} }
virtual Site* copy(Context* c) { virtual Site* copy(Context* c)
{
return constantSite(c, value); return constantSite(c, value);
} }
virtual Site* copyLow(Context* c) { virtual Site* copyLow(Context* c)
{
return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF)); return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF));
} }
virtual Site* copyHigh(Context* c) { virtual Site* copyHigh(Context* c)
{
return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF)); return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF));
} }
virtual Site* makeNextWord(Context* c, unsigned) { virtual Site* makeNextWord(Context* c, unsigned)
{
abort(c); abort(c);
} }
virtual SiteMask mask(Context*) { virtual SiteMask mask(Context*)
{
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex); return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
} }
virtual SiteMask nextWordMask(Context*, unsigned) { virtual SiteMask nextWordMask(Context*, unsigned)
{
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex); return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
} }
@ -204,7 +249,7 @@ class ConstantSite: public Site {
Site* addressSite(Context* c, Promise* address); Site* addressSite(Context* c, Promise* address);
class RegisterSite: public Site { class RegisterSite : public Site {
public: public:
RegisterSite(uint32_t mask, int number); RegisterSite(uint32_t mask, int number);
@ -230,7 +275,8 @@ class RegisterSite: public Site {
virtual lir::OperandType type(Context*); virtual lir::OperandType type(Context*);
virtual void asAssemblerOperand(Context* c UNUSED, Site* high, virtual void asAssemblerOperand(Context* c UNUSED,
Site* high,
lir::Operand* result); lir::Operand* result);
virtual Site* copy(Context* c); virtual Site* copy(Context* c);
@ -256,8 +302,7 @@ class RegisterSite: public Site {
Site* registerSite(Context* c, int number); Site* registerSite(Context* c, int number);
Site* freeRegisterSite(Context* c, uint32_t mask); Site* freeRegisterSite(Context* c, uint32_t mask);
class MemorySite : public Site {
class MemorySite: public Site {
public: public:
MemorySite(int base, int offset, int index, unsigned scale); MemorySite(int base, int offset, int index, unsigned scale);
@ -285,7 +330,8 @@ class MemorySite: public Site {
virtual lir::OperandType type(Context*); virtual lir::OperandType type(Context*);
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, virtual void asAssemblerOperand(Context* c UNUSED,
Site* high UNUSED,
lir::Operand* result); lir::Operand* result);
virtual Site* copy(Context* c); virtual Site* copy(Context* c);
@ -311,11 +357,15 @@ class MemorySite: public Site {
unsigned scale; unsigned scale;
}; };
MemorySite* memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, unsigned scale = 1); MemorySite* memorySite(Context* c,
int base,
int offset = 0,
int index = lir::NoRegister,
unsigned scale = 1);
MemorySite* frameSite(Context* c, int frameIndex); MemorySite* frameSite(Context* c, int frameIndex);
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_SITE_H #endif // AVIAN_CODEGEN_COMPILER_SITE_H

View File

@ -31,26 +31,33 @@ Value::Value(Site* site, Site* target, ir::Type type)
{ {
} }
bool Value::findSite(Site* site) { bool Value::findSite(Site* site)
{
for (Site* s = this->sites; s; s = s->next) { for (Site* s = this->sites; s; s = s->next) {
if (s == site) return true; if (s == site)
return true;
} }
return false; return false;
} }
bool Value::isBuddyOf(Value* b) { bool Value::isBuddyOf(Value* b)
{
Value* a = this; Value* a = this;
if (a == b) return true; if (a == b)
return true;
for (Value* p = a->buddy; p != a; p = p->buddy) { for (Value* p = a->buddy; p != a; p = p->buddy) {
if (p == b) return true; if (p == b)
return true;
} }
return false; return false;
} }
void Value::addSite(Context* c, Site* s) { void Value::addSite(Context* c, Site* s)
{
if (not this->findSite(s)) { if (not this->findSite(s)) {
if (DebugSites) { if (DebugSites) {
char buffer[256]; s->toString(c, buffer, 256); char buffer[256];
s->toString(c, buffer, 256);
fprintf(stderr, "add site %s to %p\n", buffer, this); fprintf(stderr, "add site %s to %p\n", buffer, this);
} }
s->acquire(c, this); s->acquire(c, this);
@ -59,9 +66,9 @@ void Value::addSite(Context* c, Site* s) {
} }
} }
void Value::grow(Context* c)
void Value::grow(Context* c) { {
assert(c, this->nextWord == this); assertT(c, this->nextWord == this);
Value* next = value(c, this->type); Value* next = value(c, this->type);
this->nextWord = next; this->nextWord = next;
@ -69,14 +76,15 @@ void Value::grow(Context* c) {
next->wordIndex = 1; next->wordIndex = 1;
} }
void Value::maybeSplit(Context* c)
void Value::maybeSplit(Context* c) { {
if (this->nextWord == this) { if (this->nextWord == this) {
this->split(c); this->split(c);
} }
} }
void Value::split(Context* c) { void Value::split(Context* c)
{
this->grow(c); this->grow(c);
for (SiteIterator it(c, this); it.hasMore();) { for (SiteIterator it(c, this); it.hasMore();) {
Site* s = it.next(); Site* s = it.next();
@ -87,11 +95,13 @@ void Value::split(Context* c) {
} }
} }
void Value::removeSite(Context* c, Site* s) { void Value::removeSite(Context* c, Site* s)
{
for (SiteIterator it(c, this); it.hasMore();) { for (SiteIterator it(c, this); it.hasMore();) {
if (s == it.next()) { if (s == it.next()) {
if (DebugSites) { if (DebugSites) {
char buffer[256]; s->toString(c, buffer, 256); char buffer[256];
s->toString(c, buffer, 256);
fprintf(stderr, "remove site %s from %p\n", buffer, this); fprintf(stderr, "remove site %s from %p\n", buffer, this);
} }
it.remove(c); it.remove(c);
@ -101,15 +111,17 @@ void Value::removeSite(Context* c, Site* s) {
if (DebugSites) { if (DebugSites) {
fprintf(stderr, "%p has more: %d\n", this, this->hasSite(c)); 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); SiteIterator it(c, this);
return it.hasMore(); return it.hasMore();
} }
bool Value::uniqueSite(Context* c, Site* s) { bool Value::uniqueSite(Context* c, Site* s)
{
SiteIterator it(c, this); SiteIterator it(c, this);
Site* p UNUSED = it.next(); Site* p UNUSED = it.next();
if (it.hasMore()) { if (it.hasMore()) {
@ -128,12 +140,13 @@ bool Value::uniqueSite(Context* c, Site* s) {
return false; return false;
} }
} else { } else {
assert(c, p == s); assertT(c, p == s);
return true; return true;
} }
} }
void Value::clearSites(Context* c) { void Value::clearSites(Context* c)
{
if (DebugSites) { if (DebugSites) {
fprintf(stderr, "clear sites for %p\n", this); fprintf(stderr, "clear sites for %p\n", this);
} }
@ -143,9 +156,9 @@ void Value::clearSites(Context* c) {
} }
} }
#ifndef NDEBUG #ifndef NDEBUG
bool Value::hasBuddy(Context* c, Value* b) { bool Value::hasBuddy(Context* c, Value* b)
{
Value* a = this; Value* a = this;
if (a == b) { if (a == b) {
return true; return true;
@ -162,13 +175,13 @@ bool Value::hasBuddy(Context* c, Value* b) {
} }
return false; return false;
} }
#endif // not NDEBUG #endif // not NDEBUG
Value* value(Context* c, ir::Type type, Site* site, Site* target) Value* value(Context* c, ir::Type type, Site* site, Site* target)
{ {
return new(c->zone) Value(site, target, type); return new (c->zone) Value(site, target, type);
} }
} // namespace regalloc } // namespace regalloc
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian

View File

@ -62,8 +62,7 @@ class Value : public ir::Value {
#ifndef NDEBUG #ifndef NDEBUG
bool hasBuddy(Context* c, Value* b); bool hasBuddy(Context* c, Value* b);
#endif // not NDEBUG #endif // not NDEBUG
}; };
inline bool isFloatValue(ir::Value* a) inline bool isFloatValue(ir::Value* a)
@ -78,8 +77,8 @@ inline bool isGeneralValue(ir::Value* a)
Value* value(Context* c, ir::Type type, Site* site = 0, Site* target = 0); Value* value(Context* c, ir::Type type, Site* site = 0, Site* target = 0);
} // namespace compiler } // namespace compiler
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_VALUE_H #endif // AVIAN_CODEGEN_COMPILER_VALUE_H

View File

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

View File

@ -277,6 +277,6 @@ uint64_t longToFloat(int64_t a)
return vm::floatToBits(static_cast<float>(a)); return vm::floatToBits(static_cast<float>(a));
} }
} // namespace runtime } // namespace runtime
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian

View File

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

View File

@ -19,13 +19,23 @@ void resolve(MyBlock*);
unsigned padding(MyBlock*, unsigned); unsigned padding(MyBlock*, unsigned);
MyBlock::MyBlock(Context* context, unsigned offset): MyBlock::MyBlock(Context* context, unsigned offset)
context(context), next(0), poolOffsetHead(0), poolOffsetTail(0), : context(context),
lastPoolOffsetTail(0), poolEventHead(0), poolEventTail(0), next(0),
lastEventOffset(0), offset(offset), start(~0), size(0) poolOffsetHead(0),
{ } poolOffsetTail(0),
lastPoolOffsetTail(0),
poolEventHead(0),
poolEventTail(0),
lastEventOffset(0),
offset(offset),
start(~0),
size(0)
{
}
unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) { unsigned MyBlock::resolve(unsigned start, Assembler::Block* next)
{
this->start = start; this->start = start;
this->next = static_cast<MyBlock*>(next); this->next = static_cast<MyBlock*>(next);
@ -34,6 +44,6 @@ unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) {
return start + size + padding(this, size); return start + size + padding(this, size);
} }
} // namespace arm } // namespace arm
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian

View File

@ -20,7 +20,7 @@ namespace arm {
class PoolEvent; class PoolEvent;
class MyBlock: public Assembler::Block { class MyBlock : public Assembler::Block {
public: public:
MyBlock(Context* context, unsigned offset); MyBlock(Context* context, unsigned offset);
@ -39,8 +39,8 @@ class MyBlock: public Assembler::Block {
unsigned size; unsigned size;
}; };
} // namespace arm } // namespace arm
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H #endif // AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H

View File

@ -31,6 +31,6 @@ Context::Context(vm::System* s, util::Allocator* a, vm::Zone* zone)
{ {
} }
} // namespace arm } // namespace arm
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian

View File

@ -18,14 +18,14 @@
namespace vm { namespace vm {
class System; class System;
class Zone; class Zone;
} // namespace vm } // namespace vm
namespace avian { namespace avian {
namespace util { namespace util {
class Aborter; class Aborter;
class Allocator; class Allocator;
} // namespace util } // namespace util
namespace codegen { namespace codegen {
namespace arm { namespace arm {
@ -57,43 +57,57 @@ typedef void (*OperationType)(Context*);
typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*);
typedef void (*BinaryOperationType) typedef void (*BinaryOperationType)(Context*,
(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*); unsigned,
lir::Operand*,
unsigned,
lir::Operand*);
typedef void (*TernaryOperationType) typedef void (*TernaryOperationType)(Context*,
(Context*, unsigned, lir::Operand*, lir::Operand*, unsigned,
lir::Operand*); lir::Operand*,
lir::Operand*,
lir::Operand*);
typedef void (*BranchOperationType) typedef void (*BranchOperationType)(Context*,
(Context*, lir::TernaryOperation, unsigned, lir::Operand*, lir::TernaryOperation,
lir::Operand*, lir::Operand*); unsigned,
lir::Operand*,
lir::Operand*,
lir::Operand*);
class ArchitectureContext { class ArchitectureContext {
public: public:
ArchitectureContext(vm::System* s): s(s) { } ArchitectureContext(vm::System* s) : s(s)
{
}
vm::System* s; vm::System* s;
OperationType operations[lir::OperationCount]; OperationType operations[lir::OperationCount];
UnaryOperationType unaryOperations[lir::UnaryOperationCount UnaryOperationType
* lir::OperandTypeCount]; unaryOperations[lir::UnaryOperationCount * lir::OperandTypeCount];
BinaryOperationType binaryOperations BinaryOperationType binaryOperations[lir::BinaryOperationCount
[lir::BinaryOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; * lir::OperandTypeCount
TernaryOperationType ternaryOperations * lir::OperandTypeCount];
[lir::NonBranchTernaryOperationCount * lir::OperandTypeCount]; TernaryOperationType ternaryOperations[lir::NonBranchTernaryOperationCount
BranchOperationType branchOperations * lir::OperandTypeCount];
[lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount]; BranchOperationType branchOperations[lir::BranchOperationCount
* lir::OperandTypeCount
* lir::OperandTypeCount];
}; };
inline avian::util::Aborter* getAborter(Context* c) { inline avian::util::Aborter* getAborter(Context* c)
{
return c->s; return c->s;
} }
inline avian::util::Aborter* getAborter(ArchitectureContext* c) { inline avian::util::Aborter* getAborter(ArchitectureContext* c)
{
return c->s; return c->s;
} }
} // namespace arm } // namespace arm
} // namespace codegen } // namespace codegen
} // namespace avian } // namespace avian
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H #endif // AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H

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