mirror of
https://github.com/corda/corda.git
synced 2025-02-07 11:30:22 +00:00
bulk, global reformat
This commit is contained in:
parent
7642b94308
commit
836cc41320
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -15,72 +15,87 @@
|
||||
|
||||
using namespace avian::classpath::sockets;
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_init(JNIEnv* e, jclass) {
|
||||
init(e);
|
||||
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_init(JNIEnv* e, jclass)
|
||||
{
|
||||
init(e);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT SOCKET JNICALL
|
||||
Java_java_net_Socket_create(JNIEnv* e, jclass) {
|
||||
return create(e);
|
||||
Java_java_net_Socket_create(JNIEnv* e, jclass)
|
||||
{
|
||||
return create(e);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_connect(JNIEnv* e,
|
||||
jclass,
|
||||
SOCKET sock,
|
||||
long addr,
|
||||
short port)
|
||||
{
|
||||
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
|
||||
Java_java_net_Socket_connect(JNIEnv* e, jclass, SOCKET sock, long addr, short port) {
|
||||
connect(e, sock, addr, port);
|
||||
Java_java_net_Socket_abort(JNIEnv* e, jclass, SOCKET sock)
|
||||
{
|
||||
abort(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_bind(JNIEnv* e, jclass, SOCKET sock, long addr, short port) {
|
||||
bind(e, sock, addr, port);
|
||||
Java_java_net_Socket_close(JNIEnv* e, jclass, SOCKET sock)
|
||||
{
|
||||
close(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_abort(JNIEnv* e, jclass, SOCKET sock) {
|
||||
abort(e, sock);
|
||||
Java_java_net_Socket_closeOutput(JNIEnv* e, jclass, SOCKET sock)
|
||||
{
|
||||
close_output(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_close(JNIEnv* e, jclass, SOCKET sock) {
|
||||
close(e, sock);
|
||||
Java_java_net_Socket_closeInput(JNIEnv* e, jclass, SOCKET sock)
|
||||
{
|
||||
close_input(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_closeOutput(JNIEnv* e, jclass, SOCKET sock) {
|
||||
close_output(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_closeInput(JNIEnv* e, jclass, SOCKET sock) {
|
||||
close_input(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
||||
avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
|
||||
Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments)
|
||||
{ /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
||||
avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
||||
return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count);
|
||||
Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments)
|
||||
{ /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
||||
return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
jclass,
|
||||
jstring name)
|
||||
Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
jclass,
|
||||
jstring name)
|
||||
{
|
||||
const char* chars = e->GetStringUTFChars(name, 0);
|
||||
if (chars) {
|
||||
@ -107,8 +122,8 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
throwNew(e, "java/net/UnknownHostException", 0);
|
||||
return 0;
|
||||
} else {
|
||||
int address = ntohl
|
||||
(reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
|
||||
int address = ntohl(
|
||||
reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
|
||||
|
||||
freeaddrinfo(result);
|
||||
return address;
|
||||
@ -119,4 +134,3 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,25 +17,25 @@
|
||||
#include "jni-util.h"
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
# include <errno.h>
|
||||
# ifdef _MSC_VER
|
||||
# define snprintf sprintf_s
|
||||
# else
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <errno.h>
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf sprintf_s
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
# include <errno.h>
|
||||
# include <netdb.h>
|
||||
# include <sys/select.h>
|
||||
# include <arpa/inet.h>
|
||||
# include <netinet/in.h>
|
||||
# include <netinet/ip.h>
|
||||
# include <netinet/tcp.h>
|
||||
# include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/select.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#define java_nio_channels_SelectionKey_OP_READ 1L
|
||||
@ -47,12 +47,14 @@
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
inline void* operator new(size_t, void* p) throw() { return p; }
|
||||
inline void* operator new(size_t, void* p) throw()
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
inline jbyteArray
|
||||
charsToArray(JNIEnv* e, const char* s)
|
||||
inline jbyteArray charsToArray(JNIEnv* e, const char* s)
|
||||
{
|
||||
unsigned length = strlen(s);
|
||||
jbyteArray a = e->NewByteArray(length + 1);
|
||||
@ -60,8 +62,7 @@ charsToArray(JNIEnv* e, const char* s)
|
||||
return a;
|
||||
}
|
||||
|
||||
inline void
|
||||
doClose(int socket)
|
||||
inline void doClose(int socket)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
closesocket(socket);
|
||||
@ -70,8 +71,7 @@ doClose(int socket)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline jbyteArray
|
||||
errorString(JNIEnv* e, int n)
|
||||
inline jbyteArray errorString(JNIEnv* e, int n)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
const unsigned size = 128;
|
||||
@ -83,8 +83,7 @@ errorString(JNIEnv* e, int n)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline jbyteArray
|
||||
socketErrorString(JNIEnv* e, int n)
|
||||
inline jbyteArray socketErrorString(JNIEnv* e, int n)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
const unsigned size = 64;
|
||||
@ -96,8 +95,7 @@ socketErrorString(JNIEnv* e, int n)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline jbyteArray
|
||||
errorString(JNIEnv* e)
|
||||
inline jbyteArray errorString(JNIEnv* e)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
const unsigned size = 64;
|
||||
@ -109,8 +107,7 @@ errorString(JNIEnv* e)
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
throwIOException(JNIEnv* e, const char* s)
|
||||
void throwIOException(JNIEnv* e, const char* s)
|
||||
{
|
||||
throwNew(e, "java/io/IOException", s);
|
||||
}
|
||||
@ -128,20 +125,17 @@ void throwIOException(JNIEnv* e, jbyteArray a)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
throwIOException(JNIEnv* e)
|
||||
void throwIOException(JNIEnv* e)
|
||||
{
|
||||
throwIOException(e, errorString(e));
|
||||
}
|
||||
|
||||
void
|
||||
throwSocketException(JNIEnv* e, const char* s)
|
||||
void throwSocketException(JNIEnv* e, const char* s)
|
||||
{
|
||||
throwNew(e, "java/net/SocketException", s);
|
||||
}
|
||||
|
||||
void
|
||||
throwSocketException(JNIEnv* e, jbyteArray a)
|
||||
void throwSocketException(JNIEnv* e, jbyteArray a)
|
||||
{
|
||||
size_t length = e->GetArrayLength(a);
|
||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||
@ -154,8 +148,7 @@ throwSocketException(JNIEnv* e, jbyteArray a)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
throwSocketException(JNIEnv* e)
|
||||
void throwSocketException(JNIEnv* e)
|
||||
{
|
||||
throwSocketException(e, errorString(e));
|
||||
}
|
||||
@ -168,41 +161,36 @@ void init(sockaddr_in* address, jint host, jint port)
|
||||
address->sin_addr.s_addr = htonl(host);
|
||||
}
|
||||
|
||||
inline bool
|
||||
einProgress(int error)
|
||||
inline bool einProgress(int error)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return error == WSAEINPROGRESS
|
||||
or error == WSAEWOULDBLOCK;
|
||||
return error == WSAEINPROGRESS or error == WSAEWOULDBLOCK;
|
||||
#else
|
||||
return error == EINPROGRESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
einProgress()
|
||||
inline bool einProgress()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return WSAGetLastError() == WSAEINPROGRESS
|
||||
or WSAGetLastError() == WSAEWOULDBLOCK;
|
||||
or WSAGetLastError() == WSAEWOULDBLOCK;
|
||||
#else
|
||||
return errno == EINPROGRESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
eagain()
|
||||
inline bool eagain()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return WSAGetLastError() == WSAEINPROGRESS
|
||||
or WSAGetLastError() == WSAEWOULDBLOCK;
|
||||
or WSAGetLastError() == WSAEWOULDBLOCK;
|
||||
#else
|
||||
return errno == EAGAIN;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
setBlocking(JNIEnv* e, int d, bool blocking)
|
||||
bool setBlocking(JNIEnv* e, int d, bool blocking)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
u_long a = (blocking ? 0 : 1);
|
||||
@ -212,9 +200,10 @@ setBlocking(JNIEnv* e, int d, bool blocking)
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
int r = fcntl(d, F_SETFL, (blocking
|
||||
? (fcntl(d, F_GETFL) & (~O_NONBLOCK))
|
||||
: (fcntl(d, F_GETFL) | O_NONBLOCK)));
|
||||
int r = fcntl(d,
|
||||
F_SETFL,
|
||||
(blocking ? (fcntl(d, F_GETFL) & (~O_NONBLOCK))
|
||||
: (fcntl(d, F_GETFL) | O_NONBLOCK)));
|
||||
if (r < 0) {
|
||||
throwIOException(e);
|
||||
return false;
|
||||
@ -223,12 +212,11 @@ setBlocking(JNIEnv* e, int d, bool blocking)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
setTcpNoDelay(JNIEnv* e, int d, bool on)
|
||||
bool setTcpNoDelay(JNIEnv* e, int d, bool on)
|
||||
{
|
||||
int flag = on;
|
||||
int r = setsockopt
|
||||
(d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&flag), sizeof(int));
|
||||
int r = setsockopt(
|
||||
d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&flag), sizeof(int));
|
||||
if (r < 0) {
|
||||
throwSocketException(e);
|
||||
return false;
|
||||
@ -236,12 +224,15 @@ setTcpNoDelay(JNIEnv* e, int d, bool on)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
doBind(JNIEnv* e, int s, sockaddr_in* address)
|
||||
void doBind(JNIEnv* e, int s, sockaddr_in* address)
|
||||
{
|
||||
{ int opt = 1;
|
||||
int r = ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||
reinterpret_cast<char*>(&opt), sizeof(int));
|
||||
{
|
||||
int opt = 1;
|
||||
int r = ::setsockopt(s,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
reinterpret_cast<char*>(&opt),
|
||||
sizeof(int));
|
||||
if (r != 0) {
|
||||
throwIOException(e);
|
||||
return;
|
||||
@ -249,9 +240,13 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
|
||||
}
|
||||
|
||||
#ifdef SO_NOSIGPIPE
|
||||
{ int opt = 1;
|
||||
int r = ::setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE,
|
||||
reinterpret_cast<char*>(&opt), sizeof(int));
|
||||
{
|
||||
int opt = 1;
|
||||
int r = ::setsockopt(s,
|
||||
SOL_SOCKET,
|
||||
SO_NOSIGPIPE,
|
||||
reinterpret_cast<char*>(&opt),
|
||||
sizeof(int));
|
||||
if (r != 0) {
|
||||
throwIOException(e);
|
||||
return;
|
||||
@ -259,8 +254,9 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
|
||||
}
|
||||
#endif
|
||||
|
||||
{ int r = ::bind
|
||||
(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
||||
{
|
||||
int r
|
||||
= ::bind(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
||||
if (r != 0) {
|
||||
throwIOException(e);
|
||||
return;
|
||||
@ -268,8 +264,7 @@ doBind(JNIEnv* e, int s, sockaddr_in* address)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
doListen(JNIEnv* e, int s)
|
||||
void doListen(JNIEnv* e, int s)
|
||||
{
|
||||
int r = ::listen(s, 100);
|
||||
if (r != 0) {
|
||||
@ -277,13 +272,12 @@ doListen(JNIEnv* e, int s)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
doFinishConnect(JNIEnv* e, int socket)
|
||||
void doFinishConnect(JNIEnv* e, int socket)
|
||||
{
|
||||
int error;
|
||||
socklen_t size = sizeof(int);
|
||||
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR,
|
||||
reinterpret_cast<char*>(&error), &size);
|
||||
int r = getsockopt(
|
||||
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
|
||||
|
||||
if (r != 0 or size != sizeof(int)) {
|
||||
throwIOException(e);
|
||||
@ -292,11 +286,10 @@ doFinishConnect(JNIEnv* e, int socket)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
doConnect(JNIEnv* e, int s, sockaddr_in* address)
|
||||
bool doConnect(JNIEnv* e, int s, sockaddr_in* address)
|
||||
{
|
||||
int r = ::connect(s, reinterpret_cast<sockaddr*>(address),
|
||||
sizeof(sockaddr_in));
|
||||
int r
|
||||
= ::connect(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
||||
if (r == 0) {
|
||||
return true;
|
||||
} else if (not einProgress()) {
|
||||
@ -307,8 +300,7 @@ doConnect(JNIEnv* e, int s, sockaddr_in* address)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
doAccept(JNIEnv* e, int s)
|
||||
int doAccept(JNIEnv* e, int s)
|
||||
{
|
||||
sockaddr address;
|
||||
socklen_t length = sizeof(address);
|
||||
@ -321,8 +313,7 @@ doAccept(JNIEnv* e, int s)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
doRead(int fd, void* buffer, size_t count)
|
||||
int doRead(int fd, void* buffer, size_t count)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return recv(fd, static_cast<char*>(buffer), count, 0);
|
||||
@ -331,16 +322,15 @@ doRead(int fd, void* buffer, size_t count)
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
|
||||
int doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
|
||||
{
|
||||
sockaddr address;
|
||||
socklen_t length = sizeof(address);
|
||||
int r = recvfrom
|
||||
(fd, static_cast<char*>(buffer), count, 0, &address, &length);
|
||||
|
||||
int r = recvfrom(fd, static_cast<char*>(buffer), count, 0, &address, &length);
|
||||
|
||||
if (r > 0) {
|
||||
sockaddr_in a; memcpy(&a, &address, length);
|
||||
sockaddr_in a;
|
||||
memcpy(&a, &address, length);
|
||||
*host = ntohl(a.sin_addr.s_addr);
|
||||
*port = ntohs(a.sin_port);
|
||||
} else {
|
||||
@ -351,8 +341,7 @@ doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
doWrite(int fd, const void* buffer, size_t count)
|
||||
int doWrite(int fd, const void* buffer, size_t count)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return send(fd, static_cast<const char*>(buffer), count, 0);
|
||||
@ -382,11 +371,12 @@ int makeSocket(JNIEnv* e, int type = SOCK_STREAM, int protocol = IPPROTO_TCP)
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace <anonymous>
|
||||
|
||||
} // namespace <anonymous>
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_ServerSocketChannel_natDoAccept(JNIEnv *e, jclass, jint socket)
|
||||
Java_java_nio_channels_ServerSocketChannel_natDoAccept(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket)
|
||||
{
|
||||
return ::doAccept(e, socket);
|
||||
}
|
||||
@ -432,29 +422,29 @@ extern "C" JNIEXPORT void JNICALL
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv *e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jboolean blocking)
|
||||
Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jboolean blocking)
|
||||
{
|
||||
setBlocking(e, socket, blocking);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e,
|
||||
jclass c,
|
||||
jint socket,
|
||||
jboolean blocking)
|
||||
Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e,
|
||||
jclass c,
|
||||
jint socket,
|
||||
jboolean blocking)
|
||||
{
|
||||
return Java_java_nio_channels_SocketChannel_configureBlocking
|
||||
(e, c, socket, blocking);
|
||||
return Java_java_nio_channels_SocketChannel_configureBlocking(
|
||||
e, c, socket, blocking);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv *e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jboolean on)
|
||||
Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jboolean on)
|
||||
{
|
||||
setTcpNoDelay(e, socket, on);
|
||||
}
|
||||
@ -498,21 +488,21 @@ extern "C" JNIEXPORT jboolean JNICALL
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv *e,
|
||||
jclass,
|
||||
jint socket)
|
||||
Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket)
|
||||
{
|
||||
doFinishConnect(e, socket);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
Java_java_nio_channels_SocketChannel_natRead(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
{
|
||||
int r;
|
||||
if (blocking) {
|
||||
@ -520,8 +510,7 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
|
||||
if (buf) {
|
||||
r = ::doRead(socket, buf, length);
|
||||
if (r > 0) {
|
||||
e->SetByteArrayRegion
|
||||
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
||||
e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
||||
}
|
||||
free(buf);
|
||||
} else {
|
||||
@ -529,8 +518,8 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
|
||||
}
|
||||
} else {
|
||||
jboolean isCopy;
|
||||
uint8_t* buf = static_cast<uint8_t*>
|
||||
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
uint8_t* buf
|
||||
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
|
||||
r = ::doRead(socket, buf + offset, length);
|
||||
|
||||
@ -550,14 +539,14 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking,
|
||||
jintArray address)
|
||||
Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking,
|
||||
jintArray address)
|
||||
{
|
||||
int r;
|
||||
int32_t host;
|
||||
@ -567,8 +556,7 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
||||
if (buf) {
|
||||
r = ::doRecv(socket, buf, length, &host, &port);
|
||||
if (r > 0) {
|
||||
e->SetByteArrayRegion
|
||||
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
||||
e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
||||
}
|
||||
free(buf);
|
||||
} else {
|
||||
@ -576,8 +564,8 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
||||
}
|
||||
} else {
|
||||
jboolean isCopy;
|
||||
uint8_t* buf = static_cast<uint8_t*>
|
||||
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
uint8_t* buf
|
||||
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
|
||||
r = ::doRecv(socket, buf + offset, length, &host, &port);
|
||||
|
||||
@ -593,28 +581,30 @@ Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
||||
} else if (r == 0) {
|
||||
return -1;
|
||||
} else {
|
||||
jint jhost = host; e->SetIntArrayRegion(address, 0, 1, &jhost);
|
||||
jint jport = port; e->SetIntArrayRegion(address, 1, 1, &jport);
|
||||
jint jhost = host;
|
||||
e->SetIntArrayRegion(address, 0, 1, &jhost);
|
||||
jint jport = port;
|
||||
e->SetIntArrayRegion(address, 1, 1, &jport);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
Java_java_nio_channels_SocketChannel_natWrite(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
{
|
||||
int r;
|
||||
if (blocking) {
|
||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||
if (buf) {
|
||||
e->GetByteArrayRegion
|
||||
(buffer, offset, length, reinterpret_cast<jbyte*>(buf));
|
||||
e->GetByteArrayRegion(
|
||||
buffer, offset, length, reinterpret_cast<jbyte*>(buf));
|
||||
r = ::doWrite(socket, buf, length);
|
||||
free(buf);
|
||||
} else {
|
||||
@ -622,8 +612,8 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
|
||||
}
|
||||
} else {
|
||||
jboolean isCopy;
|
||||
uint8_t* buf = static_cast<uint8_t*>
|
||||
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
uint8_t* buf
|
||||
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
|
||||
r = ::doWrite(socket, buf + offset, length);
|
||||
|
||||
@ -641,16 +631,16 @@ Java_java_nio_channels_SocketChannel_natWrite(JNIEnv *e,
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_write(JNIEnv* e,
|
||||
jclass c,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
Java_java_nio_channels_DatagramChannel_write(JNIEnv* e,
|
||||
jclass c,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
{
|
||||
return Java_java_nio_channels_SocketChannel_natWrite
|
||||
(e, c, socket, buffer, offset, length, blocking);
|
||||
return Java_java_nio_channels_SocketChannel_natWrite(
|
||||
e, c, socket, buffer, offset, length, blocking);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
@ -699,14 +689,14 @@ extern "C" JNIEXPORT jint JNICALL
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e,
|
||||
jclass,
|
||||
jint socket)
|
||||
Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket)
|
||||
{
|
||||
int error;
|
||||
socklen_t size = sizeof(int);
|
||||
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR,
|
||||
reinterpret_cast<char*>(&error), &size);
|
||||
int r = getsockopt(
|
||||
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
|
||||
if (r != 0 or size != sizeof(int)) {
|
||||
throwIOException(e);
|
||||
} else if (error != 0) {
|
||||
@ -715,17 +705,15 @@ Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e,
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv *,
|
||||
jclass,
|
||||
jint socket)
|
||||
Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv*,
|
||||
jclass,
|
||||
jint socket)
|
||||
{
|
||||
doClose(socket);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_close(JNIEnv *,
|
||||
jclass,
|
||||
jint socket)
|
||||
Java_java_nio_channels_DatagramChannel_close(JNIEnv*, jclass, jint socket)
|
||||
{
|
||||
doClose(socket);
|
||||
}
|
||||
@ -739,69 +727,85 @@ class Pipe {
|
||||
// pipe descriptors or others. Thus, to implement
|
||||
// Selector.wakeup(), we make a socket connection via the loopback
|
||||
// interface and use it as a pipe.
|
||||
Pipe(JNIEnv* e): connected_(false), listener_(-1), reader_(-1), writer_(-1) {
|
||||
Pipe(JNIEnv* e) : connected_(false), listener_(-1), reader_(-1), writer_(-1)
|
||||
{
|
||||
sockaddr_in address;
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = 0;
|
||||
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //INADDR_LOOPBACK;
|
||||
address.sin_addr.s_addr = inet_addr("127.0.0.1"); // INADDR_LOOPBACK;
|
||||
|
||||
listener_ = makeSocket(e);
|
||||
if (e->ExceptionCheck()) return;
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
|
||||
setBlocking(e, listener_, false);
|
||||
|
||||
::doBind(e, listener_, &address);
|
||||
if (e->ExceptionCheck()) return;
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
|
||||
::doListen(e, listener_);
|
||||
if (e->ExceptionCheck()) return;
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
|
||||
socklen_t length = sizeof(sockaddr_in);
|
||||
int r = getsockname(listener_, reinterpret_cast<sockaddr*>(&address),
|
||||
&length);
|
||||
int r = getsockname(
|
||||
listener_, reinterpret_cast<sockaddr*>(&address), &length);
|
||||
if (r) {
|
||||
throwIOException(e);
|
||||
return;
|
||||
}
|
||||
|
||||
writer_ = makeSocket(e);
|
||||
if (e->ExceptionCheck()) return;
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
|
||||
setBlocking(e, writer_, true);
|
||||
connected_ = ::doConnect(e, writer_, &address);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
if (listener_ >= 0) ::doClose(listener_);
|
||||
if (reader_ >= 0) ::doClose(reader_);
|
||||
if (writer_ >= 0) ::doClose(writer_);
|
||||
void dispose()
|
||||
{
|
||||
if (listener_ >= 0)
|
||||
::doClose(listener_);
|
||||
if (reader_ >= 0)
|
||||
::doClose(reader_);
|
||||
if (writer_ >= 0)
|
||||
::doClose(writer_);
|
||||
}
|
||||
|
||||
bool connected() {
|
||||
bool connected()
|
||||
{
|
||||
return connected_;
|
||||
}
|
||||
|
||||
void setConnected(bool v) {
|
||||
void setConnected(bool v)
|
||||
{
|
||||
connected_ = v;
|
||||
}
|
||||
|
||||
int listener() {
|
||||
int listener()
|
||||
{
|
||||
return listener_;
|
||||
}
|
||||
|
||||
void setListener(int v) {
|
||||
void setListener(int v)
|
||||
{
|
||||
listener_ = v;
|
||||
}
|
||||
|
||||
int reader() {
|
||||
int reader()
|
||||
{
|
||||
return reader_;
|
||||
}
|
||||
|
||||
void setReader(int v) {
|
||||
void setReader(int v)
|
||||
{
|
||||
reader_ = v;
|
||||
}
|
||||
|
||||
int writer() {
|
||||
int writer()
|
||||
{
|
||||
return writer_;
|
||||
}
|
||||
|
||||
@ -811,7 +815,8 @@ class Pipe {
|
||||
int reader_;
|
||||
int writer_;
|
||||
#else
|
||||
Pipe(JNIEnv* e) {
|
||||
Pipe(JNIEnv* e)
|
||||
{
|
||||
if (::pipe(pipe) != 0) {
|
||||
throwIOException(e);
|
||||
return;
|
||||
@ -824,21 +829,25 @@ class Pipe {
|
||||
open_ = true;
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
void dispose()
|
||||
{
|
||||
::doClose(pipe[0]);
|
||||
::doClose(pipe[1]);
|
||||
open_ = false;
|
||||
}
|
||||
|
||||
bool connected() {
|
||||
bool connected()
|
||||
{
|
||||
return open_;
|
||||
}
|
||||
|
||||
int reader() {
|
||||
int reader()
|
||||
{
|
||||
return pipe[0];
|
||||
}
|
||||
|
||||
int writer() {
|
||||
int writer()
|
||||
{
|
||||
return pipe[1];
|
||||
}
|
||||
|
||||
@ -853,18 +862,21 @@ struct SelectorState {
|
||||
fd_set write;
|
||||
fd_set except;
|
||||
Pipe control;
|
||||
SelectorState(JNIEnv* e) : control(e) { }
|
||||
SelectorState(JNIEnv* e) : control(e)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
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) {
|
||||
SelectorState *s = new (mem) SelectorState(e);
|
||||
if (e->ExceptionCheck()) return 0;
|
||||
SelectorState* s = new (mem) SelectorState(e);
|
||||
if (e->ExceptionCheck())
|
||||
return 0;
|
||||
|
||||
if (s) {
|
||||
FD_ZERO(&(s->read));
|
||||
@ -878,7 +890,9 @@ Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass)
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv *e, jclass, jlong state)
|
||||
Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv* e,
|
||||
jclass,
|
||||
jlong state)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
if (s->control.connected()) {
|
||||
@ -891,7 +905,7 @@ Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv *e, jclass, jlong state)
|
||||
}
|
||||
|
||||
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);
|
||||
s->control.dispose();
|
||||
@ -899,9 +913,10 @@ Java_java_nio_channels_SocketSelector_natClose(JNIEnv *, jclass, jlong state)
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv *, jclass,
|
||||
jint socket,
|
||||
jlong state)
|
||||
Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv*,
|
||||
jclass,
|
||||
jint socket,
|
||||
jlong state)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
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
|
||||
Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint interest,
|
||||
jlong state,
|
||||
jint max)
|
||||
Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(
|
||||
JNIEnv*,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint interest,
|
||||
jlong state,
|
||||
jint max)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
if (interest & (java_nio_channels_SelectionKey_OP_READ |
|
||||
java_nio_channels_SelectionKey_OP_ACCEPT)) {
|
||||
if (interest & (java_nio_channels_SelectionKey_OP_READ
|
||||
| java_nio_channels_SelectionKey_OP_ACCEPT)) {
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
||||
if (max < socket) max = socket;
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
} else {
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->read));
|
||||
}
|
||||
|
||||
if (interest & (java_nio_channels_SelectionKey_OP_WRITE |
|
||||
java_nio_channels_SelectionKey_OP_CONNECT)) {
|
||||
|
||||
if (interest & (java_nio_channels_SelectionKey_OP_WRITE
|
||||
| java_nio_channels_SelectionKey_OP_CONNECT)) {
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->write));
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->except));
|
||||
if (max < socket) max = socket;
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
} else {
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->write));
|
||||
}
|
||||
@ -938,30 +956,34 @@ Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(JNIEnv *,
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
||||
jlong state,
|
||||
jint max,
|
||||
jlong interval)
|
||||
Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv* e,
|
||||
jclass,
|
||||
jlong state,
|
||||
jint max,
|
||||
jlong interval)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
if (s->control.reader() >= 0) {
|
||||
int socket = s->control.reader();
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
||||
if (max < socket) max = socket;
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
if (s->control.listener() >= 0) {
|
||||
int socket = s->control.listener();
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
||||
if (max < socket) max = socket;
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
}
|
||||
|
||||
if (not s->control.connected()) {
|
||||
int socket = s->control.writer();
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->write));
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->except));
|
||||
if (max < socket) max = socket;
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -986,17 +1008,16 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
if (FD_ISSET(s->control.writer(), &(s->write)) or
|
||||
FD_ISSET(s->control.writer(), &(s->except)))
|
||||
{
|
||||
if (FD_ISSET(s->control.writer(), &(s->write))
|
||||
or FD_ISSET(s->control.writer(), &(s->except))) {
|
||||
int socket = s->control.writer();
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->write));
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->except));
|
||||
|
||||
int error;
|
||||
socklen_t size = sizeof(int);
|
||||
int r = getsockopt(socket, SOL_SOCKET, SO_ERROR,
|
||||
reinterpret_cast<char*>(&error), &size);
|
||||
int r = getsockopt(
|
||||
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
|
||||
if (r != 0 or size != sizeof(int)) {
|
||||
throwIOException(e);
|
||||
} else if (error != 0) {
|
||||
@ -1005,9 +1026,8 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
||||
s->control.setConnected(true);
|
||||
}
|
||||
|
||||
if (s->control.listener() >= 0 and
|
||||
FD_ISSET(s->control.listener(), &(s->read)))
|
||||
{
|
||||
if (s->control.listener() >= 0
|
||||
and FD_ISSET(s->control.listener(), &(s->read))) {
|
||||
FD_CLR(static_cast<unsigned>(s->control.listener()), &(s->read));
|
||||
|
||||
s->control.setReader(::doAccept(e, s->control.listener()));
|
||||
@ -1015,9 +1035,7 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s->control.reader() >= 0 and
|
||||
FD_ISSET(s->control.reader(), &(s->read)))
|
||||
{
|
||||
if (s->control.reader() >= 0 and FD_ISSET(s->control.reader(), &(s->read))) {
|
||||
FD_CLR(static_cast<unsigned>(s->control.reader()), &(s->read));
|
||||
|
||||
char c;
|
||||
@ -1034,24 +1052,25 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass,
|
||||
jint socket,
|
||||
jint interest,
|
||||
jlong state)
|
||||
Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv*,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint interest,
|
||||
jlong state)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
jint ready = 0;
|
||||
|
||||
|
||||
if (FD_ISSET(socket, &(s->read))) {
|
||||
if (interest & java_nio_channels_SelectionKey_OP_READ) {
|
||||
ready |= java_nio_channels_SelectionKey_OP_READ;
|
||||
}
|
||||
|
||||
|
||||
if (interest & java_nio_channels_SelectionKey_OP_ACCEPT) {
|
||||
ready |= java_nio_channels_SelectionKey_OP_ACCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (FD_ISSET(socket, &(s->write)) or FD_ISSET(socket, &(s->except))) {
|
||||
if (interest & java_nio_channels_SelectionKey_OP_WRITE) {
|
||||
ready |= java_nio_channels_SelectionKey_OP_WRITE;
|
||||
@ -1059,15 +1078,14 @@ Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass,
|
||||
|
||||
if (interest & java_nio_channels_SelectionKey_OP_CONNECT) {
|
||||
ready |= java_nio_channels_SelectionKey_OP_CONNECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ready;
|
||||
}
|
||||
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv *, jclass)
|
||||
Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv*, jclass)
|
||||
{
|
||||
union {
|
||||
uint32_t i;
|
||||
|
@ -16,17 +16,16 @@
|
||||
#include "jni-util.h"
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_Inflater_make
|
||||
(JNIEnv* e, jclass, jboolean nowrap)
|
||||
Java_java_util_zip_Inflater_make(JNIEnv* e, jclass, jboolean nowrap)
|
||||
{
|
||||
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
||||
if (s == 0) {
|
||||
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(s, 0, sizeof(z_stream));
|
||||
|
||||
|
||||
int r = inflateInit2(s, (nowrap ? -15 : 15));
|
||||
if (r != Z_OK) {
|
||||
free(s);
|
||||
@ -38,7 +37,7 @@ Java_java_util_zip_Inflater_make
|
||||
}
|
||||
|
||||
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);
|
||||
inflateEnd(s);
|
||||
@ -46,39 +45,43 @@ Java_java_util_zip_Inflater_dispose(JNIEnv*, jclass, jlong peer)
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_util_zip_Inflater_inflate
|
||||
(JNIEnv* e, jclass, jlong peer,
|
||||
jbyteArray input, jint inputOffset, jint inputLength,
|
||||
jbyteArray output, jint outputOffset, jint outputLength,
|
||||
jintArray results)
|
||||
Java_java_util_zip_Inflater_inflate(JNIEnv* e,
|
||||
jclass,
|
||||
jlong peer,
|
||||
jbyteArray input,
|
||||
jint inputOffset,
|
||||
jint inputLength,
|
||||
jbyteArray output,
|
||||
jint outputOffset,
|
||||
jint outputLength,
|
||||
jintArray results)
|
||||
{
|
||||
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||
|
||||
jbyte* in = static_cast<jbyte*>(malloc(inputLength));
|
||||
if (in == 0) {
|
||||
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
jbyte* out = static_cast<jbyte*>(malloc(outputLength));
|
||||
if (out == 0) {
|
||||
free(in);
|
||||
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
e->GetByteArrayRegion(input, inputOffset, inputLength, in);
|
||||
|
||||
|
||||
s->next_in = reinterpret_cast<Bytef*>(in);
|
||||
s->avail_in = inputLength;
|
||||
s->next_out = reinterpret_cast<Bytef*>(out);
|
||||
s->avail_out = outputLength;
|
||||
|
||||
int r = inflate(s, Z_SYNC_FLUSH);
|
||||
jint resultArray[3]
|
||||
= { r,
|
||||
static_cast<jint>(inputLength - s->avail_in),
|
||||
static_cast<jint>(outputLength - s->avail_out) };
|
||||
jint resultArray[3] = {r,
|
||||
static_cast<jint>(inputLength - s->avail_in),
|
||||
static_cast<jint>(outputLength - s->avail_out)};
|
||||
|
||||
free(in);
|
||||
|
||||
@ -89,17 +92,19 @@ Java_java_util_zip_Inflater_inflate
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_Deflater_make
|
||||
(JNIEnv* e, jclass, jboolean nowrap, jint level)
|
||||
Java_java_util_zip_Deflater_make(JNIEnv* e,
|
||||
jclass,
|
||||
jboolean nowrap,
|
||||
jint level)
|
||||
{
|
||||
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
||||
if (s == 0) {
|
||||
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(s, 0, sizeof(z_stream));
|
||||
|
||||
|
||||
int r = deflateInit2(s, level, (nowrap ? -15 : 15));
|
||||
if (r != Z_OK) {
|
||||
free(s);
|
||||
@ -111,7 +116,7 @@ Java_java_util_zip_Deflater_make
|
||||
}
|
||||
|
||||
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);
|
||||
deflateEnd(s);
|
||||
@ -119,39 +124,44 @@ Java_java_util_zip_Deflater_dispose(JNIEnv*, jclass, jlong peer)
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_util_zip_Deflater_deflate
|
||||
(JNIEnv* e, jclass, jlong peer,
|
||||
jbyteArray input, jint inputOffset, jint inputLength,
|
||||
jbyteArray output, jint outputOffset, jint outputLength,
|
||||
jboolean finish, jintArray results)
|
||||
Java_java_util_zip_Deflater_deflate(JNIEnv* e,
|
||||
jclass,
|
||||
jlong peer,
|
||||
jbyteArray input,
|
||||
jint inputOffset,
|
||||
jint inputLength,
|
||||
jbyteArray output,
|
||||
jint outputOffset,
|
||||
jint outputLength,
|
||||
jboolean finish,
|
||||
jintArray results)
|
||||
{
|
||||
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||
|
||||
jbyte* in = static_cast<jbyte*>(malloc(inputLength));
|
||||
if (in == 0) {
|
||||
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
jbyte* out = static_cast<jbyte*>(malloc(outputLength));
|
||||
if (out == 0) {
|
||||
free(in);
|
||||
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
e->GetByteArrayRegion(input, inputOffset, inputLength, in);
|
||||
|
||||
|
||||
s->next_in = reinterpret_cast<Bytef*>(in);
|
||||
s->avail_in = inputLength;
|
||||
s->next_out = reinterpret_cast<Bytef*>(out);
|
||||
s->avail_out = outputLength;
|
||||
|
||||
int r = deflate(s, finish ? Z_FINISH : Z_NO_FLUSH);
|
||||
jint resultArray[3]
|
||||
= { r,
|
||||
static_cast<jint>(inputLength - s->avail_in),
|
||||
static_cast<jint>(outputLength - s->avail_out) };
|
||||
jint resultArray[3] = {r,
|
||||
static_cast<jint>(inputLength - s->avail_in),
|
||||
static_cast<jint>(outputLength - s->avail_out)};
|
||||
|
||||
free(in);
|
||||
|
||||
|
@ -16,8 +16,7 @@ namespace {
|
||||
|
||||
#if (!defined PLATFORM_WINDOWS) || (defined _MSC_VER)
|
||||
|
||||
void
|
||||
removeNewline(char* s)
|
||||
void removeNewline(char* s)
|
||||
{
|
||||
for (; s; ++s) {
|
||||
if (*s == '\n') {
|
||||
@ -29,10 +28,10 @@ removeNewline(char* s)
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
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;
|
||||
|
||||
@ -40,13 +39,13 @@ Java_java_util_Date_toString(JNIEnv* e, jclass c UNUSED, jlong when)
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
e->MonitorEnter(c);
|
||||
# ifdef _MSC_VER
|
||||
#ifdef _MSC_VER
|
||||
char buffer[BufferSize];
|
||||
ctime_s(buffer, BufferSize, &time);
|
||||
removeNewline(buffer);
|
||||
# else
|
||||
#else
|
||||
char* buffer = ctime(&time);
|
||||
# endif
|
||||
#endif
|
||||
jstring r = e->NewStringUTF(buffer);
|
||||
e->MonitorExit(c);
|
||||
return r;
|
||||
|
@ -20,19 +20,18 @@
|
||||
#undef JNIEXPORT
|
||||
|
||||
#if (defined __MINGW32__) || (defined _MSC_VER)
|
||||
# define PLATFORM_WINDOWS
|
||||
# define PATH_SEPARATOR ';'
|
||||
# define JNIEXPORT __declspec(dllexport)
|
||||
#else // not (defined __MINGW32__) || (defined _MSC_VER)
|
||||
# define PLATFORM_POSIX
|
||||
# define PATH_SEPARATOR ':'
|
||||
# define JNIEXPORT __attribute__ ((visibility("default"))) \
|
||||
__attribute__ ((used))
|
||||
#endif // not (defined __MINGW32__) || (defined _MSC_VER)
|
||||
#define PLATFORM_WINDOWS
|
||||
#define PATH_SEPARATOR ';'
|
||||
#define JNIEXPORT __declspec(dllexport)
|
||||
#else // not (defined __MINGW32__) || (defined _MSC_VER)
|
||||
#define PLATFORM_POSIX
|
||||
#define PATH_SEPARATOR ':'
|
||||
#define JNIEXPORT __attribute__((visibility("default"))) __attribute__((used))
|
||||
#endif // not (defined __MINGW32__) || (defined _MSC_VER)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
# define UNUSED
|
||||
#define UNUSED
|
||||
|
||||
typedef char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
@ -43,38 +42,37 @@ typedef unsigned int uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
# define INT32_MAX 2147483647
|
||||
#define INT32_MAX 2147483647
|
||||
|
||||
# define not !
|
||||
# define or ||
|
||||
# define and &&
|
||||
# define xor ^
|
||||
#define not!
|
||||
#define or ||
|
||||
#define and &&
|
||||
#define xor ^
|
||||
|
||||
# ifdef _M_IX86
|
||||
# define ARCH_x86_32
|
||||
# elif defined _M_X64
|
||||
# define ARCH_x86_64
|
||||
# endif
|
||||
#ifdef _M_IX86
|
||||
#define ARCH_x86_32
|
||||
#elif defined _M_X64
|
||||
#define ARCH_x86_64
|
||||
#endif
|
||||
|
||||
#else // not _MSC_VER
|
||||
#else // not _MSC_VER
|
||||
|
||||
# define UNUSED __attribute__((unused))
|
||||
#define UNUSED __attribute__((unused))
|
||||
|
||||
# include "stdint.h"
|
||||
# include "errno.h"
|
||||
#include "stdint.h"
|
||||
#include "errno.h"
|
||||
|
||||
# ifdef __i386__
|
||||
# define ARCH_x86_32
|
||||
# elif defined __x86_64__
|
||||
# define ARCH_x86_64
|
||||
# elif defined __arm__
|
||||
# define ARCH_arm
|
||||
# endif
|
||||
#ifdef __i386__
|
||||
#define ARCH_x86_32
|
||||
#elif defined __x86_64__
|
||||
#define ARCH_x86_64
|
||||
#elif defined __arm__
|
||||
#define ARCH_arm
|
||||
#endif
|
||||
|
||||
#endif // not _MSC_VER
|
||||
#endif // not _MSC_VER
|
||||
|
||||
inline void
|
||||
throwNew(JNIEnv* e, const char* class_, const char* message, ...)
|
||||
inline void throwNew(JNIEnv* e, const char* class_, const char* message, ...)
|
||||
{
|
||||
jclass c = e->FindClass(class_);
|
||||
if (c) {
|
||||
@ -90,7 +88,7 @@ throwNew(JNIEnv* e, const char* class_, const char* message, ...)
|
||||
vsnprintf(buffer, BufferSize - 1, message, list);
|
||||
#endif
|
||||
va_end(list);
|
||||
|
||||
|
||||
e->ThrowNew(c, buffer);
|
||||
} else {
|
||||
e->ThrowNew(c, 0);
|
||||
@ -99,8 +97,7 @@ throwNew(JNIEnv* e, const char* class_, const char* message, ...)
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
throwNewErrno(JNIEnv* e, const char* class_)
|
||||
inline void throwNewErrno(JNIEnv* e, const char* class_)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
const unsigned size = 128;
|
||||
@ -112,8 +109,7 @@ throwNewErrno(JNIEnv* e, const char* class_)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void*
|
||||
allocate(JNIEnv* e, unsigned size)
|
||||
inline void* allocate(JNIEnv* e, unsigned size)
|
||||
{
|
||||
void* p = malloc(size);
|
||||
if (p == 0) {
|
||||
@ -122,4 +118,4 @@ allocate(JNIEnv* e, unsigned size)
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif//JNI_UTIL
|
||||
#endif // JNI_UTIL
|
||||
|
@ -19,166 +19,183 @@ namespace avian {
|
||||
namespace classpath {
|
||||
namespace sockets {
|
||||
|
||||
int last_socket_error() {
|
||||
int last_socket_error()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
int error = WSAGetLastError();
|
||||
int error = WSAGetLastError();
|
||||
#else
|
||||
int error = errno;
|
||||
int error = errno;
|
||||
#endif
|
||||
return error;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void init(JNIEnv* ONLY_ON_WINDOWS(e)) {
|
||||
void init(JNIEnv* ONLY_ON_WINDOWS(e))
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
static bool wsaInitialized = false;
|
||||
if (not wsaInitialized) {
|
||||
WSADATA data;
|
||||
int r = WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) {
|
||||
throwNew(e, "java/io/IOException", "WSAStartup failed");
|
||||
} else {
|
||||
wsaInitialized = true;
|
||||
}
|
||||
WSADATA data;
|
||||
int r = WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) {
|
||||
throwNew(e, "java/io/IOException", "WSAStartup failed");
|
||||
} else {
|
||||
wsaInitialized = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SOCKET create(JNIEnv* e) {
|
||||
SOCKET sock;
|
||||
if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't create a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return 0; // This doesn't matter cause we have risen an exception
|
||||
}
|
||||
return sock;
|
||||
SOCKET create(JNIEnv* e)
|
||||
{
|
||||
SOCKET sock;
|
||||
if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
|
||||
char buf[255];
|
||||
sprintf(
|
||||
buf, "Can't create a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return 0; // This doesn't matter cause we have risen an exception
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
void connect(JNIEnv* e, SOCKET sock, long addr, short port) {
|
||||
sockaddr_in adr;
|
||||
adr.sin_family = AF_INET;
|
||||
void connect(JNIEnv* e, SOCKET sock, long addr, short port)
|
||||
{
|
||||
sockaddr_in adr;
|
||||
adr.sin_family = AF_INET;
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
adr.sin_addr.S_un.S_addr = htonl(addr);
|
||||
adr.sin_addr.S_un.S_addr = htonl(addr);
|
||||
#else
|
||||
adr.sin_addr.s_addr = htonl(addr);
|
||||
adr.sin_addr.s_addr = htonl(addr);
|
||||
#endif
|
||||
adr.sin_port = htons (port);
|
||||
adr.sin_port = htons(port);
|
||||
|
||||
if (SOCKET_ERROR == ::connect(sock, (sockaddr* )&adr, sizeof(adr)))
|
||||
{
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't connect a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
if (SOCKET_ERROR == ::connect(sock, (sockaddr*)&adr, sizeof(adr))) {
|
||||
char buf[255];
|
||||
sprintf(
|
||||
buf, "Can't connect a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void bind(JNIEnv* e, SOCKET sock, long addr, short port) {
|
||||
sockaddr_in adr;
|
||||
adr.sin_family = AF_INET;
|
||||
void bind(JNIEnv* e, SOCKET sock, long addr, short port)
|
||||
{
|
||||
sockaddr_in adr;
|
||||
adr.sin_family = AF_INET;
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
adr.sin_addr.S_un.S_addr = htonl(addr);
|
||||
adr.sin_addr.S_un.S_addr = htonl(addr);
|
||||
#else
|
||||
adr.sin_addr.s_addr = htonl(addr);
|
||||
adr.sin_addr.s_addr = htonl(addr);
|
||||
#endif
|
||||
adr.sin_port = htons (port);
|
||||
adr.sin_port = htons(port);
|
||||
|
||||
if (SOCKET_ERROR == ::bind(sock, (sockaddr* )&adr, sizeof(adr)))
|
||||
{
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
if (SOCKET_ERROR == ::bind(sock, (sockaddr*)&adr, sizeof(adr))) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port) {
|
||||
sockaddr_in adr;
|
||||
SOCKET client_socket = ::accept(sock, (sockaddr* )&adr, NULL);
|
||||
if (INVALID_SOCKET == client_socket) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't accept the incoming connection. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port)
|
||||
{
|
||||
sockaddr_in adr;
|
||||
SOCKET client_socket = ::accept(sock, (sockaddr*)&adr, NULL);
|
||||
if (INVALID_SOCKET == client_socket) {
|
||||
char buf[255];
|
||||
sprintf(buf,
|
||||
"Can't accept the incoming connection. System error: %d",
|
||||
last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if (client_addr != NULL) {
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
*client_addr = ntohl(adr.sin_addr.S_un.S_addr);
|
||||
#else
|
||||
*client_addr = ntohl(adr.sin_addr.s_addr);
|
||||
#endif
|
||||
}
|
||||
if (client_addr != NULL) {
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
*client_addr = ntohl(adr.sin_addr.S_un.S_addr);
|
||||
#else
|
||||
*client_addr = ntohl(adr.sin_addr.s_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (client_port != NULL) {
|
||||
*client_port = ntohs (adr.sin_port);
|
||||
}
|
||||
if (client_port != NULL) {
|
||||
*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) {
|
||||
if (SOCKET_ERROR == ::send(sock, buff_ptr, buff_size, 0)) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't send data through the socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size)
|
||||
{
|
||||
if (SOCKET_ERROR == ::send(sock, buff_ptr, buff_size, 0)) {
|
||||
char buf[255];
|
||||
sprintf(buf,
|
||||
"Can't send data through the socket. System error: %d",
|
||||
last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size) {
|
||||
int length = ::recv(sock, buff_ptr, buff_size, 0);
|
||||
if (SOCKET_ERROR == length) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't receive data through the socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return 0; // This doesn't matter cause we have risen an exception
|
||||
}
|
||||
return length;
|
||||
int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size)
|
||||
{
|
||||
int length = ::recv(sock, buff_ptr, buff_size, 0);
|
||||
if (SOCKET_ERROR == length) {
|
||||
char buf[255];
|
||||
sprintf(buf,
|
||||
"Can't receive data through the socket. System error: %d",
|
||||
last_socket_error());
|
||||
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) {
|
||||
if (SOCKET_ERROR == ::closesocket(sock)) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't close the socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
void abort(JNIEnv* e, SOCKET sock)
|
||||
{
|
||||
if (SOCKET_ERROR == ::closesocket(sock)) {
|
||||
char buf[255];
|
||||
sprintf(
|
||||
buf, "Can't close the socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
}
|
||||
|
||||
void close(JNIEnv* e, SOCKET sock) {
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_BOTH)) {
|
||||
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(JNIEnv* e, SOCKET sock)
|
||||
{
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_BOTH)) {
|
||||
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_input(JNIEnv* e, SOCKET sock) {
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_RECEIVE)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
void close_input(JNIEnv* e, SOCKET sock)
|
||||
{
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_RECEIVE)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
|
||||
/*
|
||||
* This file represents a simple cross-platform JNI sockets API
|
||||
* It is used from different classes of the default Avian classpath
|
||||
@ -22,28 +21,28 @@
|
||||
#include "jni-util.h"
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
# include <winsock2.h>
|
||||
#include <winsock2.h>
|
||||
|
||||
# define ONLY_ON_WINDOWS(x) x
|
||||
#define ONLY_ON_WINDOWS(x) x
|
||||
|
||||
# ifndef ENOTCONN
|
||||
# define ENOTCONN WSAENOTCONN
|
||||
# endif
|
||||
#ifndef ENOTCONN
|
||||
#define ENOTCONN WSAENOTCONN
|
||||
#endif
|
||||
#else
|
||||
# include <netdb.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
|
||||
# define ONLY_ON_WINDOWS(x)
|
||||
# define SOCKET int
|
||||
# define INVALID_SOCKET -1
|
||||
# define SOCKET_ERROR -1
|
||||
# define closesocket(x) close(x)
|
||||
#define ONLY_ON_WINDOWS(x)
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define closesocket(x) close(x)
|
||||
|
||||
# define SD_RECEIVE SHUT_RD
|
||||
# define SD_SEND SHUT_WR
|
||||
# define SD_BOTH SHUT_RDWR
|
||||
#define SD_RECEIVE SHUT_RD
|
||||
#define SD_SEND SHUT_WR
|
||||
#define SD_BOTH SHUT_RDWR
|
||||
|
||||
#endif
|
||||
|
||||
@ -69,7 +68,6 @@ void abort(JNIEnv* e, SOCKET sock);
|
||||
void close(JNIEnv* e, SOCKET sock);
|
||||
void close_input(JNIEnv* e, SOCKET sock);
|
||||
void close_output(JNIEnv* e, SOCKET sock);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,116 +30,126 @@ class Assembler;
|
||||
class RegisterFile;
|
||||
|
||||
class OperandMask {
|
||||
public:
|
||||
public:
|
||||
uint8_t typeMask;
|
||||
uint64_t registerMask;
|
||||
|
||||
OperandMask(uint8_t typeMask, uint64_t registerMask):
|
||||
typeMask(typeMask),
|
||||
registerMask(registerMask)
|
||||
{ }
|
||||
OperandMask(uint8_t typeMask, uint64_t registerMask)
|
||||
: typeMask(typeMask), registerMask(registerMask)
|
||||
{
|
||||
}
|
||||
|
||||
OperandMask():
|
||||
typeMask(~0),
|
||||
registerMask(~static_cast<uint64_t>(0))
|
||||
{ }
|
||||
OperandMask() : typeMask(~0), registerMask(~static_cast<uint64_t>(0))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Architecture {
|
||||
public:
|
||||
virtual unsigned floatRegisterSize() = 0;
|
||||
public:
|
||||
virtual unsigned floatRegisterSize() = 0;
|
||||
|
||||
virtual const RegisterFile* registerFile() = 0;
|
||||
virtual const RegisterFile* registerFile() = 0;
|
||||
|
||||
virtual int scratch() = 0;
|
||||
virtual int stack() = 0;
|
||||
virtual int thread() = 0;
|
||||
virtual int returnLow() = 0;
|
||||
virtual int returnHigh() = 0;
|
||||
virtual int virtualCallTarget() = 0;
|
||||
virtual int virtualCallIndex() = 0;
|
||||
virtual int scratch() = 0;
|
||||
virtual int stack() = 0;
|
||||
virtual int thread() = 0;
|
||||
virtual int returnLow() = 0;
|
||||
virtual int returnHigh() = 0;
|
||||
virtual int virtualCallTarget() = 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::TernaryOperation op) = 0;
|
||||
virtual bool alwaysCondensed(lir::BinaryOperation 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 argumentFootprint(unsigned footprint) = 0;
|
||||
virtual bool argumentAlignment() = 0;
|
||||
virtual bool argumentRegisterAlignment() = 0;
|
||||
virtual unsigned argumentRegisterCount() = 0;
|
||||
virtual int argumentRegister(unsigned index) = 0;
|
||||
virtual unsigned frameFootprint(unsigned footprint) = 0;
|
||||
virtual unsigned argumentFootprint(unsigned footprint) = 0;
|
||||
virtual bool argumentAlignment() = 0;
|
||||
virtual bool argumentRegisterAlignment() = 0;
|
||||
virtual unsigned argumentRegisterCount() = 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,
|
||||
void* newTarget) = 0;
|
||||
virtual void updateCall(lir::UnaryOperation op,
|
||||
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,
|
||||
void* link, bool mostRecent,
|
||||
int targetParameterFootprint, void** ip,
|
||||
void** stack) = 0;
|
||||
virtual void* frameIp(void* stack) = 0;
|
||||
virtual unsigned frameHeaderSize() = 0;
|
||||
virtual unsigned frameReturnAddressSize() = 0;
|
||||
virtual unsigned frameFooterSize() = 0;
|
||||
virtual int returnAddressOffset() = 0;
|
||||
virtual int framePointerOffset() = 0;
|
||||
virtual void nextFrame(void* start,
|
||||
unsigned size,
|
||||
unsigned footprint,
|
||||
void* link,
|
||||
bool mostRecent,
|
||||
int targetParameterFootprint,
|
||||
void** ip,
|
||||
void** stack) = 0;
|
||||
virtual void* frameIp(void* stack) = 0;
|
||||
virtual unsigned frameHeaderSize() = 0;
|
||||
virtual unsigned frameReturnAddressSize() = 0;
|
||||
virtual unsigned frameFooterSize() = 0;
|
||||
virtual int returnAddressOffset() = 0;
|
||||
virtual int framePointerOffset() = 0;
|
||||
|
||||
virtual void plan
|
||||
(lir::UnaryOperation op,
|
||||
unsigned aSize, OperandMask& aMask,
|
||||
bool* thunk) = 0;
|
||||
virtual void plan(lir::UnaryOperation op,
|
||||
unsigned aSize,
|
||||
OperandMask& aMask,
|
||||
bool* thunk) = 0;
|
||||
|
||||
virtual void planSource
|
||||
(lir::BinaryOperation op,
|
||||
unsigned aSize, OperandMask& aMask,
|
||||
unsigned bSize, bool* thunk) = 0;
|
||||
|
||||
virtual void planDestination
|
||||
(lir::BinaryOperation op,
|
||||
unsigned aSize, const OperandMask& aMask,
|
||||
unsigned bSize, OperandMask& bMask) = 0;
|
||||
virtual void planSource(lir::BinaryOperation op,
|
||||
unsigned aSize,
|
||||
OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
bool* thunk) = 0;
|
||||
|
||||
virtual void planMove
|
||||
(unsigned size, OperandMask& src,
|
||||
OperandMask& tmp,
|
||||
const OperandMask& dst) = 0;
|
||||
virtual void planDestination(lir::BinaryOperation op,
|
||||
unsigned aSize,
|
||||
const OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
OperandMask& bMask) = 0;
|
||||
|
||||
virtual void planSource
|
||||
(lir::TernaryOperation op,
|
||||
unsigned aSize, OperandMask& aMask,
|
||||
unsigned bSize, OperandMask& bMask,
|
||||
unsigned cSize, bool* thunk) = 0;
|
||||
virtual void planMove(unsigned size,
|
||||
OperandMask& src,
|
||||
OperandMask& tmp,
|
||||
const OperandMask& dst) = 0;
|
||||
|
||||
virtual void planDestination
|
||||
(lir::TernaryOperation op,
|
||||
unsigned aSize, const OperandMask& aMask,
|
||||
unsigned bSize, const OperandMask& bMask,
|
||||
unsigned cSize, OperandMask& cMask) = 0;
|
||||
virtual void planSource(lir::TernaryOperation op,
|
||||
unsigned aSize,
|
||||
OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
OperandMask& bMask,
|
||||
unsigned cSize,
|
||||
bool* thunk) = 0;
|
||||
|
||||
virtual Assembler* makeAssembler(util::Allocator*, vm::Zone*) = 0;
|
||||
virtual void planDestination(lir::TernaryOperation op,
|
||||
unsigned aSize,
|
||||
const OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
const OperandMask& bMask,
|
||||
unsigned cSize,
|
||||
OperandMask& cMask) = 0;
|
||||
|
||||
virtual void acquire() = 0;
|
||||
virtual void release() = 0;
|
||||
virtual Assembler* makeAssembler(util::Allocator*, vm::Zone*) = 0;
|
||||
|
||||
virtual void acquire() = 0;
|
||||
virtual void release() = 0;
|
||||
};
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ARCHITECTURE_H
|
||||
#endif // AVIAN_CODEGEN_ARCHITECTURE_H
|
||||
|
@ -23,16 +23,17 @@ namespace codegen {
|
||||
class Architecture;
|
||||
|
||||
class OperandInfo {
|
||||
public:
|
||||
public:
|
||||
const unsigned size;
|
||||
const lir::OperandType type;
|
||||
lir::Operand* const operand;
|
||||
|
||||
inline OperandInfo(unsigned size, lir::OperandType type, lir::Operand* operand):
|
||||
size(size),
|
||||
type(type),
|
||||
operand(operand)
|
||||
{ }
|
||||
inline OperandInfo(unsigned size,
|
||||
lir::OperandType type,
|
||||
lir::Operand* operand)
|
||||
: size(size), type(type), operand(operand)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef AVIAN_TAILS
|
||||
@ -49,11 +50,9 @@ const bool UseFramePointer = false;
|
||||
|
||||
class Assembler {
|
||||
public:
|
||||
|
||||
class Client {
|
||||
public:
|
||||
virtual int acquireTemporary
|
||||
(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
|
||||
virtual int acquireTemporary(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
|
||||
virtual void releaseTemporary(int r) = 0;
|
||||
|
||||
virtual void save(int r) = 0;
|
||||
@ -75,20 +74,23 @@ class Assembler {
|
||||
virtual void allocateFrame(unsigned footprint) = 0;
|
||||
virtual void adjustFrame(unsigned difference) = 0;
|
||||
virtual void popFrame(unsigned footprint) = 0;
|
||||
virtual void popFrameForTailCall(unsigned footprint, int offset,
|
||||
virtual void popFrameForTailCall(unsigned footprint,
|
||||
int offset,
|
||||
int returnAddressSurrogate,
|
||||
int framePointerSurrogate) = 0;
|
||||
virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint,
|
||||
unsigned argumentFootprint)
|
||||
= 0;
|
||||
unsigned argumentFootprint) = 0;
|
||||
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
|
||||
unsigned stackOffsetFromThread)
|
||||
= 0;
|
||||
= 0;
|
||||
|
||||
virtual void apply(lir::Operation op) = 0;
|
||||
virtual void apply(lir::UnaryOperation op, OperandInfo a) = 0;
|
||||
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) = 0;
|
||||
virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c) = 0;
|
||||
virtual void apply(lir::TernaryOperation op,
|
||||
OperandInfo a,
|
||||
OperandInfo b,
|
||||
OperandInfo c) = 0;
|
||||
|
||||
virtual void setDestination(uint8_t* dst) = 0;
|
||||
|
||||
@ -107,7 +109,7 @@ class Assembler {
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_H
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_H
|
||||
|
@ -30,24 +30,30 @@ class Compiler {
|
||||
class Client {
|
||||
public:
|
||||
virtual intptr_t getThunk(lir::UnaryOperation op, unsigned size) = 0;
|
||||
virtual intptr_t getThunk(lir::BinaryOperation op, unsigned size,
|
||||
virtual intptr_t getThunk(lir::BinaryOperation op,
|
||||
unsigned size,
|
||||
unsigned resultSize) = 0;
|
||||
virtual intptr_t getThunk(lir::TernaryOperation op, unsigned size,
|
||||
unsigned resultSize, bool* threadParameter) = 0;
|
||||
virtual intptr_t getThunk(lir::TernaryOperation op,
|
||||
unsigned size,
|
||||
unsigned resultSize,
|
||||
bool* threadParameter) = 0;
|
||||
};
|
||||
|
||||
static const unsigned Aligned = 1 << 0;
|
||||
static const unsigned Aligned = 1 << 0;
|
||||
static const unsigned NoReturn = 1 << 1;
|
||||
static const unsigned TailJump = 1 << 2;
|
||||
static const unsigned LongJumpOrCall = 1 << 3;
|
||||
|
||||
class State { };
|
||||
class State {
|
||||
};
|
||||
|
||||
virtual State* saveState() = 0;
|
||||
virtual void restoreState(State* state) = 0;
|
||||
|
||||
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
|
||||
unsigned localFootprint, unsigned alignedFrameSize) = 0;
|
||||
virtual void init(unsigned logicalCodeSize,
|
||||
unsigned parameterFootprint,
|
||||
unsigned localFootprint,
|
||||
unsigned alignedFrameSize) = 0;
|
||||
|
||||
virtual void extendLogicalCode(unsigned more) = 0;
|
||||
|
||||
@ -128,8 +134,7 @@ class Compiler {
|
||||
ir::Type type,
|
||||
ir::Value* a,
|
||||
ir::Value* b) = 0;
|
||||
virtual ir::Value* unaryOp(lir::BinaryOperation op,
|
||||
ir::Value* a) = 0;
|
||||
virtual ir::Value* unaryOp(lir::BinaryOperation op, ir::Value* a) = 0;
|
||||
virtual void nullaryOp(lir::Operation op) = 0;
|
||||
|
||||
virtual ir::Value* f2f(ir::Type resType, ir::Value* a) = 0;
|
||||
@ -145,11 +150,12 @@ class Compiler {
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
Compiler*
|
||||
makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone,
|
||||
Compiler::Client* client);
|
||||
Compiler* makeCompiler(vm::System* system,
|
||||
Assembler* assembler,
|
||||
vm::Zone* zone,
|
||||
Compiler::Client* client);
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_H
|
||||
|
@ -17,71 +17,67 @@ class Promise;
|
||||
|
||||
namespace lir {
|
||||
enum Operation {
|
||||
#define LIR_OP_0(x) x,
|
||||
#define LIR_OP_1(x)
|
||||
#define LIR_OP_2(x)
|
||||
#define LIR_OP_3(x)
|
||||
#include "lir-ops.inc.cpp"
|
||||
#undef LIR_OP_0
|
||||
#undef LIR_OP_1
|
||||
#undef LIR_OP_2
|
||||
#undef LIR_OP_3
|
||||
#define LIR_OP_0(x) x,
|
||||
#define LIR_OP_1(x)
|
||||
#define LIR_OP_2(x)
|
||||
#define LIR_OP_3(x)
|
||||
#include "lir-ops.inc.cpp"
|
||||
#undef LIR_OP_0
|
||||
#undef LIR_OP_1
|
||||
#undef LIR_OP_2
|
||||
#undef LIR_OP_3
|
||||
};
|
||||
|
||||
const unsigned OperationCount = Trap + 1;
|
||||
|
||||
enum UnaryOperation {
|
||||
#define LIR_OP_0(x)
|
||||
#define LIR_OP_1(x) x,
|
||||
#define LIR_OP_2(x)
|
||||
#define LIR_OP_3(x)
|
||||
#include "lir-ops.inc.cpp"
|
||||
#undef LIR_OP_0
|
||||
#undef LIR_OP_1
|
||||
#undef LIR_OP_2
|
||||
#undef LIR_OP_3
|
||||
|
||||
#define LIR_OP_0(x)
|
||||
#define LIR_OP_1(x) x,
|
||||
#define LIR_OP_2(x)
|
||||
#define LIR_OP_3(x)
|
||||
#include "lir-ops.inc.cpp"
|
||||
#undef LIR_OP_0
|
||||
#undef LIR_OP_1
|
||||
#undef LIR_OP_2
|
||||
#undef LIR_OP_3
|
||||
NoUnaryOperation = -1
|
||||
};
|
||||
|
||||
const unsigned UnaryOperationCount = AlignedJump + 1;
|
||||
|
||||
enum BinaryOperation {
|
||||
#define LIR_OP_0(x)
|
||||
#define LIR_OP_1(x)
|
||||
#define LIR_OP_2(x) x,
|
||||
#define LIR_OP_3(x)
|
||||
#include "lir-ops.inc.cpp"
|
||||
#undef LIR_OP_0
|
||||
#undef LIR_OP_1
|
||||
#undef LIR_OP_2
|
||||
#undef LIR_OP_3
|
||||
|
||||
#define LIR_OP_0(x)
|
||||
#define LIR_OP_1(x)
|
||||
#define LIR_OP_2(x) x,
|
||||
#define LIR_OP_3(x)
|
||||
#include "lir-ops.inc.cpp"
|
||||
#undef LIR_OP_0
|
||||
#undef LIR_OP_1
|
||||
#undef LIR_OP_2
|
||||
#undef LIR_OP_3
|
||||
NoBinaryOperation = -1
|
||||
};
|
||||
|
||||
const unsigned BinaryOperationCount = Absolute + 1;
|
||||
|
||||
enum TernaryOperation {
|
||||
#define LIR_OP_0(x)
|
||||
#define LIR_OP_1(x)
|
||||
#define LIR_OP_2(x)
|
||||
#define LIR_OP_3(x) x,
|
||||
#include "lir-ops.inc.cpp"
|
||||
#undef LIR_OP_0
|
||||
#undef LIR_OP_1
|
||||
#undef LIR_OP_2
|
||||
#undef LIR_OP_3
|
||||
|
||||
#define LIR_OP_0(x)
|
||||
#define LIR_OP_1(x)
|
||||
#define LIR_OP_2(x)
|
||||
#define LIR_OP_3(x) x,
|
||||
#include "lir-ops.inc.cpp"
|
||||
#undef LIR_OP_0
|
||||
#undef LIR_OP_1
|
||||
#undef LIR_OP_2
|
||||
#undef LIR_OP_3
|
||||
NoTernaryOperation = -1
|
||||
};
|
||||
|
||||
const unsigned TernaryOperationCount
|
||||
= JumpIfFloatGreaterOrEqualOrUnordered + 1;
|
||||
const unsigned TernaryOperationCount = JumpIfFloatGreaterOrEqualOrUnordered + 1;
|
||||
|
||||
const unsigned NonBranchTernaryOperationCount = FloatMin + 1;
|
||||
const unsigned BranchOperationCount
|
||||
= JumpIfFloatGreaterOrEqualOrUnordered - FloatMin;
|
||||
const unsigned BranchOperationCount = JumpIfFloatGreaterOrEqualOrUnordered
|
||||
- FloatMin;
|
||||
|
||||
enum OperandType {
|
||||
ConstantOperand,
|
||||
@ -90,72 +86,84 @@ enum OperandType {
|
||||
MemoryOperand
|
||||
};
|
||||
|
||||
enum ValueType {
|
||||
ValueGeneral,
|
||||
ValueFloat
|
||||
};
|
||||
enum ValueType { ValueGeneral, ValueFloat };
|
||||
|
||||
const unsigned OperandTypeCount = MemoryOperand + 1;
|
||||
|
||||
const int NoRegister = -1;
|
||||
|
||||
inline bool isBranch(lir::TernaryOperation op) {
|
||||
inline bool isBranch(lir::TernaryOperation op)
|
||||
{
|
||||
return op > FloatMin;
|
||||
}
|
||||
|
||||
inline bool isFloatBranch(lir::TernaryOperation op) {
|
||||
inline bool isFloatBranch(lir::TernaryOperation op)
|
||||
{
|
||||
return op > JumpIfNotEqual;
|
||||
}
|
||||
|
||||
inline bool isGeneralBranch(lir::TernaryOperation op) {
|
||||
inline bool isGeneralBranch(lir::TernaryOperation op)
|
||||
{
|
||||
return isBranch(op) && !isFloatBranch(op);
|
||||
}
|
||||
|
||||
inline bool isGeneralBinaryOp(lir::TernaryOperation op) {
|
||||
inline bool isGeneralBinaryOp(lir::TernaryOperation op)
|
||||
{
|
||||
return op < FloatAdd;
|
||||
}
|
||||
|
||||
inline bool isFloatBinaryOp(lir::TernaryOperation op) {
|
||||
inline bool isFloatBinaryOp(lir::TernaryOperation op)
|
||||
{
|
||||
return op >= FloatAdd && op <= FloatMin;
|
||||
}
|
||||
|
||||
inline bool isGeneralUnaryOp(lir::BinaryOperation op) {
|
||||
inline bool isGeneralUnaryOp(lir::BinaryOperation op)
|
||||
{
|
||||
return op == Negate || op == Absolute;
|
||||
}
|
||||
|
||||
inline bool isFloatUnaryOp(lir::BinaryOperation op) {
|
||||
inline bool isFloatUnaryOp(lir::BinaryOperation op)
|
||||
{
|
||||
return op == FloatNegate || op == FloatSquareRoot || op == FloatAbsolute;
|
||||
}
|
||||
|
||||
class Operand { };
|
||||
class Operand {
|
||||
};
|
||||
|
||||
class Constant: public Operand {
|
||||
class Constant : public Operand {
|
||||
public:
|
||||
Constant(Promise* value): value(value) { }
|
||||
Constant(Promise* value) : value(value)
|
||||
{
|
||||
}
|
||||
|
||||
Promise* value;
|
||||
};
|
||||
|
||||
class Address: public Operand {
|
||||
class Address : public Operand {
|
||||
public:
|
||||
Address(Promise* address): address(address) { }
|
||||
Address(Promise* address) : address(address)
|
||||
{
|
||||
}
|
||||
|
||||
Promise* address;
|
||||
};
|
||||
|
||||
class Register: public Operand {
|
||||
class Register : public Operand {
|
||||
public:
|
||||
Register(int low, int high = NoRegister): low(low), high(high) { }
|
||||
Register(int low, int high = NoRegister) : low(low), high(high)
|
||||
{
|
||||
}
|
||||
|
||||
int low;
|
||||
int high;
|
||||
};
|
||||
|
||||
class Memory: public Operand {
|
||||
class Memory : public Operand {
|
||||
public:
|
||||
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1):
|
||||
base(base), offset(offset), index(index), scale(scale)
|
||||
{ }
|
||||
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1)
|
||||
: base(base), offset(offset), index(index), scale(scale)
|
||||
{
|
||||
}
|
||||
|
||||
int base;
|
||||
int offset;
|
||||
@ -163,8 +171,8 @@ class Memory: public Operand {
|
||||
unsigned scale;
|
||||
};
|
||||
|
||||
} // namespace lir
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace lir
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_LIR_H
|
||||
#endif // AVIAN_CODEGEN_LIR_H
|
||||
|
@ -29,35 +29,45 @@ class Promise {
|
||||
|
||||
virtual int64_t value() = 0;
|
||||
virtual bool resolved() = 0;
|
||||
virtual Listener* listen(unsigned) { return 0; }
|
||||
virtual Listener* listen(unsigned)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class ResolvedPromise: public Promise {
|
||||
class ResolvedPromise : public Promise {
|
||||
public:
|
||||
ResolvedPromise(int64_t value): value_(value) { }
|
||||
ResolvedPromise(int64_t value) : value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int64_t value() {
|
||||
virtual int64_t value()
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
virtual bool resolved()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t value_;
|
||||
};
|
||||
|
||||
class ShiftMaskPromise: public Promise {
|
||||
class ShiftMaskPromise : public Promise {
|
||||
public:
|
||||
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
|
||||
base(base), shift(shift), mask(mask)
|
||||
{ }
|
||||
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask)
|
||||
: base(base), shift(shift), mask(mask)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int64_t value() {
|
||||
virtual int64_t value()
|
||||
{
|
||||
return (base->value() >> shift) & mask;
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
virtual bool resolved()
|
||||
{
|
||||
return base->resolved();
|
||||
}
|
||||
|
||||
@ -66,17 +76,19 @@ class ShiftMaskPromise: public Promise {
|
||||
int64_t mask;
|
||||
};
|
||||
|
||||
class CombinedPromise: public Promise {
|
||||
class CombinedPromise : public Promise {
|
||||
public:
|
||||
CombinedPromise(Promise* low, Promise* high):
|
||||
low(low), high(high)
|
||||
{ }
|
||||
CombinedPromise(Promise* low, Promise* high) : low(low), high(high)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int64_t value() {
|
||||
virtual int64_t value()
|
||||
{
|
||||
return low->value() | (high->value() << 32);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
virtual bool resolved()
|
||||
{
|
||||
return low->resolved() and high->resolved();
|
||||
}
|
||||
|
||||
@ -84,17 +96,19 @@ class CombinedPromise: public Promise {
|
||||
Promise* high;
|
||||
};
|
||||
|
||||
class OffsetPromise: public Promise {
|
||||
class OffsetPromise : public Promise {
|
||||
public:
|
||||
OffsetPromise(Promise* base, int64_t offset):
|
||||
base(base), offset(offset)
|
||||
{ }
|
||||
OffsetPromise(Promise* base, int64_t offset) : base(base), offset(offset)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int64_t value() {
|
||||
virtual int64_t value()
|
||||
{
|
||||
return base->value() + offset;
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
virtual bool resolved()
|
||||
{
|
||||
return base->resolved();
|
||||
}
|
||||
|
||||
@ -102,21 +116,25 @@ class OffsetPromise: public Promise {
|
||||
int64_t offset;
|
||||
};
|
||||
|
||||
class ListenPromise: public Promise {
|
||||
class ListenPromise : public Promise {
|
||||
public:
|
||||
ListenPromise(vm::System* s, util::Allocator* allocator)
|
||||
: s(s), allocator(allocator), listener(0)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual int64_t value() {
|
||||
virtual int64_t value()
|
||||
{
|
||||
abort(s);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
virtual bool resolved()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual Listener* listen(unsigned sizeInBytes) {
|
||||
virtual Listener* listen(unsigned sizeInBytes)
|
||||
{
|
||||
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
|
||||
l->next = listener;
|
||||
listener = l;
|
||||
@ -129,24 +147,28 @@ class ListenPromise: public Promise {
|
||||
Promise* promise;
|
||||
};
|
||||
|
||||
class DelayedPromise: public ListenPromise {
|
||||
class DelayedPromise : public ListenPromise {
|
||||
public:
|
||||
DelayedPromise(vm::System* s,
|
||||
util::Allocator* allocator,
|
||||
Promise* basis,
|
||||
DelayedPromise* next)
|
||||
: ListenPromise(s, allocator), basis(basis), next(next)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual int64_t value() {
|
||||
virtual int64_t value()
|
||||
{
|
||||
abort(s);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
virtual bool resolved()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual Listener* listen(unsigned sizeInBytes) {
|
||||
virtual Listener* listen(unsigned sizeInBytes)
|
||||
{
|
||||
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
|
||||
l->next = listener;
|
||||
listener = l;
|
||||
@ -157,7 +179,7 @@ class DelayedPromise: public ListenPromise {
|
||||
DelayedPromise* next;
|
||||
};
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_PROMISE_H
|
||||
|
@ -17,7 +17,7 @@ namespace avian {
|
||||
namespace codegen {
|
||||
|
||||
class RegisterMask {
|
||||
public:
|
||||
public:
|
||||
uint32_t mask;
|
||||
uint8_t start;
|
||||
uint8_t limit;
|
||||
@ -25,49 +25,52 @@ public:
|
||||
static unsigned maskStart(uint32_t mask);
|
||||
static unsigned maskLimit(uint32_t mask);
|
||||
|
||||
inline RegisterMask(uint32_t mask):
|
||||
mask(mask),
|
||||
start(maskStart(mask)),
|
||||
limit(maskLimit(mask))
|
||||
{ }
|
||||
inline RegisterMask(uint32_t mask)
|
||||
: mask(mask), start(maskStart(mask)), limit(maskLimit(mask))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class RegisterFile {
|
||||
public:
|
||||
public:
|
||||
RegisterMask allRegisters;
|
||||
RegisterMask generalRegisters;
|
||||
RegisterMask floatRegisters;
|
||||
|
||||
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask):
|
||||
allRegisters(generalRegisterMask | floatRegisterMask),
|
||||
generalRegisters(generalRegisterMask),
|
||||
floatRegisters(floatRegisterMask)
|
||||
{ }
|
||||
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask)
|
||||
: allRegisters(generalRegisterMask | floatRegisterMask),
|
||||
generalRegisters(generalRegisterMask),
|
||||
floatRegisters(floatRegisterMask)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class RegisterIterator {
|
||||
public:
|
||||
public:
|
||||
int index;
|
||||
const RegisterMask& mask;
|
||||
|
||||
inline RegisterIterator(const RegisterMask& mask):
|
||||
index(mask.start),
|
||||
mask(mask) {}
|
||||
inline RegisterIterator(const RegisterMask& mask)
|
||||
: index(mask.start), mask(mask)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool hasNext() {
|
||||
inline bool hasNext()
|
||||
{
|
||||
return index < mask.limit;
|
||||
}
|
||||
|
||||
inline int next() {
|
||||
inline int next()
|
||||
{
|
||||
int r = index;
|
||||
do {
|
||||
index++;
|
||||
} while(index < mask.limit && !(mask.mask & (1 << index)));
|
||||
} while (index < mask.limit && !(mask.mask & (1 << index)));
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_REGISTERS_H
|
||||
|
@ -47,8 +47,8 @@ uint64_t intToFloat(int32_t a);
|
||||
uint64_t longToDouble(int64_t a);
|
||||
uint64_t longToFloat(int64_t a);
|
||||
|
||||
} // namespace runtime
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace runtime
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_RUNTIME_H
|
||||
#endif // AVIAN_CODEGEN_RUNTIME_H
|
||||
|
@ -20,12 +20,13 @@ namespace codegen {
|
||||
|
||||
class Architecture;
|
||||
|
||||
Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures);
|
||||
Architecture* makeArchitectureNative(vm::System* system,
|
||||
bool useNativeFeatures);
|
||||
|
||||
Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures);
|
||||
Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures);
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_TARGETS_H
|
||||
#endif // AVIAN_CODEGEN_TARGETS_H
|
||||
|
@ -24,17 +24,9 @@ const unsigned FixieTenureThreshold = TenureThreshold + 2;
|
||||
|
||||
class Heap : public avian::util::Allocator {
|
||||
public:
|
||||
enum CollectionType {
|
||||
MinorCollection,
|
||||
MajorCollection
|
||||
};
|
||||
enum CollectionType { MinorCollection, MajorCollection };
|
||||
|
||||
enum Status {
|
||||
Null,
|
||||
Reachable,
|
||||
Unreachable,
|
||||
Tenured
|
||||
};
|
||||
enum Status { Null, Reachable, Unreachable, Tenured };
|
||||
|
||||
class Visitor {
|
||||
public:
|
||||
@ -62,7 +54,8 @@ class Heap : public avian::util::Allocator {
|
||||
virtual unsigned remaining() = 0;
|
||||
virtual unsigned limit() = 0;
|
||||
virtual bool limitExceeded(int pendingAllocation = 0) = 0;
|
||||
virtual void collect(CollectionType type, unsigned footprint,
|
||||
virtual void collect(CollectionType type,
|
||||
unsigned footprint,
|
||||
int pendingAllocation) = 0;
|
||||
virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) = 0;
|
||||
virtual void* allocateFixed(avian::util::Allocator* allocator,
|
||||
@ -90,6 +83,6 @@ class Heap : public avian::util::Allocator {
|
||||
|
||||
Heap* makeHeap(System* system, unsigned limit);
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//HEAP_H
|
||||
#endif // HEAP_H
|
||||
|
@ -21,7 +21,8 @@ namespace system {
|
||||
// order to trigger the crash dump logic.
|
||||
NO_RETURN void crash();
|
||||
|
||||
// Registrar for unix-like "signals" (implemented with structured exceptions on windows).
|
||||
// Registrar for unix-like "signals" (implemented with structured exceptions on
|
||||
// windows).
|
||||
// TODO: remove dependence on generated code having a well-known "thread"
|
||||
// register. Use a thread-local variable instead.
|
||||
class SignalRegistrar {
|
||||
@ -40,7 +41,6 @@ class SignalRegistrar {
|
||||
// "Segmentation fault" exceptions (mostly null pointer dereference, but
|
||||
// generally access to any non-mapped memory)
|
||||
SegFault,
|
||||
|
||||
DivideByZero,
|
||||
};
|
||||
|
||||
@ -72,11 +72,10 @@ class SignalRegistrar {
|
||||
struct Data;
|
||||
|
||||
private:
|
||||
|
||||
Data* data;
|
||||
};
|
||||
|
||||
} // namespace system
|
||||
} // namespace avian
|
||||
} // namespace system
|
||||
} // namespace avian
|
||||
|
||||
#endif
|
||||
|
@ -21,12 +21,7 @@ class System : public avian::util::Aborter {
|
||||
public:
|
||||
typedef intptr_t Status;
|
||||
|
||||
enum FileType {
|
||||
TypeUnknown,
|
||||
TypeDoesNotExist,
|
||||
TypeFile,
|
||||
TypeDirectory
|
||||
};
|
||||
enum FileType { TypeUnknown, TypeDoesNotExist, TypeFile, TypeDirectory };
|
||||
|
||||
class Thread {
|
||||
public:
|
||||
@ -100,11 +95,13 @@ class System : public avian::util::Aborter {
|
||||
|
||||
class MonitorResource {
|
||||
public:
|
||||
MonitorResource(System::Thread* t, System::Monitor* m): t(t), m(m) {
|
||||
MonitorResource(System::Thread* t, System::Monitor* m) : t(t), m(m)
|
||||
{
|
||||
m->acquire(t);
|
||||
}
|
||||
|
||||
~MonitorResource() {
|
||||
~MonitorResource()
|
||||
{
|
||||
m->release(t);
|
||||
}
|
||||
|
||||
@ -126,8 +123,8 @@ class System : public avian::util::Aborter {
|
||||
virtual Status make(Monitor**) = 0;
|
||||
virtual Status make(Local**) = 0;
|
||||
|
||||
virtual Status visit(Thread* thread, Thread* target,
|
||||
ThreadVisitor* visitor) = 0;
|
||||
virtual Status visit(Thread* thread, Thread* target, ThreadVisitor* visitor)
|
||||
= 0;
|
||||
|
||||
virtual Status map(Region**, const char* name) = 0;
|
||||
virtual FileType stat(const char* name, unsigned* length) = 0;
|
||||
@ -145,23 +142,23 @@ class System : public avian::util::Aborter {
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
inline void*
|
||||
allocate(System* s, unsigned size)
|
||||
inline void* allocate(System* s, unsigned size)
|
||||
{
|
||||
void* p = s->tryAllocate(size);
|
||||
if (p == 0) s->abort();
|
||||
if (p == 0)
|
||||
s->abort();
|
||||
return p;
|
||||
}
|
||||
|
||||
#define ACQUIRE_MONITOR(t, m) \
|
||||
System::MonitorResource MAKE_NAME(monitorResource_) (t, m)
|
||||
System::MonitorResource MAKE_NAME(monitorResource_)(t, m)
|
||||
|
||||
inline avian::util::Aborter* getAborter(System* s) {
|
||||
inline avian::util::Aborter* getAborter(System* s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
inline void NO_RETURN
|
||||
sysAbort(System* s)
|
||||
inline void NO_RETURN sysAbort(System* s)
|
||||
{
|
||||
abort(s);
|
||||
}
|
||||
@ -183,9 +180,8 @@ sysAbort(System* s)
|
||||
|
||||
// #endif // not NDEBUG
|
||||
|
||||
AVIAN_EXPORT System*
|
||||
makeSystem();
|
||||
AVIAN_EXPORT System* makeSystem();
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//SYSTEM_H
|
||||
#endif // SYSTEM_H
|
||||
|
@ -23,16 +23,17 @@ namespace avian {
|
||||
namespace tools {
|
||||
|
||||
class OutputStream {
|
||||
public:
|
||||
public:
|
||||
virtual void writeChunk(const void* data, size_t size) = 0;
|
||||
virtual void write(uint8_t byte);
|
||||
virtual void writeRepeat(uint8_t byte, size_t size);
|
||||
};
|
||||
|
||||
class FileOutputStream : public OutputStream {
|
||||
private:
|
||||
private:
|
||||
FILE* file;
|
||||
public:
|
||||
|
||||
public:
|
||||
FileOutputStream(const char* name);
|
||||
~FileOutputStream();
|
||||
|
||||
@ -43,20 +44,22 @@ public:
|
||||
};
|
||||
|
||||
class SymbolInfo {
|
||||
public:
|
||||
public:
|
||||
unsigned addr;
|
||||
util::String name;
|
||||
|
||||
inline SymbolInfo(uint64_t addr, const util::String& name):
|
||||
addr(addr),
|
||||
name(name) {}
|
||||
inline SymbolInfo(uint64_t addr, const util::String& name)
|
||||
: addr(addr), name(name)
|
||||
{
|
||||
}
|
||||
|
||||
inline SymbolInfo():
|
||||
name("") {}
|
||||
inline SymbolInfo() : name("")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Buffer {
|
||||
public:
|
||||
public:
|
||||
size_t capacity;
|
||||
size_t length;
|
||||
uint8_t* data;
|
||||
@ -69,7 +72,7 @@ public:
|
||||
};
|
||||
|
||||
class StringTable : public Buffer {
|
||||
public:
|
||||
public:
|
||||
unsigned add(util::String str);
|
||||
};
|
||||
|
||||
@ -103,7 +106,7 @@ class DynamicArray : public util::Slice<T> {
|
||||
};
|
||||
|
||||
class PlatformInfo {
|
||||
public:
|
||||
public:
|
||||
enum Format {
|
||||
Elf = AVIAN_FORMAT_ELF,
|
||||
Pe = AVIAN_FORMAT_PE,
|
||||
@ -124,33 +127,31 @@ public:
|
||||
static Format formatFromString(const char* format);
|
||||
static Architecture archFromString(const char* arch);
|
||||
|
||||
inline PlatformInfo(Format format, Architecture arch):
|
||||
format(format),
|
||||
arch(arch) {}
|
||||
inline PlatformInfo(Format format, Architecture arch)
|
||||
: format(format), arch(arch)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool operator == (const PlatformInfo& other) {
|
||||
inline bool operator==(const PlatformInfo& other)
|
||||
{
|
||||
return format == other.format && arch == other.arch;
|
||||
}
|
||||
};
|
||||
|
||||
class Platform {
|
||||
private:
|
||||
private:
|
||||
Platform* next;
|
||||
static Platform* first;
|
||||
public:
|
||||
|
||||
public:
|
||||
PlatformInfo info;
|
||||
|
||||
inline Platform(PlatformInfo info):
|
||||
next(first),
|
||||
info(info)
|
||||
inline Platform(PlatformInfo info) : next(first), info(info)
|
||||
{
|
||||
first = this;
|
||||
}
|
||||
|
||||
enum AccessFlags {
|
||||
Writable = 1 << 0,
|
||||
Executable = 1 << 1
|
||||
};
|
||||
enum AccessFlags { Writable = 1 << 0, Executable = 1 << 1 };
|
||||
|
||||
virtual bool writeObject(OutputStream* out,
|
||||
util::Slice<SymbolInfo> symbols,
|
||||
@ -161,9 +162,8 @@ public:
|
||||
static Platform* getPlatform(PlatformInfo info);
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
} // namespace tools
|
||||
|
||||
} // namespace avian
|
||||
} // namespace avian
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -19,7 +19,7 @@ namespace avian {
|
||||
namespace util {
|
||||
|
||||
class Aborter {
|
||||
public:
|
||||
public:
|
||||
virtual void NO_RETURN abort() = 0;
|
||||
};
|
||||
|
||||
@ -28,15 +28,17 @@ inline Aborter* getAborter(Aborter* a)
|
||||
return a;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void NO_RETURN abort(T t) {
|
||||
template <class T>
|
||||
inline void NO_RETURN abort(T t)
|
||||
{
|
||||
getAborter(t)->abort();
|
||||
::abort();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void expect(T t, bool v) {
|
||||
if(UNLIKELY(!v)) {
|
||||
template <class T>
|
||||
inline void expect(T t, bool v)
|
||||
{
|
||||
if (UNLIKELY(!v)) {
|
||||
abort(t);
|
||||
}
|
||||
}
|
||||
@ -51,7 +53,7 @@ inline void assertT(T t, bool v)
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace util
|
||||
} // namespace avian
|
||||
} // namespace util
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_UTIL_ABORT_H
|
||||
#endif // AVIAN_UTIL_ABORT_H
|
||||
|
@ -31,7 +31,7 @@ class ArgParser {
|
||||
};
|
||||
|
||||
class Arg {
|
||||
public:
|
||||
public:
|
||||
Arg* next;
|
||||
bool required;
|
||||
const char* name;
|
||||
@ -42,8 +42,7 @@ public:
|
||||
Arg(ArgParser& parser, bool required, const char* name, const char* desc);
|
||||
};
|
||||
|
||||
|
||||
} // namespace avian
|
||||
} // namespace util
|
||||
} // namespace avian
|
||||
} // namespace util
|
||||
|
||||
#endif // AVIAN_UTIL_ARG_PARSER_H
|
||||
|
@ -18,16 +18,17 @@ namespace util {
|
||||
|
||||
template <class T>
|
||||
class List {
|
||||
public:
|
||||
List(const T& item, List<T>* next):
|
||||
item(item),
|
||||
next(next) {}
|
||||
public:
|
||||
List(const T& item, List<T>* next) : item(item), next(next)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned count() {
|
||||
unsigned count()
|
||||
{
|
||||
unsigned count = 0;
|
||||
List<T>* c = this;
|
||||
while (c) {
|
||||
++ count;
|
||||
++count;
|
||||
c = c->next;
|
||||
}
|
||||
return count;
|
||||
|
@ -17,40 +17,51 @@
|
||||
namespace avian {
|
||||
namespace util {
|
||||
|
||||
inline unsigned max(unsigned a, unsigned b) {
|
||||
inline unsigned max(unsigned a, unsigned b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
inline unsigned min(unsigned a, unsigned b) {
|
||||
inline unsigned min(unsigned a, unsigned b)
|
||||
{
|
||||
return (a < b ? a : b);
|
||||
}
|
||||
|
||||
inline unsigned avg(unsigned a, unsigned b) {
|
||||
inline unsigned avg(unsigned a, unsigned b)
|
||||
{
|
||||
return (a + b) / 2;
|
||||
}
|
||||
|
||||
inline unsigned ceilingDivide(unsigned n, unsigned d) {
|
||||
inline unsigned ceilingDivide(unsigned n, unsigned d)
|
||||
{
|
||||
return (n + d - 1) / d;
|
||||
}
|
||||
|
||||
inline bool powerOfTwo(unsigned n) {
|
||||
for (; n > 2; n >>= 1) if (n & 1) return false;
|
||||
inline bool powerOfTwo(unsigned n)
|
||||
{
|
||||
for (; n > 2; n >>= 1)
|
||||
if (n & 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned nextPowerOfTwo(unsigned n) {
|
||||
inline unsigned nextPowerOfTwo(unsigned n)
|
||||
{
|
||||
unsigned r = 1;
|
||||
while (r < n) r <<= 1;
|
||||
while (r < n)
|
||||
r <<= 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
inline unsigned log(unsigned n) {
|
||||
inline unsigned log(unsigned n)
|
||||
{
|
||||
unsigned r = 0;
|
||||
for (unsigned i = 1; i < n; ++r) i <<= 1;
|
||||
for (unsigned i = 1; i < n; ++r)
|
||||
i <<= 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_UTIL_MATH_H
|
||||
} // namespace util
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_UTIL_MATH_H
|
||||
|
@ -16,25 +16,26 @@
|
||||
template <class T>
|
||||
class RuntimeArray {
|
||||
public:
|
||||
RuntimeArray(unsigned size):
|
||||
body(static_cast<T*>(malloc(size * sizeof(T))))
|
||||
{ }
|
||||
RuntimeArray(unsigned size) : body(static_cast<T*>(malloc(size * sizeof(T))))
|
||||
{
|
||||
}
|
||||
|
||||
~RuntimeArray() {
|
||||
~RuntimeArray()
|
||||
{
|
||||
free(body);
|
||||
}
|
||||
|
||||
T* body;
|
||||
};
|
||||
|
||||
# define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size);
|
||||
# define RUNTIME_ARRAY_BODY(name) name.body
|
||||
#define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size);
|
||||
#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_BODY(name) name##_body
|
||||
#define RUNTIME_ARRAY(type, name, size) type name##_body[size];
|
||||
#define RUNTIME_ARRAY_BODY(name) name##_body
|
||||
|
||||
#endif
|
||||
|
||||
#endif // AVIAN_UTIL_RUNTIME_ARRAY_H
|
||||
#endif // AVIAN_UTIL_RUNTIME_ARRAY_H
|
||||
|
@ -22,19 +22,23 @@ class AbstractStream {
|
||||
virtual void handleError() = 0;
|
||||
};
|
||||
|
||||
AbstractStream(Client* client, unsigned size):
|
||||
client(client), size(size), position_(0)
|
||||
{ }
|
||||
AbstractStream(Client* client, unsigned size)
|
||||
: client(client), size(size), position_(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned position() {
|
||||
unsigned position()
|
||||
{
|
||||
return position_;
|
||||
}
|
||||
|
||||
void setPosition(unsigned p) {
|
||||
void setPosition(unsigned p)
|
||||
{
|
||||
position_ = p;
|
||||
}
|
||||
|
||||
void skip(unsigned size) {
|
||||
void skip(unsigned size)
|
||||
{
|
||||
if (size > this->size - position_) {
|
||||
client->handleError();
|
||||
} else {
|
||||
@ -42,7 +46,8 @@ class AbstractStream {
|
||||
}
|
||||
}
|
||||
|
||||
void read(uint8_t* dst, unsigned size) {
|
||||
void read(uint8_t* dst, unsigned size)
|
||||
{
|
||||
if (size > this->size - position_) {
|
||||
memset(dst, 0, size);
|
||||
|
||||
@ -53,35 +58,41 @@ class AbstractStream {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t read1() {
|
||||
uint8_t read1()
|
||||
{
|
||||
uint8_t v;
|
||||
read(&v, 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
uint16_t read2() {
|
||||
uint16_t read2()
|
||||
{
|
||||
uint16_t a = read1();
|
||||
uint16_t b = read1();
|
||||
return (a << 8) | b;
|
||||
}
|
||||
|
||||
uint32_t read4() {
|
||||
uint32_t read4()
|
||||
{
|
||||
uint32_t a = read2();
|
||||
uint32_t b = read2();
|
||||
return (a << 16) | b;
|
||||
}
|
||||
|
||||
uint64_t read8() {
|
||||
uint64_t read8()
|
||||
{
|
||||
uint64_t a = read4();
|
||||
uint64_t b = read4();
|
||||
return (a << 32) | b;
|
||||
}
|
||||
|
||||
uint32_t readFloat() {
|
||||
uint32_t readFloat()
|
||||
{
|
||||
return read4();
|
||||
}
|
||||
|
||||
uint64_t readDouble() {
|
||||
uint64_t readDouble()
|
||||
{
|
||||
return read8();
|
||||
}
|
||||
|
||||
@ -94,20 +105,22 @@ class AbstractStream {
|
||||
unsigned position_;
|
||||
};
|
||||
|
||||
class Stream: public AbstractStream {
|
||||
class Stream : public AbstractStream {
|
||||
public:
|
||||
Stream(Client* client, const uint8_t* data, unsigned size):
|
||||
AbstractStream(client, size), data(data)
|
||||
{ }
|
||||
Stream(Client* client, const uint8_t* data, unsigned size)
|
||||
: AbstractStream(client, size), data(data)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void copy(uint8_t* dst, unsigned offset, unsigned size) {
|
||||
virtual void copy(uint8_t* dst, unsigned offset, unsigned size)
|
||||
{
|
||||
memcpy(dst, data + offset, size);
|
||||
}
|
||||
|
||||
const uint8_t* data;
|
||||
};
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//STREAM_H
|
||||
#endif // STREAM_H
|
||||
|
@ -17,38 +17,43 @@ namespace avian {
|
||||
namespace util {
|
||||
|
||||
class String {
|
||||
public:
|
||||
public:
|
||||
const char* text;
|
||||
size_t length;
|
||||
|
||||
String(const char* text):
|
||||
text(text),
|
||||
length(strlen(text)) {}
|
||||
|
||||
inline String(const char* text, size_t length):
|
||||
text(text),
|
||||
length(length) {}
|
||||
String(const char* text) : text(text), length(strlen(text))
|
||||
{
|
||||
}
|
||||
|
||||
inline String(const char* text, size_t length) : text(text), length(length)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Tokenizer {
|
||||
public:
|
||||
Tokenizer(const char* s, char delimiter)
|
||||
: s(s), limit(0), delimiter(delimiter)
|
||||
{
|
||||
}
|
||||
|
||||
Tokenizer(const char* s, char delimiter):
|
||||
s(s), limit(0), delimiter(delimiter)
|
||||
{ }
|
||||
Tokenizer(String str, char delimiter)
|
||||
: s(str.text), limit(str.text + str.length), delimiter(delimiter)
|
||||
{
|
||||
}
|
||||
|
||||
Tokenizer(String str, char delimiter):
|
||||
s(str.text), limit(str.text + str.length), delimiter(delimiter)
|
||||
{ }
|
||||
|
||||
bool hasMore() {
|
||||
while (s != limit and *s == delimiter) ++s;
|
||||
bool hasMore()
|
||||
{
|
||||
while (s != limit and *s == delimiter)
|
||||
++s;
|
||||
return s != limit and *s != 0;
|
||||
}
|
||||
|
||||
String next() {
|
||||
String next()
|
||||
{
|
||||
const char* p = s;
|
||||
while (s != limit and *s and *s != delimiter) ++s;
|
||||
while (s != limit and *s and *s != delimiter)
|
||||
++s;
|
||||
return String(p, s - p);
|
||||
}
|
||||
|
||||
@ -57,7 +62,7 @@ class Tokenizer {
|
||||
char delimiter;
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
} // namespace avain
|
||||
} // namespace util
|
||||
} // namespace avain
|
||||
|
||||
#endif//AVIAN_UTIL_STRING_H
|
||||
#endif // AVIAN_UTIL_STRING_H
|
||||
|
@ -11,8 +11,7 @@ struct JniConstants {
|
||||
static void init(_JNIEnv* env);
|
||||
};
|
||||
|
||||
void
|
||||
JniConstants::init(_JNIEnv*)
|
||||
void JniConstants::init(_JNIEnv*)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
@ -33,13 +33,16 @@ class Vector {
|
||||
data(0, 0),
|
||||
position(0),
|
||||
minimumCapacity(minimumCapacity)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
~Vector() {
|
||||
~Vector()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
void dispose()
|
||||
{
|
||||
if (data.items and minimumCapacity > 0) {
|
||||
allocator->free(data.items, data.count);
|
||||
data.items = 0;
|
||||
@ -95,27 +98,33 @@ class Vector {
|
||||
return r;
|
||||
}
|
||||
|
||||
void append(uint8_t v) {
|
||||
void append(uint8_t v)
|
||||
{
|
||||
append(&v, 1);
|
||||
}
|
||||
|
||||
void append2(uint16_t v) {
|
||||
void append2(uint16_t v)
|
||||
{
|
||||
append(&v, 2);
|
||||
}
|
||||
|
||||
void append4(uint32_t v) {
|
||||
void append4(uint32_t v)
|
||||
{
|
||||
append(&v, 4);
|
||||
}
|
||||
|
||||
void appendTargetAddress(target_uintptr_t v) {
|
||||
void appendTargetAddress(target_uintptr_t v)
|
||||
{
|
||||
append(&v, TargetBytesPerWord);
|
||||
}
|
||||
|
||||
void appendAddress(uintptr_t v) {
|
||||
void appendAddress(uintptr_t v)
|
||||
{
|
||||
append(&v, BytesPerWord);
|
||||
}
|
||||
|
||||
void appendAddress(void* v) {
|
||||
void appendAddress(void* v)
|
||||
{
|
||||
append(&v, BytesPerWord);
|
||||
}
|
||||
|
||||
@ -127,25 +136,29 @@ class Vector {
|
||||
|
||||
size_t get(size_t offset)
|
||||
{
|
||||
uint8_t v; get(offset, &v, 1);
|
||||
uint8_t v;
|
||||
get(offset, &v, 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
size_t get2(size_t offset)
|
||||
{
|
||||
uint16_t v; get(offset, &v, 2);
|
||||
uint16_t v;
|
||||
get(offset, &v, 2);
|
||||
return v;
|
||||
}
|
||||
|
||||
size_t get4(size_t offset)
|
||||
{
|
||||
uint32_t v; get(offset, &v, 4);
|
||||
uint32_t v;
|
||||
get(offset, &v, 4);
|
||||
return v;
|
||||
}
|
||||
|
||||
uintptr_t getAddress(size_t offset)
|
||||
{
|
||||
uintptr_t v; get(offset, &v, BytesPerWord);
|
||||
uintptr_t v;
|
||||
get(offset, &v, BytesPerWord);
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -168,6 +181,6 @@ class Vector {
|
||||
size_t minimumCapacity;
|
||||
};
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//VECTOR_H
|
||||
#endif // VECTOR_H
|
||||
|
@ -12,39 +12,41 @@
|
||||
#define ARCH_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include "windows.h"
|
||||
# pragma push_macro("assert")
|
||||
# include "intrin.h"
|
||||
# pragma pop_macro("assert")
|
||||
# undef interface
|
||||
#include "windows.h"
|
||||
#pragma push_macro("assert")
|
||||
#include "intrin.h"
|
||||
#pragma pop_macro("assert")
|
||||
#undef interface
|
||||
#endif
|
||||
|
||||
#include "avian/common.h"
|
||||
|
||||
extern "C" void NO_RETURN
|
||||
vmJump(void* address, void* frame, void* stack, void* thread,
|
||||
uintptr_t returnLow, uintptr_t returnHigh);
|
||||
extern "C" void NO_RETURN vmJump(void* address,
|
||||
void* frame,
|
||||
void* stack,
|
||||
void* thread,
|
||||
uintptr_t returnLow,
|
||||
uintptr_t returnHigh);
|
||||
|
||||
namespace vm {
|
||||
|
||||
inline void
|
||||
compileTimeMemoryBarrier()
|
||||
inline void compileTimeMemoryBarrier()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
_ReadWriteBarrier();
|
||||
#else
|
||||
__asm__ __volatile__("": : :"memory");
|
||||
__asm__ __volatile__("" : : : "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#if (defined ARCH_x86_32) || (defined ARCH_x86_64)
|
||||
# include "x86.h"
|
||||
#include "x86.h"
|
||||
#elif defined ARCH_arm
|
||||
# include "arm.h"
|
||||
#include "arm.h"
|
||||
#else
|
||||
# error unsupported architecture
|
||||
#error unsupported architecture
|
||||
#endif
|
||||
|
||||
#endif//ARCH_H
|
||||
#endif // ARCH_H
|
||||
|
239
src/avian/arm.h
239
src/avian/arm.h
@ -16,61 +16,62 @@
|
||||
#include <avian/util/runtime-array.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include "libkern/OSAtomic.h"
|
||||
# include "libkern/OSCacheControl.h"
|
||||
# include "mach/mach_types.h"
|
||||
# include "mach/thread_act.h"
|
||||
# include "mach/thread_status.h"
|
||||
#include "libkern/OSAtomic.h"
|
||||
#include "libkern/OSCacheControl.h"
|
||||
#include "mach/mach_types.h"
|
||||
#include "mach/thread_act.h"
|
||||
#include "mach/thread_status.h"
|
||||
|
||||
# define THREAD_STATE ARM_THREAD_STATE
|
||||
# define THREAD_STATE_TYPE arm_thread_state_t
|
||||
# define THREAD_STATE_COUNT ARM_THREAD_STATE_COUNT
|
||||
#define THREAD_STATE ARM_THREAD_STATE
|
||||
#define THREAD_STATE_TYPE arm_thread_state_t
|
||||
#define THREAD_STATE_COUNT ARM_THREAD_STATE_COUNT
|
||||
|
||||
# if __DARWIN_UNIX03 && defined(_STRUCT_ARM_EXCEPTION_STATE)
|
||||
# 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])
|
||||
#if __DARWIN_UNIX03 && defined(_STRUCT_ARM_EXCEPTION_STATE)
|
||||
#define FIELD(x) __##x
|
||||
#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)
|
||||
#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
|
||||
#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
|
||||
|
||||
#define VA_LIST(x) (&(x))
|
||||
|
||||
extern "C" uint64_t
|
||||
vmNativeCall(void* function, unsigned stackTotal, void* memoryTable,
|
||||
unsigned memoryCount, void* gprTable, void* vfpTable,
|
||||
unsigned returnType);
|
||||
extern "C" uint64_t vmNativeCall(void* function,
|
||||
unsigned stackTotal,
|
||||
void* memoryTable,
|
||||
unsigned memoryCount,
|
||||
void* gprTable,
|
||||
void* vfpTable,
|
||||
unsigned returnType);
|
||||
|
||||
namespace vm {
|
||||
|
||||
inline void
|
||||
trap()
|
||||
inline void trap()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__debugbreak();
|
||||
@ -86,23 +87,21 @@ trap()
|
||||
// performant choice.
|
||||
|
||||
#ifndef _MSC_VER
|
||||
inline void
|
||||
memoryBarrier()
|
||||
inline void memoryBarrier()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
OSMemoryBarrier();
|
||||
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
||||
#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
||||
return __sync_synchronize();
|
||||
#elif (! defined AVIAN_ASSUME_ARMV6)
|
||||
__asm__ __volatile__ ("dmb" : : : "memory");
|
||||
#elif(!defined AVIAN_ASSUME_ARMV6)
|
||||
__asm__ __volatile__("dmb" : : : "memory");
|
||||
#else
|
||||
__asm__ __volatile__ ("" : : : "memory");
|
||||
__asm__ __volatile__("" : : : "memory");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void
|
||||
storeStoreMemoryBarrier()
|
||||
inline void storeStoreMemoryBarrier()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
_ReadWriteBarrier();
|
||||
@ -111,8 +110,7 @@ storeStoreMemoryBarrier()
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
storeLoadMemoryBarrier()
|
||||
inline void storeLoadMemoryBarrier()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
MemoryBarrier();
|
||||
@ -121,8 +119,7 @@ storeLoadMemoryBarrier()
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
loadMemoryBarrier()
|
||||
inline void loadMemoryBarrier()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
_ReadWriteBarrier();
|
||||
@ -135,52 +132,54 @@ loadMemoryBarrier()
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// http://code.google.com/p/android/issues/detail?id=1803
|
||||
extern "C" void __clear_cache (void *beg __attribute__((__unused__)), void *end __attribute__((__unused__)));
|
||||
extern "C" void __clear_cache(void* beg __attribute__((__unused__)),
|
||||
void* end __attribute__((__unused__)));
|
||||
#endif
|
||||
inline void
|
||||
syncInstructionCache(const void* start, unsigned size)
|
||||
inline void syncInstructionCache(const void* start, unsigned size)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
sys_icache_invalidate(const_cast<void*>(start), size);
|
||||
#elif (defined __QNX__)
|
||||
#elif(defined __QNX__)
|
||||
msync(const_cast<void*>(start), size, MS_INVALIDATE_ICACHE);
|
||||
#else
|
||||
__clear_cache
|
||||
(const_cast<void*>(start),
|
||||
const_cast<uint8_t*>(static_cast<const uint8_t*>(start) + size));
|
||||
__clear_cache(
|
||||
const_cast<void*>(start),
|
||||
const_cast<uint8_t*>(static_cast<const uint8_t*>(start) + size));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // AVIAN_AOT_ONLY
|
||||
#endif // AVIAN_AOT_ONLY
|
||||
|
||||
#ifndef __APPLE__
|
||||
typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
|
||||
# define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
|
||||
typedef int(__kernel_cmpxchg_t)(int oldval, int newval, int* ptr);
|
||||
#define __kernel_cmpxchg (*(__kernel_cmpxchg_t*)0xffff0fc0)
|
||||
#endif
|
||||
|
||||
inline bool
|
||||
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
||||
inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return OSAtomicCompareAndSwap32Barrier(old, new_, reinterpret_cast<int32_t*>(p));
|
||||
#elif (defined __QNX__)
|
||||
return OSAtomicCompareAndSwap32Barrier(
|
||||
old, new_, reinterpret_cast<int32_t*>(p));
|
||||
#elif(defined __QNX__)
|
||||
return old == _smp_cmpxchg(p, old, new_);
|
||||
#else
|
||||
int r = __kernel_cmpxchg(static_cast<int>(old), static_cast<int>(new_), reinterpret_cast<int*>(p));
|
||||
int r = __kernel_cmpxchg(
|
||||
static_cast<int>(old), static_cast<int>(new_), reinterpret_cast<int*>(p));
|
||||
return (!r ? true : false);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
||||
inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
||||
{
|
||||
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
|
||||
}
|
||||
|
||||
inline uint64_t
|
||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
unsigned argumentCount, unsigned argumentsSize UNUSED,
|
||||
unsigned returnType)
|
||||
inline uint64_t dynamicCall(void* function,
|
||||
uintptr_t* arguments,
|
||||
uint8_t* argumentTypes,
|
||||
unsigned argumentCount,
|
||||
unsigned argumentsSize UNUSED,
|
||||
unsigned returnType)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
const unsigned Alignment = 1;
|
||||
@ -197,34 +196,37 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
unsigned vfpIndex = 0;
|
||||
unsigned vfpBackfillIndex UNUSED = 0;
|
||||
|
||||
RUNTIME_ARRAY(uintptr_t, stack, (argumentCount * 8) / BytesPerWord); // is > argumentSize to account for padding
|
||||
RUNTIME_ARRAY(uintptr_t,
|
||||
stack,
|
||||
(argumentCount * 8)
|
||||
/ BytesPerWord); // is > argumentSize to account for padding
|
||||
unsigned stackIndex = 0;
|
||||
|
||||
unsigned ai = 0;
|
||||
for (unsigned ati = 0; ati < argumentCount; ++ ati) {
|
||||
for (unsigned ati = 0; ati < argumentCount; ++ati) {
|
||||
switch (argumentTypes[ati]) {
|
||||
case DOUBLE_TYPE:
|
||||
#if defined(__ARM_PCS_VFP)
|
||||
{
|
||||
if (vfpIndex + Alignment <= VfpCount) {
|
||||
if (vfpIndex % Alignment) {
|
||||
vfpBackfillIndex = 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;
|
||||
{
|
||||
if (vfpIndex + Alignment <= VfpCount) {
|
||||
if (vfpIndex % Alignment) {
|
||||
vfpBackfillIndex = vfpIndex;
|
||||
++vfpIndex;
|
||||
}
|
||||
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:
|
||||
if (vfpBackfillIndex) {
|
||||
@ -235,26 +237,24 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
} else {
|
||||
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
||||
}
|
||||
++ ai;
|
||||
++ai;
|
||||
break;
|
||||
#endif
|
||||
case INT64_TYPE: {
|
||||
if (gprIndex + Alignment <= GprCount) { // pass argument in register(s)
|
||||
if (Alignment == 1
|
||||
and BytesPerWord < 8
|
||||
and gprIndex + Alignment == GprCount)
|
||||
{
|
||||
if (gprIndex + Alignment <= GprCount) { // pass argument in register(s)
|
||||
if (Alignment == 1 and BytesPerWord < 8
|
||||
and gprIndex + Alignment == GprCount) {
|
||||
gprTable[gprIndex++] = arguments[ai];
|
||||
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1];
|
||||
} else {
|
||||
if (gprIndex % Alignment) {
|
||||
++gprIndex;
|
||||
}
|
||||
|
||||
|
||||
memcpy(gprTable + gprIndex, arguments + ai, 8);
|
||||
gprIndex += 8 / BytesPerWord;
|
||||
}
|
||||
} else { // pass argument on stack
|
||||
} else { // pass argument on stack
|
||||
gprIndex = GprCount;
|
||||
if (stackIndex % Alignment) {
|
||||
++stackIndex;
|
||||
@ -272,27 +272,30 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
} else {
|
||||
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
||||
}
|
||||
++ ai;
|
||||
++ai;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gprIndex < GprCount) { // pad since assembly loads all GPRs
|
||||
memset(gprTable + gprIndex, 0, (GprCount-gprIndex)*4);
|
||||
if (gprIndex < GprCount) { // pad since assembly loads all GPRs
|
||||
memset(gprTable + gprIndex, 0, (GprCount - gprIndex) * 4);
|
||||
gprIndex = GprCount;
|
||||
}
|
||||
if (vfpIndex < VfpCount) {
|
||||
memset(vfpTable + vfpIndex, 0, (VfpCount-vfpIndex)*4);
|
||||
memset(vfpTable + vfpIndex, 0, (VfpCount - vfpIndex) * 4);
|
||||
vfpIndex = VfpCount;
|
||||
}
|
||||
|
||||
unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2);
|
||||
return vmNativeCall
|
||||
(function, stackSize, RUNTIME_ARRAY_BODY(stack), stackIndex * BytesPerWord,
|
||||
(gprIndex ? gprTable : 0),
|
||||
(vfpIndex ? vfpTable : 0), returnType);
|
||||
unsigned stackSize = stackIndex * BytesPerWord + ((stackIndex & 1) << 2);
|
||||
return vmNativeCall(function,
|
||||
stackSize,
|
||||
RUNTIME_ARRAY_BODY(stack),
|
||||
stackIndex * BytesPerWord,
|
||||
(gprIndex ? gprTable : 0),
|
||||
(vfpIndex ? vfpTable : 0),
|
||||
returnType);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif // ARM_H
|
||||
#endif // ARM_H
|
||||
|
@ -24,13 +24,14 @@ class BootImage {
|
||||
public:
|
||||
class Thunk {
|
||||
public:
|
||||
Thunk():
|
||||
start(0), frameSavedOffset(0), length(0)
|
||||
{ }
|
||||
Thunk() : start(0), frameSavedOffset(0), length(0)
|
||||
{
|
||||
}
|
||||
|
||||
Thunk(uint32_t start, uint32_t frameSavedOffset, uint32_t length):
|
||||
start(start), frameSavedOffset(frameSavedOffset), length(length)
|
||||
{ }
|
||||
Thunk(uint32_t start, uint32_t frameSavedOffset, uint32_t length)
|
||||
: start(start), frameSavedOffset(frameSavedOffset), length(length)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t start;
|
||||
uint32_t frameSavedOffset;
|
||||
@ -72,6 +73,6 @@ class OffsetResolver {
|
||||
#undef LABEL
|
||||
#undef NAME
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//BOOTIMAGE_H
|
||||
#endif // BOOTIMAGE_H
|
||||
|
@ -18,16 +18,16 @@ using namespace avian::util;
|
||||
|
||||
namespace vm {
|
||||
|
||||
object
|
||||
getTrace(Thread* t, unsigned skipCount)
|
||||
object getTrace(Thread* t, unsigned skipCount)
|
||||
{
|
||||
class Visitor: public Processor::StackVisitor {
|
||||
class Visitor : public Processor::StackVisitor {
|
||||
public:
|
||||
Visitor(Thread* t, int skipCount):
|
||||
t(t), trace(0), skipCount(skipCount)
|
||||
{ }
|
||||
Visitor(Thread* t, int skipCount) : t(t), trace(0), skipCount(skipCount)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool visit(Processor::StackWalker* walker) {
|
||||
virtual bool visit(Processor::StackWalker* walker)
|
||||
{
|
||||
if (skipCount == 0) {
|
||||
GcMethod* method = walker->method();
|
||||
if (isAssignableFrom(t, type(t, GcThrowable::Type), method->class_())
|
||||
@ -39,7 +39,7 @@ getTrace(Thread* t, unsigned skipCount)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
-- skipCount;
|
||||
--skipCount;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -51,7 +51,8 @@ getTrace(Thread* t, unsigned skipCount)
|
||||
|
||||
t->m->processor->walkStack(t, &v);
|
||||
|
||||
if (v.trace == 0) v.trace = makeObjectArray(t, 0);
|
||||
if (v.trace == 0)
|
||||
v.trace = makeObjectArray(t, 0);
|
||||
|
||||
return v.trace;
|
||||
}
|
||||
@ -63,23 +64,24 @@ bool compatibleArrayTypes(Thread* t UNUSED, GcClass* a, GcClass* b)
|
||||
or (b->vmFlags() & PrimitiveFlag))));
|
||||
}
|
||||
|
||||
void
|
||||
arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
|
||||
int32_t dstOffset, int32_t length)
|
||||
void arrayCopy(Thread* t,
|
||||
object src,
|
||||
int32_t srcOffset,
|
||||
object dst,
|
||||
int32_t dstOffset,
|
||||
int32_t length)
|
||||
{
|
||||
if (LIKELY(src and dst)) {
|
||||
if (LIKELY(compatibleArrayTypes
|
||||
(t, objectClass(t, src), objectClass(t, dst))))
|
||||
{
|
||||
if (LIKELY(compatibleArrayTypes(
|
||||
t, objectClass(t, src), objectClass(t, dst)))) {
|
||||
unsigned elementSize = objectClass(t, src)->arrayElementSize();
|
||||
|
||||
if (LIKELY(elementSize)) {
|
||||
intptr_t sl = fieldAtOffset<uintptr_t>(src, BytesPerWord);
|
||||
intptr_t dl = fieldAtOffset<uintptr_t>(dst, BytesPerWord);
|
||||
if (LIKELY(length > 0)) {
|
||||
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
|
||||
dstOffset >= 0 and dstOffset + length <= dl))
|
||||
{
|
||||
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl
|
||||
and dstOffset >= 0 and dstOffset + length <= dl)) {
|
||||
uint8_t* sbody = &fieldAtOffset<uint8_t>(src, ArrayBody);
|
||||
uint8_t* dbody = &fieldAtOffset<uint8_t>(dst, ArrayBody);
|
||||
if (src == dst) {
|
||||
@ -113,8 +115,7 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
|
||||
throwNew(t, GcArrayStoreException::Type);
|
||||
}
|
||||
|
||||
void
|
||||
runOnLoadIfFound(Thread* t, System::Library* library)
|
||||
void runOnLoadIfFound(Thread* t, System::Library* library)
|
||||
{
|
||||
void* p = library->resolve("JNI_OnLoad");
|
||||
|
||||
@ -128,14 +129,13 @@ runOnLoadIfFound(Thread* t, System::Library* library)
|
||||
#endif
|
||||
|
||||
if (p) {
|
||||
jint (JNICALL * JNI_OnLoad)(Machine*, void*);
|
||||
jint(JNICALL * JNI_OnLoad)(Machine*, void*);
|
||||
memcpy(&JNI_OnLoad, &p, sizeof(void*));
|
||||
JNI_OnLoad(t->m, 0);
|
||||
}
|
||||
}
|
||||
|
||||
System::Library*
|
||||
loadLibrary(Thread* t, const char* name)
|
||||
System::Library* loadLibrary(Thread* t, const char* name)
|
||||
{
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
@ -157,9 +157,12 @@ loadLibrary(Thread* t, const char* name)
|
||||
}
|
||||
}
|
||||
|
||||
System::Library*
|
||||
loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
bool runOnLoad, bool throw_ = true)
|
||||
System::Library* loadLibrary(Thread* t,
|
||||
const char* path,
|
||||
const char* name,
|
||||
bool mapName,
|
||||
bool runOnLoad,
|
||||
bool throw_ = true)
|
||||
{
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
@ -171,8 +174,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
const char* s = builtins;
|
||||
while (*s) {
|
||||
if (::strncmp(s, name, nameLength) == 0
|
||||
and (s[nameLength] == ',' or s[nameLength] == 0))
|
||||
{
|
||||
and (s[nameLength] == ',' or s[nameLength] == 0)) {
|
||||
// library is built in to this executable
|
||||
if (runOnLoad and not t->m->triedBuiltinOnLoad) {
|
||||
t->m->triedBuiltinOnLoad = true;
|
||||
@ -182,8 +184,10 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
}
|
||||
return t->m->libraries;
|
||||
} else {
|
||||
while (*s and *s != ',') ++ s;
|
||||
if (*s) ++ s;
|
||||
while (*s and *s != ',')
|
||||
++s;
|
||||
if (*s)
|
||||
++s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,8 +196,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
const char* suffix = t->m->system->librarySuffix();
|
||||
unsigned mappedNameLength = nameLength + strlen(prefix) + strlen(suffix);
|
||||
|
||||
mappedName = static_cast<char*>
|
||||
(t->m->heap->allocate(mappedNameLength + 1));
|
||||
mappedName = static_cast<char*>(t->m->heap->allocate(mappedNameLength + 1));
|
||||
|
||||
snprintf(mappedName, mappedNameLength + 1, "%s%s%s", prefix, name, suffix);
|
||||
|
||||
@ -203,25 +206,28 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
mappedName = 0;
|
||||
}
|
||||
|
||||
THREAD_RESOURCE2
|
||||
(t, char*, mappedName, unsigned, nameLength, if (mappedName) {
|
||||
t->m->heap->free(mappedName, nameLength + 1);
|
||||
});
|
||||
THREAD_RESOURCE2(t, char*, mappedName, unsigned, nameLength, if (mappedName) {
|
||||
t->m->heap->free(mappedName, nameLength + 1);
|
||||
});
|
||||
|
||||
System::Library* lib = 0;
|
||||
for (Tokenizer tokenizer(path, t->m->system->pathSeparator());
|
||||
tokenizer.hasMore();)
|
||||
{
|
||||
tokenizer.hasMore();) {
|
||||
String token(tokenizer.next());
|
||||
|
||||
unsigned fullNameLength = token.length + 1 + nameLength;
|
||||
THREAD_RUNTIME_ARRAY(t, char, fullName, fullNameLength + 1);
|
||||
|
||||
snprintf(RUNTIME_ARRAY_BODY(fullName), fullNameLength + 1,
|
||||
"%.*s/%s", token.length, token.text, name);
|
||||
snprintf(RUNTIME_ARRAY_BODY(fullName),
|
||||
fullNameLength + 1,
|
||||
"%.*s/%s",
|
||||
token.length,
|
||||
token.text,
|
||||
name);
|
||||
|
||||
lib = loadLibrary(t, RUNTIME_ARRAY_BODY(fullName));
|
||||
if (lib) break;
|
||||
if (lib)
|
||||
break;
|
||||
}
|
||||
|
||||
if (lib == 0) {
|
||||
@ -243,8 +249,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
return lib;
|
||||
}
|
||||
|
||||
object
|
||||
clone(Thread* t, object o)
|
||||
object clone(Thread* t, object o)
|
||||
{
|
||||
PROTECT(t, o);
|
||||
|
||||
@ -396,10 +401,10 @@ GcPair* resolveParameterTypes(Thread* t,
|
||||
switch (spec->body()[offset]) {
|
||||
case 'L': {
|
||||
unsigned start = offset;
|
||||
++ offset;
|
||||
++offset;
|
||||
while (spec->body()[offset] != ';')
|
||||
++offset;
|
||||
++ offset;
|
||||
++offset;
|
||||
|
||||
GcClass* type
|
||||
= resolveClassBySpec(t,
|
||||
@ -409,7 +414,7 @@ GcPair* resolveParameterTypes(Thread* t,
|
||||
|
||||
list = makePair(t, type, list);
|
||||
|
||||
++ count;
|
||||
++count;
|
||||
} break;
|
||||
|
||||
case '[': {
|
||||
@ -418,14 +423,14 @@ GcPair* resolveParameterTypes(Thread* t,
|
||||
++offset;
|
||||
switch (spec->body()[offset]) {
|
||||
case 'L':
|
||||
++ offset;
|
||||
++offset;
|
||||
while (spec->body()[offset] != ';')
|
||||
++offset;
|
||||
++ offset;
|
||||
++offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
++ offset;
|
||||
++offset;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -436,13 +441,13 @@ GcPair* resolveParameterTypes(Thread* t,
|
||||
offset - start);
|
||||
|
||||
list = makePair(t, type, list);
|
||||
++ count;
|
||||
++count;
|
||||
} break;
|
||||
|
||||
default:
|
||||
list = makePair(t, primitiveClass(t, spec->body()[offset]), list);
|
||||
++ offset;
|
||||
++ count;
|
||||
++offset;
|
||||
++count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -570,7 +575,7 @@ object invoke(Thread* t, GcMethod* method, object instance, object args)
|
||||
objectType = true;
|
||||
unsigned nameLength;
|
||||
if (*p == 'L') {
|
||||
++ p;
|
||||
++p;
|
||||
nameLength = it.s - p;
|
||||
} else {
|
||||
nameLength = (it.s - p) + 1;
|
||||
@ -588,9 +593,10 @@ object invoke(Thread* t, GcMethod* method, object instance, object args)
|
||||
|
||||
object arg = objectArrayBody(t, args, i++);
|
||||
if ((arg == 0 and (not objectType))
|
||||
or (arg and (not instanceOf(t, type, arg))))
|
||||
{
|
||||
// fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast<const int8_t*>("<null>"), &byteArrayBody(t, className(t, type), 0));
|
||||
or (arg and (not instanceOf(t, type, arg)))) {
|
||||
// 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));
|
||||
|
||||
throwNew(t, GcIllegalArgumentException::Type);
|
||||
}
|
||||
@ -602,14 +608,14 @@ object invoke(Thread* t, GcMethod* method, object instance, object args)
|
||||
unsigned returnCode = method->returnCode();
|
||||
|
||||
THREAD_RESOURCE0(t, {
|
||||
if (t->exception) {
|
||||
t->exception = makeThrowable(
|
||||
t, GcInvocationTargetException::Type, 0, 0, t->exception);
|
||||
if (t->exception) {
|
||||
t->exception = makeThrowable(
|
||||
t, GcInvocationTargetException::Type, 0, 0, t->exception);
|
||||
|
||||
t->exception->as<GcInvocationTargetException>(t)
|
||||
->setTarget(t, t->exception->cause());
|
||||
}
|
||||
});
|
||||
t->exception->as<GcInvocationTargetException>(t)
|
||||
->setTarget(t, t->exception->cause());
|
||||
}
|
||||
});
|
||||
|
||||
object result;
|
||||
if (args) {
|
||||
@ -664,8 +670,7 @@ void intercept(Thread* t,
|
||||
}
|
||||
}
|
||||
|
||||
Finder*
|
||||
getFinder(Thread* t, const char* name, unsigned nameLength)
|
||||
Finder* getFinder(Thread* t, const char* name, unsigned nameLength)
|
||||
{
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
@ -718,7 +723,7 @@ object getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
||||
GcByteArray* outer = reference->outer();
|
||||
if (outer and byteArrayEqual(t, outer, c->name())
|
||||
and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) {
|
||||
++ count;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
@ -734,7 +739,7 @@ object getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
||||
object inner
|
||||
= getJClass(t, resolveClass(t, c->loader(), reference->inner()));
|
||||
|
||||
-- count;
|
||||
--count;
|
||||
reinterpret_cast<GcArray*>(result)->setBodyElement(t, count, inner);
|
||||
}
|
||||
}
|
||||
@ -787,6 +792,6 @@ unsigned classModifiers(Thread* t, GcClass* c)
|
||||
return c->flags();
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//CLASSPATH_COMMON_H
|
||||
#endif // CLASSPATH_COMMON_H
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define AVIAN_COMMON_H
|
||||
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
# define __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <new>
|
||||
@ -31,11 +31,11 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef linux
|
||||
# undef linux
|
||||
#undef linux
|
||||
#endif
|
||||
|
||||
// don't complain about using 'this' in member initializers:
|
||||
# pragma warning(disable:4355)
|
||||
#pragma warning(disable : 4355)
|
||||
|
||||
#define strncasecmp _strnicmp
|
||||
|
||||
@ -43,192 +43,195 @@
|
||||
#define FP_INFINITE 1
|
||||
#define FP_UNDEF 2
|
||||
|
||||
inline int fpclassify(double d) {
|
||||
|
||||
switch(_fpclass(d)) {
|
||||
case _FPCLASS_SNAN:
|
||||
case _FPCLASS_QNAN:
|
||||
return FP_NAN;
|
||||
case _FPCLASS_PINF:
|
||||
case _FPCLASS_NINF:
|
||||
return FP_INFINITE;
|
||||
}
|
||||
return FP_UNDEF;
|
||||
inline int fpclassify(double d)
|
||||
{
|
||||
switch (_fpclass(d)) {
|
||||
case _FPCLASS_SNAN:
|
||||
case _FPCLASS_QNAN:
|
||||
return FP_NAN;
|
||||
case _FPCLASS_PINF:
|
||||
case _FPCLASS_NINF:
|
||||
return FP_INFINITE;
|
||||
}
|
||||
return FP_UNDEF;
|
||||
}
|
||||
|
||||
inline int signbit(double d) {
|
||||
return _copysign(1.0, d) < 0;
|
||||
inline int signbit(double d)
|
||||
{
|
||||
return _copysign(1.0, d) < 0;
|
||||
}
|
||||
|
||||
# define not !
|
||||
# define or ||
|
||||
# define and &&
|
||||
# define xor ^
|
||||
#define not!
|
||||
#define or ||
|
||||
#define and &&
|
||||
#define xor ^
|
||||
|
||||
# define LIKELY(v) v
|
||||
# define UNLIKELY(v) v
|
||||
#define LIKELY(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 uint32_t uintptr_t;
|
||||
# define ARCH_x86_32
|
||||
# define BYTES_PER_WORD 4
|
||||
# elif defined _M_X64
|
||||
#define ARCH_x86_32
|
||||
#define BYTES_PER_WORD 4
|
||||
#elif defined _M_X64
|
||||
typedef int64_t intptr_t;
|
||||
typedef uint64_t uintptr_t;
|
||||
# define ARCH_x86_64
|
||||
# define BYTES_PER_WORD 8
|
||||
# elif defined _M_ARM_FP
|
||||
#define ARCH_x86_64
|
||||
#define BYTES_PER_WORD 8
|
||||
#elif defined _M_ARM_FP
|
||||
typedef int32_t intptr_t;
|
||||
typedef uint32_t uintptr_t;
|
||||
# define ARCH_arm
|
||||
# define BYTES_PER_WORD 4
|
||||
# else
|
||||
# error "unsupported architecture"
|
||||
# endif
|
||||
#define ARCH_arm
|
||||
#define BYTES_PER_WORD 4
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
|
||||
namespace vm {
|
||||
|
||||
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 UNLIKELY(v) __builtin_expect((v) != 0, false)
|
||||
#define LIKELY(v) __builtin_expect((v) != 0, true)
|
||||
#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__
|
||||
# define PLATFORM_WINDOWS
|
||||
# endif
|
||||
#ifdef __MINGW32__
|
||||
#define PLATFORM_WINDOWS
|
||||
#endif
|
||||
|
||||
# ifdef __i386__
|
||||
# define ARCH_x86_32
|
||||
# elif defined __x86_64__
|
||||
# define ARCH_x86_64
|
||||
# elif defined __arm__
|
||||
# define ARCH_arm
|
||||
# else
|
||||
# error "unsupported architecture"
|
||||
# endif
|
||||
#ifdef __i386__
|
||||
#define ARCH_x86_32
|
||||
#elif defined __x86_64__
|
||||
#define ARCH_x86_64
|
||||
#elif defined __arm__
|
||||
#define ARCH_arm
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
|
||||
namespace vm {
|
||||
|
||||
typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif // not _MSC_VER
|
||||
#endif // not _MSC_VER
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
# define AVIAN_EXPORT __declspec(dllexport)
|
||||
# define PATH_SEPARATOR ';'
|
||||
#else // not PLATFORM_WINDOWS
|
||||
# define AVIAN_EXPORT __attribute__ ((visibility("default"))) \
|
||||
__attribute__ ((used))
|
||||
# define PATH_SEPARATOR ':'
|
||||
#endif // not PLATFORM_WINDOWS
|
||||
#define AVIAN_EXPORT __declspec(dllexport)
|
||||
#define PATH_SEPARATOR ';'
|
||||
#else // not PLATFORM_WINDOWS
|
||||
#define AVIAN_EXPORT \
|
||||
__attribute__((visibility("default"))) __attribute__((used))
|
||||
#define PATH_SEPARATOR ':'
|
||||
#endif // not PLATFORM_WINDOWS
|
||||
|
||||
#if (defined ARCH_x86_32) || (defined ARCH_arm)
|
||||
# define LD "ld"
|
||||
# if (defined _MSC_VER) || ((defined __MINGW32__) && __GNUC__ >= 4)
|
||||
# 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
|
||||
#define LD "ld"
|
||||
#if (defined _MSC_VER) || ((defined __MINGW32__) && __GNUC__ >= 4)
|
||||
#define LLD "I64d"
|
||||
#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
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
# define SO_PREFIX ""
|
||||
#define SO_PREFIX ""
|
||||
#else
|
||||
# define SO_PREFIX "lib"
|
||||
#define SO_PREFIX "lib"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# define SO_SUFFIX ".dylib"
|
||||
#define SO_SUFFIX ".dylib"
|
||||
#elif defined PLATFORM_WINDOWS
|
||||
# define SO_SUFFIX ".dll"
|
||||
#define SO_SUFFIX ".dll"
|
||||
#else
|
||||
# define SO_SUFFIX ".so"
|
||||
#define SO_SUFFIX ".so"
|
||||
#endif
|
||||
|
||||
#define MACRO_XY(X, Y) X##Y
|
||||
#define MACRO_MakeNameXY(FX, LINE) MACRO_XY(FX, LINE)
|
||||
#define MAKE_NAME(FX) MACRO_MakeNameXY(FX, __LINE__)
|
||||
|
||||
#define RESOURCE(type, name, release) \
|
||||
class MAKE_NAME(Resource_) { \
|
||||
public: \
|
||||
MAKE_NAME(Resource_)(type name): name(name) { } \
|
||||
~MAKE_NAME(Resource_)() { release; } \
|
||||
\
|
||||
private: \
|
||||
type name; \
|
||||
#define RESOURCE(type, name, release) \
|
||||
class MAKE_NAME(Resource_) { \
|
||||
public: \
|
||||
MAKE_NAME(Resource_)(type name) : name(name) \
|
||||
{ \
|
||||
} \
|
||||
~MAKE_NAME(Resource_)() \
|
||||
{ \
|
||||
release; \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
type name; \
|
||||
} MAKE_NAME(resource_)(name);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( disable : 4291 )
|
||||
#pragma warning(disable : 4291)
|
||||
#endif
|
||||
|
||||
namespace vm {
|
||||
|
||||
inline intptr_alias_t&
|
||||
alias(void* p, unsigned offset)
|
||||
inline intptr_alias_t& alias(void* p, unsigned offset)
|
||||
{
|
||||
return *reinterpret_cast<intptr_alias_t*>(static_cast<uint8_t*>(p) + offset);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
inline int
|
||||
vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
||||
inline int vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
||||
{
|
||||
return vsnprintf_s(dst, size, _TRUNCATE, format, a);
|
||||
}
|
||||
|
||||
inline int
|
||||
snprintf(char* dst, size_t size, const char* format, ...)
|
||||
inline int snprintf(char* dst, size_t size, const char* format, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, format);
|
||||
@ -237,8 +240,7 @@ snprintf(char* dst, size_t size, const char* format, ...)
|
||||
return r;
|
||||
}
|
||||
|
||||
inline FILE*
|
||||
fopen(const char* name, const char* mode)
|
||||
inline FILE* fopen(const char* name, const char* mode)
|
||||
{
|
||||
FILE* file;
|
||||
if (fopen_s(&file, name, mode) == 0) {
|
||||
@ -248,16 +250,14 @@ fopen(const char* name, const char* mode)
|
||||
}
|
||||
}
|
||||
|
||||
#else // not _MSC_VER
|
||||
#else // not _MSC_VER
|
||||
|
||||
inline int
|
||||
vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
||||
inline int vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
||||
{
|
||||
return ::vsnprintf(dst, size, format, a);
|
||||
}
|
||||
|
||||
inline int
|
||||
snprintf(char* dst, size_t size, const char* format, ...)
|
||||
inline int snprintf(char* dst, size_t size, const char* format, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, format);
|
||||
@ -266,116 +266,105 @@ snprintf(char* dst, size_t size, const char* format, ...)
|
||||
return r;
|
||||
}
|
||||
|
||||
inline FILE*
|
||||
fopen(const char* name, const char* mode)
|
||||
inline FILE* fopen(const char* name, const char* mode)
|
||||
{
|
||||
return ::fopen(name, mode);
|
||||
}
|
||||
|
||||
#endif // not _MSC_VER
|
||||
#endif // not _MSC_VER
|
||||
|
||||
const unsigned BytesPerWord = sizeof(uintptr_t);
|
||||
const unsigned BitsPerWord = BytesPerWord * 8;
|
||||
|
||||
const uintptr_t PointerMask
|
||||
= ((~static_cast<uintptr_t>(0)) / BytesPerWord) * BytesPerWord;
|
||||
const uintptr_t PointerMask = ((~static_cast<uintptr_t>(0)) / BytesPerWord)
|
||||
* BytesPerWord;
|
||||
|
||||
const unsigned LikelyPageSizeInBytes = 4 * 1024;
|
||||
|
||||
inline unsigned
|
||||
pad(unsigned n, unsigned alignment)
|
||||
inline unsigned pad(unsigned n, unsigned alignment)
|
||||
{
|
||||
return (n + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
pad(unsigned n)
|
||||
inline unsigned pad(unsigned n)
|
||||
{
|
||||
return pad(n, BytesPerWord);
|
||||
}
|
||||
|
||||
inline uintptr_t
|
||||
padWord(uintptr_t n, uintptr_t alignment)
|
||||
inline uintptr_t padWord(uintptr_t n, uintptr_t alignment)
|
||||
{
|
||||
return (n + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
inline uintptr_t
|
||||
padWord(uintptr_t n)
|
||||
inline uintptr_t padWord(uintptr_t n)
|
||||
{
|
||||
return padWord(n, BytesPerWord);
|
||||
}
|
||||
|
||||
inline bool fitsInInt8(int64_t v) {
|
||||
inline bool fitsInInt8(int64_t v)
|
||||
{
|
||||
return v == static_cast<int8_t>(v);
|
||||
}
|
||||
|
||||
inline bool fitsInInt16(int64_t v) {
|
||||
inline bool fitsInInt16(int64_t v)
|
||||
{
|
||||
return v == static_cast<int16_t>(v);
|
||||
}
|
||||
|
||||
inline bool fitsInInt32(int64_t v) {
|
||||
inline bool fitsInInt32(int64_t v)
|
||||
{
|
||||
return v == static_cast<int32_t>(v);
|
||||
}
|
||||
template <class T>
|
||||
inline unsigned
|
||||
wordOf(unsigned i)
|
||||
inline unsigned wordOf(unsigned i)
|
||||
{
|
||||
return i / (sizeof(T) * 8);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
wordOf(unsigned i)
|
||||
inline unsigned wordOf(unsigned i)
|
||||
{
|
||||
return wordOf<uintptr_t>(i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline unsigned
|
||||
bitOf(unsigned i)
|
||||
inline unsigned bitOf(unsigned i)
|
||||
{
|
||||
return i % (sizeof(T) * 8);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
bitOf(unsigned i)
|
||||
inline unsigned bitOf(unsigned i)
|
||||
{
|
||||
return bitOf<uintptr_t>(i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline unsigned
|
||||
indexOf(unsigned word, unsigned bit)
|
||||
inline unsigned indexOf(unsigned word, unsigned bit)
|
||||
{
|
||||
return (word * (sizeof(T) * 8)) + bit;
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
indexOf(unsigned word, unsigned bit)
|
||||
inline unsigned indexOf(unsigned word, unsigned bit)
|
||||
{
|
||||
return indexOf<uintptr_t>(word, bit);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void
|
||||
markBit(T* map, unsigned i)
|
||||
inline void markBit(T* map, unsigned i)
|
||||
{
|
||||
map[wordOf<T>(i)] |= static_cast<T>(1) << bitOf<T>(i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void
|
||||
clearBit(T* map, unsigned i)
|
||||
inline void clearBit(T* map, unsigned i)
|
||||
{
|
||||
map[wordOf<T>(i)] &= ~(static_cast<T>(1) << bitOf<T>(i));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline unsigned
|
||||
getBit(T* map, unsigned i)
|
||||
inline unsigned getBit(T* map, unsigned i)
|
||||
{
|
||||
return (map[wordOf<T>(i)] & (static_cast<T>(1) << bitOf<T>(i)))
|
||||
>> bitOf<T>(i);
|
||||
>> bitOf<T>(i);
|
||||
}
|
||||
|
||||
// todo: the following (clearBits, setBits, and getBits) could be made
|
||||
@ -383,8 +372,7 @@ getBit(T* map, unsigned i)
|
||||
// a time:
|
||||
|
||||
template <class T>
|
||||
inline void
|
||||
clearBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
inline void clearBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
{
|
||||
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
||||
clearBit<T>(map, i);
|
||||
@ -392,18 +380,19 @@ clearBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void
|
||||
setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
|
||||
inline void setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
|
||||
{
|
||||
for (int i = index + bitsPerRecord - 1; i >= index; --i) {
|
||||
if (v & 1) markBit<T>(map, i); else clearBit<T>(map, i);
|
||||
if (v & 1)
|
||||
markBit<T>(map, i);
|
||||
else
|
||||
clearBit<T>(map, i);
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline unsigned
|
||||
getBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
inline unsigned getBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
{
|
||||
unsigned v = 0;
|
||||
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
||||
@ -414,86 +403,80 @@ getBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T&
|
||||
fieldAtOffset(void* p, unsigned offset)
|
||||
inline T& fieldAtOffset(void* p, unsigned offset)
|
||||
{
|
||||
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T*
|
||||
maskAlignedPointer(T* p)
|
||||
inline T* maskAlignedPointer(T* p)
|
||||
{
|
||||
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
|
||||
}
|
||||
|
||||
inline void
|
||||
write4(uint8_t* dst, uint32_t v)
|
||||
inline void write4(uint8_t* dst, uint32_t v)
|
||||
{
|
||||
memcpy(dst, &v, 4);
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
floatToBits(float f)
|
||||
inline uint32_t floatToBits(float f)
|
||||
{
|
||||
uint32_t bits; memcpy(&bits, &f, 4);
|
||||
uint32_t bits;
|
||||
memcpy(&bits, &f, 4);
|
||||
return bits;
|
||||
}
|
||||
|
||||
inline uint64_t
|
||||
doubleToBits(double d)
|
||||
inline uint64_t doubleToBits(double d)
|
||||
{
|
||||
uint64_t bits; memcpy(&bits, &d, 8);
|
||||
uint64_t bits;
|
||||
memcpy(&bits, &d, 8);
|
||||
return bits;
|
||||
}
|
||||
|
||||
inline double
|
||||
bitsToDouble(uint64_t bits)
|
||||
inline double bitsToDouble(uint64_t bits)
|
||||
{
|
||||
double d; memcpy(&d, &bits, 8);
|
||||
double d;
|
||||
memcpy(&d, &bits, 8);
|
||||
return d;
|
||||
}
|
||||
|
||||
inline float
|
||||
bitsToFloat(uint32_t bits)
|
||||
inline float bitsToFloat(uint32_t bits)
|
||||
{
|
||||
float f; memcpy(&f, &bits, 4);
|
||||
float f;
|
||||
memcpy(&f, &bits, 4);
|
||||
return f;
|
||||
}
|
||||
|
||||
inline int
|
||||
difference(void* a, void* b)
|
||||
inline int difference(void* a, void* b)
|
||||
{
|
||||
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void*
|
||||
voidPointer(T function)
|
||||
inline void* voidPointer(T function)
|
||||
{
|
||||
void* p;
|
||||
memcpy(&p, &function, sizeof(void*));
|
||||
return p;
|
||||
}
|
||||
|
||||
inline void
|
||||
replace(char a, char b, char* c)
|
||||
inline void replace(char a, char b, char* c)
|
||||
{
|
||||
for (; *c; ++c) if (*c == a) *c = b;
|
||||
for (; *c; ++c)
|
||||
if (*c == a)
|
||||
*c = b;
|
||||
}
|
||||
|
||||
inline void
|
||||
replace(char a, char b, char* dst, const char* src)
|
||||
inline void replace(char a, char b, char* dst, const char* src)
|
||||
{
|
||||
unsigned i = 0;
|
||||
for (; src[i]; ++ i) {
|
||||
for (; src[i]; ++i) {
|
||||
dst[i] = src[i] == a ? b : src[i];
|
||||
}
|
||||
dst[i] = 0;
|
||||
}
|
||||
|
||||
inline bool
|
||||
equal(const void* a, unsigned al, const void* b, unsigned bl)
|
||||
inline bool equal(const void* a, unsigned al, const void* b, unsigned bl)
|
||||
{
|
||||
if (al == bl) {
|
||||
return memcmp(a, b, al) == 0;
|
||||
@ -502,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
|
||||
|
@ -248,35 +248,35 @@ enum Constant {
|
||||
CONSTANT_Utf8 = 1
|
||||
};
|
||||
|
||||
const unsigned ACC_PUBLIC = 1 << 0;
|
||||
const unsigned ACC_PRIVATE = 1 << 1;
|
||||
const unsigned ACC_PROTECTED = 1 << 2;
|
||||
const unsigned ACC_STATIC = 1 << 3;
|
||||
const unsigned ACC_FINAL = 1 << 4;
|
||||
const unsigned ACC_SUPER = 1 << 5;
|
||||
const unsigned ACC_PUBLIC = 1 << 0;
|
||||
const unsigned ACC_PRIVATE = 1 << 1;
|
||||
const unsigned ACC_PROTECTED = 1 << 2;
|
||||
const unsigned ACC_STATIC = 1 << 3;
|
||||
const unsigned ACC_FINAL = 1 << 4;
|
||||
const unsigned ACC_SUPER = 1 << 5;
|
||||
const unsigned ACC_SYNCHRONIZED = ACC_SUPER;
|
||||
const unsigned ACC_VOLATILE = 1 << 6;
|
||||
const unsigned ACC_TRANSIENT = 1 << 7;
|
||||
const unsigned ACC_NATIVE = 1 << 8;
|
||||
const unsigned ACC_INTERFACE = 1 << 9;
|
||||
const unsigned ACC_ABSTRACT = 1 << 10;
|
||||
const unsigned ACC_STRICT = 1 << 11;
|
||||
const unsigned ACC_VOLATILE = 1 << 6;
|
||||
const unsigned ACC_TRANSIENT = 1 << 7;
|
||||
const unsigned ACC_NATIVE = 1 << 8;
|
||||
const unsigned ACC_INTERFACE = 1 << 9;
|
||||
const unsigned ACC_ABSTRACT = 1 << 10;
|
||||
const unsigned ACC_STRICT = 1 << 11;
|
||||
|
||||
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_ERR = -1;
|
||||
const int AVIAN_JNI_OK = 0;
|
||||
const int AVIAN_JNI_ERR = -1;
|
||||
const int AVIAN_JNI_EDETACHED = -2;
|
||||
const int AVIAN_JNI_EVERSION = -3;
|
||||
const int AVIAN_JNI_ENOMEM = -4;
|
||||
const int AVIAN_JNI_EEXIST = -5;
|
||||
const int AVIAN_JNI_EINVAL = -6;
|
||||
const int AVIAN_JNI_EVERSION = -3;
|
||||
const int AVIAN_JNI_ENOMEM = -4;
|
||||
const int AVIAN_JNI_EEXIST = -5;
|
||||
const int AVIAN_JNI_EINVAL = -6;
|
||||
|
||||
const int AVIAN_JNI_VERSION_1_1 = 0x00010001;
|
||||
const int AVIAN_JNI_VERSION_1_2 = 0x00010002;
|
||||
const int AVIAN_JNI_VERSION_1_4 = 0x00010004;
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//CONSTANTS_H
|
||||
#endif // CONSTANTS_H
|
||||
|
@ -30,4 +30,3 @@
|
||||
#define AVIAN_ARCH_ARM (3 << 8)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -30,96 +30,113 @@ const unsigned EntrySignature = 0x02014b50;
|
||||
|
||||
const unsigned CentralDirectorySearchStart = 22;
|
||||
|
||||
inline uint16_t get2(const uint8_t* p) {
|
||||
return
|
||||
(static_cast<uint16_t>(p[1]) << 8) |
|
||||
(static_cast<uint16_t>(p[0]) );
|
||||
inline uint16_t get2(const uint8_t* p)
|
||||
{
|
||||
return (static_cast<uint16_t>(p[1]) << 8) | (static_cast<uint16_t>(p[0]));
|
||||
}
|
||||
|
||||
inline uint32_t get4(const uint8_t* p) {
|
||||
return
|
||||
(static_cast<uint32_t>(p[3]) << 24) |
|
||||
(static_cast<uint32_t>(p[2]) << 16) |
|
||||
(static_cast<uint32_t>(p[1]) << 8) |
|
||||
(static_cast<uint32_t>(p[0]) );
|
||||
inline uint32_t get4(const uint8_t* p)
|
||||
{
|
||||
return (static_cast<uint32_t>(p[3]) << 24)
|
||||
| (static_cast<uint32_t>(p[2]) << 16)
|
||||
| (static_cast<uint32_t>(p[1]) << 8) | (static_cast<uint32_t>(p[0]));
|
||||
}
|
||||
|
||||
inline uint32_t signature(const uint8_t* p) {
|
||||
inline uint32_t signature(const uint8_t* p)
|
||||
{
|
||||
return get4(p);
|
||||
}
|
||||
|
||||
inline uint16_t compressionMethod(const uint8_t* centralHeader) {
|
||||
inline uint16_t compressionMethod(const uint8_t* centralHeader)
|
||||
{
|
||||
return get2(centralHeader + 10);
|
||||
}
|
||||
|
||||
inline uint32_t fileTime(const uint8_t* centralHeader) {
|
||||
inline uint32_t fileTime(const uint8_t* centralHeader)
|
||||
{
|
||||
return get4(centralHeader + 12);
|
||||
}
|
||||
|
||||
inline uint32_t fileCRC(const uint8_t* centralHeader) {
|
||||
inline uint32_t fileCRC(const uint8_t* centralHeader)
|
||||
{
|
||||
return get4(centralHeader + 16);
|
||||
}
|
||||
|
||||
inline uint32_t compressedSize(const uint8_t* centralHeader) {
|
||||
inline uint32_t compressedSize(const uint8_t* centralHeader)
|
||||
{
|
||||
return get4(centralHeader + 20);
|
||||
}
|
||||
|
||||
inline uint32_t uncompressedSize(const uint8_t* centralHeader) {
|
||||
inline uint32_t uncompressedSize(const uint8_t* centralHeader)
|
||||
{
|
||||
return get4(centralHeader + 24);
|
||||
}
|
||||
|
||||
inline uint16_t fileNameLength(const uint8_t* centralHeader) {
|
||||
inline uint16_t fileNameLength(const uint8_t* centralHeader)
|
||||
{
|
||||
return get2(centralHeader + 28);
|
||||
}
|
||||
|
||||
inline uint16_t extraFieldLength(const uint8_t* centralHeader) {
|
||||
inline uint16_t extraFieldLength(const uint8_t* centralHeader)
|
||||
{
|
||||
return get2(centralHeader + 30);
|
||||
}
|
||||
|
||||
inline uint16_t commentFieldLength(const uint8_t* centralHeader) {
|
||||
inline uint16_t commentFieldLength(const uint8_t* centralHeader)
|
||||
{
|
||||
return get2(centralHeader + 32);
|
||||
}
|
||||
|
||||
inline uint32_t localHeaderOffset(const uint8_t* centralHeader) {
|
||||
inline uint32_t localHeaderOffset(const uint8_t* centralHeader)
|
||||
{
|
||||
return get4(centralHeader + 42);
|
||||
}
|
||||
|
||||
inline uint16_t localFileNameLength(const uint8_t* localHeader) {
|
||||
inline uint16_t localFileNameLength(const uint8_t* localHeader)
|
||||
{
|
||||
return get2(localHeader + 26);
|
||||
}
|
||||
|
||||
inline uint16_t localExtraFieldLength(const uint8_t* localHeader) {
|
||||
inline uint16_t localExtraFieldLength(const uint8_t* localHeader)
|
||||
{
|
||||
return get2(localHeader + 28);
|
||||
}
|
||||
|
||||
inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader) {
|
||||
inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader)
|
||||
{
|
||||
return get4(centralHeader + 16);
|
||||
}
|
||||
|
||||
inline const uint8_t* fileName(const uint8_t* centralHeader) {
|
||||
inline const uint8_t* fileName(const uint8_t* centralHeader)
|
||||
{
|
||||
return centralHeader + 46;
|
||||
}
|
||||
|
||||
inline const uint8_t* fileData(const uint8_t* localHeader) {
|
||||
return localHeader + LocalHeaderSize + localFileNameLength(localHeader) +
|
||||
localExtraFieldLength(localHeader);
|
||||
inline const uint8_t* fileData(const uint8_t* localHeader)
|
||||
{
|
||||
return localHeader + LocalHeaderSize + localFileNameLength(localHeader)
|
||||
+ localExtraFieldLength(localHeader);
|
||||
}
|
||||
|
||||
inline const uint8_t* endOfEntry(const uint8_t* p) {
|
||||
return p + HeaderSize + fileNameLength(p) + extraFieldLength(p) +
|
||||
commentFieldLength(p);
|
||||
inline const uint8_t* endOfEntry(const uint8_t* p)
|
||||
{
|
||||
return p + HeaderSize + fileNameLength(p) + extraFieldLength(p)
|
||||
+ commentFieldLength(p);
|
||||
}
|
||||
|
||||
inline bool
|
||||
readLine(const uint8_t* base, unsigned total, unsigned* start,
|
||||
unsigned* length)
|
||||
inline bool readLine(const uint8_t* base,
|
||||
unsigned total,
|
||||
unsigned* start,
|
||||
unsigned* length)
|
||||
{
|
||||
const uint8_t* p = base + *start;
|
||||
const uint8_t* end = base + total;
|
||||
while (p != end and (*p == '\n' or *p == '\r')) ++ p;
|
||||
while (p != end and (*p == '\n' or *p == '\r'))
|
||||
++p;
|
||||
|
||||
*start = p - base;
|
||||
while (p != end and not (*p == '\n' or *p == '\r')) ++ p;
|
||||
while (p != end and not(*p == '\n' or *p == '\r'))
|
||||
++p;
|
||||
|
||||
*length = (p - base) - *start;
|
||||
|
||||
@ -136,22 +153,26 @@ class Finder {
|
||||
|
||||
class Iterator {
|
||||
public:
|
||||
Iterator(Finder* finder):
|
||||
it(finder->iterator()),
|
||||
current(it->next(¤tSize))
|
||||
{ }
|
||||
Iterator(Finder* finder)
|
||||
: it(finder->iterator()), current(it->next(¤tSize))
|
||||
{
|
||||
}
|
||||
|
||||
~Iterator() {
|
||||
~Iterator()
|
||||
{
|
||||
it->dispose();
|
||||
}
|
||||
|
||||
bool hasMore() {
|
||||
if (current) return true;
|
||||
bool hasMore()
|
||||
{
|
||||
if (current)
|
||||
return true;
|
||||
current = it->next(¤tSize);
|
||||
return current != 0;
|
||||
}
|
||||
|
||||
const char* next(unsigned* size) {
|
||||
const char* next(unsigned* size)
|
||||
{
|
||||
if (hasMore()) {
|
||||
*size = currentSize;
|
||||
const char* v = current;
|
||||
@ -173,7 +194,8 @@ class Finder {
|
||||
unsigned* length,
|
||||
bool tryDirectory = false) = 0;
|
||||
virtual const char* urlPrefix(const char* name) = 0;
|
||||
virtual const char* nextUrlPrefix(const char* name, void *&finderElementPtr) = 0;
|
||||
virtual const char* nextUrlPrefix(const char* name, void*& finderElementPtr)
|
||||
= 0;
|
||||
virtual const char* sourceUrl(const char* name) = 0;
|
||||
virtual const char* path() = 0;
|
||||
virtual void dispose() = 0;
|
||||
@ -189,6 +211,6 @@ Finder* makeFinder(System* s,
|
||||
const uint8_t* jarData,
|
||||
unsigned jarLength);
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//FINDER_H
|
||||
#endif // FINDER_H
|
||||
|
@ -29,8 +29,8 @@ class HeapVisitor {
|
||||
virtual void root() = 0;
|
||||
virtual unsigned visitNew(object value) = 0;
|
||||
virtual void visitOld(object value, unsigned number) = 0;
|
||||
virtual void push(object parent, unsigned parentNumber,
|
||||
unsigned childOffset) = 0;
|
||||
virtual void push(object parent, unsigned parentNumber, unsigned childOffset)
|
||||
= 0;
|
||||
virtual void pop() = 0;
|
||||
};
|
||||
|
||||
@ -42,9 +42,8 @@ class HeapWalker {
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
HeapWalker*
|
||||
makeHeapWalker(Thread* t, HeapVisitor* v);
|
||||
HeapWalker* makeHeapWalker(Thread* t, HeapVisitor* v);
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//HEAPWALK_H
|
||||
#endif // HEAPWALK_H
|
||||
|
@ -68,16 +68,16 @@ typedef uintptr_t jmethodID;
|
||||
|
||||
union jvalue {
|
||||
jboolean z;
|
||||
jbyte b;
|
||||
jchar c;
|
||||
jshort s;
|
||||
jint i;
|
||||
jlong j;
|
||||
jfloat f;
|
||||
jdouble d;
|
||||
jobject l;
|
||||
jbyte b;
|
||||
jchar c;
|
||||
jshort s;
|
||||
jint i;
|
||||
jlong j;
|
||||
jfloat f;
|
||||
jdouble d;
|
||||
jobject l;
|
||||
};
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif // JAVA_COMMON_H
|
||||
#endif // JAVA_COMMON_H
|
||||
|
@ -27,9 +27,8 @@
|
||||
|
||||
namespace vm {
|
||||
|
||||
void
|
||||
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
|
||||
void populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//JNIENV_H
|
||||
#endif // JNIENV_H
|
||||
|
@ -22,7 +22,8 @@ const unsigned Padding = 16;
|
||||
|
||||
class LzmaAllocator {
|
||||
public:
|
||||
LzmaAllocator(avian::util::Allocator* a): a(a) {
|
||||
LzmaAllocator(avian::util::Allocator* a) : a(a)
|
||||
{
|
||||
allocator.Alloc = allocate;
|
||||
allocator.Free = free;
|
||||
}
|
||||
@ -30,15 +31,17 @@ class LzmaAllocator {
|
||||
ISzAlloc allocator;
|
||||
avian::util::Allocator* a;
|
||||
|
||||
static void* allocate(void* allocator, size_t size) {
|
||||
uint8_t* p = static_cast<uint8_t*>
|
||||
(static_cast<LzmaAllocator*>(allocator)->a->allocate(size + Padding));
|
||||
static void* allocate(void* allocator, size_t size)
|
||||
{
|
||||
uint8_t* p = static_cast<uint8_t*>(
|
||||
static_cast<LzmaAllocator*>(allocator)->a->allocate(size + Padding));
|
||||
int32_t size32 = size;
|
||||
memcpy(p, &size32, 4);
|
||||
return p + Padding;
|
||||
}
|
||||
|
||||
static void free(void* allocator, void* address) {
|
||||
static void free(void* allocator, void* address)
|
||||
{
|
||||
if (address) {
|
||||
void* p = static_cast<uint8_t*>(address) - Padding;
|
||||
int32_t size32;
|
||||
@ -48,6 +51,6 @@ class LzmaAllocator {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif // LZMA_UTIL_H
|
||||
#endif // LZMA_UTIL_H
|
||||
|
@ -33,6 +33,6 @@ uint8_t* encodeLZMA(System* s,
|
||||
unsigned inSize,
|
||||
unsigned* outSize);
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif // LZMA_H
|
||||
#endif // LZMA_H
|
||||
|
2143
src/avian/machine.h
2143
src/avian/machine.h
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,6 @@ void resolveNative(Thread* t, GcMethod* method);
|
||||
|
||||
int findLineNumber(Thread* t, GcMethod* method, unsigned ip);
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//PROCESS_H
|
||||
#endif // PROCESS_H
|
||||
|
@ -69,7 +69,10 @@ class Processor {
|
||||
|
||||
class CompilationHandler {
|
||||
public:
|
||||
virtual void compiled(const void* code, unsigned size, unsigned frameSize, const char* name) = 0;
|
||||
virtual void compiled(const void* code,
|
||||
unsigned size,
|
||||
unsigned frameSize,
|
||||
const char* name) = 0;
|
||||
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
@ -112,25 +115,19 @@ class Processor {
|
||||
|
||||
virtual void initVtable(Thread* t, GcClass* c) = 0;
|
||||
|
||||
virtual void
|
||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||
virtual void visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||
|
||||
virtual void
|
||||
walkStack(Thread* t, StackVisitor* v) = 0;
|
||||
virtual void walkStack(Thread* t, StackVisitor* v) = 0;
|
||||
|
||||
virtual int lineNumber(Thread* t, GcMethod* method, int ip) = 0;
|
||||
|
||||
virtual object*
|
||||
makeLocalReference(Thread* t, object o) = 0;
|
||||
virtual object* makeLocalReference(Thread* t, object o) = 0;
|
||||
|
||||
virtual void
|
||||
disposeLocalReference(Thread* t, object* r) = 0;
|
||||
virtual void disposeLocalReference(Thread* t, object* r) = 0;
|
||||
|
||||
virtual bool
|
||||
pushLocalFrame(Thread* t, unsigned capacity) = 0;
|
||||
virtual bool pushLocalFrame(Thread* t, unsigned capacity) = 0;
|
||||
|
||||
virtual void
|
||||
popLocalFrame(Thread* t) = 0;
|
||||
virtual void popLocalFrame(Thread* t) = 0;
|
||||
|
||||
virtual object invokeArray(Thread* t,
|
||||
GcMethod* method,
|
||||
@ -156,20 +153,16 @@ class Processor {
|
||||
object this_,
|
||||
va_list arguments) = 0;
|
||||
|
||||
virtual void
|
||||
dispose(Thread* t) = 0;
|
||||
virtual void dispose(Thread* t) = 0;
|
||||
|
||||
virtual void
|
||||
dispose() = 0;
|
||||
virtual void dispose() = 0;
|
||||
|
||||
virtual object
|
||||
getStackTrace(Thread* t, Thread* target) = 0;
|
||||
virtual object getStackTrace(Thread* t, Thread* target) = 0;
|
||||
|
||||
virtual void initialize(BootImage* image, avian::util::Slice<uint8_t> code)
|
||||
= 0;
|
||||
|
||||
virtual void
|
||||
addCompilationHandler(CompilationHandler* handler) = 0;
|
||||
virtual void addCompilationHandler(CompilationHandler* handler) = 0;
|
||||
|
||||
virtual void compileMethod(Thread* t,
|
||||
Zone* zone,
|
||||
@ -179,23 +172,18 @@ class Processor {
|
||||
GcMethod* method,
|
||||
OffsetResolver* resolver) = 0;
|
||||
|
||||
virtual void
|
||||
visitRoots(Thread* t, HeapWalker* w) = 0;
|
||||
virtual void visitRoots(Thread* t, HeapWalker* w) = 0;
|
||||
|
||||
virtual void
|
||||
normalizeVirtualThunks(Thread* t) = 0;
|
||||
virtual void normalizeVirtualThunks(Thread* t) = 0;
|
||||
|
||||
virtual unsigned*
|
||||
makeCallTable(Thread* t, HeapWalker* w) = 0;
|
||||
virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) = 0;
|
||||
|
||||
virtual void
|
||||
boot(Thread* t, BootImage* image, uint8_t* code) = 0;
|
||||
virtual void boot(Thread* t, BootImage* image, uint8_t* code) = 0;
|
||||
|
||||
virtual void
|
||||
callWithCurrentContinuation(Thread* t, object receiver) = 0;
|
||||
virtual void callWithCurrentContinuation(Thread* t, object receiver) = 0;
|
||||
|
||||
virtual void
|
||||
dynamicWind(Thread* t, object before, object thunk, object after) = 0;
|
||||
virtual void dynamicWind(Thread* t, object before, object thunk, object after)
|
||||
= 0;
|
||||
|
||||
virtual void feedResultToContinuation(Thread* t,
|
||||
GcContinuation* continuation,
|
||||
@ -205,9 +193,10 @@ class Processor {
|
||||
GcContinuation* continuation,
|
||||
GcThrowable* exception) = 0;
|
||||
|
||||
virtual void
|
||||
walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start)
|
||||
= 0;
|
||||
virtual void walkContinuationBody(Thread* t,
|
||||
Heap::Walker* w,
|
||||
object o,
|
||||
unsigned start) = 0;
|
||||
|
||||
object invoke(Thread* t, GcMethod* method, object this_, ...)
|
||||
{
|
||||
@ -232,8 +221,8 @@ class Processor {
|
||||
va_list a;
|
||||
va_start(a, this_);
|
||||
|
||||
object r = invokeList
|
||||
(t, loader, className, methodName, methodSpec, this_, a);
|
||||
object r
|
||||
= invokeList(t, loader, className, methodName, methodSpec, this_, a);
|
||||
|
||||
va_end(a);
|
||||
|
||||
@ -246,6 +235,6 @@ Processor* makeProcessor(System* system,
|
||||
const char* crashDumpDirectory,
|
||||
bool useNativeFeatures);
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//PROCESSOR_H
|
||||
#endif // PROCESSOR_H
|
||||
|
@ -11,9 +11,8 @@
|
||||
#ifndef AVIAN_TARGET_FIELDS_H
|
||||
#define AVIAN_TARGET_FIELDS_H
|
||||
|
||||
|
||||
#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_EXCEPTIONSTACKADJUSTMENT 2264
|
||||
@ -33,7 +32,7 @@
|
||||
#define TARGET_THREAD_THUNKTABLE 2328
|
||||
#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_EXCEPTIONSTACKADJUSTMENT 2168
|
||||
@ -53,12 +52,11 @@
|
||||
#define TARGET_THREAD_THUNKTABLE 2200
|
||||
#define TARGET_THREAD_STACKLIMIT 2224
|
||||
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
#else
|
||||
# error
|
||||
#error
|
||||
#endif
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -17,96 +17,82 @@
|
||||
namespace vm {
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetV1(T v)
|
||||
inline T targetV1(T v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
swapV2(T v)
|
||||
inline T swapV2(T v)
|
||||
{
|
||||
return (((v >> 8) & 0xFF) |
|
||||
((v << 8)));
|
||||
return (((v >> 8) & 0xFF) | ((v << 8)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
swapV4(T v)
|
||||
inline T swapV4(T v)
|
||||
{
|
||||
return (((v >> 24) & 0x000000FF) |
|
||||
((v >> 8) & 0x0000FF00) |
|
||||
((v << 8) & 0x00FF0000) |
|
||||
((v << 24)));
|
||||
return (((v >> 24) & 0x000000FF) | ((v >> 8) & 0x0000FF00)
|
||||
| ((v << 8) & 0x00FF0000) | ((v << 24)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
swapV8(T v)
|
||||
inline T swapV8(T v)
|
||||
{
|
||||
return (((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) |
|
||||
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) |
|
||||
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) |
|
||||
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) |
|
||||
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) |
|
||||
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) |
|
||||
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) |
|
||||
((static_cast<uint64_t>(v) << 56)));
|
||||
return (((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF))
|
||||
| ((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00))
|
||||
| ((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000))
|
||||
| ((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000))
|
||||
| ((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000))
|
||||
| ((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000))
|
||||
| ((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000))
|
||||
| ((static_cast<uint64_t>(v) << 56)));
|
||||
}
|
||||
|
||||
#ifdef TARGET_OPPOSITE_ENDIAN
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetV2(T v)
|
||||
inline T targetV2(T v)
|
||||
{
|
||||
return swapV2(v);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetV4(T v)
|
||||
inline T targetV4(T v)
|
||||
{
|
||||
return swapV4(v);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetV8(T v)
|
||||
inline T targetV8(T v)
|
||||
{
|
||||
return swapV8(v);
|
||||
}
|
||||
|
||||
#else
|
||||
template <class T>
|
||||
inline T
|
||||
targetV2(T v)
|
||||
inline T targetV2(T v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetV4(T v)
|
||||
inline T targetV4(T v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetV8(T v)
|
||||
inline T targetV8(T v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_BYTES_PER_WORD
|
||||
# if (TARGET_BYTES_PER_WORD == 8)
|
||||
#if (TARGET_BYTES_PER_WORD == 8)
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetVW(T v)
|
||||
inline T targetVW(T v)
|
||||
{
|
||||
return targetV8(v);
|
||||
}
|
||||
@ -120,11 +106,10 @@ const unsigned TargetClassVtable = 136;
|
||||
|
||||
const unsigned TargetFieldOffset = 12;
|
||||
|
||||
# elif (TARGET_BYTES_PER_WORD == 4)
|
||||
#elif(TARGET_BYTES_PER_WORD == 4)
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetVW(T v)
|
||||
inline T targetVW(T v)
|
||||
{
|
||||
return targetV4(v);
|
||||
}
|
||||
@ -138,11 +123,11 @@ const unsigned TargetClassVtable = 72;
|
||||
|
||||
const unsigned TargetFieldOffset = 8;
|
||||
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
#else
|
||||
# error
|
||||
#error
|
||||
#endif
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
const unsigned TargetBytesPerWord = TARGET_BYTES_PER_WORD;
|
||||
@ -150,19 +135,18 @@ const unsigned TargetBytesPerWord = TARGET_BYTES_PER_WORD;
|
||||
const unsigned TargetBitsPerWord = TargetBytesPerWord * 8;
|
||||
|
||||
const target_uintptr_t TargetPointerMask
|
||||
= ((~static_cast<target_uintptr_t>(0)) / TargetBytesPerWord)
|
||||
* TargetBytesPerWord;
|
||||
= ((~static_cast<target_uintptr_t>(0)) / TargetBytesPerWord)
|
||||
* TargetBytesPerWord;
|
||||
|
||||
const unsigned TargetArrayLength = TargetBytesPerWord;
|
||||
const unsigned TargetArrayBody = TargetBytesPerWord * 2;
|
||||
|
||||
inline void
|
||||
targetMarkBit(target_uintptr_t* map, unsigned i)
|
||||
inline void targetMarkBit(target_uintptr_t* map, unsigned i)
|
||||
{
|
||||
map[wordOf<target_uintptr_t>(i)] |=
|
||||
targetVW(static_cast<target_uintptr_t>(1) << bitOf<target_uintptr_t>(i));
|
||||
map[wordOf<target_uintptr_t>(i)] |= targetVW(static_cast<target_uintptr_t>(1)
|
||||
<< bitOf<target_uintptr_t>(i));
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//TARGET_H
|
||||
#endif // TARGET_H
|
||||
|
@ -20,4 +20,4 @@
|
||||
#define DOUBLE_TYPE 6
|
||||
#define POINTER_TYPE 7
|
||||
|
||||
#endif//TYPES_H
|
||||
#endif // TYPES_H
|
||||
|
@ -84,15 +84,13 @@ object hashMapRemove(Thread* t,
|
||||
|
||||
object hashMapIterator(Thread* t, GcHashMap* map);
|
||||
|
||||
object
|
||||
hashMapIteratorNext(Thread* t, object it);
|
||||
object hashMapIteratorNext(Thread* t, object it);
|
||||
|
||||
void listAppend(Thread* t, GcList* list, object value);
|
||||
|
||||
GcVector* vectorAppend(Thread* t, GcVector* vector, object value);
|
||||
|
||||
object
|
||||
growArray(Thread* t, object array);
|
||||
object growArray(Thread* t, object array);
|
||||
|
||||
object treeQuery(Thread* t,
|
||||
GcTreeNode* tree,
|
||||
@ -115,7 +113,7 @@ void treeUpdate(Thread* t,
|
||||
GcTreeNode* sentinal,
|
||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||
|
||||
class HashMapIterator: public Thread::Protector {
|
||||
class HashMapIterator : public Thread::Protector {
|
||||
public:
|
||||
HashMapIterator(Thread* t, GcHashMap* map)
|
||||
: Protector(t), map(map), node(0), index(0)
|
||||
@ -123,7 +121,8 @@ class HashMapIterator: public Thread::Protector {
|
||||
find();
|
||||
}
|
||||
|
||||
void find() {
|
||||
void find()
|
||||
{
|
||||
GcArray* array = map->array();
|
||||
if (array) {
|
||||
for (unsigned i = index; i < array->length(); ++i) {
|
||||
@ -137,7 +136,8 @@ class HashMapIterator: public Thread::Protector {
|
||||
node = 0;
|
||||
}
|
||||
|
||||
bool hasMore() {
|
||||
bool hasMore()
|
||||
{
|
||||
return node != 0;
|
||||
}
|
||||
|
||||
@ -156,7 +156,8 @@ class HashMapIterator: public Thread::Protector {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(Heap::Visitor* v) {
|
||||
virtual void visit(Heap::Visitor* v)
|
||||
{
|
||||
v->visit(&map);
|
||||
v->visit(&node);
|
||||
}
|
||||
@ -166,6 +167,6 @@ class HashMapIterator: public Thread::Protector {
|
||||
unsigned index;
|
||||
};
|
||||
|
||||
} // vm
|
||||
} // vm
|
||||
|
||||
#endif//UTIL_H
|
||||
#endif // UTIL_H
|
||||
|
276
src/avian/x86.h
276
src/avian/x86.h
@ -15,150 +15,164 @@
|
||||
#include "avian/common.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include "windows.h"
|
||||
# pragma push_macro("assert")
|
||||
# include "intrin.h"
|
||||
# pragma pop_macro("assert")
|
||||
# undef interface
|
||||
#include "windows.h"
|
||||
#pragma push_macro("assert")
|
||||
#include "intrin.h"
|
||||
#pragma pop_macro("assert")
|
||||
#undef interface
|
||||
#endif
|
||||
|
||||
#if (defined ARCH_x86_32) || (defined PLATFORM_WINDOWS)
|
||||
# define VA_LIST(x) (&(x))
|
||||
#define VA_LIST(x) (&(x))
|
||||
#else
|
||||
# define VA_LIST(x) (x)
|
||||
#define VA_LIST(x) (x)
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include "mach/mach_types.h"
|
||||
# include "mach/thread_act.h"
|
||||
# include "mach/thread_status.h"
|
||||
#include "mach/mach_types.h"
|
||||
#include "mach/thread_act.h"
|
||||
#include "mach/thread_status.h"
|
||||
|
||||
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
||||
# define FIELD(x) __##x
|
||||
# else
|
||||
# define FIELD(x) x
|
||||
# endif
|
||||
#if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
||||
#define FIELD(x) __##x
|
||||
#else
|
||||
#define FIELD(x) x
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_x86_32
|
||||
|
||||
# ifdef __APPLE__
|
||||
# define THREAD_STATE x86_THREAD_STATE32
|
||||
# define THREAD_STATE_TYPE x86_thread_state32_t
|
||||
# define THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
|
||||
#ifdef __APPLE__
|
||||
#define THREAD_STATE x86_THREAD_STATE32
|
||||
#define THREAD_STATE_TYPE x86_thread_state32_t
|
||||
#define THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
|
||||
|
||||
# define THREAD_STATE_IP(state) ((state).FIELD(eip))
|
||||
# define THREAD_STATE_STACK(state) ((state).FIELD(esp))
|
||||
# define THREAD_STATE_THREAD(state) ((state).FIELD(ebx))
|
||||
# define THREAD_STATE_LINK(state) ((state).FIELD(ecx))
|
||||
# define THREAD_STATE_FRAME(state) ((state).FIELD(ebp))
|
||||
#define THREAD_STATE_IP(state) ((state).FIELD(eip))
|
||||
#define THREAD_STATE_STACK(state) ((state).FIELD(esp))
|
||||
#define THREAD_STATE_THREAD(state) ((state).FIELD(ebx))
|
||||
#define THREAD_STATE_LINK(state) ((state).FIELD(ecx))
|
||||
#define THREAD_STATE_FRAME(state) ((state).FIELD(ebp))
|
||||
|
||||
# define IP_REGISTER(context) \
|
||||
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
||||
# define STACK_REGISTER(context) \
|
||||
#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) \
|
||||
#define THREAD_REGISTER(context) \
|
||||
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
||||
# define LINK_REGISTER(context) \
|
||||
#define LINK_REGISTER(context) \
|
||||
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
||||
# define FRAME_REGISTER(context) \
|
||||
#define FRAME_REGISTER(context) \
|
||||
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
|
||||
|
||||
# elif (defined __QNX__)
|
||||
# define IP_REGISTER(context) (context->uc_mcontext.cpu.eip)
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext.cpu.esp)
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext.cpu.ebx)
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext.cpu.ecx)
|
||||
# define FRAME_REGISTER(context) (context->uc_mcontext.cpu.ebp)
|
||||
# elif (defined __FreeBSD__)
|
||||
# define IP_REGISTER(context) (context->uc_mcontext.mc_eip)
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext.mc_esp)
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext.mc_ebx)
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext.mc_ecx)
|
||||
# define FRAME_REGISTER(context) (context->uc_mcontext.mc_ebp)
|
||||
# else
|
||||
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX])
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_ECX])
|
||||
# define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
|
||||
# endif
|
||||
#elif(defined __QNX__)
|
||||
#define IP_REGISTER(context) (context->uc_mcontext.cpu.eip)
|
||||
#define STACK_REGISTER(context) (context->uc_mcontext.cpu.esp)
|
||||
#define THREAD_REGISTER(context) (context->uc_mcontext.cpu.ebx)
|
||||
#define LINK_REGISTER(context) (context->uc_mcontext.cpu.ecx)
|
||||
#define FRAME_REGISTER(context) (context->uc_mcontext.cpu.ebp)
|
||||
#elif(defined __FreeBSD__)
|
||||
#define IP_REGISTER(context) (context->uc_mcontext.mc_eip)
|
||||
#define STACK_REGISTER(context) (context->uc_mcontext.mc_esp)
|
||||
#define THREAD_REGISTER(context) (context->uc_mcontext.mc_ebx)
|
||||
#define LINK_REGISTER(context) (context->uc_mcontext.mc_ecx)
|
||||
#define FRAME_REGISTER(context) (context->uc_mcontext.mc_ebp)
|
||||
#else
|
||||
#define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
|
||||
#define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
|
||||
#define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX])
|
||||
#define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_ECX])
|
||||
#define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
|
||||
#endif
|
||||
|
||||
extern "C" uint64_t
|
||||
vmNativeCall(void* function, void* stack, unsigned stackSize,
|
||||
unsigned returnType);
|
||||
extern "C" uint64_t vmNativeCall(void* function,
|
||||
void* stack,
|
||||
unsigned stackSize,
|
||||
unsigned returnType);
|
||||
|
||||
namespace vm {
|
||||
|
||||
inline uint64_t
|
||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
||||
unsigned, unsigned argumentsSize, unsigned returnType)
|
||||
inline uint64_t dynamicCall(void* function,
|
||||
uintptr_t* arguments,
|
||||
uint8_t*,
|
||||
unsigned,
|
||||
unsigned argumentsSize,
|
||||
unsigned returnType)
|
||||
{
|
||||
return vmNativeCall(function, arguments, argumentsSize, returnType);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#elif defined ARCH_x86_64
|
||||
|
||||
# ifdef __APPLE__
|
||||
# define THREAD_STATE x86_THREAD_STATE64
|
||||
# define THREAD_STATE_TYPE x86_thread_state64_t
|
||||
# define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
|
||||
#ifdef __APPLE__
|
||||
#define THREAD_STATE x86_THREAD_STATE64
|
||||
#define THREAD_STATE_TYPE x86_thread_state64_t
|
||||
#define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
|
||||
|
||||
# define THREAD_STATE_IP(state) ((state).FIELD(rip))
|
||||
# define THREAD_STATE_STACK(state) ((state).FIELD(rsp))
|
||||
# define THREAD_STATE_THREAD(state) ((state).FIELD(rbx))
|
||||
# define THREAD_STATE_LINK(state) ((state).FIELD(rcx))
|
||||
# define THREAD_STATE_FRAME(state) ((state).FIELD(rbp))
|
||||
#define THREAD_STATE_IP(state) ((state).FIELD(rip))
|
||||
#define THREAD_STATE_STACK(state) ((state).FIELD(rsp))
|
||||
#define THREAD_STATE_THREAD(state) ((state).FIELD(rbx))
|
||||
#define THREAD_STATE_LINK(state) ((state).FIELD(rcx))
|
||||
#define THREAD_STATE_FRAME(state) ((state).FIELD(rbp))
|
||||
|
||||
# define IP_REGISTER(context) \
|
||||
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
||||
# define STACK_REGISTER(context) \
|
||||
#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) \
|
||||
#define THREAD_REGISTER(context) \
|
||||
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
||||
# define LINK_REGISTER(context) \
|
||||
#define LINK_REGISTER(context) \
|
||||
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
||||
# define FRAME_REGISTER(context) \
|
||||
#define FRAME_REGISTER(context) \
|
||||
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
|
||||
|
||||
# elif (defined __FreeBSD__)
|
||||
# define IP_REGISTER(context) (context->uc_mcontext.mc_rip)
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext.mc_rsp)
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext.mc_rbx)
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext.mc_rcx)
|
||||
# define FRAME_REGISTER(context) (context->uc_mcontext.mc_rbp)
|
||||
# else
|
||||
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_RCX])
|
||||
# define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP])
|
||||
# endif
|
||||
#elif(defined __FreeBSD__)
|
||||
#define IP_REGISTER(context) (context->uc_mcontext.mc_rip)
|
||||
#define STACK_REGISTER(context) (context->uc_mcontext.mc_rsp)
|
||||
#define THREAD_REGISTER(context) (context->uc_mcontext.mc_rbx)
|
||||
#define LINK_REGISTER(context) (context->uc_mcontext.mc_rcx)
|
||||
#define FRAME_REGISTER(context) (context->uc_mcontext.mc_rbp)
|
||||
#else
|
||||
#define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
|
||||
#define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
|
||||
#define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
|
||||
#define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_RCX])
|
||||
#define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP])
|
||||
#endif
|
||||
|
||||
extern "C" uint64_t
|
||||
# ifdef PLATFORM_WINDOWS
|
||||
vmNativeCall(void* function, void* stack, unsigned stackSize,
|
||||
unsigned returnType);
|
||||
# else
|
||||
vmNativeCall(void* function, void* stack, unsigned stackSize,
|
||||
void* gprTable, void* sseTable, unsigned returnType);
|
||||
# endif
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
vmNativeCall(void* function,
|
||||
void* stack,
|
||||
unsigned stackSize,
|
||||
unsigned returnType);
|
||||
#else
|
||||
vmNativeCall(void* function,
|
||||
void* stack,
|
||||
unsigned stackSize,
|
||||
void* gprTable,
|
||||
void* sseTable,
|
||||
unsigned returnType);
|
||||
#endif
|
||||
|
||||
namespace vm {
|
||||
|
||||
# ifdef PLATFORM_WINDOWS
|
||||
inline uint64_t
|
||||
dynamicCall(void* function, uint64_t* arguments, UNUSED uint8_t* argumentTypes,
|
||||
unsigned argumentCount, unsigned, unsigned returnType)
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
inline uint64_t dynamicCall(void* function,
|
||||
uint64_t* arguments,
|
||||
UNUSED uint8_t* argumentTypes,
|
||||
unsigned argumentCount,
|
||||
unsigned,
|
||||
unsigned returnType)
|
||||
{
|
||||
return vmNativeCall(function, arguments, argumentCount, returnType);
|
||||
}
|
||||
# else
|
||||
inline uint64_t
|
||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
unsigned argumentCount, unsigned, unsigned returnType)
|
||||
#else
|
||||
inline uint64_t dynamicCall(void* function,
|
||||
uintptr_t* arguments,
|
||||
uint8_t* argumentTypes,
|
||||
unsigned argumentCount,
|
||||
unsigned,
|
||||
unsigned returnType)
|
||||
{
|
||||
const unsigned GprCount = 6;
|
||||
uint64_t gprTable[GprCount];
|
||||
@ -192,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),
|
||||
(sseIndex ? sseTable : 0), returnType);
|
||||
(sseIndex ? sseTable : 0),
|
||||
returnType);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#else
|
||||
# error unsupported architecture
|
||||
#error unsupported architecture
|
||||
#endif
|
||||
|
||||
namespace vm {
|
||||
|
||||
inline void
|
||||
trap()
|
||||
inline void trap()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__asm int 3
|
||||
@ -216,50 +232,44 @@ trap()
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
programOrderMemoryBarrier()
|
||||
inline void programOrderMemoryBarrier()
|
||||
{
|
||||
compileTimeMemoryBarrier();
|
||||
}
|
||||
|
||||
inline void
|
||||
storeStoreMemoryBarrier()
|
||||
inline void storeStoreMemoryBarrier()
|
||||
{
|
||||
programOrderMemoryBarrier();
|
||||
}
|
||||
|
||||
inline void
|
||||
storeLoadMemoryBarrier()
|
||||
inline void storeLoadMemoryBarrier()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
MemoryBarrier();
|
||||
#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
|
||||
__asm__ __volatile__("mfence": : :"memory");
|
||||
#endif // ARCH_x86_64
|
||||
__asm__ __volatile__("mfence" : : : "memory");
|
||||
#endif // ARCH_x86_64
|
||||
}
|
||||
|
||||
inline void
|
||||
loadMemoryBarrier()
|
||||
inline void loadMemoryBarrier()
|
||||
{
|
||||
programOrderMemoryBarrier();
|
||||
}
|
||||
|
||||
inline void
|
||||
syncInstructionCache(const void*, unsigned)
|
||||
inline void syncInstructionCache(const void*, unsigned)
|
||||
{
|
||||
programOrderMemoryBarrier();
|
||||
}
|
||||
|
||||
#ifdef USE_ATOMIC_OPERATIONS
|
||||
inline bool
|
||||
atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
||||
inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return old == InterlockedCompareExchange
|
||||
(reinterpret_cast<LONG*>(p), new_, old);
|
||||
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
||||
return old
|
||||
== InterlockedCompareExchange(reinterpret_cast<LONG*>(p), new_, old);
|
||||
#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
||||
return __sync_bool_compare_and_swap(p, old, new_);
|
||||
#else
|
||||
uint8_t result;
|
||||
@ -275,13 +285,12 @@ atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
|
||||
|
||||
#define AVIAN_HAS_CAS64
|
||||
|
||||
inline bool
|
||||
atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
|
||||
inline bool atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return old == InterlockedCompareExchange64
|
||||
(reinterpret_cast<LONGLONG*>(p), new_, old);
|
||||
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
||||
return old == InterlockedCompareExchange64(
|
||||
reinterpret_cast<LONGLONG*>(p), new_, old);
|
||||
#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
|
||||
return __sync_bool_compare_and_swap(p, old, new_);
|
||||
#elif defined ARCH_x86_32
|
||||
uint8_t result;
|
||||
@ -308,17 +317,16 @@ atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
||||
inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
||||
{
|
||||
#ifdef ARCH_x86_32
|
||||
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
|
||||
#elif defined ARCH_x86_64
|
||||
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
|
||||
|
@ -13,11 +13,19 @@
|
||||
#ifdef inflateInit2
|
||||
#undef inflateInit2
|
||||
#define inflateInit2(strm, windowBits) \
|
||||
inflateInit2_((strm), (windowBits), ZLIB_VERSION, static_cast<int>(sizeof(z_stream)))
|
||||
inflateInit2_( \
|
||||
(strm), (windowBits), ZLIB_VERSION, static_cast<int>(sizeof(z_stream)))
|
||||
#endif
|
||||
|
||||
#ifdef deflateInit2
|
||||
#undef deflateInit2
|
||||
#define deflateInit2(strm, level, windowBits) \
|
||||
deflateInit2_((strm), (level), Z_DEFLATED, (windowBits), 8, Z_DEFAULT_STRATEGY, ZLIB_VERSION, static_cast<int>(sizeof(z_stream)))
|
||||
deflateInit2_((strm), \
|
||||
(level), \
|
||||
Z_DEFLATED, \
|
||||
(windowBits), \
|
||||
8, \
|
||||
Z_DEFAULT_STRATEGY, \
|
||||
ZLIB_VERSION, \
|
||||
static_cast<int>(sizeof(z_stream)))
|
||||
#endif
|
||||
|
@ -21,9 +21,9 @@ class Zone : public avian::util::Allocator {
|
||||
public:
|
||||
class Segment {
|
||||
public:
|
||||
Segment(Segment* next, unsigned size):
|
||||
next(next), size(size), position(0)
|
||||
{ }
|
||||
Segment(Segment* next, unsigned size) : next(next), size(size), position(0)
|
||||
{
|
||||
}
|
||||
|
||||
Segment* next;
|
||||
uintptr_t size;
|
||||
@ -31,19 +31,23 @@ class Zone : public avian::util::Allocator {
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
Zone(System* s, Allocator* allocator, unsigned minimumFootprint):
|
||||
s(s),
|
||||
allocator(allocator),
|
||||
segment(0),
|
||||
minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 :
|
||||
minimumFootprint - sizeof(Segment))
|
||||
{ }
|
||||
Zone(System* s, Allocator* allocator, unsigned minimumFootprint)
|
||||
: s(s),
|
||||
allocator(allocator),
|
||||
segment(0),
|
||||
minimumFootprint(minimumFootprint < sizeof(Segment)
|
||||
? 0
|
||||
: minimumFootprint - sizeof(Segment))
|
||||
{
|
||||
}
|
||||
|
||||
~Zone() {
|
||||
~Zone()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
void dispose()
|
||||
{
|
||||
for (Segment* seg = segment, *next; seg; seg = next) {
|
||||
next = seg->next;
|
||||
allocator->free(seg, sizeof(Segment) + seg->size);
|
||||
@ -52,18 +56,20 @@ class Zone : public avian::util::Allocator {
|
||||
segment = 0;
|
||||
}
|
||||
|
||||
static unsigned padToPage(unsigned size) {
|
||||
return (size + (LikelyPageSizeInBytes - 1))
|
||||
& ~(LikelyPageSizeInBytes - 1);
|
||||
static unsigned padToPage(unsigned size)
|
||||
{
|
||||
return (size + (LikelyPageSizeInBytes - 1)) & ~(LikelyPageSizeInBytes - 1);
|
||||
}
|
||||
|
||||
bool tryEnsure(unsigned space) {
|
||||
bool tryEnsure(unsigned space)
|
||||
{
|
||||
if (segment == 0 or segment->position + space > segment->size) {
|
||||
unsigned size = padToPage
|
||||
(avian::util::max
|
||||
(space, avian::util::max
|
||||
(minimumFootprint, segment == 0 ? 0 : segment->size * 2))
|
||||
+ sizeof(Segment));
|
||||
unsigned size = padToPage(
|
||||
avian::util::max(
|
||||
space,
|
||||
avian::util::max(minimumFootprint,
|
||||
segment == 0 ? 0 : segment->size * 2))
|
||||
+ sizeof(Segment));
|
||||
|
||||
void* p = allocator->tryAllocate(size);
|
||||
if (p == 0) {
|
||||
@ -79,16 +85,18 @@ class Zone : public avian::util::Allocator {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ensure(unsigned space) {
|
||||
void ensure(unsigned space)
|
||||
{
|
||||
if (segment == 0 or segment->position + space > segment->size) {
|
||||
unsigned size = padToPage(space + sizeof(Segment));
|
||||
|
||||
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);
|
||||
if (tryEnsure(size)) {
|
||||
void* r = segment->data + segment->position;
|
||||
@ -99,7 +107,8 @@ class Zone : public avian::util::Allocator {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void* allocate(unsigned size) {
|
||||
virtual void* allocate(unsigned size)
|
||||
{
|
||||
size = pad(size);
|
||||
void* p = tryAllocate(size);
|
||||
if (p) {
|
||||
@ -112,7 +121,8 @@ class Zone : public avian::util::Allocator {
|
||||
}
|
||||
}
|
||||
|
||||
void* peek(unsigned size) {
|
||||
void* peek(unsigned size)
|
||||
{
|
||||
size = pad(size);
|
||||
Segment* s = segment;
|
||||
while (s->position < size) {
|
||||
@ -122,7 +132,8 @@ class Zone : public avian::util::Allocator {
|
||||
return s->data + (s->position - size);
|
||||
}
|
||||
|
||||
void pop(unsigned size) {
|
||||
void pop(unsigned size)
|
||||
{
|
||||
size = pad(size);
|
||||
Segment* s = segment;
|
||||
while (s->position < size) {
|
||||
@ -135,11 +146,12 @@ class Zone : public avian::util::Allocator {
|
||||
segment = s;
|
||||
}
|
||||
|
||||
virtual void free(const void*, unsigned) {
|
||||
virtual void free(const void*, unsigned)
|
||||
{
|
||||
// not supported
|
||||
abort(s);
|
||||
}
|
||||
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
void* context;
|
||||
@ -147,6 +159,6 @@ class Zone : public avian::util::Allocator {
|
||||
unsigned minimumFootprint;
|
||||
};
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//ZONE_H
|
||||
#endif // ZONE_H
|
||||
|
@ -12,26 +12,23 @@
|
||||
|
||||
#ifdef BOOT_JAVAHOME
|
||||
|
||||
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||
# define SYMBOL(x) binary_javahome_jar_##x
|
||||
#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||
#define SYMBOL(x) binary_javahome_jar_##x
|
||||
#else
|
||||
# define SYMBOL(x) _binary_javahome_jar_##x
|
||||
#define SYMBOL(x) _binary_javahome_jar_##x
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
extern const uint8_t SYMBOL(start)[];
|
||||
extern const uint8_t SYMBOL(end)[];
|
||||
|
||||
extern const uint8_t SYMBOL(start)[];
|
||||
extern const uint8_t SYMBOL(end)[];
|
||||
|
||||
AVIAN_EXPORT const uint8_t*
|
||||
javahomeJar(unsigned* size)
|
||||
{
|
||||
*size = SYMBOL(end) - SYMBOL(start);
|
||||
return SYMBOL(start);
|
||||
}
|
||||
|
||||
AVIAN_EXPORT const uint8_t* javahomeJar(unsigned* size)
|
||||
{
|
||||
*size = SYMBOL(end) - SYMBOL(start);
|
||||
return SYMBOL(start);
|
||||
}
|
||||
}
|
||||
|
||||
#undef SYMBOL
|
||||
|
||||
#endif//BOOT_JAVAHOME
|
||||
#endif // BOOT_JAVAHOME
|
||||
|
74
src/boot.cpp
74
src/boot.cpp
@ -14,68 +14,64 @@
|
||||
|
||||
// since we aren't linking against libstdc++, we must implement this
|
||||
// ourselves:
|
||||
extern "C" void __cxa_pure_virtual(void) { abort(); }
|
||||
extern "C" void __cxa_pure_virtual(void)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef BOOT_IMAGE
|
||||
|
||||
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||
# define BOOTIMAGE_SYMBOL(x) binary_bootimage_bin_##x
|
||||
# define CODEIMAGE_SYMBOL(x) binary_codeimage_bin_##x
|
||||
#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||
#define BOOTIMAGE_SYMBOL(x) binary_bootimage_bin_##x
|
||||
#define CODEIMAGE_SYMBOL(x) binary_codeimage_bin_##x
|
||||
#else
|
||||
# define BOOTIMAGE_SYMBOL(x) _binary_bootimage_bin_##x
|
||||
# define CODEIMAGE_SYMBOL(x) _binary_codeimage_bin_##x
|
||||
#define BOOTIMAGE_SYMBOL(x) _binary_bootimage_bin_##x
|
||||
#define CODEIMAGE_SYMBOL(x) _binary_codeimage_bin_##x
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
extern const uint8_t BOOTIMAGE_SYMBOL(start)[];
|
||||
extern const uint8_t BOOTIMAGE_SYMBOL(end)[];
|
||||
|
||||
extern const uint8_t BOOTIMAGE_SYMBOL(start)[];
|
||||
extern const uint8_t BOOTIMAGE_SYMBOL(end)[];
|
||||
AVIAN_EXPORT const uint8_t* bootimageBin(unsigned* size)
|
||||
{
|
||||
*size = BOOTIMAGE_SYMBOL(end) - BOOTIMAGE_SYMBOL(start);
|
||||
return BOOTIMAGE_SYMBOL(start);
|
||||
}
|
||||
|
||||
AVIAN_EXPORT const uint8_t*
|
||||
bootimageBin(unsigned* size)
|
||||
{
|
||||
*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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#undef SYMBOL
|
||||
|
||||
#endif//BOOT_IMAGE
|
||||
#endif // BOOT_IMAGE
|
||||
|
||||
#ifdef BOOT_CLASSPATH
|
||||
|
||||
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||
# define SYMBOL(x) binary_classpath_jar_##x
|
||||
#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||
#define SYMBOL(x) binary_classpath_jar_##x
|
||||
#else
|
||||
# define SYMBOL(x) _binary_classpath_jar_##x
|
||||
#define SYMBOL(x) _binary_classpath_jar_##x
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
extern const uint8_t SYMBOL(start)[];
|
||||
extern const uint8_t SYMBOL(end)[];
|
||||
|
||||
extern const uint8_t SYMBOL(start)[];
|
||||
extern const uint8_t SYMBOL(end)[];
|
||||
|
||||
AVIAN_EXPORT const uint8_t*
|
||||
classpathJar(unsigned* size)
|
||||
{
|
||||
*size = SYMBOL(end) - SYMBOL(start);
|
||||
return SYMBOL(start);
|
||||
}
|
||||
|
||||
AVIAN_EXPORT const uint8_t* classpathJar(unsigned* size)
|
||||
{
|
||||
*size = SYMBOL(end) - SYMBOL(start);
|
||||
return SYMBOL(start);
|
||||
}
|
||||
}
|
||||
|
||||
#undef SYMBOL
|
||||
|
||||
#endif//BOOT_CLASSPATH
|
||||
#endif // BOOT_CLASSPATH
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef FIELD
|
||||
# define FIELD(name)
|
||||
# define FIELD_DEFINED
|
||||
#define FIELD(name)
|
||||
#define FIELD_DEFINED
|
||||
#endif
|
||||
|
||||
FIELD(magic)
|
||||
@ -23,13 +23,13 @@ FIELD(methodTreeSentinal)
|
||||
FIELD(virtualThunks)
|
||||
|
||||
#ifdef FIELD_DEFINED
|
||||
# undef FIELD
|
||||
# undef FIELD_DEFINED
|
||||
#undef FIELD
|
||||
#undef FIELD_DEFINED
|
||||
#endif
|
||||
|
||||
#ifndef THUNK_FIELD
|
||||
# define THUNK_FIELD(name)
|
||||
# define THUNK_FIELD_DEFINED
|
||||
#define THUNK_FIELD(name)
|
||||
#define THUNK_FIELD_DEFINED
|
||||
#endif
|
||||
|
||||
THUNK_FIELD(default_);
|
||||
@ -40,6 +40,6 @@ THUNK_FIELD(stackOverflow);
|
||||
THUNK_FIELD(table);
|
||||
|
||||
#ifdef THUNK_FIELD_DEFINED
|
||||
# undef THUNK_FIELD
|
||||
# undef THUNK_FIELD_DEFINED
|
||||
#undef THUNK_FIELD
|
||||
#undef THUNK_FIELD_DEFINED
|
||||
#endif
|
||||
|
@ -1,26 +1,25 @@
|
||||
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(BootFlatConstant) = 1 << NAME(BootShift);
|
||||
const unsigned NAME(BootHeapOffset) = 1 << (NAME(BootShift) + 1);
|
||||
|
||||
inline unsigned
|
||||
LABEL(codeMapSize)(unsigned codeSize)
|
||||
inline unsigned LABEL(codeMapSize)(unsigned codeSize)
|
||||
{
|
||||
return avian::util::ceilingDivide(codeSize, TargetBitsPerWord) * TargetBytesPerWord;
|
||||
return avian::util::ceilingDivide(codeSize, TargetBitsPerWord)
|
||||
* TargetBytesPerWord;
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
LABEL(heapMapSize)(unsigned heapSize)
|
||||
inline unsigned LABEL(heapMapSize)(unsigned heapSize)
|
||||
{
|
||||
return avian::util::ceilingDivide(heapSize, TargetBitsPerWord * TargetBytesPerWord)
|
||||
* TargetBytesPerWord;
|
||||
return avian::util::ceilingDivide(heapSize,
|
||||
TargetBitsPerWord * TargetBytesPerWord)
|
||||
* TargetBytesPerWord;
|
||||
}
|
||||
|
||||
inline object
|
||||
LABEL(bootObject)(LABEL(uintptr_t)* heap, unsigned offset)
|
||||
inline object LABEL(bootObject)(LABEL(uintptr_t) * heap, unsigned offset)
|
||||
{
|
||||
if (offset) {
|
||||
return reinterpret_cast<object>(heap + offset - 1);
|
||||
|
526
src/builtin.cpp
526
src/builtin.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -22,9 +22,9 @@ namespace local {
|
||||
|
||||
class MyClasspath : public Classpath {
|
||||
public:
|
||||
MyClasspath(Allocator* allocator):
|
||||
allocator(allocator)
|
||||
{ }
|
||||
MyClasspath(Allocator* allocator) : allocator(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
virtual GcJclass* makeJclass(Thread* t, GcClass* class_)
|
||||
{
|
||||
@ -97,14 +97,12 @@ class MyClasspath : public Classpath {
|
||||
return jfield->vmField();
|
||||
}
|
||||
|
||||
virtual void
|
||||
clearInterrupted(Thread*)
|
||||
virtual void clearInterrupted(Thread*)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual void
|
||||
runThread(Thread* t)
|
||||
virtual void runThread(Thread* t)
|
||||
{
|
||||
GcMethod* method = resolveMethod(t,
|
||||
roots(t)->bootLoader(),
|
||||
@ -120,14 +118,12 @@ class MyClasspath : public Classpath {
|
||||
vm::resolveNative(t, method);
|
||||
}
|
||||
|
||||
virtual void
|
||||
interceptMethods(Thread*)
|
||||
virtual void interceptMethods(Thread*)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual void
|
||||
preBoot(Thread*)
|
||||
virtual void preBoot(Thread*)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
@ -137,20 +133,17 @@ class MyClasspath : public Classpath {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void
|
||||
boot(Thread*)
|
||||
virtual void boot(Thread*)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual const char*
|
||||
bootClasspath()
|
||||
virtual const char* bootClasspath()
|
||||
{
|
||||
return AVIAN_CLASSPATH;
|
||||
}
|
||||
|
||||
virtual object
|
||||
makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
||||
virtual object makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
||||
{
|
||||
GcClass* c
|
||||
= resolveClass(t, roots(t)->bootLoader(), "java/nio/DirectByteBuffer");
|
||||
@ -161,15 +154,16 @@ class MyClasspath : public Classpath {
|
||||
|
||||
GcMethod* constructor = resolveMethod(t, c, "<init>", "(JI)V");
|
||||
|
||||
t->m->processor->invoke
|
||||
(t, constructor, instance, reinterpret_cast<int64_t>(p),
|
||||
static_cast<int32_t>(capacity));
|
||||
t->m->processor->invoke(t,
|
||||
constructor,
|
||||
instance,
|
||||
reinterpret_cast<int64_t>(p),
|
||||
static_cast<int32_t>(capacity));
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
virtual void*
|
||||
getDirectBufferAddress(Thread* t, object b)
|
||||
virtual void* getDirectBufferAddress(Thread* t, object b)
|
||||
{
|
||||
PROTECT(t, b);
|
||||
|
||||
@ -178,8 +172,7 @@ class MyClasspath : public Classpath {
|
||||
return reinterpret_cast<void*>(fieldAtOffset<int64_t>(b, field->offset()));
|
||||
}
|
||||
|
||||
virtual int64_t
|
||||
getDirectBufferCapacity(Thread* t, object b)
|
||||
virtual int64_t getDirectBufferCapacity(Thread* t, object b)
|
||||
{
|
||||
PROTECT(t, b);
|
||||
|
||||
@ -219,14 +212,12 @@ class MyClasspath : public Classpath {
|
||||
: caller->class_()->loader();
|
||||
}
|
||||
|
||||
virtual void
|
||||
shutDown(Thread*)
|
||||
virtual void shutDown(Thread*)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual void
|
||||
dispose()
|
||||
virtual void dispose()
|
||||
{
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
@ -242,32 +233,35 @@ void enumerateThreads(Thread* t,
|
||||
{
|
||||
if (*index < limit) {
|
||||
array->setBodyElement(t, *index, x->javaThread);
|
||||
++ (*index);
|
||||
++(*index);
|
||||
|
||||
if (x->peer) enumerateThreads(t, x->peer, array, index, limit);
|
||||
|
||||
if (x->child) enumerateThreads(t, x->child, array, index, limit);
|
||||
if (x->peer)
|
||||
enumerateThreads(t, x->peer, array, index, limit);
|
||||
|
||||
if (x->child)
|
||||
enumerateThreads(t, x->child, array, index, limit);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace local
|
||||
} // namespace local
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
Classpath*
|
||||
makeClasspath(System*, Allocator* allocator, const char*, const char*)
|
||||
Classpath* makeClasspath(System*,
|
||||
Allocator* allocator,
|
||||
const char*,
|
||||
const char*)
|
||||
{
|
||||
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
||||
local::MyClasspath(allocator);
|
||||
local::MyClasspath(allocator);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Object_toString
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Object_toString(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
@ -279,26 +273,24 @@ Avian_java_lang_Object_toString
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Object_getVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Object_getVMClass(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<int64_t>
|
||||
(objectClass(t, reinterpret_cast<object>(arguments[0])));
|
||||
return reinterpret_cast<int64_t>(
|
||||
objectClass(t, reinterpret_cast<object>(arguments[0])));
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_Object_wait
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Object_wait(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
int64_t milliseconds; memcpy(&milliseconds, arguments + 1, 8);
|
||||
int64_t milliseconds;
|
||||
memcpy(&milliseconds, arguments + 1, 8);
|
||||
|
||||
vm::wait(t, this_, milliseconds);
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_Object_notify
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Object_notify(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
@ -306,8 +298,7 @@ Avian_java_lang_Object_notify
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_Object_notifyAll
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Object_notifyAll(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
@ -315,8 +306,7 @@ Avian_java_lang_Object_notifyAll
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Object_hashCode
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Object_hashCode(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
@ -324,16 +314,16 @@ Avian_java_lang_Object_hashCode
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Object_clone
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Object_clone(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<int64_t>
|
||||
(clone(t, reinterpret_cast<object>(arguments[0])));
|
||||
return reinterpret_cast<int64_t>(
|
||||
clone(t, reinterpret_cast<object>(arguments[0])));
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_io_ObjectInputStream_makeInstance
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_io_ObjectInputStream_makeInstance(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
GcClass* c = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
|
||||
|
||||
@ -341,36 +331,38 @@ Avian_java_io_ObjectInputStream_makeInstance
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_avian_LegacyObjectInputStream_makeInstance
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_avian_LegacyObjectInputStream_makeInstance(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
return Avian_java_io_ObjectInputStream_makeInstance(t, NULL, arguments);
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_reflect_Field_getPrimitive
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_reflect_Field_getPrimitive(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
object instance = reinterpret_cast<object>(arguments[0]);
|
||||
int code = arguments[1];
|
||||
int offset = arguments[2];
|
||||
|
||||
switch (code) {
|
||||
case ByteField:
|
||||
case ByteField:
|
||||
return fieldAtOffset<int8_t>(instance, offset);
|
||||
case BooleanField:
|
||||
case BooleanField:
|
||||
return fieldAtOffset<uint8_t>(instance, offset);
|
||||
case CharField:
|
||||
case CharField:
|
||||
return fieldAtOffset<uint16_t>(instance, offset);
|
||||
case ShortField:
|
||||
case ShortField:
|
||||
return fieldAtOffset<int16_t>(instance, offset);
|
||||
case IntField:
|
||||
case IntField:
|
||||
return fieldAtOffset<int32_t>(instance, offset);
|
||||
case LongField:
|
||||
case LongField:
|
||||
return fieldAtOffset<int64_t>(instance, offset);
|
||||
case FloatField:
|
||||
case FloatField:
|
||||
return fieldAtOffset<uint32_t>(instance, offset);
|
||||
case DoubleField:
|
||||
case DoubleField:
|
||||
return fieldAtOffset<uint64_t>(instance, offset);
|
||||
default:
|
||||
abort(t);
|
||||
@ -378,8 +370,9 @@ Avian_java_lang_reflect_Field_getPrimitive
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_reflect_Field_getObject
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
Avian_java_lang_reflect_Field_getObject(Thread*,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
object instance = reinterpret_cast<object>(arguments[0]);
|
||||
int offset = arguments[1];
|
||||
@ -388,13 +381,15 @@ Avian_java_lang_reflect_Field_getObject
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_reflect_Field_setPrimitive
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_reflect_Field_setPrimitive(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
object instance = reinterpret_cast<object>(arguments[0]);
|
||||
int code = arguments[1];
|
||||
int offset = arguments[2];
|
||||
int64_t value; memcpy(&value, arguments + 3, 8);
|
||||
int64_t value;
|
||||
memcpy(&value, arguments + 3, 8);
|
||||
|
||||
switch (code) {
|
||||
case ByteField:
|
||||
@ -409,16 +404,16 @@ Avian_java_lang_reflect_Field_setPrimitive
|
||||
case ShortField:
|
||||
fieldAtOffset<int16_t>(instance, offset) = static_cast<int16_t>(value);
|
||||
break;
|
||||
case IntField:
|
||||
case IntField:
|
||||
fieldAtOffset<int32_t>(instance, offset) = static_cast<int32_t>(value);
|
||||
break;
|
||||
case LongField:
|
||||
case LongField:
|
||||
fieldAtOffset<int64_t>(instance, offset) = static_cast<int64_t>(value);
|
||||
break;
|
||||
case FloatField:
|
||||
case FloatField:
|
||||
fieldAtOffset<uint32_t>(instance, offset) = static_cast<uint32_t>(value);
|
||||
break;
|
||||
case DoubleField:
|
||||
case DoubleField:
|
||||
fieldAtOffset<uint64_t>(instance, offset) = static_cast<uint64_t>(value);
|
||||
break;
|
||||
default:
|
||||
@ -427,8 +422,9 @@ Avian_java_lang_reflect_Field_setPrimitive
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_reflect_Field_setObject
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_reflect_Field_setObject(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
object instance = reinterpret_cast<object>(arguments[0]);
|
||||
int offset = arguments[1];
|
||||
@ -438,8 +434,9 @@ Avian_java_lang_reflect_Field_setObject
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_reflect_Constructor_make
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_reflect_Constructor_make(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
GcClass* c = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
|
||||
|
||||
@ -447,38 +444,38 @@ Avian_java_lang_reflect_Constructor_make
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_reflect_Method_getCaller
|
||||
(Thread* t, object, uintptr_t*)
|
||||
Avian_java_lang_reflect_Method_getCaller(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
return reinterpret_cast<int64_t>(getCaller(t, 2));
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_reflect_Method_invoke
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_reflect_Method_invoke(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
GcMethod* method = cast<GcMethod>(t, reinterpret_cast<object>(arguments[0]));
|
||||
object instance = reinterpret_cast<object>(arguments[1]);
|
||||
object args = reinterpret_cast<object>(arguments[2]);
|
||||
|
||||
THREAD_RESOURCE0(t, {
|
||||
if (t->exception) {
|
||||
GcThrowable* exception = t->exception;
|
||||
t->exception = makeThrowable(
|
||||
t, GcInvocationTargetException::Type, 0, 0, exception);
|
||||
}
|
||||
});
|
||||
if (t->exception) {
|
||||
GcThrowable* exception = t->exception;
|
||||
t->exception = makeThrowable(
|
||||
t, GcInvocationTargetException::Type, 0, 0, exception);
|
||||
}
|
||||
});
|
||||
|
||||
unsigned returnCode = method->returnCode();
|
||||
|
||||
return reinterpret_cast<int64_t>
|
||||
(translateInvokeResult
|
||||
(t, returnCode, t->m->processor->invokeArray(t, method, instance, args)));
|
||||
return reinterpret_cast<int64_t>(translateInvokeResult(
|
||||
t, returnCode, t->m->processor->invokeArray(t, method, instance, args)));
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_reflect_Array_getLength
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_reflect_Array_getLength(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
object array = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
@ -496,8 +493,9 @@ Avian_java_lang_reflect_Array_getLength
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_reflect_Array_makeObjectArray
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_reflect_Array_makeObjectArray(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
GcJclass* elementType
|
||||
= cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]));
|
||||
@ -508,38 +506,41 @@ Avian_java_lang_reflect_Array_makeObjectArray
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Float_floatToRawIntBits
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Float_floatToRawIntBits(Thread*,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
return static_cast<int32_t>(*arguments);
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Float_intBitsToFloat
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Float_intBitsToFloat(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
return static_cast<int32_t>(*arguments);
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Double_doubleToRawLongBits
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Double_doubleToRawLongBits(Thread*,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
int64_t v; memcpy(&v, arguments, 8);
|
||||
int64_t v;
|
||||
memcpy(&v, arguments, 8);
|
||||
return v;
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Double_longBitsToDouble
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Double_longBitsToDouble(Thread*,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
int64_t v; memcpy(&v, arguments, 8);
|
||||
int64_t v;
|
||||
memcpy(&v, arguments, 8);
|
||||
return v;
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_String_intern
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_String_intern(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
@ -562,10 +563,10 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_System_arraycopy
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_System_arraycopy(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
arrayCopy(t, reinterpret_cast<object>(arguments[0]),
|
||||
arrayCopy(t,
|
||||
reinterpret_cast<object>(arguments[0]),
|
||||
arguments[1],
|
||||
reinterpret_cast<object>(arguments[2]),
|
||||
arguments[3],
|
||||
@ -573,8 +574,9 @@ Avian_java_lang_System_arraycopy
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_System_identityHashCode
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_System_identityHashCode(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
object o = reinterpret_cast<object>(arguments[0]);
|
||||
|
||||
@ -612,15 +614,15 @@ extern "C" AVIAN_EXPORT void JNICALL
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_Runtime_gc
|
||||
(Thread* t, object, uintptr_t*)
|
||||
Avian_java_lang_Runtime_gc(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
collect(t, Heap::MajorCollection);
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_Runtime_addShutdownHook
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Runtime_addShutdownHook(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
object hook = reinterpret_cast<object>(arguments[1]);
|
||||
PROTECT(t, hook);
|
||||
@ -633,15 +635,15 @@ Avian_java_lang_Runtime_addShutdownHook
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Throwable_trace
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Throwable_trace(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<int64_t>(getTrace(t, arguments[0]));
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Throwable_resolveTrace
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Throwable_resolveTrace(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
object trace = reinterpret_cast<object>(*arguments);
|
||||
PROTECT(t, trace);
|
||||
@ -661,63 +663,61 @@ Avian_java_lang_Throwable_resolveTrace
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Thread_currentThread
|
||||
(Thread* t, object, uintptr_t*)
|
||||
Avian_java_lang_Thread_currentThread(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
return reinterpret_cast<int64_t>(t->javaThread);
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Thread_doStart
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Thread_doStart(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<int64_t>(
|
||||
startThread(t, cast<GcThread>(t, reinterpret_cast<object>(*arguments))));
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_Thread_interrupt
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Thread_interrupt(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t peer; memcpy(&peer, arguments, 8);
|
||||
int64_t peer;
|
||||
memcpy(&peer, arguments, 8);
|
||||
|
||||
threadInterrupt(t, reinterpret_cast<Thread*>(peer)->javaThread);
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Thread_interrupted
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Thread_interrupted(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t peer; memcpy(&peer, arguments, 8);
|
||||
int64_t peer;
|
||||
memcpy(&peer, arguments, 8);
|
||||
|
||||
return threadIsInterrupted
|
||||
(t, reinterpret_cast<Thread*>(peer)->javaThread, true);
|
||||
return threadIsInterrupted(
|
||||
t, reinterpret_cast<Thread*>(peer)->javaThread, true);
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Thread_getStackTrace
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Thread_getStackTrace(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
int64_t peer; memcpy(&peer, arguments, 8);
|
||||
int64_t peer;
|
||||
memcpy(&peer, arguments, 8);
|
||||
|
||||
if (reinterpret_cast<Thread*>(peer) == t) {
|
||||
return reinterpret_cast<int64_t>(makeTrace(t));
|
||||
} else {
|
||||
return reinterpret_cast<int64_t>
|
||||
(t->m->processor->getStackTrace(t, reinterpret_cast<Thread*>(peer)));
|
||||
return reinterpret_cast<int64_t>(
|
||||
t->m->processor->getStackTrace(t, reinterpret_cast<Thread*>(peer)));
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Thread_activeCount
|
||||
(Thread* t, object, uintptr_t*)
|
||||
Avian_java_lang_Thread_activeCount(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
return t->m->liveCount;
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_java_lang_Thread_enumerate
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_java_lang_Thread_enumerate(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
GcArray* array = cast<GcArray>(t, reinterpret_cast<object>(*arguments));
|
||||
|
||||
@ -731,15 +731,13 @@ Avian_java_lang_Thread_enumerate
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_java_lang_Thread_yield
|
||||
(Thread* t, object, uintptr_t*)
|
||||
Avian_java_lang_Thread_yield(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
t->m->system->yield();
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_avian_Atomic_getOffset
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_avian_Atomic_getOffset(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[0]))
|
||||
->vmField()
|
||||
@ -747,8 +745,9 @@ Avian_avian_Atomic_getOffset
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_objectFieldOffset
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_sun_misc_Unsafe_objectFieldOffset(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[1]))
|
||||
->vmField()
|
||||
@ -756,16 +755,18 @@ Avian_sun_misc_Unsafe_objectFieldOffset
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_avian_Atomic_compareAndSwapObject
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_avian_Atomic_compareAndSwapObject(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
object target = reinterpret_cast<object>(arguments[0]);
|
||||
int64_t offset; memcpy(&offset, arguments + 1, 8);
|
||||
int64_t offset;
|
||||
memcpy(&offset, arguments + 1, 8);
|
||||
uintptr_t expect = arguments[3];
|
||||
uintptr_t update = arguments[4];
|
||||
|
||||
bool success = atomicCompareAndSwap
|
||||
(&fieldAtOffset<uintptr_t>(target, offset), expect, update);
|
||||
bool success = atomicCompareAndSwap(
|
||||
&fieldAtOffset<uintptr_t>(target, offset), expect, update);
|
||||
|
||||
if (success) {
|
||||
mark(t, target, offset);
|
||||
@ -775,8 +776,9 @@ Avian_avian_Atomic_compareAndSwapObject
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_avian_Classes_isAssignableFrom
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_avian_Classes_isAssignableFrom(Thread* t,
|
||||
object,
|
||||
uintptr_t* arguments)
|
||||
{
|
||||
GcClass* this_ = cast<GcClass>(t, reinterpret_cast<object>(arguments[0]));
|
||||
GcClass* that = cast<GcClass>(t, reinterpret_cast<object>(arguments[1]));
|
||||
@ -789,16 +791,14 @@ Avian_avian_Classes_isAssignableFrom
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_avian_Classes_getVMClass
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_avian_Classes_getVMClass(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<int64_t>
|
||||
(objectClass(t, reinterpret_cast<object>(arguments[0])));
|
||||
return reinterpret_cast<int64_t>(
|
||||
objectClass(t, reinterpret_cast<object>(arguments[0])));
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_avian_Classes_makeMethod
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
Avian_avian_Classes_makeMethod(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
GcMethod* method = cast<GcMethod>(
|
||||
t,
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -53,18 +53,22 @@ Context::Context(vm::System* system,
|
||||
- regFile->generalRegisters.start),
|
||||
targetInfo(arch->targetInfo())
|
||||
{
|
||||
for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) {
|
||||
for (unsigned i = regFile->generalRegisters.start;
|
||||
i < regFile->generalRegisters.limit;
|
||||
++i) {
|
||||
new (registerResources + i) RegisterResource(arch->reserved(i));
|
||||
|
||||
if (registerResources[i].reserved) {
|
||||
-- availableGeneralRegisterCount;
|
||||
--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));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -37,8 +37,9 @@ class ConstantPoolNode;
|
||||
class ForkState;
|
||||
class Block;
|
||||
|
||||
template<class T>
|
||||
List<T>* reverseDestroy(List<T>* cell) {
|
||||
template <class T>
|
||||
List<T>* reverseDestroy(List<T>* cell)
|
||||
{
|
||||
List<T>* previous = 0;
|
||||
while (cell) {
|
||||
List<T>* next = cell->next;
|
||||
@ -93,7 +94,9 @@ class LogicalCode {
|
||||
|
||||
class Context {
|
||||
public:
|
||||
Context(vm::System* system, Assembler* assembler, vm::Zone* zone,
|
||||
Context(vm::System* system,
|
||||
Assembler* assembler,
|
||||
vm::Zone* zone,
|
||||
Compiler::Client* client);
|
||||
|
||||
vm::System* system;
|
||||
@ -128,17 +131,19 @@ class Context {
|
||||
ir::TargetInfo targetInfo;
|
||||
};
|
||||
|
||||
inline Aborter* getAborter(Context* c) {
|
||||
inline Aborter* getAborter(Context* c)
|
||||
{
|
||||
return c->system;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
List<T>* cons(Context* c, const T& value, List<T>* next) {
|
||||
template <class T>
|
||||
List<T>* cons(Context* c, const T& value, List<T>* next)
|
||||
{
|
||||
return new (c->zone) List<T>(value, next);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_CONTEXT_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_CONTEXT_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -33,25 +33,41 @@ class Event {
|
||||
|
||||
virtual void compile(Context* c) = 0;
|
||||
|
||||
virtual bool isBranch() { return false; }
|
||||
|
||||
virtual bool allExits() { return false; }
|
||||
|
||||
virtual Local* locals() { return localsBefore; }
|
||||
virtual bool isBranch()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool allExits()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual Local* locals()
|
||||
{
|
||||
return localsBefore;
|
||||
}
|
||||
|
||||
void addRead(Context* c, Value* v, Read* r);
|
||||
|
||||
void addRead(Context* c, Value* v, const SiteMask& mask,
|
||||
Value* successor = 0);
|
||||
void addRead(Context* c,
|
||||
Value* v,
|
||||
const SiteMask& mask,
|
||||
Value* successor = 0);
|
||||
|
||||
void addReads(Context* c, Value* v, unsigned size,
|
||||
const SiteMask& lowMask, Value* lowSuccessor,
|
||||
const SiteMask& highMask, Value* highSuccessor);
|
||||
void addReads(Context* c,
|
||||
Value* v,
|
||||
unsigned size,
|
||||
const SiteMask& lowMask,
|
||||
Value* lowSuccessor,
|
||||
const SiteMask& highMask,
|
||||
Value* highSuccessor);
|
||||
|
||||
void addReads(Context* c, Value* v, unsigned size,
|
||||
const SiteMask& lowMask, const SiteMask& highMask);
|
||||
void addReads(Context* c,
|
||||
Value* v,
|
||||
unsigned size,
|
||||
const SiteMask& lowMask,
|
||||
const SiteMask& highMask);
|
||||
|
||||
CodePromise* makeCodePromise(Context* c);
|
||||
|
||||
@ -82,7 +98,9 @@ class StubReadPair {
|
||||
|
||||
class JunctionState {
|
||||
public:
|
||||
JunctionState(unsigned frameFootprint): frameFootprint(frameFootprint) { }
|
||||
JunctionState(unsigned frameFootprint) : frameFootprint(frameFootprint)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned frameFootprint;
|
||||
StubReadPair reads[0];
|
||||
@ -90,12 +108,19 @@ class JunctionState {
|
||||
|
||||
class Link {
|
||||
public:
|
||||
Link(Event* predecessor, Link* nextPredecessor, Event* successor,
|
||||
Link* nextSuccessor, ForkState* forkState):
|
||||
predecessor(predecessor), nextPredecessor(nextPredecessor),
|
||||
successor(successor), nextSuccessor(nextSuccessor), forkState(forkState),
|
||||
junctionState(0)
|
||||
{ }
|
||||
Link(Event* predecessor,
|
||||
Link* nextPredecessor,
|
||||
Event* successor,
|
||||
Link* nextSuccessor,
|
||||
ForkState* forkState)
|
||||
: predecessor(predecessor),
|
||||
nextPredecessor(nextPredecessor),
|
||||
successor(successor),
|
||||
nextSuccessor(nextSuccessor),
|
||||
forkState(forkState),
|
||||
junctionState(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned countPredecessors();
|
||||
Link* lastPredecessor();
|
||||
@ -109,9 +134,12 @@ class Link {
|
||||
JunctionState* junctionState;
|
||||
};
|
||||
|
||||
Link*
|
||||
link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor,
|
||||
Link* nextSuccessor, ForkState* forkState);
|
||||
Link* link(Context* c,
|
||||
Event* predecessor,
|
||||
Link* nextPredecessor,
|
||||
Event* successor,
|
||||
Link* nextSuccessor,
|
||||
ForkState* forkState);
|
||||
|
||||
void appendCall(Context* c,
|
||||
Value* address,
|
||||
@ -142,12 +170,14 @@ void appendTranslate(Context* c,
|
||||
Value* first,
|
||||
Value* result);
|
||||
|
||||
void
|
||||
appendOperation(Context* c, lir::Operation op);
|
||||
void appendOperation(Context* c, lir::Operation op);
|
||||
|
||||
void
|
||||
appendMemory(Context* c, Value* base, int displacement, Value* index,
|
||||
unsigned scale, Value* result);
|
||||
void appendMemory(Context* c,
|
||||
Value* base,
|
||||
int displacement,
|
||||
Value* index,
|
||||
unsigned scale,
|
||||
Value* result);
|
||||
|
||||
void appendBranch(Context* c,
|
||||
lir::TernaryOperation op,
|
||||
@ -161,23 +191,22 @@ void appendJump(Context* c,
|
||||
bool exit = false,
|
||||
bool cleanLocals = false);
|
||||
|
||||
void
|
||||
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
|
||||
Value* index, intptr_t handler);
|
||||
void appendBoundsCheck(Context* c,
|
||||
Value* object,
|
||||
unsigned lengthOffset,
|
||||
Value* index,
|
||||
intptr_t handler);
|
||||
|
||||
void
|
||||
appendFrameSite(Context* c, Value* value, int index);
|
||||
void appendFrameSite(Context* c, Value* value, int index);
|
||||
|
||||
void
|
||||
appendSaveLocals(Context* c);
|
||||
void appendSaveLocals(Context* c);
|
||||
|
||||
void
|
||||
appendDummy(Context* c);
|
||||
void appendDummy(Context* c);
|
||||
|
||||
void appendBuddy(Context* c, Value* original, Value* buddy);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_EVENT_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_EVENT_H
|
||||
|
@ -19,13 +19,14 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
unsigned totalFrameSize(Context* c) {
|
||||
return c->alignedFrameSize
|
||||
+ c->arch->frameHeaderSize()
|
||||
+ c->arch->argumentFootprint(c->parameterFootprint);
|
||||
unsigned totalFrameSize(Context* c)
|
||||
{
|
||||
return c->alignedFrameSize + c->arch->frameHeaderSize()
|
||||
+ c->arch->argumentFootprint(c->parameterFootprint);
|
||||
}
|
||||
|
||||
int frameIndex(Context* c, int localIndex) {
|
||||
int frameIndex(Context* c, int localIndex)
|
||||
{
|
||||
assertT(c, localIndex >= 0);
|
||||
|
||||
int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1;
|
||||
@ -42,13 +43,15 @@ int frameIndex(Context* c, int localIndex) {
|
||||
return index;
|
||||
}
|
||||
|
||||
unsigned frameIndexToOffset(Context* c, unsigned frameIndex) {
|
||||
unsigned frameIndexToOffset(Context* c, unsigned frameIndex)
|
||||
{
|
||||
assertT(c, frameIndex < totalFrameSize(c));
|
||||
|
||||
return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize;
|
||||
}
|
||||
|
||||
unsigned offsetToFrameIndex(Context* c, unsigned offset) {
|
||||
unsigned offsetToFrameIndex(Context* c, unsigned offset)
|
||||
{
|
||||
assertT(c,
|
||||
static_cast<int>((offset / c->targetInfo.pointerSize)
|
||||
- c->arch->frameFooterSize()) >= 0);
|
||||
@ -59,43 +62,50 @@ unsigned offsetToFrameIndex(Context* c, unsigned offset) {
|
||||
return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize();
|
||||
}
|
||||
|
||||
unsigned frameBase(Context* c) {
|
||||
return c->alignedFrameSize
|
||||
- c->arch->frameReturnAddressSize()
|
||||
- c->arch->frameFooterSize()
|
||||
+ c->arch->frameHeaderSize();
|
||||
}
|
||||
unsigned frameBase(Context* c)
|
||||
{
|
||||
return c->alignedFrameSize - c->arch->frameReturnAddressSize()
|
||||
- c->arch->frameFooterSize() + c->arch->frameHeaderSize();
|
||||
}
|
||||
|
||||
FrameIterator::Element::Element(Value* value, unsigned localIndex):
|
||||
value(value), localIndex(localIndex)
|
||||
{ }
|
||||
FrameIterator::Element::Element(Value* value, unsigned localIndex)
|
||||
: value(value), localIndex(localIndex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int FrameIterator::Element::frameIndex(Context* c) {
|
||||
int FrameIterator::Element::frameIndex(Context* c)
|
||||
{
|
||||
return compiler::frameIndex(c, this->localIndex);
|
||||
}
|
||||
|
||||
FrameIterator::FrameIterator(Context* c, Stack* stack, Local* locals,
|
||||
bool includeEmpty):
|
||||
stack(stack), locals(locals), localIndex(c->localFootprint - 1),
|
||||
includeEmpty(includeEmpty)
|
||||
{ }
|
||||
FrameIterator::FrameIterator(Context* c,
|
||||
Stack* stack,
|
||||
Local* locals,
|
||||
bool includeEmpty)
|
||||
: stack(stack),
|
||||
locals(locals),
|
||||
localIndex(c->localFootprint - 1),
|
||||
includeEmpty(includeEmpty)
|
||||
{
|
||||
}
|
||||
|
||||
bool FrameIterator::hasMore() {
|
||||
bool FrameIterator::hasMore()
|
||||
{
|
||||
if (not includeEmpty) {
|
||||
while (stack and stack->value == 0) {
|
||||
stack = stack->next;
|
||||
}
|
||||
|
||||
while (localIndex >= 0 and locals[localIndex].value == 0) {
|
||||
-- localIndex;
|
||||
--localIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return stack != 0 or localIndex >= 0;
|
||||
}
|
||||
|
||||
FrameIterator::Element FrameIterator::next(Context* c) {
|
||||
FrameIterator::Element FrameIterator::next(Context* c)
|
||||
{
|
||||
Value* v;
|
||||
unsigned li;
|
||||
if (stack) {
|
||||
@ -107,17 +117,16 @@ FrameIterator::Element FrameIterator::next(Context* c) {
|
||||
Local* l = locals + localIndex;
|
||||
v = l->value;
|
||||
li = localIndex;
|
||||
-- localIndex;
|
||||
--localIndex;
|
||||
}
|
||||
return Element(v, li);
|
||||
}
|
||||
|
||||
Stack* stack(Context* c, Value* value, Stack* next) {
|
||||
return new(c->zone) Stack(next ? next->index + 1 : 0, value, next);
|
||||
Stack* stack(Context* c, Value* value, Stack* next)
|
||||
{
|
||||
return new (c->zone) Stack(next ? next->index + 1 : 0, value, next);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -37,7 +37,9 @@ class FrameIterator {
|
||||
const unsigned localIndex;
|
||||
};
|
||||
|
||||
FrameIterator(Context* c, Stack* stack, Local* locals,
|
||||
FrameIterator(Context* c,
|
||||
Stack* stack,
|
||||
Local* locals,
|
||||
bool includeEmpty = false);
|
||||
|
||||
bool hasMore();
|
||||
@ -57,9 +59,10 @@ class Local {
|
||||
|
||||
class Stack {
|
||||
public:
|
||||
Stack(unsigned index, Value* value, Stack* next):
|
||||
index(index), value(value), next(next)
|
||||
{ }
|
||||
Stack(unsigned index, Value* value, Stack* next)
|
||||
: index(index), value(value), next(next)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned index;
|
||||
Value* value;
|
||||
@ -68,8 +71,8 @@ class Stack {
|
||||
|
||||
Stack* stack(Context* c, Value* value, Stack* next);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_FRAME_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_FRAME_H
|
||||
|
@ -23,31 +23,35 @@ LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals)
|
||||
locals(locals),
|
||||
machineOffset(0),
|
||||
/*subroutine(0), */ index(index)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
LogicalInstruction* LogicalInstruction::next(Context* c) {
|
||||
LogicalInstruction* LogicalInstruction::next(Context* c)
|
||||
{
|
||||
LogicalInstruction* i = this;
|
||||
for (size_t n = i->index + 1; n < c->logicalCode.count(); ++n) {
|
||||
i = c->logicalCode[n];
|
||||
if (i) return i;
|
||||
if (i)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
machineOffset(Context* c, int logicalIp)
|
||||
unsigned machineOffset(Context* c, int logicalIp)
|
||||
{
|
||||
return c->logicalCode[logicalIp]->machineOffset->value();
|
||||
}
|
||||
|
||||
Block::Block(Event* head):
|
||||
head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
|
||||
{ }
|
||||
|
||||
Block* block(Context* c, Event* head) {
|
||||
return new(c->zone) Block(head);
|
||||
Block::Block(Event* head)
|
||||
: head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
Block* block(Context* c, Event* head)
|
||||
{
|
||||
return new (c->zone) Block(head);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -24,17 +24,21 @@ class ForkElement {
|
||||
bool local;
|
||||
};
|
||||
|
||||
class ForkState: public Compiler::State {
|
||||
class ForkState : public Compiler::State {
|
||||
public:
|
||||
ForkState(Stack* stack, Local* locals, List<Value*>* saved, Event* predecessor,
|
||||
unsigned logicalIp):
|
||||
stack(stack),
|
||||
locals(locals),
|
||||
saved(saved),
|
||||
predecessor(predecessor),
|
||||
logicalIp(logicalIp),
|
||||
readCount(0)
|
||||
{ }
|
||||
ForkState(Stack* stack,
|
||||
Local* locals,
|
||||
List<Value*>* saved,
|
||||
Event* predecessor,
|
||||
unsigned logicalIp)
|
||||
: stack(stack),
|
||||
locals(locals),
|
||||
saved(saved),
|
||||
predecessor(predecessor),
|
||||
logicalIp(logicalIp),
|
||||
readCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
Stack* stack;
|
||||
Local* locals;
|
||||
@ -75,8 +79,8 @@ Block* block(Context* c, Event* head);
|
||||
|
||||
unsigned machineOffset(Context* c, int logicalIp);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_IR_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_IR_H
|
||||
|
@ -18,88 +18,104 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
CodePromise::CodePromise(Context* c, CodePromise* next):
|
||||
c(c), offset(0), next(next)
|
||||
{ }
|
||||
CodePromise::CodePromise(Context* c, CodePromise* next)
|
||||
: c(c), offset(0), next(next)
|
||||
{
|
||||
}
|
||||
|
||||
CodePromise::CodePromise(Context* c, Promise* offset):
|
||||
c(c), offset(offset), next(0)
|
||||
{ }
|
||||
CodePromise::CodePromise(Context* c, Promise* offset)
|
||||
: c(c), offset(offset), next(0)
|
||||
{
|
||||
}
|
||||
|
||||
int64_t CodePromise::value() {
|
||||
int64_t CodePromise::value()
|
||||
{
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
|
||||
}
|
||||
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
bool CodePromise::resolved() {
|
||||
bool CodePromise::resolved()
|
||||
{
|
||||
return c->machineCode != 0 and offset and offset->resolved();
|
||||
}
|
||||
|
||||
CodePromise* codePromise(Context* c, Promise* offset) {
|
||||
CodePromise* codePromise(Context* c, Promise* offset)
|
||||
{
|
||||
return new (c->zone) CodePromise(c, offset);
|
||||
}
|
||||
|
||||
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) {
|
||||
Promise* shiftMaskPromise(Context* c,
|
||||
Promise* base,
|
||||
unsigned shift,
|
||||
int64_t mask)
|
||||
{
|
||||
return new (c->zone) ShiftMaskPromise(base, shift, mask);
|
||||
}
|
||||
|
||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high) {
|
||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high)
|
||||
{
|
||||
return new (c->zone) CombinedPromise(low, high);
|
||||
}
|
||||
|
||||
Promise* resolvedPromise(Context* c, int64_t value) {
|
||||
Promise* resolvedPromise(Context* c, int64_t value)
|
||||
{
|
||||
return new (c->zone) ResolvedPromise(value);
|
||||
}
|
||||
|
||||
class IpPromise: public Promise {
|
||||
class IpPromise : public Promise {
|
||||
public:
|
||||
IpPromise(Context* c, int logicalIp):
|
||||
c(c),
|
||||
logicalIp(logicalIp)
|
||||
{ }
|
||||
IpPromise(Context* c, int logicalIp) : c(c), logicalIp(logicalIp)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int64_t value() {
|
||||
virtual int64_t value()
|
||||
{
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>
|
||||
(c->machineCode + machineOffset(c, logicalIp));
|
||||
return reinterpret_cast<intptr_t>(c->machineCode
|
||||
+ machineOffset(c, logicalIp));
|
||||
}
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
virtual bool resolved()
|
||||
{
|
||||
return c->machineCode != 0
|
||||
and c->logicalCode[logicalIp]->machineOffset->resolved();
|
||||
and c->logicalCode[logicalIp]->machineOffset->resolved();
|
||||
}
|
||||
|
||||
Context* c;
|
||||
int logicalIp;
|
||||
};
|
||||
|
||||
Promise* ipPromise(Context* c, int logicalIp) {
|
||||
Promise* ipPromise(Context* c, int logicalIp)
|
||||
{
|
||||
return new (c->zone) IpPromise(c, logicalIp);
|
||||
}
|
||||
|
||||
|
||||
class PoolPromise: public Promise {
|
||||
class PoolPromise : public Promise {
|
||||
public:
|
||||
PoolPromise(Context* c, int key): c(c), key(key) { }
|
||||
PoolPromise(Context* c, int key) : c(c), key(key)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int64_t value() {
|
||||
virtual int64_t value()
|
||||
{
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<int64_t>(
|
||||
c->machineCode
|
||||
+ vm::pad(c->machineCodeSize, c->targetInfo.pointerSize)
|
||||
+ (key * c->targetInfo.pointerSize));
|
||||
}
|
||||
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
virtual bool resolved()
|
||||
{
|
||||
return c->machineCode != 0;
|
||||
}
|
||||
|
||||
@ -107,11 +123,11 @@ class PoolPromise: public Promise {
|
||||
int key;
|
||||
};
|
||||
|
||||
Promise* poolPromise(Context* c, int key) {
|
||||
return new(c->zone) PoolPromise(c, key);
|
||||
Promise* poolPromise(Context* c, int key)
|
||||
{
|
||||
return new (c->zone) PoolPromise(c, key);
|
||||
}
|
||||
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -15,8 +15,7 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
|
||||
class CodePromise: public Promise {
|
||||
class CodePromise : public Promise {
|
||||
public:
|
||||
CodePromise(Context* c, CodePromise* next);
|
||||
|
||||
@ -33,7 +32,10 @@ class CodePromise: public Promise {
|
||||
|
||||
CodePromise* codePromise(Context* c, Promise* offset);
|
||||
|
||||
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask);
|
||||
Promise* shiftMaskPromise(Context* c,
|
||||
Promise* base,
|
||||
unsigned shift,
|
||||
int64_t mask);
|
||||
|
||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high);
|
||||
|
||||
@ -43,8 +45,8 @@ Promise* ipPromise(Context* c, int logicalIp);
|
||||
|
||||
Promise* poolPromise(Context* c, int key);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_PROMISE_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_PROMISE_H
|
||||
|
@ -20,43 +20,51 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
SingleRead::SingleRead(const SiteMask& mask, Value* successor)
|
||||
: next_(0), mask(mask), high_(0), successor_(successor)
|
||||
{
|
||||
}
|
||||
|
||||
SingleRead::SingleRead(const SiteMask& mask, Value* successor):
|
||||
next_(0), mask(mask), high_(0), successor_(successor)
|
||||
{ }
|
||||
|
||||
bool SingleRead::intersect(SiteMask* mask, unsigned) {
|
||||
bool SingleRead::intersect(SiteMask* mask, unsigned)
|
||||
{
|
||||
*mask = mask->intersectionWith(this->mask);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Value* SingleRead::high(Context*) {
|
||||
Value* SingleRead::high(Context*)
|
||||
{
|
||||
return high_;
|
||||
}
|
||||
|
||||
Value* SingleRead::successor() {
|
||||
Value* SingleRead::successor()
|
||||
{
|
||||
return successor_;
|
||||
}
|
||||
|
||||
bool SingleRead::valid() {
|
||||
bool SingleRead::valid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void SingleRead::append(Context* c UNUSED, Read* r) {
|
||||
void SingleRead::append(Context* c UNUSED, Read* r)
|
||||
{
|
||||
assertT(c, next_ == 0);
|
||||
next_ = r;
|
||||
}
|
||||
|
||||
Read* SingleRead::next(Context*) {
|
||||
Read* SingleRead::next(Context*)
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
MultiRead::MultiRead():
|
||||
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
||||
{ }
|
||||
MultiRead::MultiRead()
|
||||
: reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool MultiRead::intersect(SiteMask* mask, unsigned depth) {
|
||||
bool MultiRead::intersect(SiteMask* mask, unsigned depth)
|
||||
{
|
||||
if (depth > 0) {
|
||||
// short-circuit recursion to avoid poor performance in
|
||||
// deeply-nested branches
|
||||
@ -81,11 +89,13 @@ bool MultiRead::intersect(SiteMask* mask, unsigned depth) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Value* MultiRead::successor() {
|
||||
Value* MultiRead::successor()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MultiRead::valid() {
|
||||
bool MultiRead::valid()
|
||||
{
|
||||
bool result = false;
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
@ -103,7 +113,8 @@ bool MultiRead::valid() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void MultiRead::append(Context* c, Read* r) {
|
||||
void MultiRead::append(Context* c, Read* r)
|
||||
{
|
||||
List<Read*>* cell = cons<Read*>(c, r, 0);
|
||||
if (lastRead == 0) {
|
||||
reads = cell;
|
||||
@ -112,19 +123,21 @@ void MultiRead::append(Context* c, Read* r) {
|
||||
}
|
||||
lastRead = cell;
|
||||
|
||||
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
||||
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
||||
|
||||
lastTarget->item = r;
|
||||
}
|
||||
|
||||
Read* MultiRead::next(Context* c) {
|
||||
Read* MultiRead::next(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
void MultiRead::allocateTarget(Context* c) {
|
||||
void MultiRead::allocateTarget(Context* c)
|
||||
{
|
||||
List<Read*>* cell = cons<Read*>(c, 0, 0);
|
||||
|
||||
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
||||
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
||||
|
||||
if (lastTarget) {
|
||||
lastTarget->next = cell;
|
||||
@ -134,7 +147,8 @@ void MultiRead::allocateTarget(Context* c) {
|
||||
lastTarget = cell;
|
||||
}
|
||||
|
||||
Read* MultiRead::nextTarget() {
|
||||
Read* MultiRead::nextTarget()
|
||||
{
|
||||
// fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
|
||||
|
||||
Read* r = firstTarget->item;
|
||||
@ -142,12 +156,12 @@ Read* MultiRead::nextTarget() {
|
||||
return r;
|
||||
}
|
||||
|
||||
StubRead::StubRead() : next_(0), read(0), visited(false), valid_(true)
|
||||
{
|
||||
}
|
||||
|
||||
StubRead::StubRead():
|
||||
next_(0), read(0), visited(false), valid_(true)
|
||||
{ }
|
||||
|
||||
bool StubRead::intersect(SiteMask* mask, unsigned depth) {
|
||||
bool StubRead::intersect(SiteMask* mask, unsigned depth)
|
||||
{
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
if (read) {
|
||||
@ -161,32 +175,35 @@ bool StubRead::intersect(SiteMask* mask, unsigned depth) {
|
||||
return valid_;
|
||||
}
|
||||
|
||||
Value* StubRead::successor() {
|
||||
Value* StubRead::successor()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool StubRead::valid() {
|
||||
bool StubRead::valid()
|
||||
{
|
||||
return valid_;
|
||||
}
|
||||
|
||||
void StubRead::append(Context* c UNUSED, Read* r) {
|
||||
void StubRead::append(Context* c UNUSED, Read* r)
|
||||
{
|
||||
assertT(c, next_ == 0);
|
||||
next_ = r;
|
||||
}
|
||||
|
||||
Read* StubRead::next(Context*) {
|
||||
Read* StubRead::next(Context*)
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SingleRead* read(Context* c, const SiteMask& mask, Value* successor) {
|
||||
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);
|
||||
return new (c->zone) SingleRead(mask, successor);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -22,16 +22,19 @@ class Event;
|
||||
|
||||
class Read {
|
||||
public:
|
||||
Read():
|
||||
value(0), event(0), eventNext(0)
|
||||
{ }
|
||||
Read() : value(0), event(0), eventNext(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0;
|
||||
|
||||
virtual Value* high(Context* c) { abort(c); }
|
||||
virtual Value* high(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual Value* successor() = 0;
|
||||
|
||||
|
||||
virtual bool valid() = 0;
|
||||
|
||||
virtual void append(Context* c, Read* r) = 0;
|
||||
@ -43,11 +46,12 @@ class Read {
|
||||
Read* eventNext;
|
||||
};
|
||||
|
||||
inline bool valid(Read* r) {
|
||||
inline bool valid(Read* r)
|
||||
{
|
||||
return r and r->valid();
|
||||
}
|
||||
|
||||
class SingleRead: public Read {
|
||||
class SingleRead : public Read {
|
||||
public:
|
||||
SingleRead(const SiteMask& mask, Value* successor);
|
||||
|
||||
@ -56,7 +60,7 @@ class SingleRead: public Read {
|
||||
virtual Value* high(Context*);
|
||||
|
||||
virtual Value* successor();
|
||||
|
||||
|
||||
virtual bool valid();
|
||||
|
||||
virtual void append(Context* c UNUSED, Read* r);
|
||||
@ -69,8 +73,7 @@ class SingleRead: public Read {
|
||||
Value* successor_;
|
||||
};
|
||||
|
||||
|
||||
class MultiRead: public Read {
|
||||
class MultiRead : public Read {
|
||||
public:
|
||||
MultiRead();
|
||||
|
||||
@ -95,7 +98,7 @@ class MultiRead: public Read {
|
||||
bool visited;
|
||||
};
|
||||
|
||||
class StubRead: public Read {
|
||||
class StubRead : public Read {
|
||||
public:
|
||||
StubRead();
|
||||
|
||||
@ -117,9 +120,8 @@ class StubRead: public Read {
|
||||
|
||||
SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_READ_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_READ_H
|
||||
|
@ -20,24 +20,25 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile):
|
||||
a(a),
|
||||
registerFile(registerFile)
|
||||
{ }
|
||||
|
||||
RegisterAllocator::RegisterAllocator(Aborter* a,
|
||||
const RegisterFile* registerFile)
|
||||
: a(a), registerFile(registerFile)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned totalFrameSize(Context* c);
|
||||
Read* live(Context* c UNUSED, Value* v);
|
||||
|
||||
unsigned
|
||||
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
|
||||
CostCalculator* costCalculator)
|
||||
unsigned resourceCost(Context* c,
|
||||
Value* v,
|
||||
Resource* r,
|
||||
SiteMask mask,
|
||||
CostCalculator* costCalculator)
|
||||
{
|
||||
if (r->reserved or r->freezeCount or r->referenceCount) {
|
||||
return Target::Impossible;
|
||||
} else {
|
||||
unsigned baseCost =
|
||||
costCalculator ? costCalculator->cost(c, mask) : 0;
|
||||
} else {
|
||||
unsigned baseCost = costCalculator ? costCalculator->cost(c, mask) : 0;
|
||||
|
||||
if (r->value) {
|
||||
assertT(c, r->value->findSite(r->site));
|
||||
@ -55,15 +56,23 @@ resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
|
||||
unsigned* cost, CostCalculator* costCalculator)
|
||||
bool pickRegisterTarget(Context* c,
|
||||
int i,
|
||||
Value* v,
|
||||
uint32_t mask,
|
||||
int* target,
|
||||
unsigned* cost,
|
||||
CostCalculator* costCalculator)
|
||||
{
|
||||
if ((1 << i) & mask) {
|
||||
RegisterResource* r = c->registerResources + i;
|
||||
unsigned myCost = resourceCost
|
||||
(c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator)
|
||||
+ Target::MinimumRegisterCost;
|
||||
unsigned myCost
|
||||
= resourceCost(
|
||||
c,
|
||||
v,
|
||||
r,
|
||||
SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex),
|
||||
costCalculator) + Target::MinimumRegisterCost;
|
||||
|
||||
if ((static_cast<uint32_t>(1) << i) == mask) {
|
||||
*cost = myCost;
|
||||
@ -76,17 +85,19 @@ pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
|
||||
CostCalculator* costCalculator)
|
||||
int pickRegisterTarget(Context* c,
|
||||
Value* v,
|
||||
uint32_t mask,
|
||||
unsigned* cost,
|
||||
CostCalculator* costCalculator)
|
||||
{
|
||||
int target = lir::NoRegister;
|
||||
*cost = Target::Impossible;
|
||||
|
||||
if (mask & c->regFile->generalRegisters.mask) {
|
||||
for (int i = c->regFile->generalRegisters.limit - 1;
|
||||
i >= c->regFile->generalRegisters.start; --i)
|
||||
{
|
||||
i >= c->regFile->generalRegisters.start;
|
||||
--i) {
|
||||
if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
|
||||
return i;
|
||||
}
|
||||
@ -95,8 +106,8 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
|
||||
|
||||
if (mask & c->regFile->floatRegisters.mask) {
|
||||
for (int i = c->regFile->floatRegisters.start;
|
||||
i < static_cast<int>(c->regFile->floatRegisters.limit); ++i)
|
||||
{
|
||||
i < static_cast<int>(c->regFile->floatRegisters.limit);
|
||||
++i) {
|
||||
if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
|
||||
return i;
|
||||
}
|
||||
@ -106,34 +117,38 @@ pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
|
||||
return target;
|
||||
}
|
||||
|
||||
Target
|
||||
pickRegisterTarget(Context* c, Value* v, uint32_t mask,
|
||||
CostCalculator* costCalculator)
|
||||
Target pickRegisterTarget(Context* c,
|
||||
Value* v,
|
||||
uint32_t mask,
|
||||
CostCalculator* costCalculator)
|
||||
{
|
||||
unsigned cost;
|
||||
int number = pickRegisterTarget(c, v, mask, &cost, costCalculator);
|
||||
return Target(number, lir::RegisterOperand, cost);
|
||||
}
|
||||
|
||||
unsigned
|
||||
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator)
|
||||
unsigned frameCost(Context* c,
|
||||
Value* v,
|
||||
int frameIndex,
|
||||
CostCalculator* costCalculator)
|
||||
{
|
||||
return resourceCost
|
||||
(c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex),
|
||||
costCalculator)
|
||||
+ Target::MinimumFrameCost;
|
||||
return resourceCost(c,
|
||||
v,
|
||||
c->frameResources + frameIndex,
|
||||
SiteMask(1 << lir::MemoryOperand, 0, frameIndex),
|
||||
costCalculator) + Target::MinimumFrameCost;
|
||||
}
|
||||
|
||||
Target
|
||||
pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
||||
Target pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
||||
{
|
||||
Target best;
|
||||
|
||||
Value* p = v;
|
||||
do {
|
||||
if (p->home >= 0) {
|
||||
Target mine
|
||||
(p->home, lir::MemoryOperand, frameCost(c, v, p->home, costCalculator));
|
||||
Target mine(p->home,
|
||||
lir::MemoryOperand,
|
||||
frameCost(c, v, p->home, costCalculator));
|
||||
|
||||
if (mine.cost == Target::MinimumFrameCost) {
|
||||
return mine;
|
||||
@ -147,8 +162,7 @@ pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
||||
return best;
|
||||
}
|
||||
|
||||
Target
|
||||
pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
||||
Target pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
||||
{
|
||||
Target best;
|
||||
|
||||
@ -159,20 +173,22 @@ pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
||||
return mine;
|
||||
} else if (mine.cost < best.cost) {
|
||||
best = mine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
Target
|
||||
pickTarget(Context* c, Value* value, const SiteMask& mask,
|
||||
unsigned registerPenalty, Target best,
|
||||
CostCalculator* costCalculator)
|
||||
Target pickTarget(Context* c,
|
||||
Value* value,
|
||||
const SiteMask& mask,
|
||||
unsigned registerPenalty,
|
||||
Target best,
|
||||
CostCalculator* costCalculator)
|
||||
{
|
||||
if (mask.typeMask & (1 << lir::RegisterOperand)) {
|
||||
Target mine = pickRegisterTarget
|
||||
(c, value, mask.registerMask, costCalculator);
|
||||
Target mine
|
||||
= pickRegisterTarget(c, value, mask.registerMask, costCalculator);
|
||||
|
||||
mine.cost += registerPenalty;
|
||||
if (mine.cost == Target::MinimumRegisterCost) {
|
||||
@ -184,7 +200,8 @@ pickTarget(Context* c, Value* value, const SiteMask& mask,
|
||||
|
||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||
if (mask.frameIndex >= 0) {
|
||||
Target mine(mask.frameIndex, lir::MemoryOperand,
|
||||
Target mine(mask.frameIndex,
|
||||
lir::MemoryOperand,
|
||||
frameCost(c, value, mask.frameIndex, costCalculator));
|
||||
if (mine.cost == Target::MinimumFrameCost) {
|
||||
return mine;
|
||||
@ -204,13 +221,16 @@ pickTarget(Context* c, Value* value, const SiteMask& mask,
|
||||
return best;
|
||||
}
|
||||
|
||||
Target
|
||||
pickTarget(Context* c, Read* read, bool intersectRead,
|
||||
unsigned registerReserveCount, CostCalculator* costCalculator)
|
||||
Target pickTarget(Context* c,
|
||||
Read* read,
|
||||
bool intersectRead,
|
||||
unsigned registerReserveCount,
|
||||
CostCalculator* costCalculator)
|
||||
{
|
||||
unsigned registerPenalty
|
||||
= (c->availableGeneralRegisterCount > registerReserveCount
|
||||
? 0 : Target::LowRegisterPenalty);
|
||||
= (c->availableGeneralRegisterCount > registerReserveCount
|
||||
? 0
|
||||
: Target::LowRegisterPenalty);
|
||||
|
||||
Value* value = read->value;
|
||||
|
||||
@ -235,8 +255,8 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
||||
if (r) {
|
||||
SiteMask intersection = mask;
|
||||
if (r->intersect(&intersection)) {
|
||||
best = pickTarget
|
||||
(c, value, intersection, registerPenalty, best, costCalculator);
|
||||
best = pickTarget(
|
||||
c, value, intersection, registerPenalty, best, costCalculator);
|
||||
|
||||
if (best.cost <= Target::MinimumFrameCost) {
|
||||
return best;
|
||||
@ -252,14 +272,18 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
||||
|
||||
if (intersectRead) {
|
||||
if (best.cost == Target::Impossible) {
|
||||
fprintf(stderr, "mask type %d reg %d frame %d\n",
|
||||
mask.typeMask, mask.registerMask, mask.frameIndex);
|
||||
fprintf(stderr,
|
||||
"mask type %d reg %d frame %d\n",
|
||||
mask.typeMask,
|
||||
mask.registerMask,
|
||||
mask.frameIndex);
|
||||
abort(c);
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
{ Target mine = pickRegisterTarget(c, value, registerMask, costCalculator);
|
||||
{
|
||||
Target mine = pickRegisterTarget(c, value, registerMask, costCalculator);
|
||||
|
||||
mine.cost += registerPenalty;
|
||||
|
||||
@ -270,7 +294,8 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
||||
}
|
||||
}
|
||||
|
||||
{ Target mine = pickFrameTarget(c, value, costCalculator);
|
||||
{
|
||||
Target mine = pickFrameTarget(c, value, costCalculator);
|
||||
if (mine.cost == Target::MinimumFrameCost) {
|
||||
return mine;
|
||||
} else if (mine.cost < best.cost) {
|
||||
@ -279,8 +304,7 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
||||
}
|
||||
|
||||
if (best.cost >= Target::StealUniquePenalty
|
||||
and c->availableGeneralRegisterCount == 0)
|
||||
{
|
||||
and c->availableGeneralRegisterCount == 0) {
|
||||
// there are no free registers left, so moving from memory to
|
||||
// memory isn't an option - try harder to find an available frame
|
||||
// site:
|
||||
@ -295,6 +319,6 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
||||
return best;
|
||||
}
|
||||
|
||||
} // namespace regalloc
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace regalloc
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -20,7 +20,7 @@ namespace avian {
|
||||
|
||||
namespace util {
|
||||
class Aborter;
|
||||
} // namespace util
|
||||
} // namespace util
|
||||
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
@ -33,14 +33,12 @@ class SiteMask;
|
||||
class Resource;
|
||||
class Read;
|
||||
|
||||
|
||||
class RegisterAllocator {
|
||||
public:
|
||||
public:
|
||||
Aborter* a;
|
||||
const RegisterFile* registerFile;
|
||||
|
||||
RegisterAllocator(Aborter* a, const RegisterFile* registerFile);
|
||||
|
||||
};
|
||||
|
||||
class Target {
|
||||
@ -53,11 +51,14 @@ class Target {
|
||||
static const unsigned LowRegisterPenalty = 10;
|
||||
static const unsigned Impossible = 20;
|
||||
|
||||
Target(): cost(Impossible) { }
|
||||
Target() : cost(Impossible)
|
||||
{
|
||||
}
|
||||
|
||||
Target(int index, lir::OperandType type, unsigned cost):
|
||||
index(index), type(type), cost(cost)
|
||||
{ }
|
||||
Target(int index, lir::OperandType type, unsigned cost)
|
||||
: index(index), type(type), cost(cost)
|
||||
{
|
||||
}
|
||||
|
||||
int16_t index;
|
||||
lir::OperandType type;
|
||||
@ -69,43 +70,55 @@ class CostCalculator {
|
||||
virtual unsigned cost(Context* c, SiteMask mask) = 0;
|
||||
};
|
||||
|
||||
unsigned
|
||||
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
|
||||
CostCalculator* costCalculator);
|
||||
unsigned resourceCost(Context* c,
|
||||
Value* v,
|
||||
Resource* r,
|
||||
SiteMask mask,
|
||||
CostCalculator* costCalculator);
|
||||
|
||||
bool pickRegisterTarget(Context* c,
|
||||
int i,
|
||||
Value* v,
|
||||
uint32_t mask,
|
||||
int* target,
|
||||
unsigned* cost,
|
||||
CostCalculator* costCalculator = 0);
|
||||
|
||||
bool
|
||||
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
|
||||
unsigned* cost, CostCalculator* costCalculator = 0);
|
||||
int pickRegisterTarget(Context* c,
|
||||
Value* v,
|
||||
uint32_t mask,
|
||||
unsigned* cost,
|
||||
CostCalculator* costCalculator = 0);
|
||||
|
||||
int
|
||||
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
|
||||
CostCalculator* costCalculator = 0);
|
||||
Target pickRegisterTarget(Context* c,
|
||||
Value* v,
|
||||
uint32_t mask,
|
||||
CostCalculator* costCalculator = 0);
|
||||
|
||||
Target
|
||||
pickRegisterTarget(Context* c, Value* v, uint32_t mask,
|
||||
CostCalculator* costCalculator = 0);
|
||||
unsigned frameCost(Context* c,
|
||||
Value* v,
|
||||
int frameIndex,
|
||||
CostCalculator* costCalculator);
|
||||
|
||||
unsigned
|
||||
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator);
|
||||
Target pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
|
||||
|
||||
Target
|
||||
pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
|
||||
Target pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
|
||||
|
||||
Target
|
||||
pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
|
||||
Target pickTarget(Context* c,
|
||||
Value* value,
|
||||
const SiteMask& mask,
|
||||
unsigned registerPenalty,
|
||||
Target best,
|
||||
CostCalculator* costCalculator);
|
||||
|
||||
Target
|
||||
pickTarget(Context* c, Value* value, const SiteMask& mask,
|
||||
unsigned registerPenalty, Target best,
|
||||
CostCalculator* costCalculator);
|
||||
Target pickTarget(Context* c,
|
||||
Read* read,
|
||||
bool intersectRead,
|
||||
unsigned registerReserveCount,
|
||||
CostCalculator* costCalculator);
|
||||
|
||||
Target
|
||||
pickTarget(Context* c, Read* read, bool intersectRead,
|
||||
unsigned registerReserveCount, CostCalculator* costCalculator);
|
||||
} // namespace regalloc
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
} // namespace regalloc
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H
|
||||
|
@ -18,154 +18,173 @@ namespace compiler {
|
||||
|
||||
const bool DebugResources = false;
|
||||
|
||||
|
||||
void steal(Context* c, Resource* r, Value* thief);
|
||||
|
||||
void decrementAvailableGeneralRegisterCount(Context* c) {
|
||||
void decrementAvailableGeneralRegisterCount(Context* c)
|
||||
{
|
||||
assertT(c, c->availableGeneralRegisterCount);
|
||||
-- c->availableGeneralRegisterCount;
|
||||
|
||||
--c->availableGeneralRegisterCount;
|
||||
|
||||
if (DebugResources) {
|
||||
fprintf(stderr, "%d registers available\n",
|
||||
c->availableGeneralRegisterCount);
|
||||
fprintf(
|
||||
stderr, "%d registers available\n", c->availableGeneralRegisterCount);
|
||||
}
|
||||
}
|
||||
|
||||
void incrementAvailableGeneralRegisterCount(Context* c) {
|
||||
++ c->availableGeneralRegisterCount;
|
||||
void incrementAvailableGeneralRegisterCount(Context* c)
|
||||
{
|
||||
++c->availableGeneralRegisterCount;
|
||||
|
||||
if (DebugResources) {
|
||||
fprintf(stderr, "%d registers available\n",
|
||||
c->availableGeneralRegisterCount);
|
||||
fprintf(
|
||||
stderr, "%d registers available\n", c->availableGeneralRegisterCount);
|
||||
}
|
||||
}
|
||||
|
||||
void freezeResource(Context* c, Resource* r, Value* v) {
|
||||
void freezeResource(Context* c, Resource* r, Value* v)
|
||||
{
|
||||
if (DebugResources) {
|
||||
char buffer[256]; r->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
r->toString(c, buffer, 256);
|
||||
fprintf(stderr, "%p freeze %s to %d\n", v, buffer, r->freezeCount + 1);
|
||||
}
|
||||
|
||||
++ r->freezeCount;
|
||||
|
||||
++r->freezeCount;
|
||||
}
|
||||
|
||||
void thawResource(Context* c, Resource* r, Value* v) {
|
||||
void thawResource(Context* c, Resource* r, Value* v)
|
||||
{
|
||||
if (not r->reserved) {
|
||||
if (DebugResources) {
|
||||
char buffer[256]; r->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
r->toString(c, buffer, 256);
|
||||
fprintf(stderr, "%p thaw %s to %d\n", v, buffer, r->freezeCount - 1);
|
||||
}
|
||||
|
||||
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):
|
||||
value(0), site(0), previousAcquired(0), nextAcquired(0), freezeCount(0),
|
||||
referenceCount(0), reserved(reserved)
|
||||
{ }
|
||||
RegisterResource::RegisterResource(bool reserved) : Resource(reserved)
|
||||
{
|
||||
}
|
||||
|
||||
RegisterResource::RegisterResource(bool reserved):
|
||||
Resource(reserved)
|
||||
{ }
|
||||
|
||||
void RegisterResource::freeze(Context* c, Value* v) {
|
||||
void RegisterResource::freeze(Context* c, Value* v)
|
||||
{
|
||||
if (not reserved) {
|
||||
freezeResource(c, this, v);
|
||||
|
||||
if (freezeCount == 1
|
||||
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
|
||||
{
|
||||
and ((1 << index(c)) & c->regFile->generalRegisters.mask)) {
|
||||
decrementAvailableGeneralRegisterCount(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterResource::thaw(Context* c, Value* v) {
|
||||
void RegisterResource::thaw(Context* c, Value* v)
|
||||
{
|
||||
if (not reserved) {
|
||||
thawResource(c, this, v);
|
||||
|
||||
if (freezeCount == 0
|
||||
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
|
||||
{
|
||||
and ((1 << index(c)) & c->regFile->generalRegisters.mask)) {
|
||||
incrementAvailableGeneralRegisterCount(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RegisterResource::toString(Context* c, char* buffer, unsigned bufferSize) {
|
||||
unsigned RegisterResource::toString(Context* c,
|
||||
char* buffer,
|
||||
unsigned bufferSize)
|
||||
{
|
||||
return vm::snprintf(buffer, bufferSize, "register %d", index(c));
|
||||
}
|
||||
|
||||
unsigned RegisterResource::index(Context* c) {
|
||||
unsigned RegisterResource::index(Context* c)
|
||||
{
|
||||
return this - c->registerResources;
|
||||
}
|
||||
|
||||
void RegisterResource::increment(Context* c) {
|
||||
void RegisterResource::increment(Context* c)
|
||||
{
|
||||
if (not this->reserved) {
|
||||
if (DebugResources) {
|
||||
char buffer[256]; this->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
this->toString(c, buffer, 256);
|
||||
fprintf(stderr, "increment %s to %d\n", buffer, this->referenceCount + 1);
|
||||
}
|
||||
|
||||
++ this->referenceCount;
|
||||
++this->referenceCount;
|
||||
|
||||
if (this->referenceCount == 1
|
||||
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask))
|
||||
{
|
||||
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask)) {
|
||||
decrementAvailableGeneralRegisterCount(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterResource::decrement(Context* c) {
|
||||
void RegisterResource::decrement(Context* c)
|
||||
{
|
||||
if (not this->reserved) {
|
||||
if (DebugResources) {
|
||||
char buffer[256]; this->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
this->toString(c, buffer, 256);
|
||||
fprintf(stderr, "decrement %s to %d\n", buffer, this->referenceCount - 1);
|
||||
}
|
||||
|
||||
assertT(c, this->referenceCount > 0);
|
||||
|
||||
-- this->referenceCount;
|
||||
--this->referenceCount;
|
||||
|
||||
if (this->referenceCount == 0
|
||||
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask))
|
||||
{
|
||||
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask)) {
|
||||
incrementAvailableGeneralRegisterCount(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FrameResource::freeze(Context* c, Value* v) {
|
||||
void FrameResource::freeze(Context* c, Value* v)
|
||||
{
|
||||
freezeResource(c, this, v);
|
||||
}
|
||||
|
||||
void FrameResource::thaw(Context* c, Value* v) {
|
||||
void FrameResource::thaw(Context* c, Value* v)
|
||||
{
|
||||
thawResource(c, this, v);
|
||||
}
|
||||
|
||||
unsigned FrameResource::toString(Context* c, char* buffer, unsigned bufferSize) {
|
||||
unsigned FrameResource::toString(Context* c, char* buffer, unsigned bufferSize)
|
||||
{
|
||||
return vm::snprintf(buffer, bufferSize, "frame %d", index(c));
|
||||
}
|
||||
|
||||
unsigned FrameResource::index(Context* c) {
|
||||
unsigned FrameResource::index(Context* c)
|
||||
{
|
||||
return this - c->frameResources;
|
||||
}
|
||||
|
||||
|
||||
void acquire(Context* c, Resource* resource, Value* value, Site* site) {
|
||||
void acquire(Context* c, Resource* resource, Value* value, Site* site)
|
||||
{
|
||||
assertT(c, value);
|
||||
assertT(c, site);
|
||||
|
||||
if (not resource->reserved) {
|
||||
if (DebugResources) {
|
||||
char buffer[256]; resource->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
resource->toString(c, buffer, 256);
|
||||
fprintf(stderr, "%p acquire %s\n", value, buffer);
|
||||
}
|
||||
|
||||
@ -178,7 +197,7 @@ void acquire(Context* c, Resource* resource, Value* value, Site* site) {
|
||||
|
||||
if (c->acquiredResources) {
|
||||
c->acquiredResources->previousAcquired = resource;
|
||||
resource->nextAcquired = c->acquiredResources;
|
||||
resource->nextAcquired = c->acquiredResources;
|
||||
}
|
||||
c->acquiredResources = resource;
|
||||
|
||||
@ -187,10 +206,15 @@ void acquire(Context* c, Resource* resource, Value* value, Site* site) {
|
||||
}
|
||||
}
|
||||
|
||||
void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNUSED) {
|
||||
void release(Context* c,
|
||||
Resource* resource,
|
||||
Value* value UNUSED,
|
||||
Site* site UNUSED)
|
||||
{
|
||||
if (not resource->reserved) {
|
||||
if (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);
|
||||
}
|
||||
|
||||
@ -214,13 +238,12 @@ void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNU
|
||||
assertT(c, c->acquiredResources == resource);
|
||||
c->acquiredResources = next;
|
||||
}
|
||||
|
||||
|
||||
resource->value = 0;
|
||||
resource->site = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -38,7 +38,7 @@ class Resource {
|
||||
bool reserved;
|
||||
};
|
||||
|
||||
class RegisterResource: public Resource {
|
||||
class RegisterResource : public Resource {
|
||||
public:
|
||||
RegisterResource(bool reserved);
|
||||
|
||||
@ -55,7 +55,7 @@ class RegisterResource: public Resource {
|
||||
void decrement(Context*);
|
||||
};
|
||||
|
||||
class FrameResource: public Resource {
|
||||
class FrameResource : public Resource {
|
||||
public:
|
||||
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);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_RESOURCE_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_RESOURCE_H
|
||||
|
@ -21,35 +21,43 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
|
||||
|
||||
int intersectFrameIndexes(int a, int b) {
|
||||
if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex;
|
||||
if (a == AnyFrameIndex) return b;
|
||||
if (b == AnyFrameIndex) return a;
|
||||
if (a == b) return a;
|
||||
int intersectFrameIndexes(int a, int b)
|
||||
{
|
||||
if (a == NoFrameIndex or b == NoFrameIndex)
|
||||
return NoFrameIndex;
|
||||
if (a == AnyFrameIndex)
|
||||
return b;
|
||||
if (b == AnyFrameIndex)
|
||||
return a;
|
||||
if (a == b)
|
||||
return a;
|
||||
return NoFrameIndex;
|
||||
}
|
||||
|
||||
|
||||
SiteMask SiteMask::intersectionWith(const SiteMask& b) {
|
||||
return SiteMask(typeMask & b.typeMask, registerMask & b.registerMask,
|
||||
SiteMask SiteMask::intersectionWith(const SiteMask& b)
|
||||
{
|
||||
return SiteMask(typeMask & b.typeMask,
|
||||
registerMask & b.registerMask,
|
||||
intersectFrameIndexes(frameIndex, b.frameIndex));
|
||||
}
|
||||
|
||||
SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies,
|
||||
bool includeNextWord):
|
||||
c(c),
|
||||
originalValue(v),
|
||||
currentValue(v),
|
||||
includeBuddies(includeBuddies),
|
||||
includeNextWord(includeNextWord),
|
||||
pass(0),
|
||||
next_(findNext(&(v->sites))),
|
||||
previous(0)
|
||||
{ }
|
||||
SiteIterator::SiteIterator(Context* c,
|
||||
Value* v,
|
||||
bool includeBuddies,
|
||||
bool includeNextWord)
|
||||
: c(c),
|
||||
originalValue(v),
|
||||
currentValue(v),
|
||||
includeBuddies(includeBuddies),
|
||||
includeNextWord(includeNextWord),
|
||||
pass(0),
|
||||
next_(findNext(&(v->sites))),
|
||||
previous(0)
|
||||
{
|
||||
}
|
||||
|
||||
Site** SiteIterator::findNext(Site** p) {
|
||||
Site** SiteIterator::findNext(Site** p)
|
||||
{
|
||||
while (true) {
|
||||
if (*p) {
|
||||
if (pass == 0 or (*p)->registerSize(c) > c->targetInfo.pointerSize) {
|
||||
@ -83,7 +91,8 @@ Site** SiteIterator::findNext(Site** p) {
|
||||
}
|
||||
}
|
||||
|
||||
bool SiteIterator::hasMore() {
|
||||
bool SiteIterator::hasMore()
|
||||
{
|
||||
if (previous) {
|
||||
next_ = findNext(&((*previous)->next));
|
||||
previous = 0;
|
||||
@ -91,12 +100,14 @@ bool SiteIterator::hasMore() {
|
||||
return next_ != 0;
|
||||
}
|
||||
|
||||
Site* SiteIterator::next() {
|
||||
Site* SiteIterator::next()
|
||||
{
|
||||
previous = next_;
|
||||
return *previous;
|
||||
}
|
||||
|
||||
void SiteIterator::remove(Context* c) {
|
||||
void SiteIterator::remove(Context* c)
|
||||
{
|
||||
(*previous)->release(c, originalValue);
|
||||
*previous = (*previous)->next;
|
||||
next_ = findNext(previous);
|
||||
@ -108,50 +119,59 @@ unsigned Site::registerSize(Context* c)
|
||||
return c->targetInfo.pointerSize;
|
||||
}
|
||||
|
||||
Site* constantSite(Context* c, Promise* value) {
|
||||
return new(c->zone) ConstantSite(value);
|
||||
Site* constantSite(Context* c, Promise* value)
|
||||
{
|
||||
return new (c->zone) ConstantSite(value);
|
||||
}
|
||||
|
||||
Site* constantSite(Context* c, int64_t value) {
|
||||
Site* constantSite(Context* c, int64_t value)
|
||||
{
|
||||
return constantSite(c, resolvedPromise(c, value));
|
||||
}
|
||||
|
||||
|
||||
|
||||
class AddressSite: public Site {
|
||||
class AddressSite : public Site {
|
||||
public:
|
||||
AddressSite(Promise* address): address(address) { }
|
||||
AddressSite(Promise* address) : address(address)
|
||||
{
|
||||
}
|
||||
|
||||
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) {
|
||||
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize)
|
||||
{
|
||||
if (address->resolved()) {
|
||||
return vm::snprintf
|
||||
(buffer, bufferSize, "address %" LLD, address->value());
|
||||
return vm::snprintf(
|
||||
buffer, bufferSize, "address %" LLD, address->value());
|
||||
} else {
|
||||
return vm::snprintf(buffer, bufferSize, "address unresolved");
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned copyCost(Context*, Site* s) {
|
||||
virtual unsigned copyCost(Context*, Site* s)
|
||||
{
|
||||
return (s == this ? 0 : AddressCopyCost);
|
||||
}
|
||||
|
||||
virtual bool match(Context*, const SiteMask& mask) {
|
||||
virtual bool match(Context*, const SiteMask& mask)
|
||||
{
|
||||
return mask.typeMask & (1 << lir::AddressOperand);
|
||||
}
|
||||
|
||||
virtual bool loneMatch(Context*, const SiteMask&) {
|
||||
virtual bool loneMatch(Context*, const SiteMask&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool matchNextWord(Context* c, Site*, unsigned) {
|
||||
virtual bool matchNextWord(Context* c, Site*, unsigned)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual lir::OperandType type(Context*) {
|
||||
virtual lir::OperandType type(Context*)
|
||||
{
|
||||
return lir::AddressOperand;
|
||||
}
|
||||
|
||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
||||
virtual void asAssemblerOperand(Context* c UNUSED,
|
||||
Site* high UNUSED,
|
||||
lir::Operand* result)
|
||||
{
|
||||
assertT(c, high == this);
|
||||
@ -159,66 +179,74 @@ class AddressSite: public Site {
|
||||
new (result) lir::Address(address);
|
||||
}
|
||||
|
||||
virtual Site* copy(Context* c) {
|
||||
virtual Site* copy(Context* c)
|
||||
{
|
||||
return addressSite(c, address);
|
||||
}
|
||||
|
||||
virtual Site* copyLow(Context* c) {
|
||||
virtual Site* copyLow(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual Site* copyHigh(Context* c) {
|
||||
virtual Site* copyHigh(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual Site* makeNextWord(Context* c, unsigned) {
|
||||
virtual Site* makeNextWord(Context* c, unsigned)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual SiteMask mask(Context*) {
|
||||
virtual SiteMask mask(Context*)
|
||||
{
|
||||
return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex);
|
||||
}
|
||||
|
||||
virtual SiteMask nextWordMask(Context* c, unsigned) {
|
||||
virtual SiteMask nextWordMask(Context* c, unsigned)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Promise* address;
|
||||
};
|
||||
|
||||
Site* addressSite(Context* c, Promise* address) {
|
||||
return new(c->zone) AddressSite(address);
|
||||
Site* addressSite(Context* c, Promise* address)
|
||||
{
|
||||
return new (c->zone) AddressSite(address);
|
||||
}
|
||||
|
||||
RegisterSite::RegisterSite(uint32_t mask, int number)
|
||||
: mask_(mask), number(number)
|
||||
{
|
||||
}
|
||||
|
||||
RegisterSite::RegisterSite(uint32_t mask, int number):
|
||||
mask_(mask), number(number)
|
||||
{ }
|
||||
|
||||
unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize) {
|
||||
unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize)
|
||||
{
|
||||
if (number != lir::NoRegister) {
|
||||
return vm::snprintf(buffer, bufferSize, "%p register %d", this, number);
|
||||
} else {
|
||||
return vm::snprintf(buffer, bufferSize,
|
||||
"%p register unacquired (mask %d)", this, mask_);
|
||||
return vm::snprintf(
|
||||
buffer, bufferSize, "%p register unacquired (mask %d)", this, mask_);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RegisterSite::copyCost(Context* c, Site* s) {
|
||||
unsigned RegisterSite::copyCost(Context* c, Site* s)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if (s and
|
||||
(this == s or
|
||||
(s->type(c) == lir::RegisterOperand
|
||||
and (static_cast<RegisterSite*>(s)->mask_ & (1 << number)))))
|
||||
{
|
||||
if (s and (this == s
|
||||
or (s->type(c) == lir::RegisterOperand
|
||||
and (static_cast<RegisterSite*>(s)->mask_ & (1 << number))))) {
|
||||
return 0;
|
||||
} else {
|
||||
return RegisterCopyCost;
|
||||
}
|
||||
}
|
||||
|
||||
bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) {
|
||||
bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
|
||||
@ -228,7 +256,8 @@ bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) {
|
||||
}
|
||||
}
|
||||
|
||||
bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) {
|
||||
bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
|
||||
@ -238,7 +267,8 @@ bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) {
|
||||
}
|
||||
}
|
||||
|
||||
bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
|
||||
bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if (s->type(c) != lir::RegisterOperand) {
|
||||
@ -256,7 +286,8 @@ bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterSite::acquire(Context* c, Value* v) {
|
||||
void RegisterSite::acquire(Context* c, Value* v)
|
||||
{
|
||||
Target target;
|
||||
if (number != lir::NoRegister) {
|
||||
target = Target(number, lir::RegisterOperand, 0);
|
||||
@ -271,36 +302,42 @@ void RegisterSite::acquire(Context* c, Value* v) {
|
||||
number = target.index;
|
||||
}
|
||||
|
||||
void RegisterSite::release(Context* c, Value* v) {
|
||||
void RegisterSite::release(Context* c, Value* v)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
compiler::release(c, c->registerResources + number, v, this);
|
||||
}
|
||||
|
||||
void RegisterSite::freeze(Context* c, Value* v) {
|
||||
void RegisterSite::freeze(Context* c, Value* v)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
c->registerResources[number].freeze(c, v);
|
||||
}
|
||||
|
||||
void RegisterSite::thaw(Context* c, Value* v) {
|
||||
void RegisterSite::thaw(Context* c, Value* v)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
c->registerResources[number].thaw(c, v);
|
||||
}
|
||||
|
||||
bool RegisterSite::frozen(Context* c UNUSED) {
|
||||
bool RegisterSite::frozen(Context* c UNUSED)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
return c->registerResources[number].freezeCount != 0;
|
||||
}
|
||||
|
||||
lir::OperandType RegisterSite::type(Context*) {
|
||||
lir::OperandType RegisterSite::type(Context*)
|
||||
{
|
||||
return lir::RegisterOperand;
|
||||
}
|
||||
|
||||
void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high,
|
||||
lir::Operand* result)
|
||||
void RegisterSite::asAssemblerOperand(Context* c UNUSED,
|
||||
Site* high,
|
||||
lir::Operand* result)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
@ -315,9 +352,10 @@ void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high,
|
||||
new (result) lir::Register(number, highNumber);
|
||||
}
|
||||
|
||||
Site* RegisterSite::copy(Context* c) {
|
||||
Site* RegisterSite::copy(Context* c)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
|
||||
if (number != lir::NoRegister) {
|
||||
mask = 1 << number;
|
||||
} else {
|
||||
@ -327,38 +365,44 @@ Site* RegisterSite::copy(Context* c) {
|
||||
return freeRegisterSite(c, mask);
|
||||
}
|
||||
|
||||
Site* RegisterSite::copyLow(Context* c) {
|
||||
Site* RegisterSite::copyLow(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Site* RegisterSite::copyHigh(Context* c) {
|
||||
Site* RegisterSite::copyHigh(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Site* RegisterSite::makeNextWord(Context* c, unsigned) {
|
||||
Site* RegisterSite::makeNextWord(Context* c, unsigned)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
assertT(c, ((1 << number) & c->regFile->generalRegisters.mask));
|
||||
|
||||
return freeRegisterSite(c, c->regFile->generalRegisters.mask);
|
||||
return freeRegisterSite(c, c->regFile->generalRegisters.mask);
|
||||
}
|
||||
|
||||
SiteMask RegisterSite::mask(Context* c UNUSED) {
|
||||
SiteMask RegisterSite::mask(Context* c UNUSED)
|
||||
{
|
||||
return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex);
|
||||
}
|
||||
|
||||
SiteMask RegisterSite::nextWordMask(Context* c, unsigned) {
|
||||
SiteMask RegisterSite::nextWordMask(Context* c, unsigned)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if (registerSize(c) > c->targetInfo.pointerSize) {
|
||||
return SiteMask
|
||||
(1 << lir::RegisterOperand, number, NoFrameIndex);
|
||||
return SiteMask(1 << lir::RegisterOperand, number, NoFrameIndex);
|
||||
} else {
|
||||
return SiteMask
|
||||
(1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex);
|
||||
return SiteMask(1 << lir::RegisterOperand,
|
||||
c->regFile->generalRegisters.mask,
|
||||
NoFrameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RegisterSite::registerSize(Context* c) {
|
||||
unsigned RegisterSite::registerSize(Context* c)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if ((1 << number) & c->regFile->floatRegisters.mask) {
|
||||
@ -368,65 +412,68 @@ unsigned RegisterSite::registerSize(Context* c) {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RegisterSite::registerMask(Context* c UNUSED) {
|
||||
unsigned RegisterSite::registerMask(Context* c UNUSED)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
return 1 << number;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Site* registerSite(Context* c, int 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);
|
||||
return new (c->zone) RegisterSite(1 << number, number);
|
||||
}
|
||||
|
||||
Site* freeRegisterSite(Context* c, uint32_t mask) {
|
||||
return new(c->zone) RegisterSite(mask, lir::NoRegister);
|
||||
Site* freeRegisterSite(Context* c, uint32_t mask)
|
||||
{
|
||||
return new (c->zone) RegisterSite(mask, lir::NoRegister);
|
||||
}
|
||||
|
||||
MemorySite::MemorySite(int base, int offset, int index, unsigned scale):
|
||||
acquired(false), base(base), offset(offset), index(index), scale(scale)
|
||||
{ }
|
||||
MemorySite::MemorySite(int base, int offset, int index, unsigned scale)
|
||||
: acquired(false), base(base), offset(offset), index(index), scale(scale)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned MemorySite::toString(Context*, char* buffer, unsigned bufferSize) {
|
||||
unsigned MemorySite::toString(Context*, char* buffer, unsigned bufferSize)
|
||||
{
|
||||
if (acquired) {
|
||||
return vm::snprintf(buffer, bufferSize, "memory %d 0x%x %d %d",
|
||||
base, offset, index, scale);
|
||||
return vm::snprintf(
|
||||
buffer, bufferSize, "memory %d 0x%x %d %d", base, offset, index, scale);
|
||||
} else {
|
||||
return vm::snprintf(buffer, bufferSize, "memory unacquired");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned MemorySite::copyCost(Context* c, Site* s) {
|
||||
unsigned MemorySite::copyCost(Context* c, Site* s)
|
||||
{
|
||||
assertT(c, acquired);
|
||||
|
||||
if (s and
|
||||
(this == s or
|
||||
(s->type(c) == lir::MemoryOperand
|
||||
and static_cast<MemorySite*>(s)->base == base
|
||||
and static_cast<MemorySite*>(s)->offset == offset
|
||||
and static_cast<MemorySite*>(s)->index == index
|
||||
and static_cast<MemorySite*>(s)->scale == scale)))
|
||||
{
|
||||
if (s and (this == s or (s->type(c) == lir::MemoryOperand
|
||||
and static_cast<MemorySite*>(s)->base == base
|
||||
and static_cast<MemorySite*>(s)->offset == offset
|
||||
and static_cast<MemorySite*>(s)->index == index
|
||||
and static_cast<MemorySite*>(s)->scale == scale))) {
|
||||
return 0;
|
||||
} else {
|
||||
return MemoryCopyCost;
|
||||
}
|
||||
}
|
||||
|
||||
bool MemorySite::conflicts(const SiteMask& mask) {
|
||||
bool MemorySite::conflicts(const SiteMask& mask)
|
||||
{
|
||||
return (mask.typeMask & (1 << lir::RegisterOperand)) != 0
|
||||
and (((1 << base) & mask.registerMask) == 0
|
||||
or (index != lir::NoRegister
|
||||
and ((1 << index) & mask.registerMask) == 0));
|
||||
and (((1 << base) & mask.registerMask) == 0
|
||||
or (index != lir::NoRegister
|
||||
and ((1 << index) & mask.registerMask) == 0));
|
||||
}
|
||||
|
||||
bool MemorySite::match(Context* c, const SiteMask& mask) {
|
||||
bool MemorySite::match(Context* c, const SiteMask& mask)
|
||||
{
|
||||
assertT(c, acquired);
|
||||
|
||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||
@ -434,7 +481,7 @@ bool MemorySite::match(Context* c, const SiteMask& mask) {
|
||||
if (base == c->arch->stack()) {
|
||||
assertT(c, index == lir::NoRegister);
|
||||
return static_cast<int>(frameIndexToOffset(c, mask.frameIndex))
|
||||
== offset;
|
||||
== offset;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -446,7 +493,8 @@ bool MemorySite::match(Context* c, const SiteMask& mask) {
|
||||
}
|
||||
}
|
||||
|
||||
bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
|
||||
bool MemorySite::loneMatch(Context* c, const SiteMask& mask)
|
||||
{
|
||||
assertT(c, acquired);
|
||||
|
||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||
@ -463,7 +511,8 @@ bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) {
|
||||
bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index)
|
||||
{
|
||||
if (s->type(c) == lir::MemoryOperand) {
|
||||
MemorySite* ms = static_cast<MemorySite*>(s);
|
||||
return ms->base == this->base
|
||||
@ -481,7 +530,8 @@ bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) {
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySite::acquire(Context* c, Value* v) {
|
||||
void MemorySite::acquire(Context* c, Value* v)
|
||||
{
|
||||
c->registerResources[base].increment(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].increment(c);
|
||||
@ -491,20 +541,21 @@ void MemorySite::acquire(Context* c, Value* v) {
|
||||
assertT(c, index == lir::NoRegister);
|
||||
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
|
||||
compiler::acquire
|
||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
compiler::acquire(
|
||||
c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
}
|
||||
|
||||
acquired = true;
|
||||
}
|
||||
|
||||
void MemorySite::release(Context* c, Value* v) {
|
||||
void MemorySite::release(Context* c, Value* v)
|
||||
{
|
||||
if (base == c->arch->stack()) {
|
||||
assertT(c, index == lir::NoRegister);
|
||||
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
|
||||
compiler::release
|
||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
compiler::release(
|
||||
c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
}
|
||||
|
||||
c->registerResources[base].decrement(c);
|
||||
@ -515,7 +566,8 @@ void MemorySite::release(Context* c, Value* v) {
|
||||
acquired = false;
|
||||
}
|
||||
|
||||
void MemorySite::freeze(Context* c, Value* v) {
|
||||
void MemorySite::freeze(Context* c, Value* v)
|
||||
{
|
||||
if (base == c->arch->stack()) {
|
||||
c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v);
|
||||
} else {
|
||||
@ -526,7 +578,8 @@ void MemorySite::freeze(Context* c, Value* v) {
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySite::thaw(Context* c, Value* v) {
|
||||
void MemorySite::thaw(Context* c, Value* v)
|
||||
{
|
||||
if (base == c->arch->stack()) {
|
||||
c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v);
|
||||
} else {
|
||||
@ -537,17 +590,20 @@ void MemorySite::thaw(Context* c, Value* v) {
|
||||
}
|
||||
}
|
||||
|
||||
bool MemorySite::frozen(Context* c) {
|
||||
bool MemorySite::frozen(Context* c)
|
||||
{
|
||||
return base == c->arch->stack()
|
||||
and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0;
|
||||
and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0;
|
||||
}
|
||||
|
||||
lir::OperandType MemorySite::type(Context*) {
|
||||
lir::OperandType MemorySite::type(Context*)
|
||||
{
|
||||
return lir::MemoryOperand;
|
||||
}
|
||||
|
||||
void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
||||
lir::Operand* result)
|
||||
void MemorySite::asAssemblerOperand(Context* c UNUSED,
|
||||
Site* high UNUSED,
|
||||
lir::Operand* result)
|
||||
{
|
||||
// todo: endianness?
|
||||
assertT(c,
|
||||
@ -563,11 +619,13 @@ void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
||||
new (result) lir::Memory(base, offset, index, scale);
|
||||
}
|
||||
|
||||
Site* MemorySite::copy(Context* c) {
|
||||
Site* MemorySite::copy(Context* c)
|
||||
{
|
||||
return memorySite(c, base, offset, index, scale);
|
||||
}
|
||||
|
||||
Site* MemorySite::copyHalf(Context* c, bool add) {
|
||||
Site* MemorySite::copyHalf(Context* c, bool add)
|
||||
{
|
||||
if (add) {
|
||||
return memorySite(
|
||||
c, base, offset + c->targetInfo.pointerSize, index, scale);
|
||||
@ -576,15 +634,18 @@ Site* MemorySite::copyHalf(Context* c, bool add) {
|
||||
}
|
||||
}
|
||||
|
||||
Site* MemorySite::copyLow(Context* c) {
|
||||
Site* MemorySite::copyLow(Context* c)
|
||||
{
|
||||
return copyHalf(c, c->arch->bigEndian());
|
||||
}
|
||||
|
||||
Site* MemorySite::copyHigh(Context* c) {
|
||||
Site* MemorySite::copyHigh(Context* c)
|
||||
{
|
||||
return copyHalf(c, not c->arch->bigEndian());
|
||||
}
|
||||
|
||||
Site* MemorySite::makeNextWord(Context* c, unsigned index) {
|
||||
Site* MemorySite::makeNextWord(Context* c, unsigned index)
|
||||
{
|
||||
return memorySite(c,
|
||||
base,
|
||||
offset + ((index == 1) xor c->arch->bigEndian()
|
||||
@ -594,39 +655,52 @@ Site* MemorySite::makeNextWord(Context* c, unsigned index) {
|
||||
scale);
|
||||
}
|
||||
|
||||
SiteMask MemorySite::mask(Context* c) {
|
||||
return SiteMask(1 << lir::MemoryOperand, 0, (base == c->arch->stack())
|
||||
? static_cast<int>(offsetToFrameIndex(c, offset))
|
||||
: NoFrameIndex);
|
||||
SiteMask MemorySite::mask(Context* c)
|
||||
{
|
||||
return SiteMask(1 << lir::MemoryOperand,
|
||||
0,
|
||||
(base == c->arch->stack())
|
||||
? static_cast<int>(offsetToFrameIndex(c, offset))
|
||||
: NoFrameIndex);
|
||||
}
|
||||
|
||||
SiteMask MemorySite::nextWordMask(Context* c, unsigned index) {
|
||||
SiteMask MemorySite::nextWordMask(Context* c, unsigned index)
|
||||
{
|
||||
int frameIndex;
|
||||
if (base == c->arch->stack()) {
|
||||
assertT(c, this->index == lir::NoRegister);
|
||||
frameIndex = static_cast<int>(offsetToFrameIndex(c, offset))
|
||||
+ ((index == 1) xor c->arch->bigEndian() ? 1 : -1);
|
||||
+ ((index == 1) xor c->arch->bigEndian() ? 1 : -1);
|
||||
} else {
|
||||
frameIndex = NoFrameIndex;
|
||||
}
|
||||
return SiteMask(1 << lir::MemoryOperand, 0, frameIndex);
|
||||
}
|
||||
|
||||
bool MemorySite::isVolatile(Context* c) {
|
||||
bool MemorySite::isVolatile(Context* c)
|
||||
{
|
||||
return base != c->arch->stack();
|
||||
}
|
||||
|
||||
|
||||
MemorySite* memorySite(Context* c, int base, int offset, int index, unsigned scale) {
|
||||
return new(c->zone) MemorySite(base, offset, index, scale);
|
||||
MemorySite* memorySite(Context* c,
|
||||
int base,
|
||||
int offset,
|
||||
int index,
|
||||
unsigned scale)
|
||||
{
|
||||
return new (c->zone) MemorySite(base, offset, index, scale);
|
||||
}
|
||||
|
||||
MemorySite* frameSite(Context* c, int frameIndex) {
|
||||
MemorySite* frameSite(Context* c, int frameIndex)
|
||||
{
|
||||
assertT(c, frameIndex >= 0);
|
||||
return memorySite
|
||||
(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 codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -30,23 +30,29 @@ const unsigned CopyPenalty = 10;
|
||||
|
||||
class SiteMask {
|
||||
public:
|
||||
SiteMask(): typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex) { }
|
||||
SiteMask() : typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex)
|
||||
{
|
||||
}
|
||||
|
||||
SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex):
|
||||
typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex)
|
||||
{ }
|
||||
SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex)
|
||||
: typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex)
|
||||
{
|
||||
}
|
||||
|
||||
SiteMask intersectionWith(const SiteMask& b);
|
||||
|
||||
static SiteMask fixedRegisterMask(int number) {
|
||||
static SiteMask fixedRegisterMask(int number)
|
||||
{
|
||||
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
|
||||
}
|
||||
|
||||
static SiteMask lowPart(const OperandMask& mask) {
|
||||
static SiteMask lowPart(const OperandMask& mask)
|
||||
{
|
||||
return SiteMask(mask.typeMask, mask.registerMask, AnyFrameIndex);
|
||||
}
|
||||
|
||||
static SiteMask highPart(const OperandMask& mask) {
|
||||
static SiteMask highPart(const OperandMask& mask)
|
||||
{
|
||||
return SiteMask(mask.typeMask, mask.registerMask >> 32, AnyFrameIndex);
|
||||
}
|
||||
|
||||
@ -57,9 +63,14 @@ class SiteMask {
|
||||
|
||||
class Site {
|
||||
public:
|
||||
Site(): next(0) { }
|
||||
|
||||
virtual Site* readTarget(Context*, Read*) { return this; }
|
||||
Site() : next(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Site* readTarget(Context*, Read*)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual unsigned toString(Context*, char*, unsigned) = 0;
|
||||
|
||||
@ -70,16 +81,27 @@ class Site {
|
||||
virtual bool loneMatch(Context*, const SiteMask&) = 0;
|
||||
|
||||
virtual bool matchNextWord(Context*, Site*, unsigned) = 0;
|
||||
|
||||
virtual void acquire(Context*, Value*) { }
|
||||
|
||||
virtual void release(Context*, Value*) { }
|
||||
virtual void acquire(Context*, Value*)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void freeze(Context*, Value*) { }
|
||||
virtual void release(Context*, Value*)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void thaw(Context*, Value*) { }
|
||||
virtual void freeze(Context*, Value*)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool frozen(Context*) { return false; }
|
||||
virtual void thaw(Context*, Value*)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool frozen(Context*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual lir::OperandType type(Context*) = 0;
|
||||
|
||||
@ -99,16 +121,24 @@ class Site {
|
||||
|
||||
virtual unsigned registerSize(Context*);
|
||||
|
||||
virtual unsigned registerMask(Context*) { return 0; }
|
||||
virtual unsigned registerMask(Context*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool isVolatile(Context*) { return false; }
|
||||
virtual bool isVolatile(Context*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Site* next;
|
||||
};
|
||||
|
||||
class SiteIterator {
|
||||
public:
|
||||
SiteIterator(Context* c, Value* v, bool includeBuddies = true,
|
||||
SiteIterator(Context* c,
|
||||
Value* v,
|
||||
bool includeBuddies = true,
|
||||
bool includeNextWord = true);
|
||||
|
||||
Site** findNext(Site** p);
|
||||
@ -130,43 +160,52 @@ Site* constantSite(Context* c, Promise* value);
|
||||
Site* constantSite(Context* c, int64_t value);
|
||||
|
||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high);
|
||||
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask);
|
||||
Promise* shiftMaskPromise(Context* c,
|
||||
Promise* base,
|
||||
unsigned shift,
|
||||
int64_t mask);
|
||||
|
||||
class ConstantSite: public Site {
|
||||
class ConstantSite : public Site {
|
||||
public:
|
||||
ConstantSite(Promise* value): value(value) { }
|
||||
ConstantSite(Promise* value) : value(value)
|
||||
{
|
||||
}
|
||||
|
||||
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) {
|
||||
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize)
|
||||
{
|
||||
if (value->resolved()) {
|
||||
return vm::snprintf
|
||||
(buffer, bufferSize, "constant %" LLD, value->value());
|
||||
return vm::snprintf(buffer, bufferSize, "constant %" LLD, value->value());
|
||||
} else {
|
||||
return vm::snprintf(buffer, bufferSize, "constant unresolved");
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned copyCost(Context*, Site* s) {
|
||||
virtual unsigned copyCost(Context*, Site* s)
|
||||
{
|
||||
return (s == this ? 0 : ConstantCopyCost);
|
||||
}
|
||||
|
||||
virtual bool match(Context*, const SiteMask& mask) {
|
||||
virtual bool match(Context*, const SiteMask& mask)
|
||||
{
|
||||
return mask.typeMask & (1 << lir::ConstantOperand);
|
||||
}
|
||||
|
||||
virtual bool loneMatch(Context*, const SiteMask&) {
|
||||
virtual bool loneMatch(Context*, const SiteMask&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool matchNextWord(Context* c, Site* s, unsigned) {
|
||||
virtual bool matchNextWord(Context* c, Site* s, unsigned)
|
||||
{
|
||||
return s->type(c) == lir::ConstantOperand;
|
||||
}
|
||||
|
||||
virtual lir::OperandType type(Context*) {
|
||||
virtual lir::OperandType type(Context*)
|
||||
{
|
||||
return lir::ConstantOperand;
|
||||
}
|
||||
|
||||
virtual void asAssemblerOperand(Context* c, Site* high,
|
||||
lir::Operand* result)
|
||||
virtual void asAssemblerOperand(Context* c, Site* high, lir::Operand* result)
|
||||
{
|
||||
Promise* v = value;
|
||||
if (high != this) {
|
||||
@ -175,27 +214,33 @@ class ConstantSite: public Site {
|
||||
new (result) lir::Constant(v);
|
||||
}
|
||||
|
||||
virtual Site* copy(Context* c) {
|
||||
virtual Site* copy(Context* c)
|
||||
{
|
||||
return constantSite(c, value);
|
||||
}
|
||||
|
||||
virtual Site* copyLow(Context* c) {
|
||||
virtual Site* copyLow(Context* c)
|
||||
{
|
||||
return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
virtual Site* copyHigh(Context* c) {
|
||||
virtual Site* copyHigh(Context* c)
|
||||
{
|
||||
return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
virtual Site* makeNextWord(Context* c, unsigned) {
|
||||
virtual Site* makeNextWord(Context* c, unsigned)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual SiteMask mask(Context*) {
|
||||
virtual SiteMask mask(Context*)
|
||||
{
|
||||
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
|
||||
}
|
||||
|
||||
virtual SiteMask nextWordMask(Context*, unsigned) {
|
||||
virtual SiteMask nextWordMask(Context*, unsigned)
|
||||
{
|
||||
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
|
||||
}
|
||||
|
||||
@ -204,7 +249,7 @@ class ConstantSite: public Site {
|
||||
|
||||
Site* addressSite(Context* c, Promise* address);
|
||||
|
||||
class RegisterSite: public Site {
|
||||
class RegisterSite : public Site {
|
||||
public:
|
||||
RegisterSite(uint32_t mask, int number);
|
||||
|
||||
@ -230,7 +275,8 @@ class RegisterSite: public Site {
|
||||
|
||||
virtual lir::OperandType type(Context*);
|
||||
|
||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high,
|
||||
virtual void asAssemblerOperand(Context* c UNUSED,
|
||||
Site* high,
|
||||
lir::Operand* result);
|
||||
|
||||
virtual Site* copy(Context* c);
|
||||
@ -256,8 +302,7 @@ class RegisterSite: public Site {
|
||||
Site* registerSite(Context* c, int number);
|
||||
Site* freeRegisterSite(Context* c, uint32_t mask);
|
||||
|
||||
|
||||
class MemorySite: public Site {
|
||||
class MemorySite : public Site {
|
||||
public:
|
||||
MemorySite(int base, int offset, int index, unsigned scale);
|
||||
|
||||
@ -285,7 +330,8 @@ class MemorySite: public Site {
|
||||
|
||||
virtual lir::OperandType type(Context*);
|
||||
|
||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
||||
virtual void asAssemblerOperand(Context* c UNUSED,
|
||||
Site* high UNUSED,
|
||||
lir::Operand* result);
|
||||
|
||||
virtual Site* copy(Context* c);
|
||||
@ -311,11 +357,15 @@ class MemorySite: public Site {
|
||||
unsigned scale;
|
||||
};
|
||||
|
||||
MemorySite* memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, unsigned scale = 1);
|
||||
MemorySite* memorySite(Context* c,
|
||||
int base,
|
||||
int offset = 0,
|
||||
int index = lir::NoRegister,
|
||||
unsigned scale = 1);
|
||||
MemorySite* frameSite(Context* c, int frameIndex);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_SITE_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_SITE_H
|
||||
|
@ -31,26 +31,33 @@ Value::Value(Site* site, Site* target, ir::Type type)
|
||||
{
|
||||
}
|
||||
|
||||
bool Value::findSite(Site* site) {
|
||||
bool Value::findSite(Site* site)
|
||||
{
|
||||
for (Site* s = this->sites; s; s = s->next) {
|
||||
if (s == site) return true;
|
||||
if (s == site)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Value::isBuddyOf(Value* b) {
|
||||
bool Value::isBuddyOf(Value* b)
|
||||
{
|
||||
Value* a = this;
|
||||
if (a == b) return true;
|
||||
if (a == b)
|
||||
return true;
|
||||
for (Value* p = a->buddy; p != a; p = p->buddy) {
|
||||
if (p == b) return true;
|
||||
if (p == b)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Value::addSite(Context* c, Site* s) {
|
||||
void Value::addSite(Context* c, Site* s)
|
||||
{
|
||||
if (not this->findSite(s)) {
|
||||
if (DebugSites) {
|
||||
char buffer[256]; s->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
s->toString(c, buffer, 256);
|
||||
fprintf(stderr, "add site %s to %p\n", buffer, this);
|
||||
}
|
||||
s->acquire(c, this);
|
||||
@ -59,8 +66,8 @@ void Value::addSite(Context* c, Site* s) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Value::grow(Context* c) {
|
||||
void Value::grow(Context* c)
|
||||
{
|
||||
assertT(c, this->nextWord == this);
|
||||
|
||||
Value* next = value(c, this->type);
|
||||
@ -69,29 +76,32 @@ void Value::grow(Context* c) {
|
||||
next->wordIndex = 1;
|
||||
}
|
||||
|
||||
|
||||
void Value::maybeSplit(Context* c) {
|
||||
void Value::maybeSplit(Context* c)
|
||||
{
|
||||
if (this->nextWord == this) {
|
||||
this->split(c);
|
||||
}
|
||||
}
|
||||
|
||||
void Value::split(Context* c) {
|
||||
void Value::split(Context* c)
|
||||
{
|
||||
this->grow(c);
|
||||
for (SiteIterator it(c, this); it.hasMore();) {
|
||||
Site* s = it.next();
|
||||
this->removeSite(c, s);
|
||||
|
||||
|
||||
this->addSite(c, s->copyLow(c));
|
||||
this->nextWord->addSite(c, s->copyHigh(c));
|
||||
}
|
||||
}
|
||||
|
||||
void Value::removeSite(Context* c, Site* s) {
|
||||
void Value::removeSite(Context* c, Site* s)
|
||||
{
|
||||
for (SiteIterator it(c, this); it.hasMore();) {
|
||||
if (s == it.next()) {
|
||||
if (DebugSites) {
|
||||
char buffer[256]; s->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
s->toString(c, buffer, 256);
|
||||
fprintf(stderr, "remove site %s from %p\n", buffer, this);
|
||||
}
|
||||
it.remove(c);
|
||||
@ -104,12 +114,14 @@ void Value::removeSite(Context* c, Site* s) {
|
||||
assertT(c, not this->findSite(s));
|
||||
}
|
||||
|
||||
bool Value::hasSite(Context* c) {
|
||||
bool Value::hasSite(Context* c)
|
||||
{
|
||||
SiteIterator it(c, this);
|
||||
return it.hasMore();
|
||||
}
|
||||
|
||||
bool Value::uniqueSite(Context* c, Site* s) {
|
||||
bool Value::uniqueSite(Context* c, Site* s)
|
||||
{
|
||||
SiteIterator it(c, this);
|
||||
Site* p UNUSED = it.next();
|
||||
if (it.hasMore()) {
|
||||
@ -126,14 +138,15 @@ bool Value::uniqueSite(Context* c, Site* s) {
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assertT(c, p == s);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Value::clearSites(Context* c) {
|
||||
void Value::clearSites(Context* c)
|
||||
{
|
||||
if (DebugSites) {
|
||||
fprintf(stderr, "clear sites for %p\n", this);
|
||||
}
|
||||
@ -143,9 +156,9 @@ void Value::clearSites(Context* c) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool Value::hasBuddy(Context* c, Value* b) {
|
||||
bool Value::hasBuddy(Context* c, Value* b)
|
||||
{
|
||||
Value* a = this;
|
||||
if (a == b) {
|
||||
return true;
|
||||
@ -162,13 +175,13 @@ bool Value::hasBuddy(Context* c, Value* b) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // not NDEBUG
|
||||
#endif // not NDEBUG
|
||||
|
||||
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 codegen
|
||||
} // namespace avian
|
||||
} // namespace regalloc
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -62,8 +62,7 @@ class Value : public ir::Value {
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool hasBuddy(Context* c, Value* b);
|
||||
#endif // not NDEBUG
|
||||
|
||||
#endif // not NDEBUG
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_VALUE_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_VALUE_H
|
||||
|
@ -13,23 +13,23 @@
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
||||
unsigned
|
||||
RegisterMask::maskStart(uint32_t mask)
|
||||
unsigned RegisterMask::maskStart(uint32_t mask)
|
||||
{
|
||||
for (int i = 0; i <= 31; ++i) {
|
||||
if (mask & (1 << i)) return i;
|
||||
if (mask & (1 << i))
|
||||
return i;
|
||||
}
|
||||
return 32;
|
||||
}
|
||||
|
||||
unsigned
|
||||
RegisterMask::maskLimit(uint32_t mask)
|
||||
unsigned RegisterMask::maskLimit(uint32_t mask)
|
||||
{
|
||||
for (int i = 31; i >= 0; --i) {
|
||||
if (mask & (1 << i)) return i + 1;
|
||||
if (mask & (1 << i))
|
||||
return i + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -277,6 +277,6 @@ uint64_t longToFloat(int64_t a)
|
||||
return vm::floatToBits(static_cast<float>(a));
|
||||
}
|
||||
|
||||
} // namespace runtime
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace runtime
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -36,8 +36,9 @@ namespace arm {
|
||||
|
||||
namespace isa {
|
||||
// HARDWARE FLAGS
|
||||
bool vfpSupported() {
|
||||
// TODO: Use at runtime detection
|
||||
bool vfpSupported()
|
||||
{
|
||||
// TODO: Use at runtime detection
|
||||
#if defined(__ARM_PCS_VFP)
|
||||
// armhf
|
||||
return true;
|
||||
@ -49,9 +50,12 @@ bool vfpSupported() {
|
||||
return false;
|
||||
#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 MyRegisterFileWithFloats(GPR_MASK, FPR_MASK);
|
||||
@ -59,8 +63,8 @@ const RegisterFile MyRegisterFileWithFloats(GPR_MASK, FPR_MASK);
|
||||
const unsigned FrameHeaderSize = 1;
|
||||
|
||||
const unsigned StackAlignmentInBytes = 8;
|
||||
const unsigned StackAlignmentInWords
|
||||
= StackAlignmentInBytes / TargetBytesPerWord;
|
||||
const unsigned StackAlignmentInWords = StackAlignmentInBytes
|
||||
/ TargetBytesPerWord;
|
||||
|
||||
void resolve(MyBlock*);
|
||||
|
||||
@ -74,16 +78,20 @@ using namespace isa;
|
||||
|
||||
// END OPERATION COMPILERS
|
||||
|
||||
unsigned
|
||||
argumentFootprint(unsigned footprint)
|
||||
unsigned argumentFootprint(unsigned footprint)
|
||||
{
|
||||
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
|
||||
}
|
||||
|
||||
void
|
||||
nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
||||
unsigned footprint, void* link, bool,
|
||||
int targetParameterFootprint UNUSED, void** ip, void** stack)
|
||||
void nextFrame(ArchitectureContext* con,
|
||||
uint32_t* start,
|
||||
unsigned size UNUSED,
|
||||
unsigned footprint,
|
||||
void* link,
|
||||
bool,
|
||||
int targetParameterFootprint UNUSED,
|
||||
void** ip,
|
||||
void** stack)
|
||||
{
|
||||
assertT(con, *ip >= start);
|
||||
assertT(con, *ip <= start + (size / TargetBytesPerWord));
|
||||
@ -108,7 +116,7 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
||||
return;
|
||||
}
|
||||
|
||||
if (*instruction == 0xe12fff1e) { // return
|
||||
if (*instruction == 0xe12fff1e) { // return
|
||||
*ip = link;
|
||||
return;
|
||||
}
|
||||
@ -116,7 +124,7 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
||||
if (TailCalls and targetParameterFootprint >= 0) {
|
||||
if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) {
|
||||
offset += argumentFootprint(targetParameterFootprint)
|
||||
- StackAlignmentInWords;
|
||||
- StackAlignmentInWords;
|
||||
}
|
||||
|
||||
// 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 rotation = (*instruction >> 8) & 0xf;
|
||||
switch (rotation) {
|
||||
case 0: offset -= value / TargetBytesPerWord; break;
|
||||
case 15: offset -= value; break;
|
||||
default: abort(con);
|
||||
case 0:
|
||||
offset -= value / TargetBytesPerWord;
|
||||
break;
|
||||
case 15:
|
||||
offset -= value;
|
||||
break;
|
||||
default:
|
||||
abort(con);
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,45 +151,56 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
||||
*stack = static_cast<void**>(*stack) + offset;
|
||||
}
|
||||
|
||||
class MyArchitecture: public Architecture {
|
||||
class MyArchitecture : public Architecture {
|
||||
public:
|
||||
MyArchitecture(System* system): con(system), referenceCount(0) {
|
||||
MyArchitecture(System* system) : con(system), referenceCount(0)
|
||||
{
|
||||
populateTables(&con);
|
||||
}
|
||||
|
||||
virtual unsigned floatRegisterSize() {
|
||||
virtual unsigned floatRegisterSize()
|
||||
{
|
||||
return vfpSupported() ? 8 : 0;
|
||||
}
|
||||
|
||||
virtual const RegisterFile* registerFile() {
|
||||
return vfpSupported() ? &MyRegisterFileWithFloats : &MyRegisterFileWithoutFloats;
|
||||
virtual const RegisterFile* registerFile()
|
||||
{
|
||||
return vfpSupported() ? &MyRegisterFileWithFloats
|
||||
: &MyRegisterFileWithoutFloats;
|
||||
}
|
||||
|
||||
virtual int scratch() {
|
||||
virtual int scratch()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
virtual int stack() {
|
||||
virtual int stack()
|
||||
{
|
||||
return StackRegister;
|
||||
}
|
||||
|
||||
virtual int thread() {
|
||||
virtual int thread()
|
||||
{
|
||||
return ThreadRegister;
|
||||
}
|
||||
|
||||
virtual int returnLow() {
|
||||
virtual int returnLow()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int returnHigh() {
|
||||
virtual int returnHigh()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual int virtualCallTarget() {
|
||||
virtual int virtualCallTarget()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
virtual int virtualCallIndex() {
|
||||
virtual int virtualCallIndex()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
@ -185,15 +209,18 @@ class MyArchitecture: public Architecture {
|
||||
return ir::TargetInfo(TargetBytesPerWord);
|
||||
}
|
||||
|
||||
virtual bool bigEndian() {
|
||||
virtual bool bigEndian()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual uintptr_t maximumImmediateJump() {
|
||||
virtual uintptr_t maximumImmediateJump()
|
||||
{
|
||||
return 0x1FFFFFF;
|
||||
}
|
||||
|
||||
virtual bool reserved(int register_) {
|
||||
virtual bool reserved(int register_)
|
||||
{
|
||||
switch (register_) {
|
||||
case LinkRegister:
|
||||
case StackRegister:
|
||||
@ -206,15 +233,18 @@ class MyArchitecture: public Architecture {
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned frameFootprint(unsigned footprint) {
|
||||
virtual unsigned frameFootprint(unsigned footprint)
|
||||
{
|
||||
return max(footprint, StackAlignmentInWords);
|
||||
}
|
||||
|
||||
virtual unsigned argumentFootprint(unsigned footprint) {
|
||||
virtual unsigned argumentFootprint(unsigned footprint)
|
||||
{
|
||||
return arm::argumentFootprint(footprint);
|
||||
}
|
||||
|
||||
virtual bool argumentAlignment() {
|
||||
virtual bool argumentAlignment()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return false;
|
||||
#else
|
||||
@ -222,7 +252,8 @@ class MyArchitecture: public Architecture {
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual bool argumentRegisterAlignment() {
|
||||
virtual bool argumentRegisterAlignment()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return false;
|
||||
#else
|
||||
@ -230,30 +261,35 @@ class MyArchitecture: public Architecture {
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual unsigned argumentRegisterCount() {
|
||||
virtual unsigned argumentRegisterCount()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
virtual int argumentRegister(unsigned index) {
|
||||
virtual int argumentRegister(unsigned index)
|
||||
{
|
||||
assertT(&con, index < argumentRegisterCount());
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
virtual bool hasLinkRegister() {
|
||||
virtual bool hasLinkRegister()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual unsigned stackAlignmentInWords() {
|
||||
virtual unsigned stackAlignmentInWords()
|
||||
{
|
||||
return StackAlignmentInWords;
|
||||
}
|
||||
|
||||
virtual bool matchCall(void* returnAddress, void* target) {
|
||||
virtual bool matchCall(void* returnAddress, void* target)
|
||||
{
|
||||
uint32_t* instruction = static_cast<uint32_t*>(returnAddress) - 1;
|
||||
|
||||
return *instruction == static_cast<uint32_t>
|
||||
(bl(static_cast<uint8_t*>(target)
|
||||
- reinterpret_cast<uint8_t*>(instruction)));
|
||||
return *instruction == static_cast<uint32_t>(
|
||||
bl(static_cast<uint8_t*>(target)
|
||||
- reinterpret_cast<uint8_t*>(instruction)));
|
||||
}
|
||||
|
||||
virtual void updateCall(lir::UnaryOperation op UNUSED,
|
||||
@ -265,7 +301,8 @@ class MyArchitecture: public Architecture {
|
||||
case lir::Jump:
|
||||
case lir::AlignedCall:
|
||||
case lir::AlignedJump: {
|
||||
updateOffset(con.s, static_cast<uint8_t*>(returnAddress) - 4,
|
||||
updateOffset(con.s,
|
||||
static_cast<uint8_t*>(returnAddress) - 4,
|
||||
reinterpret_cast<intptr_t>(newTarget));
|
||||
} break;
|
||||
|
||||
@ -275,81 +312,105 @@ class MyArchitecture: public Architecture {
|
||||
case lir::AlignedLongJump: {
|
||||
uint32_t* p = static_cast<uint32_t*>(returnAddress) - 2;
|
||||
*reinterpret_cast<void**>(p + (((*p & PoolOffsetMask) + 8) / 4))
|
||||
= newTarget;
|
||||
= newTarget;
|
||||
} break;
|
||||
|
||||
default: abort(&con);
|
||||
default:
|
||||
abort(&con);
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned constantCallSize() {
|
||||
virtual unsigned constantCallSize()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
virtual void setConstant(void* dst, uint64_t constant) {
|
||||
virtual void setConstant(void* dst, uint64_t constant)
|
||||
{
|
||||
*static_cast<target_uintptr_t*>(dst) = constant;
|
||||
}
|
||||
|
||||
virtual unsigned alignFrameSize(unsigned sizeInWords) {
|
||||
virtual unsigned alignFrameSize(unsigned sizeInWords)
|
||||
{
|
||||
return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords)
|
||||
- FrameHeaderSize;
|
||||
- FrameHeaderSize;
|
||||
}
|
||||
|
||||
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
||||
void* link, bool mostRecent,
|
||||
int targetParameterFootprint, void** ip,
|
||||
virtual void nextFrame(void* start,
|
||||
unsigned size,
|
||||
unsigned footprint,
|
||||
void* link,
|
||||
bool mostRecent,
|
||||
int targetParameterFootprint,
|
||||
void** ip,
|
||||
void** stack)
|
||||
{
|
||||
arm::nextFrame(&con, static_cast<uint32_t*>(start), size, footprint, link,
|
||||
mostRecent, targetParameterFootprint, ip, stack);
|
||||
arm::nextFrame(&con,
|
||||
static_cast<uint32_t*>(start),
|
||||
size,
|
||||
footprint,
|
||||
link,
|
||||
mostRecent,
|
||||
targetParameterFootprint,
|
||||
ip,
|
||||
stack);
|
||||
}
|
||||
|
||||
virtual void* frameIp(void* stack) {
|
||||
virtual void* frameIp(void* stack)
|
||||
{
|
||||
return stack ? static_cast<void**>(stack)[returnAddressOffset()] : 0;
|
||||
}
|
||||
|
||||
virtual unsigned frameHeaderSize() {
|
||||
virtual unsigned frameHeaderSize()
|
||||
{
|
||||
return FrameHeaderSize;
|
||||
}
|
||||
|
||||
virtual unsigned frameReturnAddressSize() {
|
||||
virtual unsigned frameReturnAddressSize()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned frameFooterSize() {
|
||||
virtual unsigned frameFooterSize()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int returnAddressOffset() {
|
||||
virtual int returnAddressOffset()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int framePointerOffset() {
|
||||
virtual int framePointerOffset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool alwaysCondensed(lir::BinaryOperation) {
|
||||
|
||||
virtual bool alwaysCondensed(lir::BinaryOperation)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool alwaysCondensed(lir::TernaryOperation) {
|
||||
|
||||
virtual bool alwaysCondensed(lir::TernaryOperation)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void plan
|
||||
(lir::UnaryOperation,
|
||||
unsigned, OperandMask& aMask,
|
||||
bool* thunk)
|
||||
|
||||
virtual void plan(lir::UnaryOperation,
|
||||
unsigned,
|
||||
OperandMask& aMask,
|
||||
bool* thunk)
|
||||
{
|
||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
|
||||
aMask.registerMask = ~static_cast<uint64_t>(0);
|
||||
*thunk = false;
|
||||
}
|
||||
|
||||
virtual void planSource
|
||||
(lir::BinaryOperation op,
|
||||
unsigned aSize, OperandMask& aMask,
|
||||
unsigned bSize, bool* thunk)
|
||||
virtual void planSource(lir::BinaryOperation op,
|
||||
unsigned aSize,
|
||||
OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
bool* thunk)
|
||||
{
|
||||
*thunk = false;
|
||||
aMask.typeMask = ~0;
|
||||
@ -403,11 +464,12 @@ class MyArchitecture: public Architecture {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void planDestination
|
||||
(lir::BinaryOperation op,
|
||||
unsigned, const OperandMask& aMask,
|
||||
unsigned, OperandMask& bMask)
|
||||
|
||||
virtual void planDestination(lir::BinaryOperation op,
|
||||
unsigned,
|
||||
const OperandMask& aMask,
|
||||
unsigned,
|
||||
OperandMask& bMask)
|
||||
{
|
||||
bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
||||
bMask.registerMask = GPR_MASK64;
|
||||
@ -443,10 +505,10 @@ class MyArchitecture: public Architecture {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void planMove
|
||||
(unsigned, OperandMask& srcMask,
|
||||
OperandMask& tmpMask,
|
||||
const OperandMask& dstMask)
|
||||
virtual void planMove(unsigned,
|
||||
OperandMask& srcMask,
|
||||
OperandMask& tmpMask,
|
||||
const OperandMask& dstMask)
|
||||
{
|
||||
srcMask.typeMask = ~0;
|
||||
srcMask.registerMask = ~static_cast<uint64_t>(0);
|
||||
@ -459,20 +521,21 @@ class MyArchitecture: public Architecture {
|
||||
srcMask.typeMask = 1 << lir::RegisterOperand;
|
||||
tmpMask.typeMask = 1 << lir::RegisterOperand;
|
||||
tmpMask.registerMask = GPR_MASK64;
|
||||
} else if (vfpSupported() &&
|
||||
dstMask.typeMask & 1 << lir::RegisterOperand &&
|
||||
dstMask.registerMask & FPR_MASK) {
|
||||
srcMask.typeMask = tmpMask.typeMask = 1 << lir::RegisterOperand |
|
||||
1 << lir::MemoryOperand;
|
||||
} else if (vfpSupported() && dstMask.typeMask & 1 << lir::RegisterOperand
|
||||
&& dstMask.registerMask & FPR_MASK) {
|
||||
srcMask.typeMask = tmpMask.typeMask = 1 << lir::RegisterOperand
|
||||
| 1 << lir::MemoryOperand;
|
||||
tmpMask.registerMask = ~static_cast<uint64_t>(0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void planSource
|
||||
(lir::TernaryOperation op,
|
||||
unsigned, OperandMask& aMask,
|
||||
unsigned bSize, OperandMask& bMask,
|
||||
unsigned, bool* thunk)
|
||||
virtual void planSource(lir::TernaryOperation op,
|
||||
unsigned,
|
||||
OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
OperandMask& bMask,
|
||||
unsigned,
|
||||
bool* thunk)
|
||||
{
|
||||
aMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::ConstantOperand);
|
||||
aMask.registerMask = GPR_MASK64;
|
||||
@ -486,7 +549,8 @@ class MyArchitecture: public Architecture {
|
||||
case lir::ShiftLeft:
|
||||
case lir::ShiftRight:
|
||||
case lir::UnsignedShiftRight:
|
||||
if (bSize == 8) aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand);
|
||||
if (bSize == 8)
|
||||
aMask.typeMask = bMask.typeMask = (1 << lir::RegisterOperand);
|
||||
break;
|
||||
|
||||
case lir::Add:
|
||||
@ -512,7 +576,7 @@ class MyArchitecture: public Architecture {
|
||||
aMask.registerMask = bMask.registerMask = FPR_MASK64;
|
||||
} else {
|
||||
*thunk = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case lir::JumpIfFloatEqual:
|
||||
@ -538,11 +602,13 @@ class MyArchitecture: public Architecture {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void planDestination
|
||||
(lir::TernaryOperation op,
|
||||
unsigned, const OperandMask& aMask UNUSED,
|
||||
unsigned, const OperandMask& bMask,
|
||||
unsigned, OperandMask& cMask)
|
||||
virtual void planDestination(lir::TernaryOperation op,
|
||||
unsigned,
|
||||
const OperandMask& aMask UNUSED,
|
||||
unsigned,
|
||||
const OperandMask& bMask,
|
||||
unsigned,
|
||||
OperandMask& cMask)
|
||||
{
|
||||
if (isBranch(op)) {
|
||||
cMask.typeMask = (1 << lir::ConstantOperand);
|
||||
@ -555,12 +621,14 @@ class MyArchitecture: public Architecture {
|
||||
|
||||
virtual Assembler* makeAssembler(Allocator* allocator, Zone* zone);
|
||||
|
||||
virtual void acquire() {
|
||||
++ referenceCount;
|
||||
virtual void acquire()
|
||||
{
|
||||
++referenceCount;
|
||||
}
|
||||
|
||||
virtual void release() {
|
||||
if (-- referenceCount == 0) {
|
||||
virtual void release()
|
||||
{
|
||||
if (--referenceCount == 0) {
|
||||
con.s->free(this);
|
||||
}
|
||||
}
|
||||
@ -569,18 +637,21 @@ class MyArchitecture: public Architecture {
|
||||
unsigned referenceCount;
|
||||
};
|
||||
|
||||
class MyAssembler: public Assembler {
|
||||
class MyAssembler : public Assembler {
|
||||
public:
|
||||
MyAssembler(System* s, Allocator* a, Zone* zone, MyArchitecture* arch):
|
||||
con(s, a, zone), arch_(arch)
|
||||
{ }
|
||||
MyAssembler(System* s, Allocator* a, Zone* zone, MyArchitecture* arch)
|
||||
: con(s, a, zone), arch_(arch)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void setClient(Client* client) {
|
||||
virtual void setClient(Client* client)
|
||||
{
|
||||
assertT(&con, con.client == 0);
|
||||
con.client = client;
|
||||
}
|
||||
|
||||
virtual Architecture* arch() {
|
||||
virtual Architecture* arch()
|
||||
{
|
||||
return arch_;
|
||||
}
|
||||
|
||||
@ -589,12 +660,17 @@ class MyAssembler: public Assembler {
|
||||
{
|
||||
lir::Register stack(StackRegister);
|
||||
lir::Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread);
|
||||
lir::Constant handlerConstant(new(con.zone) ResolvedPromise(handler));
|
||||
branchRM(&con, lir::JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit,
|
||||
lir::Constant handlerConstant(new (con.zone) ResolvedPromise(handler));
|
||||
branchRM(&con,
|
||||
lir::JumpIfGreaterOrEqual,
|
||||
TargetBytesPerWord,
|
||||
&stack,
|
||||
&stackLimit,
|
||||
&handlerConstant);
|
||||
}
|
||||
|
||||
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) {
|
||||
virtual void saveFrame(unsigned stackOffset, unsigned ipOffset)
|
||||
{
|
||||
lir::Register link(LinkRegister);
|
||||
lir::Memory linkDst(ThreadRegister, ipOffset);
|
||||
moveRM(&con, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst);
|
||||
@ -604,7 +680,8 @@ class MyAssembler: public Assembler {
|
||||
moveRM(&con, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst);
|
||||
}
|
||||
|
||||
virtual void pushFrame(unsigned argumentCount, ...) {
|
||||
virtual void pushFrame(unsigned argumentCount, ...)
|
||||
{
|
||||
struct Argument {
|
||||
unsigned size;
|
||||
lir::OperandType type;
|
||||
@ -612,49 +689,57 @@ class MyAssembler: public Assembler {
|
||||
};
|
||||
RUNTIME_ARRAY(Argument, arguments, argumentCount);
|
||||
|
||||
va_list a; va_start(a, argumentCount);
|
||||
va_list a;
|
||||
va_start(a, argumentCount);
|
||||
unsigned footprint = 0;
|
||||
for (unsigned i = 0; i < argumentCount; ++i) {
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned);
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type = static_cast<lir::OperandType>(va_arg(a, int));
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type
|
||||
= static_cast<lir::OperandType>(va_arg(a, int));
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*);
|
||||
footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
|
||||
footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
TargetBytesPerWord);
|
||||
}
|
||||
va_end(a);
|
||||
|
||||
allocateFrame(arch_->alignFrameSize(footprint));
|
||||
|
||||
|
||||
unsigned offset = 0;
|
||||
for (unsigned i = 0; i < argumentCount; ++i) {
|
||||
if (i < arch_->argumentRegisterCount()) {
|
||||
lir::Register dst(arch_->argumentRegister(i));
|
||||
|
||||
apply(lir::Move,
|
||||
OperandInfo(
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
||||
OperandInfo(
|
||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), lir::RegisterOperand, &dst));
|
||||
OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
||||
OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
TargetBytesPerWord),
|
||||
lir::RegisterOperand,
|
||||
&dst));
|
||||
|
||||
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
|
||||
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
TargetBytesPerWord);
|
||||
} else {
|
||||
lir::Memory dst(StackRegister, offset * TargetBytesPerWord);
|
||||
|
||||
apply(lir::Move,
|
||||
OperandInfo(
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
||||
OperandInfo(
|
||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord), lir::MemoryOperand, &dst));
|
||||
OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].operand),
|
||||
OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
TargetBytesPerWord),
|
||||
lir::MemoryOperand,
|
||||
&dst));
|
||||
|
||||
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
|
||||
offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
TargetBytesPerWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void allocateFrame(unsigned footprint) {
|
||||
virtual void allocateFrame(unsigned footprint)
|
||||
{
|
||||
footprint += FrameHeaderSize;
|
||||
|
||||
// larger frames may require multiple subtract/add instructions
|
||||
@ -668,28 +753,36 @@ class MyAssembler: public Assembler {
|
||||
subC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
|
||||
|
||||
lir::Register returnAddress(LinkRegister);
|
||||
lir::Memory returnAddressDst
|
||||
(StackRegister, (footprint - 1) * TargetBytesPerWord);
|
||||
moveRM(&con, TargetBytesPerWord, &returnAddress, TargetBytesPerWord,
|
||||
lir::Memory returnAddressDst(StackRegister,
|
||||
(footprint - 1) * TargetBytesPerWord);
|
||||
moveRM(&con,
|
||||
TargetBytesPerWord,
|
||||
&returnAddress,
|
||||
TargetBytesPerWord,
|
||||
&returnAddressDst);
|
||||
}
|
||||
|
||||
virtual void adjustFrame(unsigned difference) {
|
||||
virtual void adjustFrame(unsigned difference)
|
||||
{
|
||||
lir::Register stack(StackRegister);
|
||||
ResolvedPromise differencePromise(difference * TargetBytesPerWord);
|
||||
lir::Constant differenceConstant(&differencePromise);
|
||||
subC(&con, TargetBytesPerWord, &differenceConstant, &stack, &stack);
|
||||
}
|
||||
|
||||
virtual void popFrame(unsigned footprint) {
|
||||
virtual void popFrame(unsigned footprint)
|
||||
{
|
||||
footprint += FrameHeaderSize;
|
||||
|
||||
lir::Register returnAddress(LinkRegister);
|
||||
lir::Memory returnAddressSrc
|
||||
(StackRegister, (footprint - 1) * TargetBytesPerWord);
|
||||
moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord,
|
||||
lir::Memory returnAddressSrc(StackRegister,
|
||||
(footprint - 1) * TargetBytesPerWord);
|
||||
moveMR(&con,
|
||||
TargetBytesPerWord,
|
||||
&returnAddressSrc,
|
||||
TargetBytesPerWord,
|
||||
&returnAddress);
|
||||
|
||||
|
||||
lir::Register stack(StackRegister);
|
||||
ResolvedPromise footprintPromise(footprint * TargetBytesPerWord);
|
||||
lir::Constant footprintConstant(&footprintPromise);
|
||||
@ -708,14 +801,17 @@ class MyAssembler: public Assembler {
|
||||
footprint += FrameHeaderSize;
|
||||
|
||||
lir::Register link(LinkRegister);
|
||||
lir::Memory returnAddressSrc
|
||||
(StackRegister, (footprint - 1) * TargetBytesPerWord);
|
||||
moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord,
|
||||
lir::Memory returnAddressSrc(StackRegister,
|
||||
(footprint - 1) * TargetBytesPerWord);
|
||||
moveMR(&con,
|
||||
TargetBytesPerWord,
|
||||
&returnAddressSrc,
|
||||
TargetBytesPerWord,
|
||||
&link);
|
||||
|
||||
|
||||
lir::Register stack(StackRegister);
|
||||
ResolvedPromise footprintPromise
|
||||
((footprint - offset) * TargetBytesPerWord);
|
||||
ResolvedPromise footprintPromise((footprint - offset)
|
||||
* TargetBytesPerWord);
|
||||
lir::Constant footprintConstant(&footprintPromise);
|
||||
addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
|
||||
|
||||
@ -769,46 +865,52 @@ class MyAssembler: public Assembler {
|
||||
return_(&con);
|
||||
}
|
||||
|
||||
virtual void apply(lir::Operation op) {
|
||||
virtual void apply(lir::Operation op)
|
||||
{
|
||||
arch_->con.operations[op](&con);
|
||||
}
|
||||
|
||||
virtual void apply(lir::UnaryOperation op, OperandInfo a)
|
||||
{
|
||||
arch_->con.unaryOperations[Multimethod::index(op, a.type)]
|
||||
(&con, a.size, a.operand);
|
||||
arch_->con.unaryOperations[Multimethod::index(op, a.type)](
|
||||
&con, a.size, a.operand);
|
||||
}
|
||||
|
||||
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b)
|
||||
{
|
||||
arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)]
|
||||
(&con, a.size, a.operand, b.size, b.operand);
|
||||
arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)](
|
||||
&con, a.size, a.operand, b.size, b.operand);
|
||||
}
|
||||
|
||||
virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c)
|
||||
virtual void apply(lir::TernaryOperation op,
|
||||
OperandInfo a,
|
||||
OperandInfo b,
|
||||
OperandInfo c)
|
||||
{
|
||||
if (isBranch(op)) {
|
||||
assertT(&con, a.size == b.size);
|
||||
assertT(&con, c.size == TargetBytesPerWord);
|
||||
assertT(&con, c.type == lir::ConstantOperand);
|
||||
|
||||
arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)]
|
||||
(&con, op, a.size, a.operand, b.operand, c.operand);
|
||||
arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)](
|
||||
&con, op, a.size, a.operand, b.operand, c.operand);
|
||||
} else {
|
||||
assertT(&con, b.size == c.size);
|
||||
assertT(&con, b.type == lir::RegisterOperand);
|
||||
assertT(&con, c.type == lir::RegisterOperand);
|
||||
|
||||
arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)]
|
||||
(&con, b.size, a.operand, b.operand, c.operand);
|
||||
arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)](
|
||||
&con, b.size, a.operand, b.operand, c.operand);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setDestination(uint8_t* dst) {
|
||||
virtual void setDestination(uint8_t* dst)
|
||||
{
|
||||
con.result = dst;
|
||||
}
|
||||
|
||||
virtual void write() {
|
||||
virtual void write()
|
||||
{
|
||||
uint8_t* dst = con.result;
|
||||
unsigned dstOffset = 0;
|
||||
for (MyBlock* b = con.firstBlock; b; b = b->next) {
|
||||
@ -828,8 +930,11 @@ class MyAssembler: public Assembler {
|
||||
unsigned poolSize = 0;
|
||||
for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) {
|
||||
if (DebugPool) {
|
||||
fprintf(stderr, "visit pool offset %p %d in block %p\n",
|
||||
o, o->offset, b);
|
||||
fprintf(stderr,
|
||||
"visit pool offset %p %d in block %p\n",
|
||||
o,
|
||||
o->offset,
|
||||
b);
|
||||
}
|
||||
|
||||
unsigned entry = dstOffset + poolSize;
|
||||
@ -840,8 +945,8 @@ class MyAssembler: public Assembler {
|
||||
|
||||
o->entry->address = dst + entry;
|
||||
|
||||
unsigned instruction = o->block->start
|
||||
+ padding(o->block, o->offset) + o->offset;
|
||||
unsigned instruction = o->block->start + padding(o->block, o->offset)
|
||||
+ o->offset;
|
||||
|
||||
int32_t v = (entry - 8) - instruction;
|
||||
expect(&con, v == (v & PoolOffsetMask));
|
||||
@ -854,8 +959,8 @@ class MyAssembler: public Assembler {
|
||||
|
||||
bool jump = needJump(b);
|
||||
if (jump) {
|
||||
write4
|
||||
(dst + dstOffset, isa::b((poolSize + TargetBytesPerWord - 8) >> 2));
|
||||
write4(dst + dstOffset,
|
||||
isa::b((poolSize + TargetBytesPerWord - 8) >> 2));
|
||||
}
|
||||
|
||||
dstOffset += poolSize + (jump ? TargetBytesPerWord : 0);
|
||||
@ -879,20 +984,23 @@ class MyAssembler: public Assembler {
|
||||
*static_cast<target_uintptr_t*>(e->address) = e->constant->value();
|
||||
} else {
|
||||
new (e->constant->listen(sizeof(ConstantPoolListener)))
|
||||
ConstantPoolListener(con.s, static_cast<target_uintptr_t*>(e->address),
|
||||
e->callOffset
|
||||
? dst + e->callOffset->value() + 8
|
||||
: 0);
|
||||
ConstantPoolListener(
|
||||
con.s,
|
||||
static_cast<target_uintptr_t*>(e->address),
|
||||
e->callOffset ? dst + e->callOffset->value() + 8 : 0);
|
||||
}
|
||||
// fprintf(stderr, "constant %p at %p\n", reinterpret_cast<void*>(e->constant->value()), e->address);
|
||||
// fprintf(stderr, "constant %p at %p\n",
|
||||
// reinterpret_cast<void*>(e->constant->value()), e->address);
|
||||
}
|
||||
}
|
||||
|
||||
virtual Promise* offset(bool forTrace) {
|
||||
virtual Promise* offset(bool forTrace)
|
||||
{
|
||||
return arm::offsetPromise(&con, forTrace);
|
||||
}
|
||||
|
||||
virtual Block* endBlock(bool startNew) {
|
||||
virtual Block* endBlock(bool startNew)
|
||||
{
|
||||
MyBlock* b = con.lastBlock;
|
||||
b->size = con.code.length() - b->offset;
|
||||
if (startNew) {
|
||||
@ -903,26 +1011,33 @@ class MyAssembler: public Assembler {
|
||||
return b;
|
||||
}
|
||||
|
||||
virtual void endEvent() {
|
||||
virtual void endEvent()
|
||||
{
|
||||
MyBlock* b = con.lastBlock;
|
||||
unsigned thisEventOffset = con.code.length() - b->offset;
|
||||
if (b->poolOffsetHead) {
|
||||
int32_t v = (thisEventOffset + TargetBytesPerWord - 8)
|
||||
- b->poolOffsetHead->offset;
|
||||
- b->poolOffsetHead->offset;
|
||||
|
||||
if (v > 0 and v != (v & PoolOffsetMask)) {
|
||||
appendPoolEvent
|
||||
(&con, b, b->lastEventOffset, b->poolOffsetHead,
|
||||
b->lastPoolOffsetTail);
|
||||
appendPoolEvent(&con,
|
||||
b,
|
||||
b->lastEventOffset,
|
||||
b->poolOffsetHead,
|
||||
b->lastPoolOffsetTail);
|
||||
|
||||
if (DebugPool) {
|
||||
for (PoolOffset* o = b->poolOffsetHead;
|
||||
o != b->lastPoolOffsetTail->next; o = o->next)
|
||||
{
|
||||
o != b->lastPoolOffsetTail->next;
|
||||
o = o->next) {
|
||||
fprintf(stderr,
|
||||
"in endEvent, include %p %d in pool event %p at offset %d "
|
||||
"in block %p\n",
|
||||
o, o->offset, b->poolEventTail, b->lastEventOffset, b);
|
||||
o,
|
||||
o->offset,
|
||||
b->poolEventTail,
|
||||
b->lastEventOffset,
|
||||
b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -937,15 +1052,18 @@ class MyAssembler: public Assembler {
|
||||
b->lastPoolOffsetTail = b->poolOffsetTail;
|
||||
}
|
||||
|
||||
virtual unsigned length() {
|
||||
virtual unsigned length()
|
||||
{
|
||||
return con.code.length();
|
||||
}
|
||||
|
||||
virtual unsigned footerSize() {
|
||||
virtual unsigned footerSize()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
virtual void dispose()
|
||||
{
|
||||
con.code.dispose();
|
||||
}
|
||||
|
||||
@ -953,17 +1071,18 @@ class MyAssembler: public Assembler {
|
||||
MyArchitecture* arch_;
|
||||
};
|
||||
|
||||
Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone) {
|
||||
return new(zone) MyAssembler(this->con.s, allocator, zone, this);
|
||||
}
|
||||
|
||||
} // namespace arm
|
||||
|
||||
Architecture*
|
||||
makeArchitectureArm(System* system, bool)
|
||||
Assembler* MyArchitecture::makeAssembler(Allocator* allocator, Zone* zone)
|
||||
{
|
||||
return new (allocate(system, sizeof(arm::MyArchitecture))) arm::MyArchitecture(system);
|
||||
return new (zone) MyAssembler(this->con.s, allocator, zone, this);
|
||||
}
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
|
||||
Architecture* makeArchitectureArm(System* system, bool)
|
||||
{
|
||||
return new (allocate(system, sizeof(arm::MyArchitecture)))
|
||||
arm::MyArchitecture(system);
|
||||
}
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -19,13 +19,23 @@ void resolve(MyBlock*);
|
||||
|
||||
unsigned padding(MyBlock*, unsigned);
|
||||
|
||||
MyBlock::MyBlock(Context* context, unsigned offset):
|
||||
context(context), next(0), poolOffsetHead(0), poolOffsetTail(0),
|
||||
lastPoolOffsetTail(0), poolEventHead(0), poolEventTail(0),
|
||||
lastEventOffset(0), offset(offset), start(~0), size(0)
|
||||
{ }
|
||||
MyBlock::MyBlock(Context* context, unsigned offset)
|
||||
: context(context),
|
||||
next(0),
|
||||
poolOffsetHead(0),
|
||||
poolOffsetTail(0),
|
||||
lastPoolOffsetTail(0),
|
||||
poolEventHead(0),
|
||||
poolEventTail(0),
|
||||
lastEventOffset(0),
|
||||
offset(offset),
|
||||
start(~0),
|
||||
size(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) {
|
||||
unsigned MyBlock::resolve(unsigned start, Assembler::Block* next)
|
||||
{
|
||||
this->start = start;
|
||||
this->next = static_cast<MyBlock*>(next);
|
||||
|
||||
@ -34,6 +44,6 @@ unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) {
|
||||
return start + size + padding(this, size);
|
||||
}
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -20,7 +20,7 @@ namespace arm {
|
||||
|
||||
class PoolEvent;
|
||||
|
||||
class MyBlock: public Assembler::Block {
|
||||
class MyBlock : public Assembler::Block {
|
||||
public:
|
||||
MyBlock(Context* context, unsigned offset);
|
||||
|
||||
@ -39,8 +39,8 @@ class MyBlock: public Assembler::Block {
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H
|
||||
|
@ -31,6 +31,6 @@ Context::Context(vm::System* s, util::Allocator* a, vm::Zone* zone)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -18,14 +18,14 @@
|
||||
namespace vm {
|
||||
class System;
|
||||
class Zone;
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
namespace avian {
|
||||
|
||||
namespace util {
|
||||
class Aborter;
|
||||
class Allocator;
|
||||
} // namespace util
|
||||
} // namespace util
|
||||
|
||||
namespace codegen {
|
||||
namespace arm {
|
||||
@ -57,43 +57,57 @@ typedef void (*OperationType)(Context*);
|
||||
|
||||
typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*);
|
||||
|
||||
typedef void (*BinaryOperationType)
|
||||
(Context*, unsigned, lir::Operand*, unsigned, lir::Operand*);
|
||||
typedef void (*BinaryOperationType)(Context*,
|
||||
unsigned,
|
||||
lir::Operand*,
|
||||
unsigned,
|
||||
lir::Operand*);
|
||||
|
||||
typedef void (*TernaryOperationType)
|
||||
(Context*, unsigned, lir::Operand*, lir::Operand*,
|
||||
lir::Operand*);
|
||||
typedef void (*TernaryOperationType)(Context*,
|
||||
unsigned,
|
||||
lir::Operand*,
|
||||
lir::Operand*,
|
||||
lir::Operand*);
|
||||
|
||||
typedef void (*BranchOperationType)
|
||||
(Context*, lir::TernaryOperation, unsigned, lir::Operand*,
|
||||
lir::Operand*, lir::Operand*);
|
||||
typedef void (*BranchOperationType)(Context*,
|
||||
lir::TernaryOperation,
|
||||
unsigned,
|
||||
lir::Operand*,
|
||||
lir::Operand*,
|
||||
lir::Operand*);
|
||||
|
||||
class ArchitectureContext {
|
||||
public:
|
||||
ArchitectureContext(vm::System* s): s(s) { }
|
||||
ArchitectureContext(vm::System* s) : s(s)
|
||||
{
|
||||
}
|
||||
|
||||
vm::System* s;
|
||||
OperationType operations[lir::OperationCount];
|
||||
UnaryOperationType unaryOperations[lir::UnaryOperationCount
|
||||
* lir::OperandTypeCount];
|
||||
BinaryOperationType binaryOperations
|
||||
[lir::BinaryOperationCount * lir::OperandTypeCount * lir::OperandTypeCount];
|
||||
TernaryOperationType ternaryOperations
|
||||
[lir::NonBranchTernaryOperationCount * lir::OperandTypeCount];
|
||||
BranchOperationType branchOperations
|
||||
[lir::BranchOperationCount * lir::OperandTypeCount * lir::OperandTypeCount];
|
||||
UnaryOperationType
|
||||
unaryOperations[lir::UnaryOperationCount * lir::OperandTypeCount];
|
||||
BinaryOperationType binaryOperations[lir::BinaryOperationCount
|
||||
* lir::OperandTypeCount
|
||||
* lir::OperandTypeCount];
|
||||
TernaryOperationType ternaryOperations[lir::NonBranchTernaryOperationCount
|
||||
* lir::OperandTypeCount];
|
||||
BranchOperationType branchOperations[lir::BranchOperationCount
|
||||
* lir::OperandTypeCount
|
||||
* lir::OperandTypeCount];
|
||||
};
|
||||
|
||||
inline avian::util::Aborter* getAborter(Context* c) {
|
||||
inline avian::util::Aborter* getAborter(Context* c)
|
||||
{
|
||||
return c->s;
|
||||
}
|
||||
|
||||
inline avian::util::Aborter* getAborter(ArchitectureContext* c) {
|
||||
inline avian::util::Aborter* getAborter(ArchitectureContext* c)
|
||||
{
|
||||
return c->s;
|
||||
}
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H
|
||||
|
@ -25,162 +25,668 @@ const int FPSID = 0x0;
|
||||
const int FPSCR = 0x1;
|
||||
const int FPEXC = 0x8;
|
||||
// INSTRUCTION OPTIONS
|
||||
enum CONDITION { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV };
|
||||
enum CONDITION {
|
||||
EQ,
|
||||
NE,
|
||||
CS,
|
||||
CC,
|
||||
MI,
|
||||
PL,
|
||||
VS,
|
||||
VC,
|
||||
HI,
|
||||
LS,
|
||||
GE,
|
||||
LT,
|
||||
GT,
|
||||
LE,
|
||||
AL,
|
||||
NV
|
||||
};
|
||||
enum SHIFTOP { LSL, LSR, ASR, ROR };
|
||||
// INSTRUCTION FORMATS
|
||||
inline int DATA(int cond, int opcode, int S, int Rn, int Rd, int shift, int Sh, int Rm)
|
||||
{ return cond<<28 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | shift<<7 | Sh<<5 | Rm; }
|
||||
inline int DATAS(int cond, int opcode, int S, int Rn, int Rd, int Rs, int Sh, int Rm)
|
||||
{ return cond<<28 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | Rs<<8 | Sh<<5 | 1<<4 | Rm; }
|
||||
inline int
|
||||
DATA(int cond, int opcode, int S, int Rn, int Rd, int shift, int Sh, int Rm)
|
||||
{
|
||||
return cond << 28 | opcode << 21 | S << 20 | Rn << 16 | Rd << 12 | shift << 7
|
||||
| Sh << 5 | Rm;
|
||||
}
|
||||
inline int
|
||||
DATAS(int cond, int opcode, int S, int Rn, int Rd, int Rs, int Sh, int Rm)
|
||||
{
|
||||
return cond << 28 | opcode << 21 | S << 20 | Rn << 16 | Rd << 12 | Rs << 8
|
||||
| Sh << 5 | 1 << 4 | Rm;
|
||||
}
|
||||
inline int DATAI(int cond, int opcode, int S, int Rn, int Rd, int rot, int imm)
|
||||
{ return cond<<28 | 1<<25 | opcode<<21 | S<<20 | Rn<<16 | Rd<<12 | rot<<8 | (imm&0xff); }
|
||||
{
|
||||
return cond << 28 | 1 << 25 | opcode << 21 | S << 20 | Rn << 16 | Rd << 12
|
||||
| rot << 8 | (imm & 0xff);
|
||||
}
|
||||
inline int BRANCH(int cond, int L, int offset)
|
||||
{ return cond<<28 | 5<<25 | L<<24 | (offset&0xffffff); }
|
||||
{
|
||||
return cond << 28 | 5 << 25 | L << 24 | (offset & 0xffffff);
|
||||
}
|
||||
inline int BRANCHX(int cond, int L, int Rm)
|
||||
{ return cond<<28 | 0x4bffc<<6 | L<<5 | 1<<4 | Rm; }
|
||||
{
|
||||
return cond << 28 | 0x4bffc << 6 | L << 5 | 1 << 4 | Rm;
|
||||
}
|
||||
inline int MULTIPLY(int cond, int mul, int S, int Rd, int Rn, int Rs, int Rm)
|
||||
{ return cond<<28 | mul<<21 | S<<20 | Rd<<16 | Rn<<12 | Rs<<8 | 9<<4 | Rm; }
|
||||
inline int XFER(int cond, int P, int U, int B, int W, int L, int Rn, int Rd, int shift, int Sh, int Rm)
|
||||
{ return cond<<28 | 3<<25 | P<<24 | U<<23 | B<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | shift<<7 | Sh<<5 | Rm; }
|
||||
inline int XFERI(int cond, int P, int U, int B, int W, int L, int Rn, int Rd, int offset)
|
||||
{ return cond<<28 | 2<<25 | P<<24 | U<<23 | B<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | (offset&0xfff); }
|
||||
inline int XFER2(int cond, int P, int U, int W, int L, int Rn, int Rd, int S, int H, int Rm)
|
||||
{ return cond<<28 | P<<24 | U<<23 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | 1<<7 | S<<6 | H<<5 | 1<<4 | Rm; }
|
||||
inline int XFER2I(int cond, int P, int U, int W, int L, int Rn, int Rd, int offsetH, int S, int H, int offsetL)
|
||||
{ return cond<<28 | P<<24 | U<<23 | 1<<22 | W<<21 | L<<20 | Rn<<16 | Rd<<12 | offsetH<<8 | 1<<7 | S<<6 | H<<5 | 1<<4 | (offsetL&0xf); }
|
||||
inline int COOP(int cond, int opcode_1, int CRn, int CRd, int cp_num, int opcode_2, int CRm)
|
||||
{ return cond<<28 | 0xe<<24 | opcode_1<<20 | CRn<<16 | CRd<<12 | cp_num<<8 | opcode_2<<5 | CRm; }
|
||||
inline int COXFER(int cond, int P, int U, int N, int W, int L, int Rn, int CRd, int cp_num, int offset) // offset is in words, not bytes
|
||||
{ return cond<<28 | 0x6<<25 | P<<24 | U<<23 | N<<22 | W<<21 | L<<20 | Rn<<16 | CRd<<12 | cp_num<<8 | (offset&0xff)>>2; }
|
||||
inline int COREG(int cond, int opcode_1, int L, int CRn, int Rd, int cp_num, int opcode_2, int CRm)
|
||||
{ return cond<<28 | 0xe<<24 | opcode_1<<21 | L<<20 | CRn<<16 | Rd<<12 | cp_num<<8 | opcode_2<<5 | 1<<4 | CRm; }
|
||||
inline int COREG2(int cond, int L, int Rn, int Rd, int cp_num, int opcode, int CRm)
|
||||
{ return cond<<28 | 0xc4<<20 | L<<20 | Rn<<16 | Rd<<12 | cp_num<<8 | opcode<<4 | CRm;}
|
||||
{
|
||||
return cond << 28 | mul << 21 | S << 20 | Rd << 16 | Rn << 12 | Rs << 8
|
||||
| 9 << 4 | Rm;
|
||||
}
|
||||
inline int XFER(int cond,
|
||||
int P,
|
||||
int U,
|
||||
int B,
|
||||
int W,
|
||||
int L,
|
||||
int Rn,
|
||||
int Rd,
|
||||
int shift,
|
||||
int Sh,
|
||||
int Rm)
|
||||
{
|
||||
return cond << 28 | 3 << 25 | P << 24 | U << 23 | B << 22 | W << 21 | L << 20
|
||||
| Rn << 16 | Rd << 12 | shift << 7 | Sh << 5 | Rm;
|
||||
}
|
||||
inline int XFERI(int cond,
|
||||
int P,
|
||||
int U,
|
||||
int B,
|
||||
int W,
|
||||
int L,
|
||||
int Rn,
|
||||
int Rd,
|
||||
int offset)
|
||||
{
|
||||
return cond << 28 | 2 << 25 | P << 24 | U << 23 | B << 22 | W << 21 | L << 20
|
||||
| Rn << 16 | Rd << 12 | (offset & 0xfff);
|
||||
}
|
||||
inline int XFER2(int cond,
|
||||
int P,
|
||||
int U,
|
||||
int W,
|
||||
int L,
|
||||
int Rn,
|
||||
int Rd,
|
||||
int S,
|
||||
int H,
|
||||
int Rm)
|
||||
{
|
||||
return cond << 28 | P << 24 | U << 23 | W << 21 | L << 20 | Rn << 16
|
||||
| Rd << 12 | 1 << 7 | S << 6 | H << 5 | 1 << 4 | Rm;
|
||||
}
|
||||
inline int XFER2I(int cond,
|
||||
int P,
|
||||
int U,
|
||||
int W,
|
||||
int L,
|
||||
int Rn,
|
||||
int Rd,
|
||||
int offsetH,
|
||||
int S,
|
||||
int H,
|
||||
int offsetL)
|
||||
{
|
||||
return cond << 28 | P << 24 | U << 23 | 1 << 22 | W << 21 | L << 20 | Rn << 16
|
||||
| Rd << 12 | offsetH << 8 | 1 << 7 | S << 6 | H << 5 | 1 << 4
|
||||
| (offsetL & 0xf);
|
||||
}
|
||||
inline int COOP(int cond,
|
||||
int opcode_1,
|
||||
int CRn,
|
||||
int CRd,
|
||||
int cp_num,
|
||||
int opcode_2,
|
||||
int CRm)
|
||||
{
|
||||
return cond << 28 | 0xe << 24 | opcode_1 << 20 | CRn << 16 | CRd << 12
|
||||
| cp_num << 8 | opcode_2 << 5 | CRm;
|
||||
}
|
||||
inline int COXFER(int cond,
|
||||
int P,
|
||||
int U,
|
||||
int N,
|
||||
int W,
|
||||
int L,
|
||||
int Rn,
|
||||
int CRd,
|
||||
int cp_num,
|
||||
int offset) // offset is in words, not bytes
|
||||
{
|
||||
return cond << 28 | 0x6 << 25 | P << 24 | U << 23 | N << 22 | W << 21
|
||||
| L << 20 | Rn << 16 | CRd << 12 | cp_num << 8 | (offset & 0xff) >> 2;
|
||||
}
|
||||
inline int COREG(int cond,
|
||||
int opcode_1,
|
||||
int L,
|
||||
int CRn,
|
||||
int Rd,
|
||||
int cp_num,
|
||||
int opcode_2,
|
||||
int CRm)
|
||||
{
|
||||
return cond << 28 | 0xe << 24 | opcode_1 << 21 | L << 20 | CRn << 16
|
||||
| Rd << 12 | cp_num << 8 | opcode_2 << 5 | 1 << 4 | CRm;
|
||||
}
|
||||
inline int
|
||||
COREG2(int cond, int L, int Rn, int Rd, int cp_num, int opcode, int CRm)
|
||||
{
|
||||
return cond << 28 | 0xc4 << 20 | L << 20 | Rn << 16 | Rd << 12 | cp_num << 8
|
||||
| opcode << 4 | CRm;
|
||||
}
|
||||
// FIELD CALCULATORS
|
||||
inline int calcU(int imm) { return imm >= 0 ? 1 : 0; }
|
||||
inline int calcU(int imm)
|
||||
{
|
||||
return imm >= 0 ? 1 : 0;
|
||||
}
|
||||
// INSTRUCTIONS
|
||||
// The "cond" and "S" fields are set using the SETCOND() and SETS() functions
|
||||
inline int b(int offset) { return BRANCH(AL, 0, offset); }
|
||||
inline int bl(int offset) { return BRANCH(AL, 1, offset); }
|
||||
inline int bx(int Rm) { return BRANCHX(AL, 0, Rm); }
|
||||
inline int blx(int Rm) { return BRANCHX(AL, 1, Rm); }
|
||||
inline int and_(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x0, 0, Rn, Rd, shift, Sh, Rm); }
|
||||
inline int eor(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x1, 0, Rn, Rd, shift, Sh, Rm); }
|
||||
inline int rsb(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x3, 0, Rn, Rd, shift, Sh, Rm); }
|
||||
inline int add(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x4, 0, Rn, Rd, shift, Sh, Rm); }
|
||||
inline int adc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x5, 0, Rn, Rd, shift, Sh, Rm); }
|
||||
inline int rsc(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0x7, 0, Rn, Rd, shift, Sh, Rm); }
|
||||
inline int cmp(int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xa, 1, Rn, 0, shift, Sh, Rm); }
|
||||
inline int orr(int Rd, int Rn, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xc, 0, Rn, Rd, shift, Sh, Rm); }
|
||||
inline int mov(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xd, 0, 0, Rd, shift, Sh, Rm); }
|
||||
inline int mvn(int Rd, int Rm, int Sh=0, int shift=0) { return DATA(AL, 0xf, 0, 0, Rd, shift, Sh, Rm); }
|
||||
inline int andi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x0, 0, Rn, Rd, rot, imm); }
|
||||
inline int subi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x2, 0, Rn, Rd, rot, imm); }
|
||||
inline int rsbi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x3, 0, Rn, Rd, rot, imm); }
|
||||
inline int addi(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x4, 0, Rn, Rd, rot, imm); }
|
||||
inline int adci(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0x5, 0, Rn, Rd, rot, imm); }
|
||||
inline int bici(int Rd, int Rn, int imm, int rot=0) { return DATAI(AL, 0xe, 0, Rn, Rd, rot, imm); }
|
||||
inline int cmpi(int Rn, int imm, int rot=0) { return DATAI(AL, 0xa, 1, Rn, 0, rot, imm); }
|
||||
inline int movi(int Rd, int imm, int rot=0) { return DATAI(AL, 0xd, 0, 0, Rd, rot, imm); }
|
||||
inline int orrsh(int Rd, int Rn, int Rm, int Rs, int Sh) { return DATAS(AL, 0xc, 0, Rn, Rd, Rs, Sh, Rm); }
|
||||
inline int movsh(int Rd, int Rm, int Rs, int Sh) { return DATAS(AL, 0xd, 0, 0, Rd, Rs, Sh, Rm); }
|
||||
inline int mul(int Rd, int Rm, int Rs) { return MULTIPLY(AL, 0, 0, Rd, 0, Rs, Rm); }
|
||||
inline int mla(int Rd, int Rm, int Rs, int Rn) { return MULTIPLY(AL, 1, 0, Rd, Rn, Rs, Rm); }
|
||||
inline int umull(int RdLo, int RdHi, int Rm, int Rs) { return MULTIPLY(AL, 4, 0, RdHi, RdLo, Rs, Rm); }
|
||||
inline int ldr(int Rd, int Rn, int Rm, int W=0) { return XFER(AL, 1, 1, 0, W, 1, Rn, Rd, 0, 0, Rm); }
|
||||
inline int ldri(int Rd, int Rn, int imm, int W=0) { return XFERI(AL, 1, calcU(imm), 0, W, 1, Rn, Rd, abs(imm)); }
|
||||
inline int ldrb(int Rd, int Rn, int Rm) { return XFER(AL, 1, 1, 1, 0, 1, Rn, Rd, 0, 0, Rm); }
|
||||
inline int ldrbi(int Rd, int Rn, int imm) { return XFERI(AL, 1, calcU(imm), 1, 0, 1, Rn, Rd, abs(imm)); }
|
||||
inline int str(int Rd, int Rn, int Rm, int W=0) { return XFER(AL, 1, 1, 0, W, 0, Rn, Rd, 0, 0, Rm); }
|
||||
inline int stri(int Rd, int Rn, int imm, int W=0) { return XFERI(AL, 1, calcU(imm), 0, W, 0, Rn, Rd, abs(imm)); }
|
||||
inline int strb(int Rd, int Rn, int Rm) { return XFER(AL, 1, 1, 1, 0, 0, Rn, Rd, 0, 0, Rm); }
|
||||
inline int strbi(int Rd, int Rn, int imm) { return XFERI(AL, 1, calcU(imm), 1, 0, 0, Rn, Rd, abs(imm)); }
|
||||
inline int ldrh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 0, 1, Rm); }
|
||||
inline int ldrhi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 0, 1, abs(imm)&0xf); }
|
||||
inline int strh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 0, Rn, Rd, 0, 1, Rm); }
|
||||
inline int strhi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 0, Rn, Rd, abs(imm)>>4 & 0xf, 0, 1, abs(imm)&0xf); }
|
||||
inline int ldrsh(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 1, Rm); }
|
||||
inline int ldrshi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 1, abs(imm)&0xf); }
|
||||
inline int ldrsb(int Rd, int Rn, int Rm) { return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 0, Rm); }
|
||||
inline int ldrsbi(int Rd, int Rn, int imm) { return XFER2I(AL, 1, calcU(imm), 0, 1, Rn, Rd, abs(imm)>>4 & 0xf, 1, 0, abs(imm)&0xf); }
|
||||
inline int b(int offset)
|
||||
{
|
||||
return BRANCH(AL, 0, offset);
|
||||
}
|
||||
inline int bl(int offset)
|
||||
{
|
||||
return BRANCH(AL, 1, offset);
|
||||
}
|
||||
inline int bx(int Rm)
|
||||
{
|
||||
return BRANCHX(AL, 0, Rm);
|
||||
}
|
||||
inline int blx(int Rm)
|
||||
{
|
||||
return BRANCHX(AL, 1, Rm);
|
||||
}
|
||||
inline int and_(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0x0, 0, Rn, Rd, shift, Sh, Rm);
|
||||
}
|
||||
inline int eor(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0x1, 0, Rn, Rd, shift, Sh, Rm);
|
||||
}
|
||||
inline int rsb(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0x3, 0, Rn, Rd, shift, Sh, Rm);
|
||||
}
|
||||
inline int add(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0x4, 0, Rn, Rd, shift, Sh, Rm);
|
||||
}
|
||||
inline int adc(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0x5, 0, Rn, Rd, shift, Sh, Rm);
|
||||
}
|
||||
inline int rsc(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0x7, 0, Rn, Rd, shift, Sh, Rm);
|
||||
}
|
||||
inline int cmp(int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0xa, 1, Rn, 0, shift, Sh, Rm);
|
||||
}
|
||||
inline int orr(int Rd, int Rn, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0xc, 0, Rn, Rd, shift, Sh, Rm);
|
||||
}
|
||||
inline int mov(int Rd, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0xd, 0, 0, Rd, shift, Sh, Rm);
|
||||
}
|
||||
inline int mvn(int Rd, int Rm, int Sh = 0, int shift = 0)
|
||||
{
|
||||
return DATA(AL, 0xf, 0, 0, Rd, shift, Sh, Rm);
|
||||
}
|
||||
inline int andi(int Rd, int Rn, int imm, int rot = 0)
|
||||
{
|
||||
return DATAI(AL, 0x0, 0, Rn, Rd, rot, imm);
|
||||
}
|
||||
inline int subi(int Rd, int Rn, int imm, int rot = 0)
|
||||
{
|
||||
return DATAI(AL, 0x2, 0, Rn, Rd, rot, imm);
|
||||
}
|
||||
inline int rsbi(int Rd, int Rn, int imm, int rot = 0)
|
||||
{
|
||||
return DATAI(AL, 0x3, 0, Rn, Rd, rot, imm);
|
||||
}
|
||||
inline int addi(int Rd, int Rn, int imm, int rot = 0)
|
||||
{
|
||||
return DATAI(AL, 0x4, 0, Rn, Rd, rot, imm);
|
||||
}
|
||||
inline int adci(int Rd, int Rn, int imm, int rot = 0)
|
||||
{
|
||||
return DATAI(AL, 0x5, 0, Rn, Rd, rot, imm);
|
||||
}
|
||||
inline int bici(int Rd, int Rn, int imm, int rot = 0)
|
||||
{
|
||||
return DATAI(AL, 0xe, 0, Rn, Rd, rot, imm);
|
||||
}
|
||||
inline int cmpi(int Rn, int imm, int rot = 0)
|
||||
{
|
||||
return DATAI(AL, 0xa, 1, Rn, 0, rot, imm);
|
||||
}
|
||||
inline int movi(int Rd, int imm, int rot = 0)
|
||||
{
|
||||
return DATAI(AL, 0xd, 0, 0, Rd, rot, imm);
|
||||
}
|
||||
inline int orrsh(int Rd, int Rn, int Rm, int Rs, int Sh)
|
||||
{
|
||||
return DATAS(AL, 0xc, 0, Rn, Rd, Rs, Sh, Rm);
|
||||
}
|
||||
inline int movsh(int Rd, int Rm, int Rs, int Sh)
|
||||
{
|
||||
return DATAS(AL, 0xd, 0, 0, Rd, Rs, Sh, Rm);
|
||||
}
|
||||
inline int mul(int Rd, int Rm, int Rs)
|
||||
{
|
||||
return MULTIPLY(AL, 0, 0, Rd, 0, Rs, Rm);
|
||||
}
|
||||
inline int mla(int Rd, int Rm, int Rs, int Rn)
|
||||
{
|
||||
return MULTIPLY(AL, 1, 0, Rd, Rn, Rs, Rm);
|
||||
}
|
||||
inline int umull(int RdLo, int RdHi, int Rm, int Rs)
|
||||
{
|
||||
return MULTIPLY(AL, 4, 0, RdHi, RdLo, Rs, Rm);
|
||||
}
|
||||
inline int ldr(int Rd, int Rn, int Rm, int W = 0)
|
||||
{
|
||||
return XFER(AL, 1, 1, 0, W, 1, Rn, Rd, 0, 0, Rm);
|
||||
}
|
||||
inline int ldri(int Rd, int Rn, int imm, int W = 0)
|
||||
{
|
||||
return XFERI(AL, 1, calcU(imm), 0, W, 1, Rn, Rd, abs(imm));
|
||||
}
|
||||
inline int ldrb(int Rd, int Rn, int Rm)
|
||||
{
|
||||
return XFER(AL, 1, 1, 1, 0, 1, Rn, Rd, 0, 0, Rm);
|
||||
}
|
||||
inline int ldrbi(int Rd, int Rn, int imm)
|
||||
{
|
||||
return XFERI(AL, 1, calcU(imm), 1, 0, 1, Rn, Rd, abs(imm));
|
||||
}
|
||||
inline int str(int Rd, int Rn, int Rm, int W = 0)
|
||||
{
|
||||
return XFER(AL, 1, 1, 0, W, 0, Rn, Rd, 0, 0, Rm);
|
||||
}
|
||||
inline int stri(int Rd, int Rn, int imm, int W = 0)
|
||||
{
|
||||
return XFERI(AL, 1, calcU(imm), 0, W, 0, Rn, Rd, abs(imm));
|
||||
}
|
||||
inline int strb(int Rd, int Rn, int Rm)
|
||||
{
|
||||
return XFER(AL, 1, 1, 1, 0, 0, Rn, Rd, 0, 0, Rm);
|
||||
}
|
||||
inline int strbi(int Rd, int Rn, int imm)
|
||||
{
|
||||
return XFERI(AL, 1, calcU(imm), 1, 0, 0, Rn, Rd, abs(imm));
|
||||
}
|
||||
inline int ldrh(int Rd, int Rn, int Rm)
|
||||
{
|
||||
return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 0, 1, Rm);
|
||||
}
|
||||
inline int ldrhi(int Rd, int Rn, int imm)
|
||||
{
|
||||
return XFER2I(AL,
|
||||
1,
|
||||
calcU(imm),
|
||||
0,
|
||||
1,
|
||||
Rn,
|
||||
Rd,
|
||||
abs(imm) >> 4 & 0xf,
|
||||
0,
|
||||
1,
|
||||
abs(imm) & 0xf);
|
||||
}
|
||||
inline int strh(int Rd, int Rn, int Rm)
|
||||
{
|
||||
return XFER2(AL, 1, 1, 0, 0, Rn, Rd, 0, 1, Rm);
|
||||
}
|
||||
inline int strhi(int Rd, int Rn, int imm)
|
||||
{
|
||||
return XFER2I(AL,
|
||||
1,
|
||||
calcU(imm),
|
||||
0,
|
||||
0,
|
||||
Rn,
|
||||
Rd,
|
||||
abs(imm) >> 4 & 0xf,
|
||||
0,
|
||||
1,
|
||||
abs(imm) & 0xf);
|
||||
}
|
||||
inline int ldrsh(int Rd, int Rn, int Rm)
|
||||
{
|
||||
return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 1, Rm);
|
||||
}
|
||||
inline int ldrshi(int Rd, int Rn, int imm)
|
||||
{
|
||||
return XFER2I(AL,
|
||||
1,
|
||||
calcU(imm),
|
||||
0,
|
||||
1,
|
||||
Rn,
|
||||
Rd,
|
||||
abs(imm) >> 4 & 0xf,
|
||||
1,
|
||||
1,
|
||||
abs(imm) & 0xf);
|
||||
}
|
||||
inline int ldrsb(int Rd, int Rn, int Rm)
|
||||
{
|
||||
return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 0, Rm);
|
||||
}
|
||||
inline int ldrsbi(int Rd, int Rn, int imm)
|
||||
{
|
||||
return XFER2I(AL,
|
||||
1,
|
||||
calcU(imm),
|
||||
0,
|
||||
1,
|
||||
Rn,
|
||||
Rd,
|
||||
abs(imm) >> 4 & 0xf,
|
||||
1,
|
||||
0,
|
||||
abs(imm) & 0xf);
|
||||
}
|
||||
// breakpoint instruction, this really has its own instruction format
|
||||
inline int bkpt(int16_t immed) { return 0xe1200070 | (((unsigned)immed & 0xffff) >> 4 << 8) | (immed & 0xf); }
|
||||
inline int bkpt(int16_t immed)
|
||||
{
|
||||
return 0xe1200070 | (((unsigned)immed & 0xffff) >> 4 << 8) | (immed & 0xf);
|
||||
}
|
||||
// COPROCESSOR INSTRUCTIONS
|
||||
inline int mcr(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm); }
|
||||
inline int mcrr(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm); }
|
||||
inline int mrc(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm); }
|
||||
inline int mrrc(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm); }
|
||||
inline int mcr(int coproc,
|
||||
int opcode_1,
|
||||
int Rd,
|
||||
int CRn,
|
||||
int CRm,
|
||||
int opcode_2 = 0)
|
||||
{
|
||||
return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm);
|
||||
}
|
||||
inline int mcrr(int coproc, int opcode, int Rd, int Rn, int CRm)
|
||||
{
|
||||
return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm);
|
||||
}
|
||||
inline int mrc(int coproc,
|
||||
int opcode_1,
|
||||
int Rd,
|
||||
int CRn,
|
||||
int CRm,
|
||||
int opcode_2 = 0)
|
||||
{
|
||||
return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm);
|
||||
}
|
||||
inline int mrrc(int coproc, int opcode, int Rd, int Rn, int CRm)
|
||||
{
|
||||
return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm);
|
||||
}
|
||||
// VFP FLOATING-POINT INSTRUCTIONS
|
||||
inline int fmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); }
|
||||
inline int fadds(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); }
|
||||
inline int fsubs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); }
|
||||
inline int fdivs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|8, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); }
|
||||
inline int fmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 0, Dm); }
|
||||
inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); }
|
||||
inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); }
|
||||
inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); }
|
||||
inline int fcpys(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 2|(Sm&1), Sm>>1); }
|
||||
inline int fabss(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 6|(Sm&1), Sm>>1); }
|
||||
inline int fnegs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 2|(Sm&1), Sm>>1); }
|
||||
inline int fsqrts(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 6|(Sm&1), Sm>>1); }
|
||||
inline int fcmps(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 2|(Sm&1), Sm>>1); }
|
||||
inline int fcvtds(int Dd, int Sm) { return COOP(AL, 0xb, 7, Dd, 10, 6|(Sm&1), Sm>>1); }
|
||||
inline int fsitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 6|(Sm&1), Sm>>1); }
|
||||
inline int ftosizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 6|(Sm&1), Sm>>1); }
|
||||
inline int fcpyd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); }
|
||||
inline int fabsd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); }
|
||||
inline int fnegd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); }
|
||||
inline int fsqrtd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 6, Dm); }
|
||||
inline int fmuls(int Sd, int Sn, int Sm)
|
||||
{
|
||||
return COOP(AL,
|
||||
(Sd & 1) << 2 | 2,
|
||||
Sn >> 1,
|
||||
Sd >> 1,
|
||||
10,
|
||||
(Sn & 1) << 2 | (Sm & 1),
|
||||
Sm >> 1);
|
||||
}
|
||||
inline int fadds(int Sd, int Sn, int Sm)
|
||||
{
|
||||
return COOP(AL,
|
||||
(Sd & 1) << 2 | 3,
|
||||
Sn >> 1,
|
||||
Sd >> 1,
|
||||
10,
|
||||
(Sn & 1) << 2 | (Sm & 1),
|
||||
Sm >> 1);
|
||||
}
|
||||
inline int fsubs(int Sd, int Sn, int Sm)
|
||||
{
|
||||
return COOP(AL,
|
||||
(Sd & 1) << 2 | 3,
|
||||
Sn >> 1,
|
||||
Sd >> 1,
|
||||
10,
|
||||
(Sn & 1) << 2 | (Sm & 1) | 2,
|
||||
Sm >> 1);
|
||||
}
|
||||
inline int fdivs(int Sd, int Sn, int Sm)
|
||||
{
|
||||
return COOP(AL,
|
||||
(Sd & 1) << 2 | 8,
|
||||
Sn >> 1,
|
||||
Sd >> 1,
|
||||
10,
|
||||
(Sn & 1) << 2 | (Sm & 1),
|
||||
Sm >> 1);
|
||||
}
|
||||
inline int fmuld(int Dd, int Dn, int Dm)
|
||||
{
|
||||
return COOP(AL, 2, Dn, Dd, 11, 0, Dm);
|
||||
}
|
||||
inline int faddd(int Dd, int Dn, int Dm)
|
||||
{
|
||||
return COOP(AL, 3, Dn, Dd, 11, 0, Dm);
|
||||
}
|
||||
inline int fsubd(int Dd, int Dn, int Dm)
|
||||
{
|
||||
return COOP(AL, 3, Dn, Dd, 11, 2, Dm);
|
||||
}
|
||||
inline int fdivd(int Dd, int Dn, int Dm)
|
||||
{
|
||||
return COOP(AL, 8, Dn, Dd, 11, 0, Dm);
|
||||
}
|
||||
inline int fcpys(int Sd, int Sm)
|
||||
{
|
||||
return COOP(AL, 0xb | (Sd & 1) << 2, 0, Sd >> 1, 10, 2 | (Sm & 1), Sm >> 1);
|
||||
}
|
||||
inline int fabss(int Sd, int Sm)
|
||||
{
|
||||
return COOP(AL, 0xb | (Sd & 1) << 2, 0, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1);
|
||||
}
|
||||
inline int fnegs(int Sd, int Sm)
|
||||
{
|
||||
return COOP(AL, 0xb | (Sd & 1) << 2, 1, Sd >> 1, 10, 2 | (Sm & 1), Sm >> 1);
|
||||
}
|
||||
inline int fsqrts(int Sd, int Sm)
|
||||
{
|
||||
return COOP(AL, 0xb | (Sd & 1) << 2, 1, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1);
|
||||
}
|
||||
inline int fcmps(int Sd, int Sm)
|
||||
{
|
||||
return COOP(AL, 0xb | (Sd & 1) << 2, 4, Sd >> 1, 10, 2 | (Sm & 1), Sm >> 1);
|
||||
}
|
||||
inline int fcvtds(int Dd, int Sm)
|
||||
{
|
||||
return COOP(AL, 0xb, 7, Dd, 10, 6 | (Sm & 1), Sm >> 1);
|
||||
}
|
||||
inline int fsitos(int Sd, int Sm)
|
||||
{
|
||||
return COOP(AL, 0xb | (Sd & 1) << 2, 8, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1);
|
||||
}
|
||||
inline int ftosizs(int Sd, int Sm)
|
||||
{
|
||||
return COOP(AL, 0xb | (Sd & 1) << 2, 0xd, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1);
|
||||
}
|
||||
inline int fcpyd(int Dd, int Dm)
|
||||
{
|
||||
return COOP(AL, 0xb, 0, Dd, 11, 2, Dm);
|
||||
}
|
||||
inline int fabsd(int Dd, int Dm)
|
||||
{
|
||||
return COOP(AL, 0xb, 0, Dd, 11, 6, Dm);
|
||||
}
|
||||
inline int fnegd(int Dd, int Dm)
|
||||
{
|
||||
return COOP(AL, 0xb, 1, Dd, 11, 2, Dm);
|
||||
}
|
||||
inline int fsqrtd(int Dd, int Dm)
|
||||
{
|
||||
return COOP(AL, 0xb, 1, Dd, 11, 6, Dm);
|
||||
}
|
||||
// double-precision comparison instructions
|
||||
inline int fcmpd(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); }
|
||||
inline int fcmpd(int Dd, int Dm)
|
||||
{
|
||||
return COOP(AL, 0xb, 4, Dd, 11, 2, Dm);
|
||||
}
|
||||
// double-precision conversion instructions
|
||||
inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 7, Sd>>1, 11, 6, Dm); }
|
||||
inline int fsitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 6|(Sm&1), Sm>>1); }
|
||||
inline int ftosizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 6, Dm); }
|
||||
inline int fcvtsd(int Sd, int Dm)
|
||||
{
|
||||
return COOP(AL, 0xb | (Sd & 1) << 2, 7, Sd >> 1, 11, 6, Dm);
|
||||
}
|
||||
inline int fsitod(int Dd, int Sm)
|
||||
{
|
||||
return COOP(AL, 0xb, 8, Dd, 11, 6 | (Sm & 1), Sm >> 1);
|
||||
}
|
||||
inline int ftosizd(int Sd, int Dm)
|
||||
{
|
||||
return COOP(AL, 0xb | (Sd & 1) << 2, 0xd, Sd >> 1, 11, 6, Dm);
|
||||
}
|
||||
// single load/store instructions for both precision types
|
||||
inline int flds(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); };
|
||||
inline int fldd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); };
|
||||
inline int fsts(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); };
|
||||
inline int fstd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset); };
|
||||
inline int flds(int Sd, int Rn, int offset = 0)
|
||||
{
|
||||
return COXFER(AL, 1, 1, Sd & 1, 0, 1, Rn, Sd >> 1, 10, offset);
|
||||
};
|
||||
inline int fldd(int Dd, int Rn, int offset = 0)
|
||||
{
|
||||
return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset);
|
||||
};
|
||||
inline int fsts(int Sd, int Rn, int offset = 0)
|
||||
{
|
||||
return COXFER(AL, 1, 1, Sd & 1, 0, 0, Rn, Sd >> 1, 10, offset);
|
||||
};
|
||||
inline int fstd(int Dd, int Rn, int offset = 0)
|
||||
{
|
||||
return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset);
|
||||
};
|
||||
// move between GPRs and FPRs
|
||||
inline int fmsr(int Sn, int Rd) { return mcr(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); }
|
||||
inline int fmrs(int Rd, int Sn) { return mrc(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); }
|
||||
inline int fmsr(int Sn, int Rd)
|
||||
{
|
||||
return mcr(10, 0, Rd, Sn >> 1, 0, (Sn & 1) << 2);
|
||||
}
|
||||
inline int fmrs(int Rd, int Sn)
|
||||
{
|
||||
return mrc(10, 0, Rd, Sn >> 1, 0, (Sn & 1) << 2);
|
||||
}
|
||||
// move to/from VFP system registers
|
||||
inline int fmrx(int Rd, int reg) { return mrc(10, 7, Rd, reg, 0); }
|
||||
inline int fmrx(int Rd, int reg)
|
||||
{
|
||||
return mrc(10, 7, Rd, reg, 0);
|
||||
}
|
||||
// these move around pairs of single-precision registers
|
||||
inline int fmdrr(int Dm, int Rd, int Rn) { return mcrr(11, 1, Rd, Rn, Dm); }
|
||||
inline int fmrrd(int Rd, int Rn, int Dm) { return mrrc(11, 1, Rd, Rn, Dm); }
|
||||
inline int fmdrr(int Dm, int Rd, int Rn)
|
||||
{
|
||||
return mcrr(11, 1, Rd, Rn, Dm);
|
||||
}
|
||||
inline int fmrrd(int Rd, int Rn, int Dm)
|
||||
{
|
||||
return mrrc(11, 1, Rd, Rn, Dm);
|
||||
}
|
||||
// FLAG SETTERS
|
||||
inline int SETCOND(int ins, int cond) { return ((ins&0x0fffffff) | (cond<<28)); }
|
||||
inline int SETS(int ins) { return ins | 1<<20; }
|
||||
inline int SETCOND(int ins, int cond)
|
||||
{
|
||||
return ((ins & 0x0fffffff) | (cond << 28));
|
||||
}
|
||||
inline int SETS(int ins)
|
||||
{
|
||||
return ins | 1 << 20;
|
||||
}
|
||||
// PSEUDO-INSTRUCTIONS
|
||||
inline int lsl(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSL); }
|
||||
inline int lsli(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSL, imm); }
|
||||
inline int lsr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, LSR); }
|
||||
inline int lsri(int Rd, int Rm, int imm) { return mov(Rd, Rm, LSR, imm); }
|
||||
inline int asr(int Rd, int Rm, int Rs) { return movsh(Rd, Rm, Rs, ASR); }
|
||||
inline int asri(int Rd, int Rm, int imm) { return mov(Rd, Rm, ASR, imm); }
|
||||
inline int beq(int offset) { return SETCOND(b(offset), EQ); }
|
||||
inline int bne(int offset) { return SETCOND(b(offset), NE); }
|
||||
inline int bls(int offset) { return SETCOND(b(offset), LS); }
|
||||
inline int bhi(int offset) { return SETCOND(b(offset), HI); }
|
||||
inline int blt(int offset) { return SETCOND(b(offset), LT); }
|
||||
inline int bgt(int offset) { return SETCOND(b(offset), GT); }
|
||||
inline int ble(int offset) { return SETCOND(b(offset), LE); }
|
||||
inline int bge(int offset) { return SETCOND(b(offset), GE); }
|
||||
inline int blo(int offset) { return SETCOND(b(offset), CC); }
|
||||
inline int bhs(int offset) { return SETCOND(b(offset), CS); }
|
||||
inline int bpl(int offset) { return SETCOND(b(offset), PL); }
|
||||
inline int fmstat() { return fmrx(15, FPSCR); }
|
||||
inline int lsl(int Rd, int Rm, int Rs)
|
||||
{
|
||||
return movsh(Rd, Rm, Rs, LSL);
|
||||
}
|
||||
inline int lsli(int Rd, int Rm, int imm)
|
||||
{
|
||||
return mov(Rd, Rm, LSL, imm);
|
||||
}
|
||||
inline int lsr(int Rd, int Rm, int Rs)
|
||||
{
|
||||
return movsh(Rd, Rm, Rs, LSR);
|
||||
}
|
||||
inline int lsri(int Rd, int Rm, int imm)
|
||||
{
|
||||
return mov(Rd, Rm, LSR, imm);
|
||||
}
|
||||
inline int asr(int Rd, int Rm, int Rs)
|
||||
{
|
||||
return movsh(Rd, Rm, Rs, ASR);
|
||||
}
|
||||
inline int asri(int Rd, int Rm, int imm)
|
||||
{
|
||||
return mov(Rd, Rm, ASR, imm);
|
||||
}
|
||||
inline int beq(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), EQ);
|
||||
}
|
||||
inline int bne(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), NE);
|
||||
}
|
||||
inline int bls(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), LS);
|
||||
}
|
||||
inline int bhi(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), HI);
|
||||
}
|
||||
inline int blt(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), LT);
|
||||
}
|
||||
inline int bgt(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), GT);
|
||||
}
|
||||
inline int ble(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), LE);
|
||||
}
|
||||
inline int bge(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), GE);
|
||||
}
|
||||
inline int blo(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), CC);
|
||||
}
|
||||
inline int bhs(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), CS);
|
||||
}
|
||||
inline int bpl(int offset)
|
||||
{
|
||||
return SETCOND(b(offset), PL);
|
||||
}
|
||||
inline int fmstat()
|
||||
{
|
||||
return fmrx(15, FPSCR);
|
||||
}
|
||||
// todo: make this pretty:
|
||||
inline int dmb() { return 0xf57ff05f; }
|
||||
inline int dmb()
|
||||
{
|
||||
return 0xf57ff05f;
|
||||
}
|
||||
|
||||
} // namespace isa
|
||||
} // namespace isa
|
||||
|
||||
inline void emit(Context* con, int code) { con->code.append4(code); }
|
||||
inline void emit(Context* con, int code)
|
||||
{
|
||||
con->code.append4(code);
|
||||
}
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H
|
||||
|
@ -20,65 +20,78 @@ using namespace util;
|
||||
|
||||
unsigned padding(MyBlock*, unsigned);
|
||||
|
||||
OffsetPromise::OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace):
|
||||
con(con), block(block), offset(offset), forTrace(forTrace)
|
||||
{ }
|
||||
OffsetPromise::OffsetPromise(Context* con,
|
||||
MyBlock* block,
|
||||
unsigned offset,
|
||||
bool forTrace)
|
||||
: con(con), block(block), offset(offset), forTrace(forTrace)
|
||||
{
|
||||
}
|
||||
|
||||
bool OffsetPromise::resolved() {
|
||||
bool OffsetPromise::resolved()
|
||||
{
|
||||
return block->start != static_cast<unsigned>(~0);
|
||||
}
|
||||
|
||||
int64_t OffsetPromise::value() {
|
||||
int64_t OffsetPromise::value()
|
||||
{
|
||||
assertT(con, resolved());
|
||||
|
||||
unsigned o = offset - block->offset;
|
||||
return block->start + padding
|
||||
(block, forTrace ? o - vm::TargetBytesPerWord : o) + o;
|
||||
return block->start
|
||||
+ padding(block, forTrace ? o - vm::TargetBytesPerWord : o) + o;
|
||||
}
|
||||
|
||||
|
||||
Promise* offsetPromise(Context* con, bool forTrace) {
|
||||
return new(con->zone) OffsetPromise(con, con->lastBlock, con->code.length(), forTrace);
|
||||
Promise* offsetPromise(Context* con, bool forTrace)
|
||||
{
|
||||
return new (con->zone)
|
||||
OffsetPromise(con, con->lastBlock, con->code.length(), forTrace);
|
||||
}
|
||||
|
||||
OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction)
|
||||
: s(s), instruction(instruction)
|
||||
{
|
||||
}
|
||||
|
||||
OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction):
|
||||
s(s),
|
||||
instruction(instruction)
|
||||
{ }
|
||||
|
||||
bool OffsetListener::resolve(int64_t value, void** location) {
|
||||
bool OffsetListener::resolve(int64_t value, void** location)
|
||||
{
|
||||
void* p = updateOffset(s, instruction, value);
|
||||
if (location) *location = p;
|
||||
if (location)
|
||||
*location = p;
|
||||
return false;
|
||||
}
|
||||
|
||||
OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset)
|
||||
: Task(next), promise(promise), instructionOffset(instructionOffset)
|
||||
{
|
||||
}
|
||||
|
||||
OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset):
|
||||
Task(next),
|
||||
promise(promise),
|
||||
instructionOffset(instructionOffset)
|
||||
{ }
|
||||
|
||||
void OffsetTask::run(Context* con) {
|
||||
void OffsetTask::run(Context* con)
|
||||
{
|
||||
if (promise->resolved()) {
|
||||
updateOffset
|
||||
(con->s, con->result + instructionOffset->value(), promise->value());
|
||||
updateOffset(
|
||||
con->s, con->result + instructionOffset->value(), promise->value());
|
||||
} else {
|
||||
new (promise->listen(sizeof(OffsetListener)))
|
||||
OffsetListener(con->s, con->result + instructionOffset->value());
|
||||
OffsetListener(con->s, con->result + instructionOffset->value());
|
||||
}
|
||||
}
|
||||
|
||||
void appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset) {
|
||||
con->tasks = new(con->zone) OffsetTask(con->tasks, promise, instructionOffset);
|
||||
void appendOffsetTask(Context* con,
|
||||
Promise* promise,
|
||||
Promise* instructionOffset)
|
||||
{
|
||||
con->tasks = new (con->zone)
|
||||
OffsetTask(con->tasks, promise, instructionOffset);
|
||||
}
|
||||
|
||||
bool bounded(int right, int left, int32_t v) {
|
||||
bool bounded(int right, int left, int32_t v)
|
||||
{
|
||||
return ((v << left) >> left) == v and ((v >> right) << right) == v;
|
||||
}
|
||||
|
||||
void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value) {
|
||||
void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value)
|
||||
{
|
||||
// ARM's PC is two words ahead, and branches drop the bottom 2 bits.
|
||||
int32_t v = (reinterpret_cast<uint8_t*>(value) - (instruction + 8)) >> 2;
|
||||
|
||||
@ -92,30 +105,39 @@ void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value) {
|
||||
return instruction + 4;
|
||||
}
|
||||
|
||||
ConstantPoolEntry::ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next,
|
||||
Promise* callOffset):
|
||||
con(con), constant(constant), next(next), callOffset(callOffset),
|
||||
address(0)
|
||||
{ }
|
||||
ConstantPoolEntry::ConstantPoolEntry(Context* con,
|
||||
Promise* constant,
|
||||
ConstantPoolEntry* next,
|
||||
Promise* callOffset)
|
||||
: con(con),
|
||||
constant(constant),
|
||||
next(next),
|
||||
callOffset(callOffset),
|
||||
address(0)
|
||||
{
|
||||
}
|
||||
|
||||
int64_t ConstantPoolEntry::value() {
|
||||
int64_t ConstantPoolEntry::value()
|
||||
{
|
||||
assertT(con, resolved());
|
||||
|
||||
return reinterpret_cast<int64_t>(address);
|
||||
}
|
||||
|
||||
bool ConstantPoolEntry::resolved() {
|
||||
bool ConstantPoolEntry::resolved()
|
||||
{
|
||||
return address != 0;
|
||||
}
|
||||
|
||||
ConstantPoolListener::ConstantPoolListener(vm::System* s, vm::target_uintptr_t* address,
|
||||
uint8_t* returnAddress):
|
||||
s(s),
|
||||
address(address),
|
||||
returnAddress(returnAddress)
|
||||
{ }
|
||||
ConstantPoolListener::ConstantPoolListener(vm::System* s,
|
||||
vm::target_uintptr_t* address,
|
||||
uint8_t* returnAddress)
|
||||
: s(s), address(address), returnAddress(returnAddress)
|
||||
{
|
||||
}
|
||||
|
||||
bool ConstantPoolListener::resolve(int64_t value, void** location) {
|
||||
bool ConstantPoolListener::resolve(int64_t value, void** location)
|
||||
{
|
||||
*address = value;
|
||||
if (location) {
|
||||
*location = returnAddress ? static_cast<void*>(returnAddress) : address;
|
||||
@ -123,32 +145,49 @@ bool ConstantPoolListener::resolve(int64_t value, void** location) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PoolOffset::PoolOffset(MyBlock* block, ConstantPoolEntry* entry, unsigned offset):
|
||||
block(block), entry(entry), next(0), offset(offset)
|
||||
{ }
|
||||
PoolOffset::PoolOffset(MyBlock* block,
|
||||
ConstantPoolEntry* entry,
|
||||
unsigned offset)
|
||||
: block(block), entry(entry), next(0), offset(offset)
|
||||
{
|
||||
}
|
||||
|
||||
PoolEvent::PoolEvent(PoolOffset* poolOffsetHead, PoolOffset* poolOffsetTail,
|
||||
unsigned offset):
|
||||
poolOffsetHead(poolOffsetHead), poolOffsetTail(poolOffsetTail), next(0),
|
||||
offset(offset)
|
||||
{ }
|
||||
PoolEvent::PoolEvent(PoolOffset* poolOffsetHead,
|
||||
PoolOffset* poolOffsetTail,
|
||||
unsigned offset)
|
||||
: poolOffsetHead(poolOffsetHead),
|
||||
poolOffsetTail(poolOffsetTail),
|
||||
next(0),
|
||||
offset(offset)
|
||||
{
|
||||
}
|
||||
|
||||
void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset) {
|
||||
void appendConstantPoolEntry(Context* con,
|
||||
Promise* constant,
|
||||
Promise* callOffset)
|
||||
{
|
||||
if (constant->resolved()) {
|
||||
// make a copy, since the original might be allocated on the
|
||||
// stack, and we need our copy to live until assembly is complete
|
||||
constant = new(con->zone) ResolvedPromise(constant->value());
|
||||
constant = new (con->zone) ResolvedPromise(constant->value());
|
||||
}
|
||||
|
||||
con->constantPool = new(con->zone) ConstantPoolEntry(con, constant, con->constantPool, callOffset);
|
||||
con->constantPool = new (con->zone)
|
||||
ConstantPoolEntry(con, constant, con->constantPool, callOffset);
|
||||
|
||||
++ con->constantPoolCount;
|
||||
++con->constantPoolCount;
|
||||
|
||||
PoolOffset* o = new(con->zone) PoolOffset(con->lastBlock, con->constantPool, con->code.length() - con->lastBlock->offset);
|
||||
PoolOffset* o = new (con->zone)
|
||||
PoolOffset(con->lastBlock,
|
||||
con->constantPool,
|
||||
con->code.length() - con->lastBlock->offset);
|
||||
|
||||
if (DebugPool) {
|
||||
fprintf(stderr, "add pool offset %p %d to block %p\n",
|
||||
o, o->offset, con->lastBlock);
|
||||
fprintf(stderr,
|
||||
"add pool offset %p %d to block %p\n",
|
||||
o,
|
||||
o->offset,
|
||||
con->lastBlock);
|
||||
}
|
||||
|
||||
if (con->lastBlock->poolOffsetTail) {
|
||||
@ -159,10 +198,13 @@ void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffse
|
||||
con->lastBlock->poolOffsetTail = o;
|
||||
}
|
||||
|
||||
void appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head,
|
||||
PoolOffset* tail)
|
||||
void appendPoolEvent(Context* con,
|
||||
MyBlock* b,
|
||||
unsigned offset,
|
||||
PoolOffset* head,
|
||||
PoolOffset* tail)
|
||||
{
|
||||
PoolEvent* e = new(con->zone) PoolEvent(head, tail, offset);
|
||||
PoolEvent* e = new (con->zone) PoolEvent(head, tail, offset);
|
||||
|
||||
if (b->poolEventTail) {
|
||||
b->poolEventTail->next = e;
|
||||
@ -172,6 +214,6 @@ void appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head
|
||||
b->poolEventTail = e;
|
||||
}
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -31,19 +31,21 @@ const int32_t PoolOffsetMask = 0xFFF;
|
||||
|
||||
class Task {
|
||||
public:
|
||||
Task(Task* next): next(next) { }
|
||||
Task(Task* next) : next(next)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void run(Context* con) = 0;
|
||||
|
||||
Task* next;
|
||||
};
|
||||
|
||||
class OffsetPromise: public Promise {
|
||||
class OffsetPromise : public Promise {
|
||||
public:
|
||||
OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace);
|
||||
|
||||
virtual bool resolved();
|
||||
|
||||
|
||||
virtual int64_t value();
|
||||
|
||||
Context* con;
|
||||
@ -54,7 +56,7 @@ class OffsetPromise: public Promise {
|
||||
|
||||
Promise* offsetPromise(Context* con, bool forTrace = false);
|
||||
|
||||
class OffsetListener: public Promise::Listener {
|
||||
class OffsetListener : public Promise::Listener {
|
||||
public:
|
||||
OffsetListener(vm::System* s, uint8_t* instruction);
|
||||
|
||||
@ -64,7 +66,7 @@ class OffsetListener: public Promise::Listener {
|
||||
uint8_t* instruction;
|
||||
};
|
||||
|
||||
class OffsetTask: public Task {
|
||||
class OffsetTask : public Task {
|
||||
public:
|
||||
OffsetTask(Task* next, Promise* promise, Promise* instructionOffset);
|
||||
|
||||
@ -74,13 +76,17 @@ class OffsetTask: public Task {
|
||||
Promise* instructionOffset;
|
||||
};
|
||||
|
||||
void appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset);
|
||||
void appendOffsetTask(Context* con,
|
||||
Promise* promise,
|
||||
Promise* instructionOffset);
|
||||
|
||||
void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value);
|
||||
|
||||
class ConstantPoolEntry: public Promise {
|
||||
class ConstantPoolEntry : public Promise {
|
||||
public:
|
||||
ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next,
|
||||
ConstantPoolEntry(Context* con,
|
||||
Promise* constant,
|
||||
ConstantPoolEntry* next,
|
||||
Promise* callOffset);
|
||||
|
||||
virtual int64_t value();
|
||||
@ -95,9 +101,10 @@ class ConstantPoolEntry: public Promise {
|
||||
unsigned constantPoolCount;
|
||||
};
|
||||
|
||||
class ConstantPoolListener: public Promise::Listener {
|
||||
class ConstantPoolListener : public Promise::Listener {
|
||||
public:
|
||||
ConstantPoolListener(vm::System* s, vm::target_uintptr_t* address,
|
||||
ConstantPoolListener(vm::System* s,
|
||||
vm::target_uintptr_t* address,
|
||||
uint8_t* returnAddress);
|
||||
|
||||
virtual bool resolve(int64_t value, void** location);
|
||||
@ -119,7 +126,8 @@ class PoolOffset {
|
||||
|
||||
class PoolEvent {
|
||||
public:
|
||||
PoolEvent(PoolOffset* poolOffsetHead, PoolOffset* poolOffsetTail,
|
||||
PoolEvent(PoolOffset* poolOffsetHead,
|
||||
PoolOffset* poolOffsetTail,
|
||||
unsigned offset);
|
||||
|
||||
PoolOffset* poolOffsetHead;
|
||||
@ -128,13 +136,18 @@ class PoolEvent {
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
void appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset);
|
||||
void appendConstantPoolEntry(Context* con,
|
||||
Promise* constant,
|
||||
Promise* callOffset);
|
||||
|
||||
void appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head,
|
||||
PoolOffset* tail);
|
||||
void appendPoolEvent(Context* con,
|
||||
MyBlock* b,
|
||||
unsigned offset,
|
||||
PoolOffset* head,
|
||||
PoolOffset* tail);
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_PROMISE_H
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_PROMISE_H
|
||||
|
@ -21,31 +21,32 @@ namespace arm {
|
||||
using namespace util;
|
||||
|
||||
unsigned index(ArchitectureContext*,
|
||||
lir::BinaryOperation operation,
|
||||
lir::OperandType operand1,
|
||||
lir::OperandType operand2)
|
||||
lir::BinaryOperation operation,
|
||||
lir::OperandType operand1,
|
||||
lir::OperandType operand2)
|
||||
{
|
||||
return operation
|
||||
+ (lir::BinaryOperationCount * operand1)
|
||||
+ (lir::BinaryOperationCount * lir::OperandTypeCount * operand2);
|
||||
return operation + (lir::BinaryOperationCount * operand1)
|
||||
+ (lir::BinaryOperationCount * lir::OperandTypeCount * operand2);
|
||||
}
|
||||
|
||||
unsigned index(ArchitectureContext* con UNUSED,
|
||||
lir::TernaryOperation operation,
|
||||
lir::OperandType operand1)
|
||||
lir::TernaryOperation operation,
|
||||
lir::OperandType operand1)
|
||||
{
|
||||
assertT(con, not isBranch(operation));
|
||||
|
||||
return operation + (lir::NonBranchTernaryOperationCount * operand1);
|
||||
}
|
||||
|
||||
unsigned branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1,
|
||||
lir::OperandType operand2)
|
||||
unsigned branchIndex(ArchitectureContext* con UNUSED,
|
||||
lir::OperandType operand1,
|
||||
lir::OperandType operand2)
|
||||
{
|
||||
return operand1 + (lir::OperandTypeCount * operand2);
|
||||
}
|
||||
|
||||
void populateTables(ArchitectureContext* con) {
|
||||
void populateTables(ArchitectureContext* con)
|
||||
{
|
||||
const lir::OperandType C = lir::ConstantOperand;
|
||||
const lir::OperandType A = lir::AddressOperand;
|
||||
const lir::OperandType R = lir::RegisterOperand;
|
||||
@ -136,6 +137,6 @@ void populateTables(ArchitectureContext* con) {
|
||||
bro[branchIndex(con, R, M)] = CAST_BRANCH(branchRM);
|
||||
}
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -24,21 +24,22 @@ namespace codegen {
|
||||
namespace arm {
|
||||
|
||||
unsigned index(ArchitectureContext*,
|
||||
lir::BinaryOperation operation,
|
||||
lir::OperandType operand1,
|
||||
lir::OperandType operand2);
|
||||
lir::BinaryOperation operation,
|
||||
lir::OperandType operand1,
|
||||
lir::OperandType operand2);
|
||||
|
||||
unsigned index(ArchitectureContext* con UNUSED,
|
||||
lir::TernaryOperation operation,
|
||||
lir::OperandType operand1);
|
||||
lir::TernaryOperation operation,
|
||||
lir::OperandType operand1);
|
||||
|
||||
unsigned branchIndex(ArchitectureContext* con UNUSED, lir::OperandType operand1,
|
||||
lir::OperandType operand2);
|
||||
unsigned branchIndex(ArchitectureContext* con UNUSED,
|
||||
lir::OperandType operand1,
|
||||
lir::OperandType operand2);
|
||||
|
||||
void populateTables(ArchitectureContext* con);
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,51 +25,87 @@ class Context;
|
||||
|
||||
// shortcut functions
|
||||
|
||||
inline int newTemp(Context* con) {
|
||||
inline int newTemp(Context* con)
|
||||
{
|
||||
return con->client->acquireTemporary(GPR_MASK);
|
||||
}
|
||||
|
||||
inline int newTemp(Context* con, unsigned mask) {
|
||||
inline int newTemp(Context* con, unsigned mask)
|
||||
{
|
||||
return con->client->acquireTemporary(mask);
|
||||
}
|
||||
|
||||
inline void freeTemp(Context* con, int r) {
|
||||
inline void freeTemp(Context* con, int r)
|
||||
{
|
||||
con->client->releaseTemporary(r);
|
||||
}
|
||||
|
||||
inline int64_t getValue(lir::Constant* con) {
|
||||
inline int64_t getValue(lir::Constant* con)
|
||||
{
|
||||
return con->value->value();
|
||||
}
|
||||
|
||||
inline lir::Register makeTemp(Context* con) {
|
||||
inline lir::Register makeTemp(Context* con)
|
||||
{
|
||||
lir::Register tmp(newTemp(con));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline lir::Register makeTemp64(Context* con) {
|
||||
inline lir::Register makeTemp64(Context* con)
|
||||
{
|
||||
lir::Register tmp(newTemp(con), newTemp(con));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline void freeTemp(Context* con, const lir::Register& tmp) {
|
||||
if (tmp.low != lir::NoRegister) freeTemp(con, tmp.low);
|
||||
if (tmp.high != lir::NoRegister) freeTemp(con, tmp.high);
|
||||
inline void freeTemp(Context* con, const lir::Register& tmp)
|
||||
{
|
||||
if (tmp.low != lir::NoRegister)
|
||||
freeTemp(con, tmp.low);
|
||||
if (tmp.high != lir::NoRegister)
|
||||
freeTemp(con, tmp.high);
|
||||
}
|
||||
|
||||
void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void shiftLeftR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void moveRR(Context* con, unsigned srcSize, lir::Register* src,
|
||||
unsigned dstSize, lir::Register* dst);
|
||||
void moveRR(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Register* src,
|
||||
unsigned dstSize,
|
||||
lir::Register* dst);
|
||||
|
||||
void shiftLeftC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t);
|
||||
void shiftLeftC(Context* con,
|
||||
unsigned size UNUSED,
|
||||
lir::Constant* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void shiftRightR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void shiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t);
|
||||
void shiftRightC(Context* con,
|
||||
unsigned size UNUSED,
|
||||
lir::Constant* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void unsignedShiftRightR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void unsignedShiftRightC(Context* con, unsigned size UNUSED, lir::Constant* a, lir::Register* b, lir::Register* t);
|
||||
void unsignedShiftRightC(Context* con,
|
||||
unsigned size UNUSED,
|
||||
lir::Constant* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
bool needJump(MyBlock* b);
|
||||
|
||||
@ -79,142 +115,297 @@ void resolve(MyBlock* b);
|
||||
|
||||
void jumpR(Context* con, unsigned size UNUSED, lir::Register* target);
|
||||
|
||||
void swapRR(Context* con, unsigned aSize, lir::Register* a,
|
||||
unsigned bSize, lir::Register* b);
|
||||
void swapRR(Context* con,
|
||||
unsigned aSize,
|
||||
lir::Register* a,
|
||||
unsigned bSize,
|
||||
lir::Register* b);
|
||||
|
||||
void moveRR(Context* con, unsigned srcSize, lir::Register* src,
|
||||
unsigned dstSize, lir::Register* dst);
|
||||
void moveRR(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Register* src,
|
||||
unsigned dstSize,
|
||||
lir::Register* dst);
|
||||
|
||||
void moveZRR(Context* con, unsigned srcSize, lir::Register* src,
|
||||
unsigned, lir::Register* dst);
|
||||
void moveZRR(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Register* src,
|
||||
unsigned,
|
||||
lir::Register* dst);
|
||||
|
||||
void moveCR(Context* con, unsigned size, lir::Constant* src,
|
||||
unsigned, lir::Register* dst);
|
||||
void moveCR(Context* con,
|
||||
unsigned size,
|
||||
lir::Constant* src,
|
||||
unsigned,
|
||||
lir::Register* dst);
|
||||
|
||||
void moveCR2(Context* con, unsigned size, lir::Constant* src,
|
||||
lir::Register* dst, Promise* callOffset);
|
||||
void moveCR2(Context* con,
|
||||
unsigned size,
|
||||
lir::Constant* src,
|
||||
lir::Register* dst,
|
||||
Promise* callOffset);
|
||||
|
||||
void moveCR(Context* con, unsigned size, lir::Constant* src,
|
||||
unsigned, lir::Register* dst);
|
||||
void moveCR(Context* con,
|
||||
unsigned size,
|
||||
lir::Constant* src,
|
||||
unsigned,
|
||||
lir::Register* dst);
|
||||
|
||||
void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void addR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void subR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void addC(Context* con, unsigned size, lir::Constant* a,
|
||||
lir::Register* b, lir::Register* dst);
|
||||
void addC(Context* con,
|
||||
unsigned size,
|
||||
lir::Constant* a,
|
||||
lir::Register* b,
|
||||
lir::Register* dst);
|
||||
|
||||
void subC(Context* con, unsigned size, lir::Constant* a,
|
||||
lir::Register* b, lir::Register* dst);
|
||||
void subC(Context* con,
|
||||
unsigned size,
|
||||
lir::Constant* a,
|
||||
lir::Register* b,
|
||||
lir::Register* dst);
|
||||
|
||||
void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void multiplyR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void floatAbsoluteRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
||||
void floatAbsoluteRR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
unsigned,
|
||||
lir::Register* b);
|
||||
|
||||
void floatNegateRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
||||
void floatNegateRR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
unsigned,
|
||||
lir::Register* b);
|
||||
|
||||
void float2FloatRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
||||
void float2FloatRR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
unsigned,
|
||||
lir::Register* b);
|
||||
|
||||
void float2IntRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
||||
void float2IntRR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
unsigned,
|
||||
lir::Register* b);
|
||||
|
||||
void int2FloatRR(Context* con, unsigned, lir::Register* a, unsigned size, lir::Register* b);
|
||||
void int2FloatRR(Context* con,
|
||||
unsigned,
|
||||
lir::Register* a,
|
||||
unsigned size,
|
||||
lir::Register* b);
|
||||
|
||||
void floatSqrtRR(Context* con, unsigned size, lir::Register* a, unsigned, lir::Register* b);
|
||||
void floatSqrtRR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
unsigned,
|
||||
lir::Register* b);
|
||||
|
||||
void floatAddR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void floatAddR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void floatSubtractR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void floatSubtractR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void floatMultiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void floatMultiplyR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
void floatDivideR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
|
||||
void floatDivideR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* t);
|
||||
|
||||
int normalize(Context* con, int offset, int index, unsigned scale,
|
||||
bool* preserveIndex, bool* release);
|
||||
int normalize(Context* con,
|
||||
int offset,
|
||||
int index,
|
||||
unsigned scale,
|
||||
bool* preserveIndex,
|
||||
bool* release);
|
||||
|
||||
void store(Context* con, unsigned size, lir::Register* src,
|
||||
int base, int offset, int index, unsigned scale, bool preserveIndex);
|
||||
void store(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* src,
|
||||
int base,
|
||||
int offset,
|
||||
int index,
|
||||
unsigned scale,
|
||||
bool preserveIndex);
|
||||
|
||||
void moveRM(Context* con, unsigned srcSize, lir::Register* src,
|
||||
unsigned dstSize UNUSED, lir::Memory* dst);
|
||||
void moveRM(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Register* src,
|
||||
unsigned dstSize UNUSED,
|
||||
lir::Memory* dst);
|
||||
|
||||
void load(Context* con, unsigned srcSize, int base, int offset, int index,
|
||||
unsigned scale, unsigned dstSize, lir::Register* dst,
|
||||
bool preserveIndex, bool signExtend);
|
||||
void load(Context* con,
|
||||
unsigned srcSize,
|
||||
int base,
|
||||
int offset,
|
||||
int index,
|
||||
unsigned scale,
|
||||
unsigned dstSize,
|
||||
lir::Register* dst,
|
||||
bool preserveIndex,
|
||||
bool signExtend);
|
||||
|
||||
void moveMR(Context* con, unsigned srcSize, lir::Memory* src,
|
||||
unsigned dstSize, lir::Register* dst);
|
||||
void moveMR(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Memory* src,
|
||||
unsigned dstSize,
|
||||
lir::Register* dst);
|
||||
|
||||
void moveZMR(Context* con, unsigned srcSize, lir::Memory* src,
|
||||
unsigned dstSize, lir::Register* dst);
|
||||
void moveZMR(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Memory* src,
|
||||
unsigned dstSize,
|
||||
lir::Register* dst);
|
||||
|
||||
void andR(Context* con, unsigned size, lir::Register* a,
|
||||
lir::Register* b, lir::Register* dst);
|
||||
void andR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* dst);
|
||||
|
||||
void andC(Context* con, unsigned size, lir::Constant* a,
|
||||
lir::Register* b, lir::Register* dst);
|
||||
void andC(Context* con,
|
||||
unsigned size,
|
||||
lir::Constant* a,
|
||||
lir::Register* b,
|
||||
lir::Register* dst);
|
||||
|
||||
void orR(Context* con, unsigned size, lir::Register* a,
|
||||
lir::Register* b, lir::Register* dst);
|
||||
void orR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* dst);
|
||||
|
||||
void xorR(Context* con, unsigned size, lir::Register* a,
|
||||
lir::Register* b, lir::Register* dst);
|
||||
void xorR(Context* con,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Register* dst);
|
||||
|
||||
void moveAR2(Context* con, unsigned srcSize, lir::Address* src,
|
||||
unsigned dstSize, lir::Register* dst);
|
||||
void moveAR2(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Address* src,
|
||||
unsigned dstSize,
|
||||
lir::Register* dst);
|
||||
|
||||
void moveAR(Context* con, unsigned srcSize, lir::Address* src,
|
||||
unsigned dstSize, lir::Register* dst);
|
||||
void moveAR(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Address* src,
|
||||
unsigned dstSize,
|
||||
lir::Register* dst);
|
||||
|
||||
void compareRR(Context* con, unsigned aSize, lir::Register* a,
|
||||
unsigned bSize UNUSED, lir::Register* b);
|
||||
void compareRR(Context* con,
|
||||
unsigned aSize,
|
||||
lir::Register* a,
|
||||
unsigned bSize UNUSED,
|
||||
lir::Register* b);
|
||||
|
||||
void compareCR(Context* con, unsigned aSize, lir::Constant* a,
|
||||
unsigned bSize, lir::Register* b);
|
||||
void compareCR(Context* con,
|
||||
unsigned aSize,
|
||||
lir::Constant* a,
|
||||
unsigned bSize,
|
||||
lir::Register* b);
|
||||
|
||||
void compareCM(Context* con, unsigned aSize, lir::Constant* a,
|
||||
unsigned bSize, lir::Memory* b);
|
||||
void compareCM(Context* con,
|
||||
unsigned aSize,
|
||||
lir::Constant* a,
|
||||
unsigned bSize,
|
||||
lir::Memory* b);
|
||||
|
||||
void compareRM(Context* con, unsigned aSize, lir::Register* a,
|
||||
unsigned bSize, lir::Memory* b);
|
||||
void compareRM(Context* con,
|
||||
unsigned aSize,
|
||||
lir::Register* a,
|
||||
unsigned bSize,
|
||||
lir::Memory* b);
|
||||
|
||||
int32_t
|
||||
branch(Context* con, lir::TernaryOperation op);
|
||||
int32_t branch(Context* con, lir::TernaryOperation op);
|
||||
|
||||
void conditional(Context* con, int32_t branch, lir::Constant* target);
|
||||
|
||||
void branch(Context* con, lir::TernaryOperation op, lir::Constant* target);
|
||||
|
||||
void branchLong(Context* con, lir::TernaryOperation op, lir::Operand* al,
|
||||
lir::Operand* ah, lir::Operand* bl,
|
||||
lir::Operand* bh, lir::Constant* target,
|
||||
BinaryOperationType compareSigned,
|
||||
BinaryOperationType compareUnsigned);
|
||||
void branchLong(Context* con,
|
||||
lir::TernaryOperation op,
|
||||
lir::Operand* al,
|
||||
lir::Operand* ah,
|
||||
lir::Operand* bl,
|
||||
lir::Operand* bh,
|
||||
lir::Constant* target,
|
||||
BinaryOperationType compareSigned,
|
||||
BinaryOperationType compareUnsigned);
|
||||
|
||||
void branchRR(Context* con, lir::TernaryOperation op, unsigned size,
|
||||
lir::Register* a, lir::Register* b,
|
||||
lir::Constant* target);
|
||||
void branchRR(Context* con,
|
||||
lir::TernaryOperation op,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Register* b,
|
||||
lir::Constant* target);
|
||||
|
||||
void branchCR(Context* con, lir::TernaryOperation op, unsigned size,
|
||||
lir::Constant* a, lir::Register* b,
|
||||
lir::Constant* target);
|
||||
void branchCR(Context* con,
|
||||
lir::TernaryOperation op,
|
||||
unsigned size,
|
||||
lir::Constant* a,
|
||||
lir::Register* b,
|
||||
lir::Constant* target);
|
||||
|
||||
void branchRM(Context* con, lir::TernaryOperation op, unsigned size,
|
||||
lir::Register* a, lir::Memory* b,
|
||||
lir::Constant* target);
|
||||
void branchRM(Context* con,
|
||||
lir::TernaryOperation op,
|
||||
unsigned size,
|
||||
lir::Register* a,
|
||||
lir::Memory* b,
|
||||
lir::Constant* target);
|
||||
|
||||
void branchCM(Context* con, lir::TernaryOperation op, unsigned size,
|
||||
lir::Constant* a, lir::Memory* b,
|
||||
lir::Constant* target);
|
||||
void branchCM(Context* con,
|
||||
lir::TernaryOperation op,
|
||||
unsigned size,
|
||||
lir::Constant* a,
|
||||
lir::Memory* b,
|
||||
lir::Constant* target);
|
||||
|
||||
ShiftMaskPromise*
|
||||
shiftMaskPromise(Context* con, Promise* base, unsigned shift, int64_t mask);
|
||||
ShiftMaskPromise* shiftMaskPromise(Context* con,
|
||||
Promise* base,
|
||||
unsigned shift,
|
||||
int64_t mask);
|
||||
|
||||
void moveCM(Context* con, unsigned srcSize, lir::Constant* src,
|
||||
unsigned dstSize, lir::Memory* dst);
|
||||
void moveCM(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Constant* src,
|
||||
unsigned dstSize,
|
||||
lir::Memory* dst);
|
||||
|
||||
void negateRR(Context* con, unsigned srcSize, lir::Register* src,
|
||||
unsigned dstSize UNUSED, lir::Register* dst);
|
||||
void negateRR(Context* con,
|
||||
unsigned srcSize,
|
||||
lir::Register* src,
|
||||
unsigned dstSize UNUSED,
|
||||
lir::Register* dst);
|
||||
|
||||
void callR(Context* con, unsigned size UNUSED, lir::Register* target);
|
||||
|
||||
@ -236,9 +427,8 @@ void storeStoreBarrier(Context*);
|
||||
|
||||
void storeLoadBarrier(Context*);
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H
|
||||
|
@ -18,10 +18,9 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace arm {
|
||||
|
||||
|
||||
const uint64_t MASK_LO32 = 0xffffffff;
|
||||
const unsigned MASK_LO16 = 0xffff;
|
||||
const unsigned MASK_LO8 = 0xff;
|
||||
const unsigned MASK_LO8 = 0xff;
|
||||
|
||||
const int N_GPRS = 16;
|
||||
const int N_FPRS = 16;
|
||||
@ -31,22 +30,35 @@ const uint32_t FPR_MASK = 0xffff0000;
|
||||
const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32;
|
||||
const uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32;
|
||||
|
||||
inline bool isFpr(lir::Register* reg) {
|
||||
inline bool isFpr(lir::Register* reg)
|
||||
{
|
||||
return reg->low >= N_GPRS;
|
||||
}
|
||||
|
||||
inline int fpr64(int reg) { return reg - N_GPRS; }
|
||||
inline int fpr64(lir::Register* reg) { return fpr64(reg->low); }
|
||||
inline int fpr32(int reg) { return fpr64(reg) << 1; }
|
||||
inline int fpr32(lir::Register* reg) { return fpr64(reg) << 1; }
|
||||
inline int fpr64(int reg)
|
||||
{
|
||||
return reg - N_GPRS;
|
||||
}
|
||||
inline int fpr64(lir::Register* reg)
|
||||
{
|
||||
return fpr64(reg->low);
|
||||
}
|
||||
inline int fpr32(int reg)
|
||||
{
|
||||
return fpr64(reg) << 1;
|
||||
}
|
||||
inline int fpr32(lir::Register* reg)
|
||||
{
|
||||
return fpr64(reg) << 1;
|
||||
}
|
||||
|
||||
const int ThreadRegister = 8;
|
||||
const int StackRegister = 13;
|
||||
const int LinkRegister = 14;
|
||||
const int ProgramCounter = 15;
|
||||
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace arm
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H
|
||||
#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H
|
||||
|
@ -11,19 +11,19 @@
|
||||
#ifndef AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
||||
#define AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
||||
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
||||
class Multimethod {
|
||||
public:
|
||||
inline static unsigned index(lir::UnaryOperation operation, lir::OperandType operand) {
|
||||
public:
|
||||
inline static unsigned index(lir::UnaryOperation operation,
|
||||
lir::OperandType operand)
|
||||
{
|
||||
return operation + (lir::UnaryOperationCount * operand);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_TARGET_MULTIMETHOD_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,21 +16,29 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace x86 {
|
||||
|
||||
unsigned
|
||||
padding(AlignmentPadding* p, unsigned index, unsigned offset, AlignmentPadding* limit);
|
||||
unsigned padding(AlignmentPadding* p,
|
||||
unsigned index,
|
||||
unsigned offset,
|
||||
AlignmentPadding* limit);
|
||||
|
||||
MyBlock::MyBlock(unsigned offset):
|
||||
next(0), firstPadding(0), lastPadding(0), offset(offset), start(~0),
|
||||
size(0)
|
||||
{ }
|
||||
MyBlock::MyBlock(unsigned offset)
|
||||
: next(0),
|
||||
firstPadding(0),
|
||||
lastPadding(0),
|
||||
offset(offset),
|
||||
start(~0),
|
||||
size(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) {
|
||||
unsigned MyBlock::resolve(unsigned start, Assembler::Block* next)
|
||||
{
|
||||
this->start = start;
|
||||
this->next = static_cast<MyBlock*>(next);
|
||||
|
||||
return start + size + padding(firstPadding, start, offset, lastPadding);
|
||||
}
|
||||
|
||||
} // namespace x86
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace x86
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user