mirror of
https://github.com/corda/corda.git
synced 2025-01-21 03:55:00 +00:00
Merge pull request #289 from joshuawarner32/refactor-type-gen
Refactor type generator
This commit is contained in:
commit
a80ac91728
@ -11,7 +11,7 @@
|
||||
package avian;
|
||||
|
||||
public class Addendum {
|
||||
public Object pool;
|
||||
public Singleton pool;
|
||||
public Object annotationTable;
|
||||
public Object signature;
|
||||
}
|
||||
|
@ -21,6 +21,10 @@ public class ClassAddendum extends Addendum {
|
||||
* extended by that class.
|
||||
*/
|
||||
public int declaredMethodCount;
|
||||
|
||||
// Either a byte[] or a Pair, apparently...
|
||||
// TODO: make it monomorphic
|
||||
public Object enclosingClass;
|
||||
|
||||
public Object enclosingMethod;
|
||||
}
|
||||
|
5
classpath/avian/Code.java
Normal file
5
classpath/avian/Code.java
Normal file
@ -0,0 +1,5 @@
|
||||
package avian;
|
||||
|
||||
abstract class Code {
|
||||
// VM-visible fields in types.def
|
||||
}
|
@ -302,11 +302,11 @@ public class Continuations {
|
||||
}
|
||||
|
||||
private static class UnwindResult {
|
||||
public final Callback continuation;
|
||||
public final Continuation continuation;
|
||||
public final Object result;
|
||||
public final Throwable exception;
|
||||
|
||||
public UnwindResult(Callback continuation, Object result,
|
||||
public UnwindResult(Continuation continuation, Object result,
|
||||
Throwable exception)
|
||||
{
|
||||
this.continuation = continuation;
|
||||
|
@ -14,4 +14,6 @@ public abstract class Singleton {
|
||||
public static native int getInt(Object singleton, int offset);
|
||||
public static native long getLong(Object singleton, int offset);
|
||||
public static native Object getObject(Object singleton, int offset);
|
||||
|
||||
// Fields in types.def
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ public class VMClass {
|
||||
public short fixedSize;
|
||||
public byte arrayElementSize;
|
||||
public byte arrayDimensions;
|
||||
public VMClass arrayElementClass;
|
||||
public int runtimeDataIndex;
|
||||
public int[] objectMask;
|
||||
public byte[] name;
|
||||
@ -35,7 +36,7 @@ public class VMClass {
|
||||
*/
|
||||
public VMMethod[] methodTable;
|
||||
public ClassAddendum addendum;
|
||||
public Object staticTable;
|
||||
public Singleton staticTable;
|
||||
public ClassLoader loader;
|
||||
public byte[] source;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class VMMethod {
|
||||
public byte[] spec;
|
||||
public MethodAddendum addendum;
|
||||
public VMClass class_;
|
||||
public Object code;
|
||||
public Code code;
|
||||
|
||||
public boolean hasAnnotations() {
|
||||
return addendum != null && addendum.annotationTable != null;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -15,70 +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::object buffer_obj = reinterpret_cast<vm::object>(arguments[2]);
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&vm::byteArrayBody(t, buffer_obj, start_pos));
|
||||
avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
|
||||
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::object buffer_obj = reinterpret_cast<vm::object>(arguments[2]);
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&vm::byteArrayBody(t, buffer_obj, start_pos));
|
||||
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) {
|
||||
@ -105,8 +122,8 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
throwNew(e, "java/net/UnknownHostException", 0);
|
||||
return 0;
|
||||
} else {
|
||||
int address = ntohl
|
||||
(reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
|
||||
int address = ntohl(
|
||||
reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
|
||||
|
||||
freeaddrinfo(result);
|
||||
return address;
|
||||
@ -117,4 +134,3 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,10 +1052,11 @@ 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;
|
||||
@ -1065,9 +1084,8 @@ Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv *, jclass,
|
||||
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,8 +16,7 @@
|
||||
#include "jni-util.h"
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_Inflater_make
|
||||
(JNIEnv* e, jclass, jboolean nowrap)
|
||||
Java_java_util_zip_Inflater_make(JNIEnv* e, jclass, jboolean nowrap)
|
||||
{
|
||||
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
||||
if (s == 0) {
|
||||
@ -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,11 +45,16 @@ 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);
|
||||
|
||||
@ -75,10 +79,9 @@ Java_java_util_zip_Inflater_inflate
|
||||
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,8 +92,10 @@ Java_java_util_zip_Inflater_inflate
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_Deflater_make
|
||||
(JNIEnv* e, jclass, jboolean nowrap, jint level)
|
||||
Java_java_util_zip_Deflater_make(JNIEnv* e,
|
||||
jclass,
|
||||
jboolean nowrap,
|
||||
jint level)
|
||||
{
|
||||
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
||||
if (s == 0) {
|
||||
@ -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,11 +124,17 @@ Java_java_util_zip_Deflater_dispose(JNIEnv*, jclass, jlong peer)
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_util_zip_Deflater_deflate
|
||||
(JNIEnv* e, jclass, jlong peer,
|
||||
jbyteArray input, jint inputOffset, jint inputLength,
|
||||
jbyteArray output, jint outputOffset, jint outputLength,
|
||||
jboolean finish, jintArray results)
|
||||
Java_java_util_zip_Deflater_deflate(JNIEnv* e,
|
||||
jclass,
|
||||
jlong peer,
|
||||
jbyteArray input,
|
||||
jint inputOffset,
|
||||
jint inputLength,
|
||||
jbyteArray output,
|
||||
jint outputOffset,
|
||||
jint outputLength,
|
||||
jboolean finish,
|
||||
jintArray results)
|
||||
{
|
||||
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||
|
||||
@ -148,10 +159,9 @@ Java_java_util_zip_Deflater_deflate
|
||||
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;
|
||||
|
@ -171,8 +171,8 @@ public final class Class <T> implements Type, AnnotatedElement {
|
||||
return SystemClassLoader.getClass(Classes.primitiveClass('D'));
|
||||
}
|
||||
|
||||
if (vmClass.staticTable == null) throw new AssertionError();
|
||||
return SystemClassLoader.getClass((VMClass) vmClass.staticTable);
|
||||
if (vmClass.arrayElementClass == null) throw new AssertionError();
|
||||
return SystemClassLoader.getClass((VMClass) vmClass.arrayElementClass);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -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) {
|
||||
@ -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 planSource(lir::BinaryOperation op,
|
||||
unsigned aSize,
|
||||
OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
bool* thunk) = 0;
|
||||
|
||||
virtual void planDestination
|
||||
(lir::BinaryOperation op,
|
||||
unsigned aSize, const OperandMask& aMask,
|
||||
unsigned bSize, OperandMask& bMask) = 0;
|
||||
virtual void planDestination(lir::BinaryOperation op,
|
||||
unsigned aSize,
|
||||
const OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
OperandMask& bMask) = 0;
|
||||
|
||||
virtual void planMove
|
||||
(unsigned size, OperandMask& src,
|
||||
OperandMask& tmp,
|
||||
const OperandMask& dst) = 0;
|
||||
virtual void planMove(unsigned size,
|
||||
OperandMask& src,
|
||||
OperandMask& tmp,
|
||||
const OperandMask& dst) = 0;
|
||||
|
||||
virtual void planSource
|
||||
(lir::TernaryOperation op,
|
||||
unsigned aSize, OperandMask& aMask,
|
||||
unsigned bSize, OperandMask& bMask,
|
||||
unsigned cSize, bool* thunk) = 0;
|
||||
virtual void planSource(lir::TernaryOperation op,
|
||||
unsigned aSize,
|
||||
OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
OperandMask& bMask,
|
||||
unsigned cSize,
|
||||
bool* thunk) = 0;
|
||||
|
||||
virtual void planDestination
|
||||
(lir::TernaryOperation op,
|
||||
unsigned aSize, const OperandMask& aMask,
|
||||
unsigned bSize, const OperandMask& bMask,
|
||||
unsigned cSize, OperandMask& cMask) = 0;
|
||||
virtual void planDestination(lir::TernaryOperation op,
|
||||
unsigned aSize,
|
||||
const OperandMask& aMask,
|
||||
unsigned bSize,
|
||||
const OperandMask& bMask,
|
||||
unsigned cSize,
|
||||
OperandMask& cMask) = 0;
|
||||
|
||||
virtual Assembler* makeAssembler(util::Allocator*, vm::Zone*) = 0;
|
||||
virtual Assembler* makeAssembler(util::Allocator*, vm::Zone*) = 0;
|
||||
|
||||
virtual void acquire() = 0;
|
||||
virtual void release() = 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
|
||||
#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
|
||||
#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,
|
||||
@ -74,6 +67,13 @@ class Heap : public avian::util::Allocator {
|
||||
virtual void mark(void* p, unsigned offset, unsigned count) = 0;
|
||||
virtual void pad(void* p) = 0;
|
||||
virtual void* follow(void* p) = 0;
|
||||
|
||||
template <class T>
|
||||
T* follow(T* p)
|
||||
{
|
||||
return static_cast<T*>(follow(static_cast<void*>(p)));
|
||||
}
|
||||
|
||||
virtual void postVisit() = 0;
|
||||
virtual Status status(void* p) = 0;
|
||||
virtual CollectionType collectionType() = 0;
|
||||
@ -83,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,47 +142,46 @@ 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);
|
||||
}
|
||||
|
||||
// #ifdef NDEBUG
|
||||
|
||||
// # define assert(a, b)
|
||||
// # define assertT(a, b)
|
||||
// # define vm_assert(a, b)
|
||||
|
||||
// #else // not NDEBUG
|
||||
|
||||
// inline void
|
||||
// assert(System* s, bool v)
|
||||
// assertT(System* s, bool v)
|
||||
// {
|
||||
// expect(s, v);
|
||||
// }
|
||||
|
||||
// # define vm_assert(a, b) vm::assert(a, b)
|
||||
// # define vm_assert(a, b) vm::assertT(a, b)
|
||||
|
||||
// #endif // not NDEBUG
|
||||
|
||||
AVIAN_EXPORT System*
|
||||
makeSystem();
|
||||
AVIAN_EXPORT System* makeSystem();
|
||||
|
||||
} // namespace vm
|
||||
} // 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,29 +28,32 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define assert(t, v)
|
||||
#define assertT(t, v)
|
||||
#else
|
||||
template<class T>
|
||||
inline void assert(T t, bool v) {
|
||||
template <class T>
|
||||
inline void assertT(T t, bool v)
|
||||
{
|
||||
expect(t, v);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace util
|
||||
} // namespace avian
|
||||
} // namespace util
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_UTIL_ABORT_H
|
||||
#endif // AVIAN_UTIL_ABORT_H
|
||||
|
@ -17,18 +17,21 @@ namespace util {
|
||||
class Arg;
|
||||
|
||||
class ArgParser {
|
||||
public:
|
||||
Arg* first;
|
||||
Arg** last;
|
||||
|
||||
public:
|
||||
ArgParser();
|
||||
|
||||
bool parse(int ac, const char* const* av);
|
||||
void printUsage(const char* exe);
|
||||
|
||||
private:
|
||||
friend class Arg;
|
||||
|
||||
Arg* first;
|
||||
Arg** last;
|
||||
};
|
||||
|
||||
class Arg {
|
||||
public:
|
||||
public:
|
||||
Arg* next;
|
||||
bool required;
|
||||
const char* name;
|
||||
@ -39,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
|
||||
#endif // AVIAN_UTIL_ARG_PARSER_H
|
||||
|
57
include/avian/util/hash.h
Normal file
57
include/avian/util/hash.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* Copyright (c) 2008-2014, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#ifndef AVIAN_UTIL_HASH_H
|
||||
#define AVIAN_UTIL_HASH_H
|
||||
|
||||
#include "slice.h"
|
||||
|
||||
namespace avian {
|
||||
namespace util {
|
||||
|
||||
inline uint32_t hash(const char* s)
|
||||
{
|
||||
uint32_t h = 0;
|
||||
for (unsigned i = 0; s[i]; ++i) {
|
||||
h = (h * 31) + s[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
inline uint32_t hash(Slice<const uint8_t> data)
|
||||
{
|
||||
const uint8_t* s = data.begin();
|
||||
uint32_t h = 0;
|
||||
for (size_t i = 0; i < data.count; ++i) {
|
||||
h = (h * 31) + s[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
inline uint32_t hash(Slice<const int8_t> data)
|
||||
{
|
||||
return hash(Slice<const uint8_t>(
|
||||
reinterpret_cast<const uint8_t*>(data.begin()), data.count));
|
||||
}
|
||||
|
||||
inline uint32_t hash(Slice<const uint16_t> data)
|
||||
{
|
||||
const uint16_t* s = data.begin();
|
||||
uint32_t h = 0;
|
||||
for (size_t i = 0; i < data.count; ++i) {
|
||||
h = (h * 31) + s[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_UTIL_HASH_H
|
@ -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
|
||||
} // namespace util
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_UTIL_MATH_H
|
||||
#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
|
||||
|
@ -18,6 +18,19 @@
|
||||
namespace avian {
|
||||
namespace util {
|
||||
|
||||
template <class T>
|
||||
struct NonConst;
|
||||
|
||||
template <class T>
|
||||
struct NonConst<const T> {
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct NonConst {
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Slice {
|
||||
public:
|
||||
@ -28,7 +41,8 @@ class Slice {
|
||||
{
|
||||
}
|
||||
|
||||
inline Slice(const Slice<T>& copy) : items(copy.items), count(copy.count)
|
||||
inline Slice(const Slice<typename NonConst<T>::Type>& copy)
|
||||
: items(copy.items), count(copy.count)
|
||||
{
|
||||
}
|
||||
|
||||
@ -48,6 +62,13 @@ class Slice {
|
||||
return items + count;
|
||||
}
|
||||
|
||||
inline Slice<T> subslice(size_t begin, size_t count)
|
||||
{
|
||||
ASSERT(begin <= this->count);
|
||||
ASSERT(begin + count <= this->count);
|
||||
return Slice<T>(this->begin() + begin, count);
|
||||
}
|
||||
|
||||
static Slice<T> alloc(Allocator* a, size_t count)
|
||||
{
|
||||
return Slice<T>((T*)a->allocate(sizeof(T) * count), count);
|
||||
|
@ -22,19 +22,23 @@ class AbstractStream {
|
||||
virtual void handleError() = 0;
|
||||
};
|
||||
|
||||
AbstractStream(Client* client, unsigned size):
|
||||
client(client), size(size), position_(0)
|
||||
{ }
|
||||
AbstractStream(Client* client, unsigned size)
|
||||
: client(client), size(size), position_(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned position() {
|
||||
unsigned position()
|
||||
{
|
||||
return position_;
|
||||
}
|
||||
|
||||
void setPosition(unsigned p) {
|
||||
void setPosition(unsigned p)
|
||||
{
|
||||
position_ = p;
|
||||
}
|
||||
|
||||
void skip(unsigned size) {
|
||||
void skip(unsigned size)
|
||||
{
|
||||
if (size > this->size - position_) {
|
||||
client->handleError();
|
||||
} else {
|
||||
@ -42,7 +46,8 @@ class AbstractStream {
|
||||
}
|
||||
}
|
||||
|
||||
void read(uint8_t* dst, unsigned size) {
|
||||
void read(uint8_t* dst, unsigned size)
|
||||
{
|
||||
if (size > this->size - position_) {
|
||||
memset(dst, 0, size);
|
||||
|
||||
@ -53,35 +58,41 @@ class AbstractStream {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t read1() {
|
||||
uint8_t read1()
|
||||
{
|
||||
uint8_t v;
|
||||
read(&v, 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
uint16_t read2() {
|
||||
uint16_t read2()
|
||||
{
|
||||
uint16_t a = read1();
|
||||
uint16_t b = read1();
|
||||
return (a << 8) | b;
|
||||
}
|
||||
|
||||
uint32_t read4() {
|
||||
uint32_t read4()
|
||||
{
|
||||
uint32_t a = read2();
|
||||
uint32_t b = read2();
|
||||
return (a << 16) | b;
|
||||
}
|
||||
|
||||
uint64_t read8() {
|
||||
uint64_t read8()
|
||||
{
|
||||
uint64_t a = read4();
|
||||
uint64_t b = read4();
|
||||
return (a << 32) | b;
|
||||
}
|
||||
|
||||
uint32_t readFloat() {
|
||||
uint32_t readFloat()
|
||||
{
|
||||
return read4();
|
||||
}
|
||||
|
||||
uint64_t readDouble() {
|
||||
uint64_t readDouble()
|
||||
{
|
||||
return read8();
|
||||
}
|
||||
|
||||
@ -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)) {}
|
||||
String(const char* text) : text(text), length(strlen(text))
|
||||
{
|
||||
}
|
||||
|
||||
inline String(const char* text, size_t length):
|
||||
text(text),
|
||||
length(length) {}
|
||||
inline String(const char* text, size_t length) : text(text), length(length)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Tokenizer {
|
||||
public:
|
||||
Tokenizer(const char* s, char delimiter)
|
||||
: s(s), limit(0), delimiter(delimiter)
|
||||
{
|
||||
}
|
||||
|
||||
Tokenizer(const char* s, char delimiter):
|
||||
s(s), limit(0), delimiter(delimiter)
|
||||
{ }
|
||||
Tokenizer(String str, char delimiter)
|
||||
: s(str.text), limit(str.text + str.length), delimiter(delimiter)
|
||||
{
|
||||
}
|
||||
|
||||
Tokenizer(String str, char delimiter):
|
||||
s(str.text), limit(str.text + str.length), delimiter(delimiter)
|
||||
{ }
|
||||
|
||||
bool hasMore() {
|
||||
while (s != limit and *s == delimiter) ++s;
|
||||
bool hasMore()
|
||||
{
|
||||
while (s != limit and *s == delimiter)
|
||||
++s;
|
||||
return s != limit and *s != 0;
|
||||
}
|
||||
|
||||
String next() {
|
||||
String next()
|
||||
{
|
||||
const char* p = s;
|
||||
while (s != limit and *s and *s != delimiter) ++s;
|
||||
while (s != limit and *s and *s != delimiter)
|
||||
++s;
|
||||
return String(p, s - p);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
9
makefile
9
makefile
@ -443,6 +443,7 @@ asm-format = S
|
||||
as = $(cc)
|
||||
ld = $(cc)
|
||||
build-ld = $(build-cc)
|
||||
build-ld-cpp = $(build-cxx)
|
||||
|
||||
default-remote-test-host = localhost
|
||||
default-remote-test-port = 22
|
||||
@ -1268,7 +1269,8 @@ generator-sources = \
|
||||
$(src)/tools/type-generator/main.cpp \
|
||||
$(src)/system/$(build-system).cpp \
|
||||
$(src)/system/$(build-system)/signal.cpp \
|
||||
$(src)/finder.cpp
|
||||
$(src)/finder.cpp \
|
||||
$(src)/util/arg-parser.cpp
|
||||
|
||||
ifneq ($(lzma),)
|
||||
common-cflags += -I$(lzma) -DAVIAN_USE_LZMA -D_7ZIP_ST
|
||||
@ -1353,6 +1355,7 @@ ifneq ($(classpath),avian)
|
||||
# them to synthesize a class:
|
||||
classpath-sources := \
|
||||
$(classpath-src)/avian/Addendum.java \
|
||||
$(classpath-src)/avian/Code.java \
|
||||
$(classpath-src)/avian/AnnotationInvocationHandler.java \
|
||||
$(classpath-src)/avian/Assembler.java \
|
||||
$(classpath-src)/avian/Callback.java \
|
||||
@ -1573,7 +1576,7 @@ gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:')
|
||||
$(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep)
|
||||
@echo "generating $(@)"
|
||||
@mkdir -p $(dir $(@))
|
||||
$(generator) $(boot-classpath) $(<) $(@) $(call gen-arg,$(@))
|
||||
$(generator) -cp $(boot-classpath) -i $(<) -o $(@) -t $(call gen-arg,$(@))
|
||||
|
||||
$(classpath-build)/%.class: $(classpath-src)/%.java
|
||||
@echo $(<)
|
||||
@ -1982,7 +1985,7 @@ endif
|
||||
|
||||
$(generator): $(generator-objects) $(generator-lzma-objects)
|
||||
@echo "linking $(@)"
|
||||
$(build-ld) $(^) $(build-lflags) -o $(@)
|
||||
$(build-ld-cpp) $(^) $(build-lflags) -o $(@)
|
||||
|
||||
$(openjdk-objects): $(build)/openjdk/%-openjdk.o: $(openjdk-src)/%.c \
|
||||
$(openjdk-headers-dep)
|
||||
|
@ -11,8 +11,7 @@ struct JniConstants {
|
||||
static void init(_JNIEnv* env);
|
||||
};
|
||||
|
||||
void
|
||||
JniConstants::init(_JNIEnv*)
|
||||
void JniConstants::init(_JNIEnv*)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
@ -33,13 +33,16 @@ class Vector {
|
||||
data(0, 0),
|
||||
position(0),
|
||||
minimumCapacity(minimumCapacity)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
~Vector() {
|
||||
~Vector()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
void dispose()
|
||||
{
|
||||
if (data.items and minimumCapacity > 0) {
|
||||
allocator->free(data.items, data.count);
|
||||
data.items = 0;
|
||||
@ -50,7 +53,7 @@ class Vector {
|
||||
void ensure(size_t space)
|
||||
{
|
||||
if (position + space > data.count) {
|
||||
assert(a, minimumCapacity > 0);
|
||||
assertT(a, minimumCapacity > 0);
|
||||
|
||||
size_t newCapacity = avian::util::max(
|
||||
position + space, avian::util::max(minimumCapacity, data.count * 2));
|
||||
@ -64,13 +67,13 @@ class Vector {
|
||||
|
||||
void get(size_t offset, void* dst, size_t size)
|
||||
{
|
||||
assert(a, offset + size <= position);
|
||||
assertT(a, offset + size <= position);
|
||||
memcpy(dst, data.begin() + offset, size);
|
||||
}
|
||||
|
||||
void set(size_t offset, const void* src, size_t size)
|
||||
{
|
||||
assert(a, offset + size <= position);
|
||||
assertT(a, offset + size <= position);
|
||||
memcpy(data.begin() + offset, src, size);
|
||||
}
|
||||
|
||||
@ -95,57 +98,67 @@ class Vector {
|
||||
return r;
|
||||
}
|
||||
|
||||
void append(uint8_t v) {
|
||||
void append(uint8_t v)
|
||||
{
|
||||
append(&v, 1);
|
||||
}
|
||||
|
||||
void append2(uint16_t v) {
|
||||
void append2(uint16_t v)
|
||||
{
|
||||
append(&v, 2);
|
||||
}
|
||||
|
||||
void append4(uint32_t v) {
|
||||
void append4(uint32_t v)
|
||||
{
|
||||
append(&v, 4);
|
||||
}
|
||||
|
||||
void appendTargetAddress(target_uintptr_t v) {
|
||||
void appendTargetAddress(target_uintptr_t v)
|
||||
{
|
||||
append(&v, TargetBytesPerWord);
|
||||
}
|
||||
|
||||
void appendAddress(uintptr_t v) {
|
||||
void appendAddress(uintptr_t v)
|
||||
{
|
||||
append(&v, BytesPerWord);
|
||||
}
|
||||
|
||||
void appendAddress(void* v) {
|
||||
void appendAddress(void* v)
|
||||
{
|
||||
append(&v, BytesPerWord);
|
||||
}
|
||||
|
||||
void set2(size_t offset, uint16_t v)
|
||||
{
|
||||
assert(a, offset <= position - 2);
|
||||
assertT(a, offset <= position - 2);
|
||||
memcpy(data.begin() + offset, &v, 2);
|
||||
}
|
||||
|
||||
size_t get(size_t offset)
|
||||
{
|
||||
uint8_t v; get(offset, &v, 1);
|
||||
uint8_t v;
|
||||
get(offset, &v, 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
size_t get2(size_t offset)
|
||||
{
|
||||
uint16_t v; get(offset, &v, 2);
|
||||
uint16_t v;
|
||||
get(offset, &v, 2);
|
||||
return v;
|
||||
}
|
||||
|
||||
size_t get4(size_t offset)
|
||||
{
|
||||
uint32_t v; get(offset, &v, 4);
|
||||
uint32_t v;
|
||||
get(offset, &v, 4);
|
||||
return v;
|
||||
}
|
||||
|
||||
uintptr_t getAddress(size_t offset)
|
||||
{
|
||||
uintptr_t v; get(offset, &v, BytesPerWord);
|
||||
uintptr_t v;
|
||||
get(offset, &v, BytesPerWord);
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -157,7 +170,7 @@ class Vector {
|
||||
template <class T>
|
||||
T* peek(size_t offset)
|
||||
{
|
||||
assert(a, offset + sizeof(T) <= position);
|
||||
assertT(a, offset + sizeof(T) <= position);
|
||||
return reinterpret_cast<T*>(data.begin() + offset);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
237
src/avian/arm.h
237
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,15 +237,13 @@ 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 {
|
||||
@ -254,7 +254,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
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;
|
||||
@ -53,9 +54,11 @@ class BootImage {
|
||||
ThunkCollection thunks;
|
||||
} PACKED;
|
||||
|
||||
class GcField;
|
||||
|
||||
class OffsetResolver {
|
||||
public:
|
||||
virtual unsigned fieldOffset(Thread*, object) = 0;
|
||||
virtual unsigned fieldOffset(Thread*, GcField*) = 0;
|
||||
};
|
||||
|
||||
#define NAME(x) Target##x
|
||||
@ -70,6 +73,6 @@ class OffsetResolver {
|
||||
#undef LABEL
|
||||
#undef NAME
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//BOOTIMAGE_H
|
||||
#endif // BOOTIMAGE_H
|
||||
|
@ -18,31 +18,28 @@ 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) {
|
||||
object method = walker->method();
|
||||
if (isAssignableFrom
|
||||
(t, type(t, Machine::ThrowableType), methodClass(t, method))
|
||||
GcMethod* method = walker->method();
|
||||
if (isAssignableFrom(t, type(t, GcThrowable::Type), method->class_())
|
||||
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||
&byteArrayBody(t, methodName(t, method), 0))
|
||||
== 0)
|
||||
{
|
||||
method->name()->body().begin()) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
trace = makeTrace(t, walker);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
-- skipCount;
|
||||
--skipCount;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -54,38 +51,37 @@ getTrace(Thread* t, unsigned skipCount)
|
||||
|
||||
t->m->processor->walkStack(t, &v);
|
||||
|
||||
if (v.trace == 0) v.trace = makeObjectArray(t, 0);
|
||||
if (v.trace == 0)
|
||||
v.trace = makeObjectArray(t, 0);
|
||||
|
||||
return v.trace;
|
||||
}
|
||||
|
||||
bool
|
||||
compatibleArrayTypes(Thread* t, object a, object b)
|
||||
bool compatibleArrayTypes(Thread* t UNUSED, GcClass* a, GcClass* b)
|
||||
{
|
||||
return classArrayElementSize(t, a)
|
||||
and classArrayElementSize(t, b)
|
||||
and (a == b
|
||||
or (not ((classVmFlags(t, a) & PrimitiveFlag)
|
||||
or (classVmFlags(t, b) & PrimitiveFlag))));
|
||||
return a->arrayElementSize() and b->arrayElementSize()
|
||||
and (a == b or (not((a->vmFlags() & PrimitiveFlag)
|
||||
or (b->vmFlags() & PrimitiveFlag))));
|
||||
}
|
||||
|
||||
void
|
||||
arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
|
||||
int32_t dstOffset, int32_t length)
|
||||
void arrayCopy(Thread* t,
|
||||
object src,
|
||||
int32_t srcOffset,
|
||||
object dst,
|
||||
int32_t dstOffset,
|
||||
int32_t length)
|
||||
{
|
||||
if (LIKELY(src and dst)) {
|
||||
if (LIKELY(compatibleArrayTypes
|
||||
(t, objectClass(t, src), objectClass(t, dst))))
|
||||
{
|
||||
unsigned elementSize = classArrayElementSize(t, objectClass(t, src));
|
||||
if (LIKELY(compatibleArrayTypes(
|
||||
t, objectClass(t, src), objectClass(t, dst)))) {
|
||||
unsigned elementSize = objectClass(t, src)->arrayElementSize();
|
||||
|
||||
if (LIKELY(elementSize)) {
|
||||
intptr_t sl = fieldAtOffset<uintptr_t>(src, BytesPerWord);
|
||||
intptr_t dl = fieldAtOffset<uintptr_t>(dst, BytesPerWord);
|
||||
if (LIKELY(length > 0)) {
|
||||
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
|
||||
dstOffset >= 0 and dstOffset + length <= dl))
|
||||
{
|
||||
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl
|
||||
and dstOffset >= 0 and dstOffset + length <= dl)) {
|
||||
uint8_t* sbody = &fieldAtOffset<uint8_t>(src, ArrayBody);
|
||||
uint8_t* dbody = &fieldAtOffset<uint8_t>(dst, ArrayBody);
|
||||
if (src == dst) {
|
||||
@ -98,13 +94,13 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
|
||||
length * elementSize);
|
||||
}
|
||||
|
||||
if (classObjectMask(t, objectClass(t, dst))) {
|
||||
if (objectClass(t, dst)->objectMask()) {
|
||||
mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length);
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
throwNew(t, Machine::IndexOutOfBoundsExceptionType);
|
||||
throwNew(t, GcIndexOutOfBoundsException::Type);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
@ -112,15 +108,14 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throwNew(t, Machine::NullPointerExceptionType);
|
||||
throwNew(t, GcNullPointerException::Type);
|
||||
return;
|
||||
}
|
||||
|
||||
throwNew(t, Machine::ArrayStoreExceptionType);
|
||||
throwNew(t, GcArrayStoreException::Type);
|
||||
}
|
||||
|
||||
void
|
||||
runOnLoadIfFound(Thread* t, System::Library* library)
|
||||
void runOnLoadIfFound(Thread* t, System::Library* library)
|
||||
{
|
||||
void* p = library->resolve("JNI_OnLoad");
|
||||
|
||||
@ -134,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);
|
||||
|
||||
@ -163,9 +157,12 @@ loadLibrary(Thread* t, const char* name)
|
||||
}
|
||||
}
|
||||
|
||||
System::Library*
|
||||
loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
bool runOnLoad, bool throw_ = true)
|
||||
System::Library* loadLibrary(Thread* t,
|
||||
const char* path,
|
||||
const char* name,
|
||||
bool mapName,
|
||||
bool runOnLoad,
|
||||
bool throw_ = true)
|
||||
{
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
@ -177,8 +174,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
const char* s = builtins;
|
||||
while (*s) {
|
||||
if (::strncmp(s, name, nameLength) == 0
|
||||
and (s[nameLength] == ',' or s[nameLength] == 0))
|
||||
{
|
||||
and (s[nameLength] == ',' or s[nameLength] == 0)) {
|
||||
// library is built in to this executable
|
||||
if (runOnLoad and not t->m->triedBuiltinOnLoad) {
|
||||
t->m->triedBuiltinOnLoad = true;
|
||||
@ -188,8 +184,10 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
}
|
||||
return t->m->libraries;
|
||||
} else {
|
||||
while (*s and *s != ',') ++ s;
|
||||
if (*s) ++ s;
|
||||
while (*s and *s != ',')
|
||||
++s;
|
||||
if (*s)
|
||||
++s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,8 +196,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
const char* suffix = t->m->system->librarySuffix();
|
||||
unsigned mappedNameLength = nameLength + strlen(prefix) + strlen(suffix);
|
||||
|
||||
mappedName = static_cast<char*>
|
||||
(t->m->heap->allocate(mappedNameLength + 1));
|
||||
mappedName = static_cast<char*>(t->m->heap->allocate(mappedNameLength + 1));
|
||||
|
||||
snprintf(mappedName, mappedNameLength + 1, "%s%s%s", prefix, name, suffix);
|
||||
|
||||
@ -209,25 +206,28 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
mappedName = 0;
|
||||
}
|
||||
|
||||
THREAD_RESOURCE2
|
||||
(t, char*, mappedName, unsigned, nameLength, if (mappedName) {
|
||||
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) {
|
||||
@ -239,109 +239,121 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
||||
runOnLoadIfFound(t, lib);
|
||||
}
|
||||
} else if (throw_) {
|
||||
throwNew(t, Machine::UnsatisfiedLinkErrorType,
|
||||
"library not found in %s: %s", path, name);
|
||||
throwNew(t,
|
||||
GcUnsatisfiedLinkError::Type,
|
||||
"library not found in %s: %s",
|
||||
path,
|
||||
name);
|
||||
}
|
||||
|
||||
return lib;
|
||||
}
|
||||
|
||||
object
|
||||
clone(Thread* t, object o)
|
||||
object clone(Thread* t, object o)
|
||||
{
|
||||
PROTECT(t, o);
|
||||
|
||||
object class_ = objectClass(t, o);
|
||||
GcClass* class_ = objectClass(t, o);
|
||||
unsigned size = baseSize(t, o, class_) * BytesPerWord;
|
||||
object clone;
|
||||
|
||||
if (classArrayElementSize(t, class_)) {
|
||||
clone = static_cast<object>(allocate(t, size, classObjectMask(t, class_)));
|
||||
if (class_->arrayElementSize()) {
|
||||
clone = static_cast<object>(allocate(t, size, class_->objectMask()));
|
||||
memcpy(clone, o, size);
|
||||
// clear any object header flags:
|
||||
setObjectClass(t, o, objectClass(t, o));
|
||||
} else if (instanceOf(t, type(t, Machine::CloneableType), o)) {
|
||||
} else if (instanceOf(t, type(t, GcCloneable::Type), o)) {
|
||||
clone = make(t, class_);
|
||||
memcpy(reinterpret_cast<void**>(clone) + 1,
|
||||
reinterpret_cast<void**>(o) + 1,
|
||||
size - BytesPerWord);
|
||||
} else {
|
||||
object classNameSlash = className(t, objectClass(t, o));
|
||||
THREAD_RUNTIME_ARRAY(t, char, classNameDot, byteArrayLength(t, classNameSlash));
|
||||
replace('/', '.', RUNTIME_ARRAY_BODY(classNameDot),
|
||||
reinterpret_cast<char*>(&byteArrayBody(t, classNameSlash, 0)));
|
||||
throwNew(t, Machine::CloneNotSupportedExceptionType, "%s",
|
||||
GcByteArray* classNameSlash = objectClass(t, o)->name();
|
||||
THREAD_RUNTIME_ARRAY(t, char, classNameDot, classNameSlash->length());
|
||||
replace('/',
|
||||
'.',
|
||||
RUNTIME_ARRAY_BODY(classNameDot),
|
||||
reinterpret_cast<char*>(classNameSlash->body().begin()));
|
||||
throwNew(t,
|
||||
GcCloneNotSupportedException::Type,
|
||||
"%s",
|
||||
RUNTIME_ARRAY_BODY(classNameDot));
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
object
|
||||
makeStackTraceElement(Thread* t, object e)
|
||||
GcStackTraceElement* makeStackTraceElement(Thread* t, GcTraceElement* e)
|
||||
{
|
||||
PROTECT(t, e);
|
||||
|
||||
object class_ = className(t, methodClass(t, traceElementMethod(t, e)));
|
||||
PROTECT(t, class_);
|
||||
|
||||
THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, class_));
|
||||
replace('/', '.', RUNTIME_ARRAY_BODY(s),
|
||||
reinterpret_cast<char*>(&byteArrayBody(t, class_, 0)));
|
||||
class_ = makeString(t, "%s", RUNTIME_ARRAY_BODY(s));
|
||||
|
||||
object method = methodName(t, traceElementMethod(t, e));
|
||||
GcMethod* method = cast<GcMethod>(t, e->method());
|
||||
PROTECT(t, method);
|
||||
|
||||
method = t->m->classpath->makeString
|
||||
(t, method, 0, byteArrayLength(t, method) - 1);
|
||||
GcByteArray* class_name = method->class_()->name();
|
||||
PROTECT(t, class_name);
|
||||
|
||||
unsigned line = t->m->processor->lineNumber
|
||||
(t, traceElementMethod(t, e), traceElementIp(t, e));
|
||||
THREAD_RUNTIME_ARRAY(t, char, s, class_name->length());
|
||||
replace('/',
|
||||
'.',
|
||||
RUNTIME_ARRAY_BODY(s),
|
||||
reinterpret_cast<char*>(class_name->body().begin()));
|
||||
GcString* class_name_string = makeString(t, "%s", RUNTIME_ARRAY_BODY(s));
|
||||
PROTECT(t, class_name_string);
|
||||
|
||||
object file = classSourceFile(t, methodClass(t, traceElementMethod(t, e)));
|
||||
file = file ? t->m->classpath->makeString
|
||||
(t, file, 0, byteArrayLength(t, file) - 1) : 0;
|
||||
GcByteArray* method_name = method->name();
|
||||
PROTECT(t, method_name);
|
||||
|
||||
return makeStackTraceElement(t, class_, method, file, line);
|
||||
GcString* method_name_string = t->m->classpath->makeString(
|
||||
t, method_name, 0, method_name->length() - 1);
|
||||
PROTECT(t, method_name_string);
|
||||
|
||||
unsigned line = t->m->processor->lineNumber(t, method, e->ip());
|
||||
|
||||
GcByteArray* file = method->class_()->sourceFile();
|
||||
GcString* file_string
|
||||
= file ? t->m->classpath->makeString(t, file, 0, file->length() - 1) : 0;
|
||||
|
||||
return makeStackTraceElement(
|
||||
t, class_name_string, method_name_string, file_string, line);
|
||||
}
|
||||
|
||||
object
|
||||
translateInvokeResult(Thread* t, unsigned returnCode, object o)
|
||||
GcObject* translateInvokeResult(Thread* t, unsigned returnCode, object o)
|
||||
{
|
||||
switch (returnCode) {
|
||||
case ByteField:
|
||||
return makeByte(t, intValue(t, o));
|
||||
return makeByte(t, cast<GcInt>(t, o)->value());
|
||||
|
||||
case BooleanField:
|
||||
return makeBoolean(t, intValue(t, o) != 0);
|
||||
return makeBoolean(t, cast<GcInt>(t, o)->value() != 0);
|
||||
|
||||
case CharField:
|
||||
return makeChar(t, intValue(t, o));
|
||||
return makeChar(t, cast<GcInt>(t, o)->value());
|
||||
|
||||
case ShortField:
|
||||
return makeShort(t, intValue(t, o));
|
||||
return makeShort(t, cast<GcInt>(t, o)->value());
|
||||
|
||||
case FloatField:
|
||||
return makeFloat(t, intValue(t, o));
|
||||
return makeFloat(t, cast<GcInt>(t, o)->value());
|
||||
|
||||
case IntField:
|
||||
case LongField:
|
||||
case ObjectField:
|
||||
case VoidField:
|
||||
return o;
|
||||
return reinterpret_cast<GcObject*>(o);
|
||||
|
||||
case DoubleField:
|
||||
return makeDouble(t, longValue(t, o));
|
||||
return makeDouble(t, cast<GcLong>(t, o)->value());
|
||||
|
||||
default:
|
||||
abort(t);
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
resolveClassBySpec(Thread* t, object loader, const char* spec,
|
||||
unsigned specLength)
|
||||
GcClass* resolveClassBySpec(Thread* t,
|
||||
GcClassLoader* loader,
|
||||
const char* spec,
|
||||
unsigned specLength)
|
||||
{
|
||||
switch (*spec) {
|
||||
case 'L': {
|
||||
@ -363,69 +375,79 @@ resolveClassBySpec(Thread* t, object loader, const char* spec,
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
resolveJType(Thread* t, object loader, const char* spec, unsigned specLength)
|
||||
GcJclass* resolveJType(Thread* t,
|
||||
GcClassLoader* loader,
|
||||
const char* spec,
|
||||
unsigned specLength)
|
||||
{
|
||||
return getJClass(t, resolveClassBySpec(t, loader, spec, specLength));
|
||||
}
|
||||
|
||||
object
|
||||
resolveParameterTypes(Thread* t, object loader, object spec,
|
||||
unsigned* parameterCount, unsigned* returnTypeSpec)
|
||||
GcPair* resolveParameterTypes(Thread* t,
|
||||
GcClassLoader* loader,
|
||||
GcByteArray* spec,
|
||||
unsigned* parameterCount,
|
||||
unsigned* returnTypeSpec)
|
||||
{
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, spec);
|
||||
|
||||
object list = 0;
|
||||
GcPair* list = 0;
|
||||
PROTECT(t, list);
|
||||
|
||||
unsigned offset = 1;
|
||||
unsigned count = 0;
|
||||
while (byteArrayBody(t, spec, offset) != ')') {
|
||||
switch (byteArrayBody(t, spec, offset)) {
|
||||
while (spec->body()[offset] != ')') {
|
||||
switch (spec->body()[offset]) {
|
||||
case 'L': {
|
||||
unsigned start = offset;
|
||||
++ offset;
|
||||
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
|
||||
++ offset;
|
||||
++offset;
|
||||
while (spec->body()[offset] != ';')
|
||||
++offset;
|
||||
++offset;
|
||||
|
||||
object type = resolveClassBySpec
|
||||
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
|
||||
offset - start);
|
||||
GcClass* type
|
||||
= resolveClassBySpec(t,
|
||||
loader,
|
||||
reinterpret_cast<char*>(&spec->body()[start]),
|
||||
offset - start);
|
||||
|
||||
list = makePair(t, type, list);
|
||||
|
||||
++ count;
|
||||
++count;
|
||||
} break;
|
||||
|
||||
case '[': {
|
||||
unsigned start = offset;
|
||||
while (byteArrayBody(t, spec, offset) == '[') ++ offset;
|
||||
switch (byteArrayBody(t, spec, offset)) {
|
||||
while (spec->body()[offset] == '[')
|
||||
++offset;
|
||||
switch (spec->body()[offset]) {
|
||||
case 'L':
|
||||
++ offset;
|
||||
while (byteArrayBody(t, spec, offset) != ';') ++ offset;
|
||||
++ offset;
|
||||
++offset;
|
||||
while (spec->body()[offset] != ';')
|
||||
++offset;
|
||||
++offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
++ offset;
|
||||
++offset;
|
||||
break;
|
||||
}
|
||||
|
||||
object type = resolveClassBySpec
|
||||
(t, loader, reinterpret_cast<char*>(&byteArrayBody(t, spec, start)),
|
||||
offset - start);
|
||||
GcClass* type
|
||||
= resolveClassBySpec(t,
|
||||
loader,
|
||||
reinterpret_cast<char*>(&spec->body()[start]),
|
||||
offset - start);
|
||||
|
||||
list = makePair(t, type, list);
|
||||
++ count;
|
||||
++count;
|
||||
} break;
|
||||
|
||||
default:
|
||||
list = makePair
|
||||
(t, primitiveClass(t, byteArrayBody(t, spec, offset)), list);
|
||||
++ offset;
|
||||
++ count;
|
||||
list = makePair(t, primitiveClass(t, spec->body()[offset]), list);
|
||||
++offset;
|
||||
++count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -435,109 +457,125 @@ resolveParameterTypes(Thread* t, object loader, object spec,
|
||||
return list;
|
||||
}
|
||||
|
||||
object
|
||||
resolveParameterJTypes(Thread* t, object loader, object spec,
|
||||
unsigned* parameterCount, unsigned* returnTypeSpec)
|
||||
object resolveParameterJTypes(Thread* t,
|
||||
GcClassLoader* loader,
|
||||
GcByteArray* spec,
|
||||
unsigned* parameterCount,
|
||||
unsigned* returnTypeSpec)
|
||||
{
|
||||
object list = resolveParameterTypes
|
||||
(t, loader, spec, parameterCount, returnTypeSpec);
|
||||
GcPair* list
|
||||
= resolveParameterTypes(t, loader, spec, parameterCount, returnTypeSpec);
|
||||
|
||||
PROTECT(t, list);
|
||||
|
||||
object array = makeObjectArray
|
||||
(t, type(t, Machine::JclassType), *parameterCount);
|
||||
object array = makeObjectArray(t, type(t, GcJclass::Type), *parameterCount);
|
||||
PROTECT(t, array);
|
||||
|
||||
for (int i = *parameterCount - 1; i >= 0; --i) {
|
||||
object c = getJClass(t, pairFirst(t, list));
|
||||
set(t, array, ArrayBody + (i * BytesPerWord), c);
|
||||
list = pairSecond(t, list);
|
||||
object c = getJClass(t, cast<GcClass>(t, list->first()));
|
||||
reinterpret_cast<GcArray*>(array)->setBodyElement(t, i, c);
|
||||
list = cast<GcPair>(t, list->second());
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
object
|
||||
resolveExceptionJTypes(Thread* t, object loader, object addendum)
|
||||
object resolveExceptionJTypes(Thread* t,
|
||||
GcClassLoader* loader,
|
||||
GcMethodAddendum* addendum)
|
||||
{
|
||||
if (addendum == 0 or methodAddendumExceptionTable(t, addendum) == 0) {
|
||||
return makeObjectArray(t, type(t, Machine::JclassType), 0);
|
||||
if (addendum == 0 or addendum->exceptionTable() == 0) {
|
||||
return makeObjectArray(t, type(t, GcJclass::Type), 0);
|
||||
}
|
||||
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, addendum);
|
||||
|
||||
object array = makeObjectArray
|
||||
(t, type(t, Machine::JclassType),
|
||||
shortArrayLength(t, methodAddendumExceptionTable(t, addendum)));
|
||||
GcShortArray* exceptionTable
|
||||
= cast<GcShortArray>(t, addendum->exceptionTable());
|
||||
PROTECT(t, exceptionTable);
|
||||
|
||||
object array
|
||||
= makeObjectArray(t, type(t, GcJclass::Type), exceptionTable->length());
|
||||
PROTECT(t, array);
|
||||
|
||||
for (unsigned i = 0; i < shortArrayLength
|
||||
(t, methodAddendumExceptionTable(t, addendum)); ++i)
|
||||
{
|
||||
uint16_t index = shortArrayBody
|
||||
(t, methodAddendumExceptionTable(t, addendum), i) - 1;
|
||||
for (unsigned i = 0; i < exceptionTable->length(); ++i) {
|
||||
uint16_t index = exceptionTable->body()[i] - 1;
|
||||
|
||||
object o = singletonObject(t, addendumPool(t, addendum), index);
|
||||
object o = singletonObject(t, addendum->pool()->as<GcSingleton>(t), index);
|
||||
|
||||
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
|
||||
o = resolveClass(t, loader, referenceName(t, o));
|
||||
if (objectClass(t, o) == type(t, GcReference::Type)) {
|
||||
o = resolveClass(t, loader, cast<GcReference>(t, o)->name());
|
||||
|
||||
set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord),
|
||||
o);
|
||||
addendum->pool()->setBodyElement(
|
||||
t, index, reinterpret_cast<uintptr_t>(o));
|
||||
}
|
||||
|
||||
o = getJClass(t, o);
|
||||
o = getJClass(t, cast<GcClass>(t, o));
|
||||
|
||||
set(t, array, ArrayBody + (i * BytesPerWord), o);
|
||||
reinterpret_cast<GcArray*>(array)->setBodyElement(t, i, o);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
object
|
||||
invoke(Thread* t, object method, object instance, object args)
|
||||
object invoke(Thread* t, GcMethod* method, object instance, object args)
|
||||
{
|
||||
PROTECT(t, method);
|
||||
PROTECT(t, instance);
|
||||
PROTECT(t, args);
|
||||
|
||||
if (methodFlags(t, method) & ACC_STATIC) {
|
||||
if (method->flags() & ACC_STATIC) {
|
||||
instance = 0;
|
||||
}
|
||||
|
||||
if ((args == 0 ? 0 : objectArrayLength(t, args))
|
||||
!= methodParameterCount(t, method))
|
||||
{
|
||||
throwNew(t, Machine::IllegalArgumentExceptionType);
|
||||
!= method->parameterCount()) {
|
||||
throwNew(t, GcIllegalArgumentException::Type);
|
||||
}
|
||||
|
||||
if (methodParameterCount(t, method)) {
|
||||
unsigned specLength = byteArrayLength(t, methodSpec(t, method));
|
||||
if (method->parameterCount()) {
|
||||
unsigned specLength = method->spec()->length();
|
||||
THREAD_RUNTIME_ARRAY(t, char, spec, specLength);
|
||||
memcpy(RUNTIME_ARRAY_BODY(spec),
|
||||
&byteArrayBody(t, methodSpec(t, method), 0), specLength);
|
||||
memcpy(
|
||||
RUNTIME_ARRAY_BODY(spec), method->spec()->body().begin(), specLength);
|
||||
unsigned i = 0;
|
||||
for (MethodSpecIterator it(t, RUNTIME_ARRAY_BODY(spec)); it.hasNext();) {
|
||||
object type;
|
||||
GcClass* type;
|
||||
bool objectType = false;
|
||||
const char* p = it.next();
|
||||
switch (*p) {
|
||||
case 'Z': type = vm::type(t, Machine::BooleanType); break;
|
||||
case 'B': type = vm::type(t, Machine::ByteType); break;
|
||||
case 'S': type = vm::type(t, Machine::ShortType); break;
|
||||
case 'C': type = vm::type(t, Machine::CharType); break;
|
||||
case 'I': type = vm::type(t, Machine::IntType); break;
|
||||
case 'F': type = vm::type(t, Machine::FloatType); break;
|
||||
case 'J': type = vm::type(t, Machine::LongType); break;
|
||||
case 'D': type = vm::type(t, Machine::DoubleType); break;
|
||||
case 'Z':
|
||||
type = vm::type(t, GcBoolean::Type);
|
||||
break;
|
||||
case 'B':
|
||||
type = vm::type(t, GcByte::Type);
|
||||
break;
|
||||
case 'S':
|
||||
type = vm::type(t, GcShort::Type);
|
||||
break;
|
||||
case 'C':
|
||||
type = vm::type(t, GcChar::Type);
|
||||
break;
|
||||
case 'I':
|
||||
type = vm::type(t, GcInt::Type);
|
||||
break;
|
||||
case 'F':
|
||||
type = vm::type(t, GcFloat::Type);
|
||||
break;
|
||||
case 'J':
|
||||
type = vm::type(t, GcLong::Type);
|
||||
break;
|
||||
case 'D':
|
||||
type = vm::type(t, GcDouble::Type);
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
case '[': {
|
||||
objectType = true;
|
||||
unsigned nameLength;
|
||||
if (*p == 'L') {
|
||||
++ p;
|
||||
++p;
|
||||
nameLength = it.s - p;
|
||||
} else {
|
||||
nameLength = (it.s - p) + 1;
|
||||
@ -545,9 +583,8 @@ invoke(Thread* t, object method, object instance, object args)
|
||||
THREAD_RUNTIME_ARRAY(t, char, name, nameLength);
|
||||
memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1);
|
||||
RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0;
|
||||
type = resolveClass
|
||||
(t, classLoader(t, methodClass(t, method)),
|
||||
RUNTIME_ARRAY_BODY(name));
|
||||
type = resolveClass(
|
||||
t, method->class_()->loader(), RUNTIME_ARRAY_BODY(name));
|
||||
} break;
|
||||
|
||||
default:
|
||||
@ -556,28 +593,33 @@ invoke(Thread* t, object method, object instance, object args)
|
||||
|
||||
object arg = objectArrayBody(t, args, i++);
|
||||
if ((arg == 0 and (not objectType))
|
||||
or (arg and (not instanceOf(t, type, arg))))
|
||||
{
|
||||
// fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast<const int8_t*>("<null>"), &byteArrayBody(t, className(t, type), 0));
|
||||
or (arg and (not instanceOf(t, type, arg)))) {
|
||||
if (false) {
|
||||
fprintf(stderr,
|
||||
"%s is not a %s\n",
|
||||
arg ? objectClass(t, arg)->name()->body().begin()
|
||||
: reinterpret_cast<const int8_t*>("<null>"),
|
||||
type->name()->body().begin());
|
||||
}
|
||||
|
||||
throwNew(t, Machine::IllegalArgumentExceptionType);
|
||||
throwNew(t, GcIllegalArgumentException::Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initClass(t, methodClass(t, method));
|
||||
initClass(t, method->class_());
|
||||
|
||||
unsigned returnCode = methodReturnCode(t, method);
|
||||
unsigned returnCode = method->returnCode();
|
||||
|
||||
THREAD_RESOURCE0(t, {
|
||||
if (t->exception) {
|
||||
t->exception = makeThrowable
|
||||
(t, Machine::InvocationTargetExceptionType, 0, 0, t->exception);
|
||||
if (t->exception) {
|
||||
t->exception = makeThrowable(
|
||||
t, GcInvocationTargetException::Type, 0, 0, t->exception);
|
||||
|
||||
set(t, t->exception, InvocationTargetExceptionTarget,
|
||||
throwableCause(t, t->exception));
|
||||
}
|
||||
});
|
||||
t->exception->as<GcInvocationTargetException>(t)
|
||||
->setTarget(t, t->exception->cause());
|
||||
}
|
||||
});
|
||||
|
||||
object result;
|
||||
if (args) {
|
||||
@ -591,66 +633,70 @@ invoke(Thread* t, object method, object instance, object args)
|
||||
|
||||
// only safe to call during bootstrap when there's only one thread
|
||||
// running:
|
||||
void
|
||||
intercept(Thread* t, object c, const char* name, const char* spec,
|
||||
void* function, bool updateRuntimeData)
|
||||
void intercept(Thread* t,
|
||||
GcClass* c,
|
||||
const char* name,
|
||||
const char* spec,
|
||||
void* function,
|
||||
bool updateRuntimeData)
|
||||
{
|
||||
object m = findMethodOrNull(t, c, name, spec);
|
||||
GcMethod* m = findMethodOrNull(t, c, name, spec);
|
||||
if (m) {
|
||||
PROTECT(t, m);
|
||||
|
||||
methodFlags(t, m) |= ACC_NATIVE;
|
||||
m->flags() |= ACC_NATIVE;
|
||||
|
||||
if (updateRuntimeData) {
|
||||
object clone = methodClone(t, m);
|
||||
GcMethod* clone = methodClone(t, m);
|
||||
|
||||
// make clone private to prevent vtable updates at compilation
|
||||
// time. Otherwise, our interception might be bypassed by calls
|
||||
// through the vtable.
|
||||
methodFlags(t, clone) |= ACC_PRIVATE;
|
||||
clone->flags() |= ACC_PRIVATE;
|
||||
|
||||
object native = makeNativeIntercept(t, function, true, clone);
|
||||
GcNativeIntercept* native = makeNativeIntercept(t, function, true, clone);
|
||||
|
||||
PROTECT(t, native);
|
||||
|
||||
object runtimeData = getMethodRuntimeData(t, m);
|
||||
GcMethodRuntimeData* runtimeData = getMethodRuntimeData(t, m);
|
||||
|
||||
set(t, runtimeData, MethodRuntimeDataNative, native);
|
||||
runtimeData->setNative(t, native->as<GcNative>(t));
|
||||
}
|
||||
} else {
|
||||
// If we can't find the method, just ignore it, since ProGuard may
|
||||
// have stripped it out as unused. Otherwise, the code below can
|
||||
// be uncommented for debugging purposes.
|
||||
// be enabled for debugging purposes.
|
||||
|
||||
// fprintf(stderr, "unable to find %s%s in %s\n",
|
||||
// name, spec, &byteArrayBody(t, className(t, c), 0));
|
||||
if (false) {
|
||||
fprintf(stderr,
|
||||
"unable to find %s%s in %s\n",
|
||||
name,
|
||||
spec,
|
||||
c->name()->body().begin());
|
||||
|
||||
// abort(t);
|
||||
abort(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Finder*
|
||||
getFinder(Thread* t, const char* name, unsigned nameLength)
|
||||
Finder* getFinder(Thread* t, const char* name, unsigned nameLength)
|
||||
{
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
for (object p = root(t, Machine::VirtualFileFinders);
|
||||
p; p = finderNext(t, p))
|
||||
{
|
||||
if (byteArrayLength(t, finderName(t, p)) == nameLength
|
||||
and strncmp(reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, finderName(t, p), 0)),
|
||||
name, nameLength))
|
||||
{
|
||||
return static_cast<Finder*>(finderFinder(t, p));
|
||||
for (GcFinder* p = roots(t)->virtualFileFinders(); p; p = p->next()) {
|
||||
if (p->name()->length() == nameLength
|
||||
and strncmp(reinterpret_cast<const char*>(p->name()->body().begin()),
|
||||
name,
|
||||
nameLength)) {
|
||||
return static_cast<Finder*>(p->finder());
|
||||
}
|
||||
}
|
||||
|
||||
object n = makeByteArray(t, nameLength + 1);
|
||||
memcpy(&byteArrayBody(t, n, 0), name, nameLength);
|
||||
GcByteArray* n = makeByteArray(t, nameLength + 1);
|
||||
memcpy(n->body().begin(), name, nameLength);
|
||||
|
||||
void* p = t->m->libraries->resolve
|
||||
(reinterpret_cast<const char*>(&byteArrayBody(t, n, 0)));
|
||||
void* p = t->m->libraries->resolve(
|
||||
reinterpret_cast<const char*>(n->body().begin()));
|
||||
|
||||
if (p) {
|
||||
uint8_t* (*function)(unsigned*);
|
||||
@ -660,10 +706,9 @@ getFinder(Thread* t, const char* name, unsigned nameLength)
|
||||
uint8_t* data = function(&size);
|
||||
if (data) {
|
||||
Finder* f = makeFinder(t->m->system, t->m->heap, data, size);
|
||||
object finder = makeFinder
|
||||
(t, f, n, root(t, Machine::VirtualFileFinders));
|
||||
GcFinder* finder = makeFinder(t, f, n, roots(t)->virtualFileFinders());
|
||||
|
||||
setRoot(t, Machine::VirtualFileFinders, finder);
|
||||
roots(t)->setVirtualFileFinders(t, finder);
|
||||
|
||||
return f;
|
||||
}
|
||||
@ -672,44 +717,39 @@ getFinder(Thread* t, const char* name, unsigned nameLength)
|
||||
return 0;
|
||||
}
|
||||
|
||||
object
|
||||
getDeclaredClasses(Thread* t, object c, bool publicOnly)
|
||||
object getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
||||
{
|
||||
object addendum = classAddendum(t, c);
|
||||
GcClassAddendum* addendum = c->addendum();
|
||||
if (addendum) {
|
||||
object table = classAddendumInnerClassTable(t, addendum);
|
||||
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
|
||||
if (table) {
|
||||
PROTECT(t, table);
|
||||
|
||||
unsigned count = 0;
|
||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||
object reference = arrayBody(t, table, i);
|
||||
object outer = innerClassReferenceOuter(t, reference);
|
||||
if (outer and byteArrayEqual(t, outer, className(t, c))
|
||||
and ((not publicOnly)
|
||||
or (innerClassReferenceFlags(t, reference) & ACC_PUBLIC)))
|
||||
{
|
||||
++ count;
|
||||
for (unsigned i = 0; i < table->length(); ++i) {
|
||||
GcInnerClassReference* reference
|
||||
= cast<GcInnerClassReference>(t, table->body()[i]);
|
||||
GcByteArray* outer = reference->outer();
|
||||
if (outer and byteArrayEqual(t, outer, c->name())
|
||||
and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
object result = makeObjectArray(t, type(t, Machine::JclassType), count);
|
||||
object result = makeObjectArray(t, type(t, GcJclass::Type), count);
|
||||
PROTECT(t, result);
|
||||
|
||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||
object reference = arrayBody(t, table, i);
|
||||
object outer = innerClassReferenceOuter(t, reference);
|
||||
if (outer and byteArrayEqual(t, outer, className(t, c))
|
||||
and ((not publicOnly)
|
||||
or (innerClassReferenceFlags(t, reference) & ACC_PUBLIC)))
|
||||
{
|
||||
object inner = getJClass
|
||||
(t, resolveClass
|
||||
(t, classLoader(t, c),
|
||||
innerClassReferenceInner(t, arrayBody(t, table, i))));
|
||||
for (unsigned i = 0; i < table->length(); ++i) {
|
||||
GcInnerClassReference* reference
|
||||
= cast<GcInnerClassReference>(t, table->body()[i]);
|
||||
GcByteArray* outer = reference->outer();
|
||||
if (outer and byteArrayEqual(t, outer, c->name())
|
||||
and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) {
|
||||
object inner
|
||||
= getJClass(t, resolveClass(t, c->loader(), reference->inner()));
|
||||
|
||||
-- count;
|
||||
set(t, result, ArrayBody + (count * BytesPerWord), inner);
|
||||
--count;
|
||||
reinterpret_cast<GcArray*>(result)->setBodyElement(t, count, inner);
|
||||
}
|
||||
}
|
||||
|
||||
@ -717,25 +757,22 @@ getDeclaredClasses(Thread* t, object c, bool publicOnly)
|
||||
}
|
||||
}
|
||||
|
||||
return makeObjectArray(t, type(t, Machine::JclassType), 0);
|
||||
return makeObjectArray(t, type(t, GcJclass::Type), 0);
|
||||
}
|
||||
|
||||
object
|
||||
getDeclaringClass(Thread* t, object c)
|
||||
GcJclass* getDeclaringClass(Thread* t, GcClass* c)
|
||||
{
|
||||
object addendum = classAddendum(t, c);
|
||||
GcClassAddendum* addendum = c->addendum();
|
||||
if (addendum) {
|
||||
object table = classAddendumInnerClassTable(t, addendum);
|
||||
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
|
||||
if (table) {
|
||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||
object reference = arrayBody(t, table, i);
|
||||
if (innerClassReferenceOuter(t, reference) and strcmp
|
||||
(&byteArrayBody(t, innerClassReferenceInner(t, reference), 0),
|
||||
&byteArrayBody(t, className(t, c), 0)) == 0)
|
||||
{
|
||||
return getJClass
|
||||
(t, resolveClass
|
||||
(t, classLoader(t, c), innerClassReferenceOuter(t, reference)));
|
||||
for (unsigned i = 0; i < table->length(); ++i) {
|
||||
GcInnerClassReference* reference
|
||||
= cast<GcInnerClassReference>(t, table->body()[i]);
|
||||
if (reference->outer()
|
||||
and strcmp(reference->inner()->body().begin(),
|
||||
c->name()->body().begin()) == 0) {
|
||||
return getJClass(t, resolveClass(t, c->loader(), reference->outer()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -744,28 +781,26 @@ getDeclaringClass(Thread* t, object c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
classModifiers(Thread* t, object c)
|
||||
unsigned classModifiers(Thread* t, GcClass* c)
|
||||
{
|
||||
object addendum = classAddendum(t, c);
|
||||
GcClassAddendum* addendum = c->addendum();
|
||||
if (addendum) {
|
||||
object table = classAddendumInnerClassTable(t, addendum);
|
||||
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
|
||||
if (table) {
|
||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||
object reference = arrayBody(t, table, i);
|
||||
if (0 == strcmp
|
||||
(&byteArrayBody(t, className(t, c), 0),
|
||||
&byteArrayBody(t, innerClassReferenceInner(t, reference), 0)))
|
||||
{
|
||||
return innerClassReferenceFlags(t, reference);
|
||||
for (unsigned i = 0; i < table->length(); ++i) {
|
||||
GcInnerClassReference* reference
|
||||
= cast<GcInnerClassReference>(t, table->body()[i]);
|
||||
if (0 == strcmp(c->name()->body().begin(),
|
||||
reference->inner()->body().begin())) {
|
||||
return reference->flags();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return classFlags(t, c);
|
||||
return c->flags();
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//CLASSPATH_COMMON_H
|
||||
#endif // CLASSPATH_COMMON_H
|
||||
|
@ -12,9 +12,11 @@
|
||||
#define AVIAN_COMMON_H
|
||||
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
# define __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "stdarg.h"
|
||||
#include "stddef.h"
|
||||
@ -29,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
|
||||
|
||||
@ -41,193 +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
|
||||
inline void* operator new(size_t, void* p) throw() { return p; }
|
||||
|
||||
namespace vm {
|
||||
|
||||
inline intptr_alias_t&
|
||||
alias(void* p, unsigned offset)
|
||||
inline intptr_alias_t& alias(void* p, unsigned offset)
|
||||
{
|
||||
return *reinterpret_cast<intptr_alias_t*>(static_cast<uint8_t*>(p) + offset);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
inline int
|
||||
vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
||||
inline int vsnprintf(char* dst, size_t size, const char* format, va_list a)
|
||||
{
|
||||
return vsnprintf_s(dst, size, _TRUNCATE, format, a);
|
||||
}
|
||||
|
||||
inline int
|
||||
snprintf(char* dst, size_t size, const char* format, ...)
|
||||
inline int snprintf(char* dst, size_t size, const char* format, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, format);
|
||||
@ -236,8 +240,7 @@ snprintf(char* dst, size_t size, const char* format, ...)
|
||||
return r;
|
||||
}
|
||||
|
||||
inline FILE*
|
||||
fopen(const char* name, const char* mode)
|
||||
inline FILE* fopen(const char* name, const char* mode)
|
||||
{
|
||||
FILE* file;
|
||||
if (fopen_s(&file, name, mode) == 0) {
|
||||
@ -247,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);
|
||||
@ -265,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
|
||||
@ -382,8 +372,7 @@ getBit(T* map, unsigned i)
|
||||
// a time:
|
||||
|
||||
template <class T>
|
||||
inline void
|
||||
clearBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
inline void clearBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
{
|
||||
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
||||
clearBit<T>(map, i);
|
||||
@ -391,18 +380,19 @@ clearBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void
|
||||
setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
|
||||
inline void setBits(T* map, unsigned bitsPerRecord, int index, unsigned v)
|
||||
{
|
||||
for (int i = index + bitsPerRecord - 1; i >= index; --i) {
|
||||
if (v & 1) markBit<T>(map, i); else clearBit<T>(map, i);
|
||||
if (v & 1)
|
||||
markBit<T>(map, i);
|
||||
else
|
||||
clearBit<T>(map, i);
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline unsigned
|
||||
getBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
inline unsigned getBits(T* map, unsigned bitsPerRecord, unsigned index)
|
||||
{
|
||||
unsigned v = 0;
|
||||
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
||||
@ -413,122 +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 uint32_t
|
||||
hash(const char* s)
|
||||
{
|
||||
uint32_t h = 0;
|
||||
for (unsigned i = 0; s[i]; ++i) {
|
||||
h = (h * 31) + s[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
hash(const uint8_t* s, unsigned length)
|
||||
{
|
||||
uint32_t h = 0;
|
||||
for (unsigned i = 0; i < length; ++i) {
|
||||
h = (h * 31) + s[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
hash(const int8_t* s, unsigned length)
|
||||
{
|
||||
return hash(reinterpret_cast<const uint8_t*>(s), length);
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
hash(const uint16_t* s, unsigned length)
|
||||
{
|
||||
uint32_t h = 0;
|
||||
for (unsigned i = 0; i < length; ++i) {
|
||||
h = (h * 31) + s[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
inline void
|
||||
write4(uint8_t* dst, uint32_t v)
|
||||
inline void write4(uint8_t* dst, uint32_t v)
|
||||
{
|
||||
memcpy(dst, &v, 4);
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
floatToBits(float f)
|
||||
inline uint32_t floatToBits(float f)
|
||||
{
|
||||
uint32_t bits; memcpy(&bits, &f, 4);
|
||||
uint32_t bits;
|
||||
memcpy(&bits, &f, 4);
|
||||
return bits;
|
||||
}
|
||||
|
||||
inline uint64_t
|
||||
doubleToBits(double d)
|
||||
inline uint64_t doubleToBits(double d)
|
||||
{
|
||||
uint64_t bits; memcpy(&bits, &d, 8);
|
||||
uint64_t bits;
|
||||
memcpy(&bits, &d, 8);
|
||||
return bits;
|
||||
}
|
||||
|
||||
inline double
|
||||
bitsToDouble(uint64_t bits)
|
||||
inline double bitsToDouble(uint64_t bits)
|
||||
{
|
||||
double d; memcpy(&d, &bits, 8);
|
||||
double d;
|
||||
memcpy(&d, &bits, 8);
|
||||
return d;
|
||||
}
|
||||
|
||||
inline float
|
||||
bitsToFloat(uint32_t bits)
|
||||
inline float bitsToFloat(uint32_t bits)
|
||||
{
|
||||
float f; memcpy(&f, &bits, 4);
|
||||
float f;
|
||||
memcpy(&f, &bits, 4);
|
||||
return f;
|
||||
}
|
||||
|
||||
inline int
|
||||
difference(void* a, void* b)
|
||||
inline int difference(void* a, void* b)
|
||||
{
|
||||
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void*
|
||||
voidPointer(T function)
|
||||
inline void* voidPointer(T function)
|
||||
{
|
||||
void* p;
|
||||
memcpy(&p, &function, sizeof(void*));
|
||||
return p;
|
||||
}
|
||||
|
||||
inline void
|
||||
replace(char a, char b, char* c)
|
||||
inline void replace(char a, char b, char* c)
|
||||
{
|
||||
for (; *c; ++c) if (*c == a) *c = b;
|
||||
for (; *c; ++c)
|
||||
if (*c == a)
|
||||
*c = b;
|
||||
}
|
||||
|
||||
inline void
|
||||
replace(char a, char b, char* dst, const char* src)
|
||||
inline void replace(char a, char b, char* dst, const char* src)
|
||||
{
|
||||
unsigned i = 0;
|
||||
for (; src[i]; ++ i) {
|
||||
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;
|
||||
@ -537,6 +485,6 @@ equal(const void* a, unsigned al, const void* b, unsigned bl)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif // AVIAN_COMMON_H
|
||||
#endif // AVIAN_COMMON_H
|
||||
|
@ -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
|
||||
|
@ -16,9 +16,10 @@ namespace vm {
|
||||
class Machine;
|
||||
class Thread;
|
||||
|
||||
struct Object { };
|
||||
class GcObject;
|
||||
;
|
||||
|
||||
typedef Object* object;
|
||||
typedef GcObject* object;
|
||||
|
||||
typedef uint8_t jboolean;
|
||||
typedef int8_t jbyte;
|
||||
@ -33,37 +34,50 @@ typedef jint jsize;
|
||||
|
||||
typedef object* jobject;
|
||||
|
||||
typedef jobject jclass;
|
||||
typedef jobject jthrowable;
|
||||
typedef jobject jstring;
|
||||
class GcString;
|
||||
class GcJclass;
|
||||
class GcThrowable;
|
||||
class GcBooleanArray;
|
||||
class GcByteArray;
|
||||
class GcCharArray;
|
||||
class GcShortArray;
|
||||
class GcIntArray;
|
||||
class GcLongArray;
|
||||
class GcFloatArray;
|
||||
class GcDoubleArray;
|
||||
class GcObjectArray;
|
||||
|
||||
typedef GcJclass** jclass;
|
||||
typedef GcThrowable** jthrowable;
|
||||
typedef GcString** jstring;
|
||||
typedef jobject jweak;
|
||||
|
||||
typedef jobject jarray;
|
||||
typedef jarray jbooleanArray;
|
||||
typedef jarray jbyteArray;
|
||||
typedef jarray jcharArray;
|
||||
typedef jarray jshortArray;
|
||||
typedef jarray jintArray;
|
||||
typedef jarray jlongArray;
|
||||
typedef jarray jfloatArray;
|
||||
typedef jarray jdoubleArray;
|
||||
typedef jarray jobjectArray;
|
||||
typedef GcBooleanArray** jbooleanArray;
|
||||
typedef GcByteArray** jbyteArray;
|
||||
typedef GcCharArray** jcharArray;
|
||||
typedef GcShortArray** jshortArray;
|
||||
typedef GcIntArray** jintArray;
|
||||
typedef GcLongArray** jlongArray;
|
||||
typedef GcFloatArray** jfloatArray;
|
||||
typedef GcDoubleArray** jdoubleArray;
|
||||
typedef GcObjectArray** jobjectArray;
|
||||
|
||||
typedef uintptr_t jfieldID;
|
||||
typedef uintptr_t jmethodID;
|
||||
|
||||
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
|
||||
|
3630
src/avian/machine.h
3630
src/avian/machine.h
File diff suppressed because it is too large
Load Diff
@ -18,28 +18,25 @@
|
||||
|
||||
namespace vm {
|
||||
|
||||
inline int16_t
|
||||
codeReadInt16(Thread* t, object code, unsigned& ip)
|
||||
inline int16_t codeReadInt16(Thread* t UNUSED, GcCode* code, unsigned& ip)
|
||||
{
|
||||
uint8_t v1 = codeBody(t, code, ip++);
|
||||
uint8_t v2 = codeBody(t, code, ip++);
|
||||
uint8_t v1 = code->body()[ip++];
|
||||
uint8_t v2 = code->body()[ip++];
|
||||
return ((v1 << 8) | v2);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
codeReadInt32(Thread* t, object code, unsigned& ip)
|
||||
inline int32_t codeReadInt32(Thread* t UNUSED, GcCode* code, unsigned& ip)
|
||||
{
|
||||
uint8_t v1 = codeBody(t, code, ip++);
|
||||
uint8_t v2 = codeBody(t, code, ip++);
|
||||
uint8_t v3 = codeBody(t, code, ip++);
|
||||
uint8_t v4 = codeBody(t, code, ip++);
|
||||
uint8_t v1 = code->body()[ip++];
|
||||
uint8_t v2 = code->body()[ip++];
|
||||
uint8_t v3 = code->body()[ip++];
|
||||
uint8_t v4 = code->body()[ip++];
|
||||
return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4);
|
||||
}
|
||||
|
||||
inline bool
|
||||
isSuperclass(Thread* t, object class_, object base)
|
||||
inline bool isSuperclass(Thread* t UNUSED, GcClass* class_, GcClass* base)
|
||||
{
|
||||
for (object oc = classSuper(t, base); oc; oc = classSuper(t, oc)) {
|
||||
for (GcClass* oc = base->super(); oc; oc = oc->super()) {
|
||||
if (oc == class_) {
|
||||
return true;
|
||||
}
|
||||
@ -47,21 +44,18 @@ isSuperclass(Thread* t, object class_, object base)
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
isSpecialMethod(Thread* t, object method, object class_)
|
||||
inline bool isSpecialMethod(Thread* t, GcMethod* method, GcClass* class_)
|
||||
{
|
||||
return (classFlags(t, class_) & ACC_SUPER)
|
||||
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||
&byteArrayBody(t, methodName(t, method), 0)) != 0
|
||||
and isSuperclass(t, methodClass(t, method), class_);
|
||||
return (class_->flags() & ACC_SUPER)
|
||||
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||
method->name()->body().begin()) != 0
|
||||
and isSuperclass(t, method->class_(), class_);
|
||||
}
|
||||
|
||||
void
|
||||
resolveNative(Thread* t, object method);
|
||||
void resolveNative(Thread* t, GcMethod* method);
|
||||
|
||||
int
|
||||
findLineNumber(Thread* t, object method, unsigned ip);
|
||||
int findLineNumber(Thread* t, GcMethod* method, unsigned ip);
|
||||
|
||||
} // namespace vm
|
||||
} // namespace vm
|
||||
|
||||
#endif//PROCESS_H
|
||||
#endif // PROCESS_H
|
||||
|
@ -32,6 +32,21 @@ class Slice;
|
||||
|
||||
namespace vm {
|
||||
|
||||
class GcByteArray;
|
||||
class GcCode;
|
||||
class GcClass;
|
||||
class GcMethod;
|
||||
class GcMethodAddendum;
|
||||
class GcIntArray;
|
||||
class GcContinuation;
|
||||
class GcThrowable;
|
||||
class GcThread;
|
||||
class GcClassAddendum;
|
||||
class GcClassLoader;
|
||||
class GcArray;
|
||||
class GcSingleton;
|
||||
class GcTriple;
|
||||
|
||||
class Processor {
|
||||
public:
|
||||
class StackWalker;
|
||||
@ -45,7 +60,7 @@ class Processor {
|
||||
public:
|
||||
virtual void walk(StackVisitor* v) = 0;
|
||||
|
||||
virtual object method() = 0;
|
||||
virtual GcMethod* method() = 0;
|
||||
|
||||
virtual int ip() = 0;
|
||||
|
||||
@ -54,139 +69,136 @@ class Processor {
|
||||
|
||||
class CompilationHandler {
|
||||
public:
|
||||
virtual void compiled(const void* code, unsigned size, unsigned frameSize, const char* name) = 0;
|
||||
virtual void compiled(const void* code,
|
||||
unsigned size,
|
||||
unsigned frameSize,
|
||||
const char* name) = 0;
|
||||
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
virtual Thread*
|
||||
makeThread(Machine* m, object javaThread, Thread* parent) = 0;
|
||||
virtual Thread* makeThread(Machine* m, GcThread* javaThread, Thread* parent)
|
||||
= 0;
|
||||
|
||||
virtual object
|
||||
makeMethod(Thread* t,
|
||||
uint8_t vmFlags,
|
||||
uint8_t returnCode,
|
||||
uint8_t parameterCount,
|
||||
uint8_t parameterFootprint,
|
||||
uint16_t flags,
|
||||
uint16_t offset,
|
||||
object name,
|
||||
object spec,
|
||||
object addendum,
|
||||
object class_,
|
||||
object code) = 0;
|
||||
virtual GcMethod* makeMethod(Thread* t,
|
||||
uint8_t vmFlags,
|
||||
uint8_t returnCode,
|
||||
uint8_t parameterCount,
|
||||
uint8_t parameterFootprint,
|
||||
uint16_t flags,
|
||||
uint16_t offset,
|
||||
GcByteArray* name,
|
||||
GcByteArray* spec,
|
||||
GcMethodAddendum* addendum,
|
||||
GcClass* class_,
|
||||
GcCode* code) = 0;
|
||||
|
||||
virtual object
|
||||
makeClass(Thread* t,
|
||||
uint16_t flags,
|
||||
uint16_t vmFlags,
|
||||
uint16_t fixedSize,
|
||||
uint8_t arrayElementSize,
|
||||
uint8_t arrayDimensions,
|
||||
object objectMask,
|
||||
object name,
|
||||
object sourceFile,
|
||||
object super,
|
||||
object interfaceTable,
|
||||
object virtualTable,
|
||||
object fieldTable,
|
||||
object methodTable,
|
||||
object addendum,
|
||||
object staticTable,
|
||||
object loader,
|
||||
unsigned vtableLength) = 0;
|
||||
virtual GcClass* makeClass(Thread* t,
|
||||
uint16_t flags,
|
||||
uint16_t vmFlags,
|
||||
uint16_t fixedSize,
|
||||
uint8_t arrayElementSize,
|
||||
uint8_t arrayDimensions,
|
||||
GcClass* arrayElementClass,
|
||||
GcIntArray* objectMask,
|
||||
GcByteArray* name,
|
||||
GcByteArray* sourceFile,
|
||||
GcClass* super,
|
||||
object interfaceTable,
|
||||
object virtualTable,
|
||||
object fieldTable,
|
||||
object methodTable,
|
||||
GcClassAddendum* addendum,
|
||||
GcSingleton* staticTable,
|
||||
GcClassLoader* loader,
|
||||
unsigned vtableLength) = 0;
|
||||
|
||||
virtual void
|
||||
initVtable(Thread* t, object c) = 0;
|
||||
virtual void initVtable(Thread* t, GcClass* c) = 0;
|
||||
|
||||
virtual void
|
||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||
virtual void visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||
|
||||
virtual void
|
||||
walkStack(Thread* t, StackVisitor* v) = 0;
|
||||
virtual void walkStack(Thread* t, StackVisitor* v) = 0;
|
||||
|
||||
virtual int
|
||||
lineNumber(Thread* t, object method, int ip) = 0;
|
||||
virtual int lineNumber(Thread* t, GcMethod* method, int ip) = 0;
|
||||
|
||||
virtual object*
|
||||
makeLocalReference(Thread* t, object o) = 0;
|
||||
virtual object* makeLocalReference(Thread* t, object o) = 0;
|
||||
|
||||
virtual void
|
||||
disposeLocalReference(Thread* t, object* r) = 0;
|
||||
virtual void disposeLocalReference(Thread* t, object* r) = 0;
|
||||
|
||||
virtual bool
|
||||
pushLocalFrame(Thread* t, unsigned capacity) = 0;
|
||||
virtual bool pushLocalFrame(Thread* t, unsigned capacity) = 0;
|
||||
|
||||
virtual void
|
||||
popLocalFrame(Thread* t) = 0;
|
||||
virtual void popLocalFrame(Thread* t) = 0;
|
||||
|
||||
virtual object
|
||||
invokeArray(Thread* t, object method, object this_, object arguments) = 0;
|
||||
virtual object invokeArray(Thread* t,
|
||||
GcMethod* method,
|
||||
object this_,
|
||||
object arguments) = 0;
|
||||
|
||||
virtual object
|
||||
invokeArray(Thread* t, object method, object this_, const jvalue* arguments)
|
||||
= 0;
|
||||
virtual object invokeArray(Thread* t,
|
||||
GcMethod* method,
|
||||
object this_,
|
||||
const jvalue* arguments) = 0;
|
||||
|
||||
virtual object
|
||||
invokeList(Thread* t, object method, object this_, bool indirectObjects,
|
||||
va_list arguments) = 0;
|
||||
virtual object invokeList(Thread* t,
|
||||
GcMethod* method,
|
||||
object this_,
|
||||
bool indirectObjects,
|
||||
va_list arguments) = 0;
|
||||
|
||||
virtual object
|
||||
invokeList(Thread* t, object loader, const char* className,
|
||||
const char* methodName, const char* methodSpec,
|
||||
object this_, va_list arguments) = 0;
|
||||
virtual object invokeList(Thread* t,
|
||||
GcClassLoader* loader,
|
||||
const char* className,
|
||||
const char* methodName,
|
||||
const char* methodSpec,
|
||||
object this_,
|
||||
va_list arguments) = 0;
|
||||
|
||||
virtual void
|
||||
dispose(Thread* t) = 0;
|
||||
virtual void dispose(Thread* t) = 0;
|
||||
|
||||
virtual void
|
||||
dispose() = 0;
|
||||
virtual void dispose() = 0;
|
||||
|
||||
virtual object
|
||||
getStackTrace(Thread* t, Thread* target) = 0;
|
||||
virtual object getStackTrace(Thread* t, Thread* target) = 0;
|
||||
|
||||
virtual void initialize(BootImage* image, avian::util::Slice<uint8_t> code)
|
||||
= 0;
|
||||
|
||||
virtual void
|
||||
addCompilationHandler(CompilationHandler* handler) = 0;
|
||||
virtual void addCompilationHandler(CompilationHandler* handler) = 0;
|
||||
|
||||
virtual void
|
||||
compileMethod(Thread* t, Zone* zone, object* constants, object* calls,
|
||||
avian::codegen::DelayedPromise** addresses, object method,
|
||||
OffsetResolver* resolver) = 0;
|
||||
virtual void compileMethod(Thread* t,
|
||||
Zone* zone,
|
||||
GcTriple** constants,
|
||||
GcTriple** calls,
|
||||
avian::codegen::DelayedPromise** addresses,
|
||||
GcMethod* method,
|
||||
OffsetResolver* resolver) = 0;
|
||||
|
||||
virtual void
|
||||
visitRoots(Thread* t, HeapWalker* w) = 0;
|
||||
virtual void visitRoots(Thread* t, HeapWalker* w) = 0;
|
||||
|
||||
virtual void
|
||||
normalizeVirtualThunks(Thread* t) = 0;
|
||||
virtual void normalizeVirtualThunks(Thread* t) = 0;
|
||||
|
||||
virtual unsigned*
|
||||
makeCallTable(Thread* t, HeapWalker* w) = 0;
|
||||
virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) = 0;
|
||||
|
||||
virtual void
|
||||
boot(Thread* t, BootImage* image, uint8_t* code) = 0;
|
||||
virtual void boot(Thread* t, BootImage* image, uint8_t* code) = 0;
|
||||
|
||||
virtual void
|
||||
callWithCurrentContinuation(Thread* t, object receiver) = 0;
|
||||
virtual void callWithCurrentContinuation(Thread* t, object receiver) = 0;
|
||||
|
||||
virtual void
|
||||
dynamicWind(Thread* t, object before, object thunk, object after) = 0;
|
||||
virtual void dynamicWind(Thread* t, object before, object thunk, object after)
|
||||
= 0;
|
||||
|
||||
virtual void
|
||||
feedResultToContinuation(Thread* t, object continuation, object result) = 0;
|
||||
virtual void feedResultToContinuation(Thread* t,
|
||||
GcContinuation* continuation,
|
||||
object result) = 0;
|
||||
|
||||
virtual void
|
||||
feedExceptionToContinuation(Thread* t, object continuation,
|
||||
object exception) = 0;
|
||||
virtual void feedExceptionToContinuation(Thread* t,
|
||||
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, object method, object this_, ...)
|
||||
object invoke(Thread* t, GcMethod* method, object this_, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, this_);
|
||||
@ -198,15 +210,19 @@ class Processor {
|
||||
return r;
|
||||
}
|
||||
|
||||
object
|
||||
invoke(Thread* t, object loader, const char* className,
|
||||
const char* methodName, const char* methodSpec, object this_, ...)
|
||||
object invoke(Thread* t,
|
||||
GcClassLoader* loader,
|
||||
const char* className,
|
||||
const char* methodName,
|
||||
const char* methodSpec,
|
||||
object this_,
|
||||
...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, this_);
|
||||
|
||||
object r = invokeList
|
||||
(t, loader, className, methodName, methodSpec, this_, a);
|
||||
object r
|
||||
= invokeList(t, loader, className, methodName, methodSpec, this_, a);
|
||||
|
||||
va_end(a);
|
||||
|
||||
@ -219,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);
|
||||
}
|
||||
@ -116,15 +102,14 @@ typedef int64_t target_intptr_t;
|
||||
|
||||
const unsigned TargetClassFixedSize = 12;
|
||||
const unsigned TargetClassArrayElementSize = 14;
|
||||
const unsigned TargetClassVtable = 128;
|
||||
const unsigned TargetClassVtable = 136;
|
||||
|
||||
const unsigned TargetFieldOffset = 12;
|
||||
|
||||
# elif (TARGET_BYTES_PER_WORD == 4)
|
||||
#elif(TARGET_BYTES_PER_WORD == 4)
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
targetVW(T v)
|
||||
inline T targetVW(T v)
|
||||
{
|
||||
return targetV4(v);
|
||||
}
|
||||
@ -134,15 +119,15 @@ typedef int32_t target_intptr_t;
|
||||
|
||||
const unsigned TargetClassFixedSize = 8;
|
||||
const unsigned TargetClassArrayElementSize = 10;
|
||||
const unsigned TargetClassVtable = 68;
|
||||
const unsigned TargetClassVtable = 72;
|
||||
|
||||
const unsigned TargetFieldOffset = 8;
|
||||
|
||||
# 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
|
||||
|
175
src/avian/util.h
175
src/avian/util.h
@ -16,49 +16,58 @@
|
||||
|
||||
namespace vm {
|
||||
|
||||
object
|
||||
hashMapFindNode(Thread* t, object map, object key,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object));
|
||||
GcTriple* hashMapFindNode(Thread* t,
|
||||
GcHashMap* map,
|
||||
object key,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object));
|
||||
|
||||
inline object
|
||||
hashMapFind(Thread* t, object map, object key,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object))
|
||||
inline object hashMapFind(Thread* t,
|
||||
GcHashMap* map,
|
||||
object key,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object))
|
||||
{
|
||||
object n = hashMapFindNode(t, map, key, hash, equal);
|
||||
return (n ? tripleSecond(t, n) : 0);
|
||||
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
|
||||
return (n ? n->second() : 0);
|
||||
}
|
||||
|
||||
void
|
||||
hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
|
||||
unsigned size);
|
||||
|
||||
void
|
||||
hashMapInsert(Thread* t, object map, object key, object value,
|
||||
uint32_t (*hash)(Thread*, object));
|
||||
|
||||
inline bool
|
||||
hashMapInsertOrReplace(Thread* t, object map, object key, object value,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object))
|
||||
{
|
||||
object n = hashMapFindNode(t, map, key, hash, equal);
|
||||
if (n == 0) {
|
||||
hashMapInsert(t, map, key, value, hash);
|
||||
return true;
|
||||
} else {
|
||||
set(t, n, TripleSecond, value);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
hashMapInsertMaybe(Thread* t, object map, object key, object value,
|
||||
void hashMapResize(Thread* t,
|
||||
GcHashMap* map,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object))
|
||||
unsigned size);
|
||||
|
||||
void hashMapInsert(Thread* t,
|
||||
GcHashMap* map,
|
||||
object key,
|
||||
object value,
|
||||
uint32_t (*hash)(Thread*, object));
|
||||
|
||||
inline bool hashMapInsertOrReplace(Thread* t,
|
||||
GcHashMap* map,
|
||||
object key,
|
||||
object value,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object))
|
||||
{
|
||||
object n = hashMapFindNode(t, map, key, hash, equal);
|
||||
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
|
||||
if (n == 0) {
|
||||
hashMapInsert(t, map, key, value, hash);
|
||||
return true;
|
||||
} else {
|
||||
n->setSecond(t, value);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool hashMapInsertMaybe(Thread* t,
|
||||
GcHashMap* map,
|
||||
object key,
|
||||
object value,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object))
|
||||
{
|
||||
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
|
||||
if (n == 0) {
|
||||
hashMapInsert(t, map, key, value, hash);
|
||||
return true;
|
||||
@ -67,53 +76,58 @@ hashMapInsertMaybe(Thread* t, object map, object key, object value,
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
hashMapRemove(Thread* t, object map, object key,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object));
|
||||
object hashMapRemove(Thread* t,
|
||||
GcHashMap* map,
|
||||
object key,
|
||||
uint32_t (*hash)(Thread*, object),
|
||||
bool (*equal)(Thread*, object, object));
|
||||
|
||||
object
|
||||
hashMapIterator(Thread* t, object map);
|
||||
object hashMapIterator(Thread* t, GcHashMap* map);
|
||||
|
||||
object
|
||||
hashMapIteratorNext(Thread* t, object it);
|
||||
object hashMapIteratorNext(Thread* t, object it);
|
||||
|
||||
void
|
||||
listAppend(Thread* t, object list, object value);
|
||||
void listAppend(Thread* t, GcList* list, object value);
|
||||
|
||||
object
|
||||
vectorAppend(Thread* t, object vector, object value);
|
||||
GcVector* vectorAppend(Thread* t, GcVector* vector, object value);
|
||||
|
||||
object
|
||||
growArray(Thread* t, object array);
|
||||
object growArray(Thread* t, object array);
|
||||
|
||||
object
|
||||
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
|
||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||
object treeQuery(Thread* t,
|
||||
GcTreeNode* tree,
|
||||
intptr_t key,
|
||||
GcTreeNode* sentinal,
|
||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||
|
||||
object
|
||||
treeInsert(Thread* t, Zone* zone, object tree, intptr_t key, object value,
|
||||
object sentinal,
|
||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||
GcTreeNode* treeInsert(Thread* t,
|
||||
Zone* zone,
|
||||
GcTreeNode* tree,
|
||||
intptr_t key,
|
||||
object value,
|
||||
GcTreeNode* sentinal,
|
||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||
|
||||
void
|
||||
treeUpdate(Thread* t, object tree, intptr_t key, object value, object sentinal,
|
||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||
void treeUpdate(Thread* t,
|
||||
GcTreeNode* tree,
|
||||
intptr_t key,
|
||||
object value,
|
||||
GcTreeNode* sentinal,
|
||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||
|
||||
class HashMapIterator: public Thread::Protector {
|
||||
class HashMapIterator : public Thread::Protector {
|
||||
public:
|
||||
HashMapIterator(Thread* t, object map):
|
||||
Protector(t), map(map), node(0), index(0)
|
||||
HashMapIterator(Thread* t, GcHashMap* map)
|
||||
: Protector(t), map(map), node(0), index(0)
|
||||
{
|
||||
find();
|
||||
}
|
||||
|
||||
void find() {
|
||||
object array = hashMapArray(t, map);
|
||||
void find()
|
||||
{
|
||||
GcArray* array = map->array();
|
||||
if (array) {
|
||||
for (unsigned i = index; i < arrayLength(t, array); ++i) {
|
||||
if (arrayBody(t, array, i)) {
|
||||
node = arrayBody(t, array, i);
|
||||
for (unsigned i = index; i < array->length(); ++i) {
|
||||
if (array->body()[i]) {
|
||||
node = cast<GcTriple>(t, array->body()[i]);
|
||||
index = i + 1;
|
||||
return;
|
||||
}
|
||||
@ -122,15 +136,17 @@ class HashMapIterator: public Thread::Protector {
|
||||
node = 0;
|
||||
}
|
||||
|
||||
bool hasMore() {
|
||||
bool hasMore()
|
||||
{
|
||||
return node != 0;
|
||||
}
|
||||
|
||||
object next() {
|
||||
GcTriple* next()
|
||||
{
|
||||
if (node) {
|
||||
object n = node;
|
||||
if (tripleThird(t, node)) {
|
||||
node = tripleThird(t, node);
|
||||
GcTriple* n = node;
|
||||
if (node->third()) {
|
||||
node = cast<GcTriple>(t, node->third());
|
||||
} else {
|
||||
find();
|
||||
}
|
||||
@ -140,16 +156,17 @@ class HashMapIterator: public Thread::Protector {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(Heap::Visitor* v) {
|
||||
virtual void visit(Heap::Visitor* v)
|
||||
{
|
||||
v->visit(&map);
|
||||
v->visit(&node);
|
||||
}
|
||||
|
||||
object map;
|
||||
object node;
|
||||
GcHashMap* map;
|
||||
GcTriple* node;
|
||||
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,7 +146,8 @@ class Zone : public avian::util::Allocator {
|
||||
segment = s;
|
||||
}
|
||||
|
||||
virtual void free(const void*, unsigned) {
|
||||
virtual void free(const void*, unsigned)
|
||||
{
|
||||
// not supported
|
||||
abort(s);
|
||||
}
|
||||
@ -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);
|
||||
|
805
src/builtin.cpp
805
src/builtin.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
@ -73,7 +74,7 @@ class LogicalCode {
|
||||
= logicalCode.cloneAndSet(zone, logicalCode.count + more, 0);
|
||||
|
||||
for (size_t i = 0; i < logicalCode.count; i++) {
|
||||
assert((vm::System*)0, logicalCode[i] == newCode[i]);
|
||||
assertT((vm::System*)0, logicalCode[i] == newCode[i]);
|
||||
}
|
||||
|
||||
logicalCode = newCode;
|
||||
@ -93,7 +94,9 @@ class LogicalCode {
|
||||
|
||||
class Context {
|
||||
public:
|
||||
Context(vm::System* system, Assembler* assembler, vm::Zone* zone,
|
||||
Context(vm::System* system,
|
||||
Assembler* assembler,
|
||||
vm::Zone* zone,
|
||||
Compiler::Client* client);
|
||||
|
||||
vm::System* system;
|
||||
@ -128,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,14 +19,15 @@ 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) {
|
||||
assert(c, localIndex >= 0);
|
||||
int frameIndex(Context* c, int localIndex)
|
||||
{
|
||||
assertT(c, localIndex >= 0);
|
||||
|
||||
int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1;
|
||||
|
||||
@ -36,66 +37,75 @@ int frameIndex(Context* c, int localIndex) {
|
||||
index -= c->arch->frameFooterSize();
|
||||
}
|
||||
|
||||
assert(c, index >= 0);
|
||||
assert(c, static_cast<unsigned>(index) < totalFrameSize(c));
|
||||
assertT(c, index >= 0);
|
||||
assertT(c, static_cast<unsigned>(index) < totalFrameSize(c));
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
unsigned frameIndexToOffset(Context* c, unsigned frameIndex) {
|
||||
assert(c, frameIndex < totalFrameSize(c));
|
||||
unsigned frameIndexToOffset(Context* c, unsigned frameIndex)
|
||||
{
|
||||
assertT(c, frameIndex < totalFrameSize(c));
|
||||
|
||||
return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize;
|
||||
}
|
||||
|
||||
unsigned offsetToFrameIndex(Context* c, unsigned offset) {
|
||||
assert(c,
|
||||
static_cast<int>((offset / c->targetInfo.pointerSize)
|
||||
- c->arch->frameFooterSize()) >= 0);
|
||||
assert(c,
|
||||
((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize())
|
||||
< totalFrameSize(c));
|
||||
unsigned offsetToFrameIndex(Context* c, unsigned offset)
|
||||
{
|
||||
assertT(c,
|
||||
static_cast<int>((offset / c->targetInfo.pointerSize)
|
||||
- c->arch->frameFooterSize()) >= 0);
|
||||
assertT(c,
|
||||
((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize())
|
||||
< totalFrameSize(c));
|
||||
|
||||
return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize();
|
||||
}
|
||||
|
||||
unsigned frameBase(Context* c) {
|
||||
return c->alignedFrameSize
|
||||
- c->arch->frameReturnAddressSize()
|
||||
- c->arch->frameFooterSize()
|
||||
+ c->arch->frameHeaderSize();
|
||||
unsigned frameBase(Context* c)
|
||||
{
|
||||
return c->alignedFrameSize - c->arch->frameReturnAddressSize()
|
||||
- c->arch->frameFooterSize() + c->arch->frameHeaderSize();
|
||||
}
|
||||
|
||||
FrameIterator::Element::Element(Value* value, unsigned localIndex):
|
||||
value(value), localIndex(localIndex)
|
||||
{ }
|
||||
FrameIterator::Element::Element(Value* value, unsigned localIndex)
|
||||
: value(value), localIndex(localIndex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int FrameIterator::Element::frameIndex(Context* c) {
|
||||
int FrameIterator::Element::frameIndex(Context* c)
|
||||
{
|
||||
return compiler::frameIndex(c, this->localIndex);
|
||||
}
|
||||
|
||||
FrameIterator::FrameIterator(Context* c, Stack* stack, Local* locals,
|
||||
bool includeEmpty):
|
||||
stack(stack), locals(locals), localIndex(c->localFootprint - 1),
|
||||
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,15 +18,18 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
CodePromise::CodePromise(Context* c, CodePromise* next):
|
||||
c(c), offset(0), next(next)
|
||||
{ }
|
||||
CodePromise::CodePromise(Context* c, CodePromise* next)
|
||||
: c(c), offset(0), next(next)
|
||||
{
|
||||
}
|
||||
|
||||
CodePromise::CodePromise(Context* c, Promise* offset):
|
||||
c(c), offset(offset), next(0)
|
||||
{ }
|
||||
CodePromise::CodePromise(Context* c, Promise* offset)
|
||||
: c(c), offset(offset), next(0)
|
||||
{
|
||||
}
|
||||
|
||||
int64_t CodePromise::value() {
|
||||
int64_t CodePromise::value()
|
||||
{
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
|
||||
}
|
||||
@ -34,61 +37,73 @@ int64_t CodePromise::value() {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
bool CodePromise::resolved() {
|
||||
bool CodePromise::resolved()
|
||||
{
|
||||
return c->machineCode != 0 and offset and offset->resolved();
|
||||
}
|
||||
|
||||
CodePromise* codePromise(Context* c, Promise* offset) {
|
||||
CodePromise* codePromise(Context* c, Promise* offset)
|
||||
{
|
||||
return new (c->zone) CodePromise(c, offset);
|
||||
}
|
||||
|
||||
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) {
|
||||
Promise* shiftMaskPromise(Context* c,
|
||||
Promise* base,
|
||||
unsigned shift,
|
||||
int64_t mask)
|
||||
{
|
||||
return new (c->zone) ShiftMaskPromise(base, shift, mask);
|
||||
}
|
||||
|
||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high) {
|
||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high)
|
||||
{
|
||||
return new (c->zone) CombinedPromise(low, high);
|
||||
}
|
||||
|
||||
Promise* resolvedPromise(Context* c, int64_t value) {
|
||||
Promise* resolvedPromise(Context* c, int64_t value)
|
||||
{
|
||||
return new (c->zone) ResolvedPromise(value);
|
||||
}
|
||||
|
||||
class IpPromise: public Promise {
|
||||
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
|
||||
@ -99,7 +114,8 @@ class PoolPromise: public Promise {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
virtual bool resolved()
|
||||
{
|
||||
return c->machineCode != 0;
|
||||
}
|
||||
|
||||
@ -107,11 +123,11 @@ class PoolPromise: public Promise {
|
||||
int key;
|
||||
};
|
||||
|
||||
Promise* poolPromise(Context* c, int key) {
|
||||
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) {
|
||||
assert(c, next_ == 0);
|
||||
void SingleRead::append(Context* c UNUSED, Read* r)
|
||||
{
|
||||
assertT(c, next_ == 0);
|
||||
next_ = r;
|
||||
}
|
||||
|
||||
Read* SingleRead::next(Context*) {
|
||||
Read* SingleRead::next(Context*)
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
MultiRead::MultiRead():
|
||||
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
||||
{ }
|
||||
MultiRead::MultiRead()
|
||||
: reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool MultiRead::intersect(SiteMask* mask, unsigned depth) {
|
||||
bool MultiRead::intersect(SiteMask* mask, unsigned depth)
|
||||
{
|
||||
if (depth > 0) {
|
||||
// short-circuit recursion to avoid poor performance in
|
||||
// deeply-nested branches
|
||||
@ -81,11 +89,13 @@ bool MultiRead::intersect(SiteMask* mask, unsigned depth) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Value* MultiRead::successor() {
|
||||
Value* MultiRead::successor()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MultiRead::valid() {
|
||||
bool MultiRead::valid()
|
||||
{
|
||||
bool result = false;
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
@ -103,7 +113,8 @@ bool MultiRead::valid() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void MultiRead::append(Context* c, Read* r) {
|
||||
void MultiRead::append(Context* c, Read* r)
|
||||
{
|
||||
List<Read*>* cell = cons<Read*>(c, r, 0);
|
||||
if (lastRead == 0) {
|
||||
reads = cell;
|
||||
@ -112,19 +123,25 @@ void MultiRead::append(Context* c, Read* r) {
|
||||
}
|
||||
lastRead = cell;
|
||||
|
||||
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
||||
if (false) {
|
||||
fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
||||
}
|
||||
|
||||
lastTarget->item = r;
|
||||
}
|
||||
|
||||
Read* MultiRead::next(Context* c) {
|
||||
Read* MultiRead::next(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
void MultiRead::allocateTarget(Context* c) {
|
||||
void MultiRead::allocateTarget(Context* c)
|
||||
{
|
||||
List<Read*>* cell = cons<Read*>(c, 0, 0);
|
||||
|
||||
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
||||
if (false) {
|
||||
fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
||||
}
|
||||
|
||||
if (lastTarget) {
|
||||
lastTarget->next = cell;
|
||||
@ -134,20 +151,23 @@ void MultiRead::allocateTarget(Context* c) {
|
||||
lastTarget = cell;
|
||||
}
|
||||
|
||||
Read* MultiRead::nextTarget() {
|
||||
// fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
|
||||
Read* MultiRead::nextTarget()
|
||||
{
|
||||
if (false) {
|
||||
fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
|
||||
}
|
||||
|
||||
Read* r = firstTarget->item;
|
||||
firstTarget = firstTarget->next;
|
||||
return r;
|
||||
}
|
||||
|
||||
StubRead::StubRead() : next_(0), read(0), visited(false), valid_(true)
|
||||
{
|
||||
}
|
||||
|
||||
StubRead::StubRead():
|
||||
next_(0), read(0), visited(false), valid_(true)
|
||||
{ }
|
||||
|
||||
bool StubRead::intersect(SiteMask* mask, unsigned depth) {
|
||||
bool StubRead::intersect(SiteMask* mask, unsigned depth)
|
||||
{
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
if (read) {
|
||||
@ -161,31 +181,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) {
|
||||
assert(c, next_ == 0);
|
||||
void StubRead::append(Context* c UNUSED, Read* r)
|
||||
{
|
||||
assertT(c, next_ == 0);
|
||||
next_ = r;
|
||||
}
|
||||
|
||||
Read* StubRead::next(Context*) {
|
||||
Read* StubRead::next(Context*)
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
SingleRead* read(Context* c, const SiteMask& mask, Value* successor)
|
||||
{
|
||||
assertT(c,
|
||||
(mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
|
||||
|
||||
|
||||
SingleRead* read(Context* c, const SiteMask& mask, Value* successor) {
|
||||
assert(c, (mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
|
||||
|
||||
return new(c->zone) SingleRead(mask, successor);
|
||||
return new (c->zone) SingleRead(mask, successor);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -22,13 +22,16 @@ class Event;
|
||||
|
||||
class Read {
|
||||
public:
|
||||
Read():
|
||||
value(0), event(0), eventNext(0)
|
||||
{ }
|
||||
Read() : value(0), event(0), eventNext(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0;
|
||||
|
||||
virtual Value* high(Context* c) { abort(c); }
|
||||
virtual Value* high(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual Value* successor() = 0;
|
||||
|
||||
@ -43,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);
|
||||
|
||||
@ -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,27 +20,28 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile):
|
||||
a(a),
|
||||
registerFile(registerFile)
|
||||
{ }
|
||||
|
||||
RegisterAllocator::RegisterAllocator(Aborter* a,
|
||||
const RegisterFile* registerFile)
|
||||
: a(a), registerFile(registerFile)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned totalFrameSize(Context* c);
|
||||
Read* live(Context* c UNUSED, Value* v);
|
||||
|
||||
unsigned
|
||||
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
|
||||
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;
|
||||
unsigned baseCost = costCalculator ? costCalculator->cost(c, mask) : 0;
|
||||
|
||||
if (r->value) {
|
||||
assert(c, r->value->findSite(r->site));
|
||||
assertT(c, r->value->findSite(r->site));
|
||||
|
||||
if (v and r->value->isBuddyOf(v)) {
|
||||
return baseCost;
|
||||
@ -55,15 +56,23 @@ resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
|
||||
unsigned* cost, CostCalculator* costCalculator)
|
||||
bool pickRegisterTarget(Context* c,
|
||||
int i,
|
||||
Value* v,
|
||||
uint32_t mask,
|
||||
int* target,
|
||||
unsigned* cost,
|
||||
CostCalculator* costCalculator)
|
||||
{
|
||||
if ((1 << i) & mask) {
|
||||
RegisterResource* r = c->registerResources + i;
|
||||
unsigned myCost = resourceCost
|
||||
(c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator)
|
||||
+ Target::MinimumRegisterCost;
|
||||
unsigned myCost
|
||||
= resourceCost(
|
||||
c,
|
||||
v,
|
||||
r,
|
||||
SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex),
|
||||
costCalculator) + Target::MinimumRegisterCost;
|
||||
|
||||
if ((static_cast<uint32_t>(1) << i) == mask) {
|
||||
*cost = myCost;
|
||||
@ -76,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;
|
||||
|
||||
@ -165,14 +179,16 @@ pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
|
||||
return best;
|
||||
}
|
||||
|
||||
Target
|
||||
pickTarget(Context* c, Value* value, const SiteMask& mask,
|
||||
unsigned registerPenalty, Target best,
|
||||
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,13 +304,12 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
||||
}
|
||||
|
||||
if (best.cost >= Target::StealUniquePenalty
|
||||
and c->availableGeneralRegisterCount == 0)
|
||||
{
|
||||
and c->availableGeneralRegisterCount == 0) {
|
||||
// there are no free registers left, so moving from memory to
|
||||
// memory isn't an option - try harder to find an available frame
|
||||
// site:
|
||||
best = pickAnyFrameTarget(c, value, costCalculator);
|
||||
assert(c, best.cost <= 3);
|
||||
assertT(c, best.cost <= 3);
|
||||
}
|
||||
|
||||
if (best.cost == Target::Impossible) {
|
||||
@ -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,160 +18,179 @@ namespace compiler {
|
||||
|
||||
const bool DebugResources = false;
|
||||
|
||||
|
||||
void steal(Context* c, Resource* r, Value* thief);
|
||||
|
||||
void decrementAvailableGeneralRegisterCount(Context* c) {
|
||||
assert(c, c->availableGeneralRegisterCount);
|
||||
-- c->availableGeneralRegisterCount;
|
||||
void decrementAvailableGeneralRegisterCount(Context* c)
|
||||
{
|
||||
assertT(c, c->availableGeneralRegisterCount);
|
||||
--c->availableGeneralRegisterCount;
|
||||
|
||||
if (DebugResources) {
|
||||
fprintf(stderr, "%d registers available\n",
|
||||
c->availableGeneralRegisterCount);
|
||||
fprintf(
|
||||
stderr, "%d registers available\n", c->availableGeneralRegisterCount);
|
||||
}
|
||||
}
|
||||
|
||||
void incrementAvailableGeneralRegisterCount(Context* c) {
|
||||
++ 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);
|
||||
}
|
||||
|
||||
assert(c, r->freezeCount);
|
||||
assertT(c, r->freezeCount);
|
||||
|
||||
-- r->freezeCount;
|
||||
--r->freezeCount;
|
||||
}
|
||||
}
|
||||
|
||||
Resource::Resource(bool reserved)
|
||||
: value(0),
|
||||
site(0),
|
||||
previousAcquired(0),
|
||||
nextAcquired(0),
|
||||
freezeCount(0),
|
||||
referenceCount(0),
|
||||
reserved(reserved)
|
||||
{
|
||||
}
|
||||
|
||||
Resource::Resource(bool reserved):
|
||||
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);
|
||||
}
|
||||
|
||||
assert(c, this->referenceCount > 0);
|
||||
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) {
|
||||
assert(c, value);
|
||||
assert(c, site);
|
||||
void acquire(Context* c, Resource* resource, Value* value, Site* site)
|
||||
{
|
||||
assertT(c, value);
|
||||
assertT(c, site);
|
||||
|
||||
if (not resource->reserved) {
|
||||
if (DebugResources) {
|
||||
char buffer[256]; resource->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
resource->toString(c, buffer, 256);
|
||||
fprintf(stderr, "%p acquire %s\n", value, buffer);
|
||||
}
|
||||
|
||||
if (resource->value) {
|
||||
assert(c, resource->value->findSite(resource->site));
|
||||
assert(c, not value->findSite(resource->site));
|
||||
assertT(c, resource->value->findSite(resource->site));
|
||||
assertT(c, not value->findSite(resource->site));
|
||||
|
||||
steal(c, resource, value);
|
||||
}
|
||||
@ -187,18 +206,23 @@ void acquire(Context* c, Resource* resource, Value* value, Site* site) {
|
||||
}
|
||||
}
|
||||
|
||||
void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNUSED) {
|
||||
void release(Context* c,
|
||||
Resource* resource,
|
||||
Value* value UNUSED,
|
||||
Site* site UNUSED)
|
||||
{
|
||||
if (not resource->reserved) {
|
||||
if (DebugResources) {
|
||||
char buffer[256]; resource->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
resource->toString(c, buffer, 256);
|
||||
fprintf(stderr, "%p release %s\n", resource->value, buffer);
|
||||
}
|
||||
|
||||
assert(c, resource->value);
|
||||
assert(c, resource->site);
|
||||
assertT(c, resource->value);
|
||||
assertT(c, resource->site);
|
||||
|
||||
assert(c, resource->value->isBuddyOf(value));
|
||||
assert(c, site == resource->site);
|
||||
assertT(c, resource->value->isBuddyOf(value));
|
||||
assertT(c, site == resource->site);
|
||||
|
||||
Resource* next = resource->nextAcquired;
|
||||
if (next) {
|
||||
@ -211,7 +235,7 @@ void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNU
|
||||
previous->nextAcquired = next;
|
||||
resource->previousAcquired = 0;
|
||||
} else {
|
||||
assert(c, c->acquiredResources == resource);
|
||||
assertT(c, c->acquiredResources == resource);
|
||||
c->acquiredResources = next;
|
||||
}
|
||||
|
||||
@ -220,7 +244,6 @@ void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNU
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // 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,118 +119,135 @@ 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)
|
||||
{
|
||||
assert(c, high == this);
|
||||
assertT(c, high == this);
|
||||
|
||||
new (result) lir::Address(address);
|
||||
}
|
||||
|
||||
virtual Site* copy(Context* c) {
|
||||
virtual Site* copy(Context* c)
|
||||
{
|
||||
return addressSite(c, address);
|
||||
}
|
||||
|
||||
virtual Site* copyLow(Context* c) {
|
||||
virtual Site* copyLow(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual Site* copyHigh(Context* c) {
|
||||
virtual Site* copyHigh(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual Site* makeNextWord(Context* c, unsigned) {
|
||||
virtual Site* makeNextWord(Context* c, unsigned)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual SiteMask mask(Context*) {
|
||||
virtual SiteMask mask(Context*)
|
||||
{
|
||||
return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex);
|
||||
}
|
||||
|
||||
virtual SiteMask nextWordMask(Context* c, unsigned) {
|
||||
virtual SiteMask nextWordMask(Context* c, unsigned)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Promise* address;
|
||||
};
|
||||
|
||||
Site* addressSite(Context* c, Promise* address) {
|
||||
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) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
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) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
|
||||
return ((static_cast<uint64_t>(1) << number) & mask.registerMask);
|
||||
@ -228,8 +256,9 @@ bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) {
|
||||
}
|
||||
}
|
||||
|
||||
bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
|
||||
return ((static_cast<uint64_t>(1) << number) == mask.registerMask);
|
||||
@ -238,8 +267,9 @@ bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) {
|
||||
}
|
||||
}
|
||||
|
||||
bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if (s->type(c) != lir::RegisterOperand) {
|
||||
return false;
|
||||
@ -248,7 +278,7 @@ bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
|
||||
RegisterSite* rs = static_cast<RegisterSite*>(s);
|
||||
unsigned size = rs->registerSize(c);
|
||||
if (size > c->targetInfo.pointerSize) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
assertT(c, number != lir::NoRegister);
|
||||
return number == rs->number;
|
||||
} else {
|
||||
uint32_t mask = c->regFile->generalRegisters.mask;
|
||||
@ -256,7 +286,8 @@ bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterSite::acquire(Context* c, Value* v) {
|
||||
void RegisterSite::acquire(Context* c, Value* v)
|
||||
{
|
||||
Target target;
|
||||
if (number != lir::NoRegister) {
|
||||
target = Target(number, lir::RegisterOperand, 0);
|
||||
@ -271,43 +302,49 @@ void RegisterSite::acquire(Context* c, Value* v) {
|
||||
number = target.index;
|
||||
}
|
||||
|
||||
void RegisterSite::release(Context* c, Value* v) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
void RegisterSite::release(Context* c, Value* v)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
compiler::release(c, c->registerResources + number, v, this);
|
||||
}
|
||||
|
||||
void RegisterSite::freeze(Context* c, Value* v) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
void RegisterSite::freeze(Context* c, Value* v)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
c->registerResources[number].freeze(c, v);
|
||||
}
|
||||
|
||||
void RegisterSite::thaw(Context* c, Value* v) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
void RegisterSite::thaw(Context* c, Value* v)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
c->registerResources[number].thaw(c, v);
|
||||
}
|
||||
|
||||
bool RegisterSite::frozen(Context* c UNUSED) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
bool RegisterSite::frozen(Context* c UNUSED)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
return c->registerResources[number].freezeCount != 0;
|
||||
}
|
||||
|
||||
lir::OperandType RegisterSite::type(Context*) {
|
||||
lir::OperandType RegisterSite::type(Context*)
|
||||
{
|
||||
return lir::RegisterOperand;
|
||||
}
|
||||
|
||||
void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high,
|
||||
lir::Operand* result)
|
||||
void RegisterSite::asAssemblerOperand(Context* c UNUSED,
|
||||
Site* high,
|
||||
lir::Operand* result)
|
||||
{
|
||||
assert(c, number != lir::NoRegister);
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
int highNumber;
|
||||
if (high != this) {
|
||||
highNumber = static_cast<RegisterSite*>(high)->number;
|
||||
assert(c, highNumber != lir::NoRegister);
|
||||
assertT(c, highNumber != lir::NoRegister);
|
||||
} else {
|
||||
highNumber = lir::NoRegister;
|
||||
}
|
||||
@ -315,7 +352,8 @@ void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high,
|
||||
new (result) lir::Register(number, highNumber);
|
||||
}
|
||||
|
||||
Site* RegisterSite::copy(Context* c) {
|
||||
Site* RegisterSite::copy(Context* c)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
if (number != lir::NoRegister) {
|
||||
@ -327,39 +365,45 @@ Site* RegisterSite::copy(Context* c) {
|
||||
return freeRegisterSite(c, mask);
|
||||
}
|
||||
|
||||
Site* RegisterSite::copyLow(Context* c) {
|
||||
Site* RegisterSite::copyLow(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Site* RegisterSite::copyHigh(Context* c) {
|
||||
Site* RegisterSite::copyHigh(Context* c)
|
||||
{
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Site* RegisterSite::makeNextWord(Context* c, unsigned) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
assert(c, ((1 << number) & c->regFile->generalRegisters.mask));
|
||||
Site* RegisterSite::makeNextWord(Context* c, unsigned)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
assertT(c, ((1 << number) & c->regFile->generalRegisters.mask));
|
||||
|
||||
return freeRegisterSite(c, c->regFile->generalRegisters.mask);
|
||||
}
|
||||
|
||||
SiteMask RegisterSite::mask(Context* c UNUSED) {
|
||||
SiteMask RegisterSite::mask(Context* c UNUSED)
|
||||
{
|
||||
return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex);
|
||||
}
|
||||
|
||||
SiteMask RegisterSite::nextWordMask(Context* c, unsigned) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
SiteMask RegisterSite::nextWordMask(Context* c, unsigned)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if (registerSize(c) > c->targetInfo.pointerSize) {
|
||||
return SiteMask
|
||||
(1 << lir::RegisterOperand, number, NoFrameIndex);
|
||||
return SiteMask(1 << lir::RegisterOperand, number, NoFrameIndex);
|
||||
} else {
|
||||
return SiteMask
|
||||
(1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex);
|
||||
return SiteMask(1 << lir::RegisterOperand,
|
||||
c->regFile->generalRegisters.mask,
|
||||
NoFrameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RegisterSite::registerSize(Context* c) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
unsigned RegisterSite::registerSize(Context* c)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
if ((1 << number) & c->regFile->floatRegisters.mask) {
|
||||
return c->arch->floatRegisterSize();
|
||||
@ -368,72 +412,76 @@ unsigned RegisterSite::registerSize(Context* c) {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RegisterSite::registerMask(Context* c UNUSED) {
|
||||
assert(c, number != lir::NoRegister);
|
||||
unsigned RegisterSite::registerMask(Context* c UNUSED)
|
||||
{
|
||||
assertT(c, number != lir::NoRegister);
|
||||
|
||||
return 1 << number;
|
||||
}
|
||||
|
||||
Site* registerSite(Context* c, int number)
|
||||
{
|
||||
assertT(c, number >= 0);
|
||||
assertT(c,
|
||||
(1 << number) & (c->regFile->generalRegisters.mask
|
||||
| c->regFile->floatRegisters.mask));
|
||||
|
||||
|
||||
Site* registerSite(Context* c, int number) {
|
||||
assert(c, number >= 0);
|
||||
assert(c, (1 << number) & (c->regFile->generalRegisters.mask
|
||||
| c->regFile->floatRegisters.mask));
|
||||
|
||||
return new(c->zone) RegisterSite(1 << number, number);
|
||||
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) {
|
||||
assert(c, acquired);
|
||||
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) {
|
||||
assert(c, acquired);
|
||||
bool MemorySite::match(Context* c, const SiteMask& mask)
|
||||
{
|
||||
assertT(c, acquired);
|
||||
|
||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||
if (mask.frameIndex >= 0) {
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
assertT(c, index == lir::NoRegister);
|
||||
return static_cast<int>(frameIndexToOffset(c, mask.frameIndex))
|
||||
== offset;
|
||||
== offset;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -445,12 +493,13 @@ bool MemorySite::match(Context* c, const SiteMask& mask) {
|
||||
}
|
||||
}
|
||||
|
||||
bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
|
||||
assert(c, acquired);
|
||||
bool MemorySite::loneMatch(Context* c, const SiteMask& mask)
|
||||
{
|
||||
assertT(c, acquired);
|
||||
|
||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
assertT(c, index == lir::NoRegister);
|
||||
|
||||
if (mask.frameIndex == AnyFrameIndex) {
|
||||
return false;
|
||||
@ -462,7 +511,8 @@ bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) {
|
||||
bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index)
|
||||
{
|
||||
if (s->type(c) == lir::MemoryOperand) {
|
||||
MemorySite* ms = static_cast<MemorySite*>(s);
|
||||
return ms->base == this->base
|
||||
@ -480,32 +530,32 @@ bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) {
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySite::acquire(Context* c, Value* v) {
|
||||
void MemorySite::acquire(Context* c, Value* v)
|
||||
{
|
||||
c->registerResources[base].increment(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].increment(c);
|
||||
}
|
||||
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
assert
|
||||
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
assertT(c, index == lir::NoRegister);
|
||||
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
|
||||
compiler::acquire
|
||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
compiler::acquire(
|
||||
c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
}
|
||||
|
||||
acquired = true;
|
||||
}
|
||||
|
||||
void MemorySite::release(Context* c, Value* v) {
|
||||
void MemorySite::release(Context* c, Value* v)
|
||||
{
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
assert
|
||||
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
assertT(c, index == lir::NoRegister);
|
||||
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
|
||||
compiler::release
|
||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
compiler::release(
|
||||
c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
}
|
||||
|
||||
c->registerResources[base].decrement(c);
|
||||
@ -516,7 +566,8 @@ void MemorySite::release(Context* c, Value* v) {
|
||||
acquired = false;
|
||||
}
|
||||
|
||||
void MemorySite::freeze(Context* c, Value* v) {
|
||||
void MemorySite::freeze(Context* c, Value* v)
|
||||
{
|
||||
if (base == c->arch->stack()) {
|
||||
c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v);
|
||||
} else {
|
||||
@ -527,7 +578,8 @@ void MemorySite::freeze(Context* c, Value* v) {
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySite::thaw(Context* c, Value* v) {
|
||||
void MemorySite::thaw(Context* c, Value* v)
|
||||
{
|
||||
if (base == c->arch->stack()) {
|
||||
c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v);
|
||||
} else {
|
||||
@ -538,37 +590,42 @@ void MemorySite::thaw(Context* c, Value* v) {
|
||||
}
|
||||
}
|
||||
|
||||
bool MemorySite::frozen(Context* c) {
|
||||
bool MemorySite::frozen(Context* c)
|
||||
{
|
||||
return base == c->arch->stack()
|
||||
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?
|
||||
assert(c,
|
||||
high == this
|
||||
or (static_cast<MemorySite*>(high)->base == base
|
||||
and static_cast<MemorySite*>(high)->offset
|
||||
== static_cast<int>(offset + c->targetInfo.pointerSize)
|
||||
and static_cast<MemorySite*>(high)->index == index
|
||||
and static_cast<MemorySite*>(high)->scale == scale));
|
||||
assertT(c,
|
||||
high == this
|
||||
or (static_cast<MemorySite*>(high)->base == base
|
||||
and static_cast<MemorySite*>(high)->offset
|
||||
== static_cast<int>(offset + c->targetInfo.pointerSize)
|
||||
and static_cast<MemorySite*>(high)->index == index
|
||||
and static_cast<MemorySite*>(high)->scale == scale));
|
||||
|
||||
assert(c, acquired);
|
||||
assertT(c, acquired);
|
||||
|
||||
new (result) lir::Memory(base, offset, index, scale);
|
||||
}
|
||||
|
||||
Site* MemorySite::copy(Context* c) {
|
||||
Site* MemorySite::copy(Context* c)
|
||||
{
|
||||
return memorySite(c, base, offset, index, scale);
|
||||
}
|
||||
|
||||
Site* MemorySite::copyHalf(Context* c, bool add) {
|
||||
Site* MemorySite::copyHalf(Context* c, bool add)
|
||||
{
|
||||
if (add) {
|
||||
return memorySite(
|
||||
c, base, offset + c->targetInfo.pointerSize, index, scale);
|
||||
@ -577,15 +634,18 @@ Site* MemorySite::copyHalf(Context* c, bool add) {
|
||||
}
|
||||
}
|
||||
|
||||
Site* MemorySite::copyLow(Context* c) {
|
||||
Site* MemorySite::copyLow(Context* c)
|
||||
{
|
||||
return copyHalf(c, c->arch->bigEndian());
|
||||
}
|
||||
|
||||
Site* MemorySite::copyHigh(Context* c) {
|
||||
Site* MemorySite::copyHigh(Context* c)
|
||||
{
|
||||
return copyHalf(c, not c->arch->bigEndian());
|
||||
}
|
||||
|
||||
Site* MemorySite::makeNextWord(Context* c, unsigned index) {
|
||||
Site* MemorySite::makeNextWord(Context* c, unsigned index)
|
||||
{
|
||||
return memorySite(c,
|
||||
base,
|
||||
offset + ((index == 1) xor c->arch->bigEndian()
|
||||
@ -595,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()) {
|
||||
assert(c, this->index == lir::NoRegister);
|
||||
assertT(c, this->index == lir::NoRegister);
|
||||
frameIndex = static_cast<int>(offsetToFrameIndex(c, offset))
|
||||
+ ((index == 1) xor c->arch->bigEndian() ? 1 : -1);
|
||||
+ ((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) {
|
||||
assert(c, frameIndex >= 0);
|
||||
return memorySite
|
||||
(c, c->arch->stack(), frameIndexToOffset(c, frameIndex), lir::NoRegister, 0);
|
||||
MemorySite* frameSite(Context* c, int frameIndex)
|
||||
{
|
||||
assertT(c, frameIndex >= 0);
|
||||
return memorySite(c,
|
||||
c->arch->stack(),
|
||||
frameIndexToOffset(c, frameIndex),
|
||||
lir::NoRegister,
|
||||
0);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // 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) { }
|
||||
Site() : next(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Site* readTarget(Context*, Read*) { return this; }
|
||||
virtual Site* readTarget(Context*, Read*)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual unsigned toString(Context*, char*, unsigned) = 0;
|
||||
|
||||
@ -71,15 +82,26 @@ class Site {
|
||||
|
||||
virtual bool matchNextWord(Context*, Site*, unsigned) = 0;
|
||||
|
||||
virtual void acquire(Context*, Value*) { }
|
||||
virtual void acquire(Context*, Value*)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void release(Context*, Value*) { }
|
||||
virtual void release(Context*, Value*)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void freeze(Context*, Value*) { }
|
||||
virtual void freeze(Context*, Value*)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void thaw(Context*, Value*) { }
|
||||
virtual void thaw(Context*, Value*)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool frozen(Context*) { return false; }
|
||||
virtual bool frozen(Context*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual lir::OperandType type(Context*) = 0;
|
||||
|
||||
@ -99,16 +121,24 @@ class Site {
|
||||
|
||||
virtual unsigned registerSize(Context*);
|
||||
|
||||
virtual unsigned registerMask(Context*) { return 0; }
|
||||
virtual unsigned registerMask(Context*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool isVolatile(Context*) { return false; }
|
||||
virtual bool isVolatile(Context*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Site* next;
|
||||
};
|
||||
|
||||
class SiteIterator {
|
||||
public:
|
||||
SiteIterator(Context* c, Value* v, bool includeBuddies = true,
|
||||
SiteIterator(Context* c,
|
||||
Value* v,
|
||||
bool includeBuddies = true,
|
||||
bool includeNextWord = true);
|
||||
|
||||
Site** findNext(Site** p);
|
||||
@ -130,43 +160,52 @@ Site* constantSite(Context* c, Promise* value);
|
||||
Site* constantSite(Context* c, int64_t value);
|
||||
|
||||
Promise* combinedPromise(Context* c, Promise* low, Promise* high);
|
||||
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask);
|
||||
Promise* shiftMaskPromise(Context* c,
|
||||
Promise* base,
|
||||
unsigned shift,
|
||||
int64_t mask);
|
||||
|
||||
class ConstantSite: public Site {
|
||||
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,9 +66,9 @@ void Value::addSite(Context* c, Site* s) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Value::grow(Context* c) {
|
||||
assert(c, this->nextWord == this);
|
||||
void Value::grow(Context* c)
|
||||
{
|
||||
assertT(c, this->nextWord == this);
|
||||
|
||||
Value* next = value(c, this->type);
|
||||
this->nextWord = next;
|
||||
@ -69,14 +76,15 @@ void Value::grow(Context* c) {
|
||||
next->wordIndex = 1;
|
||||
}
|
||||
|
||||
|
||||
void Value::maybeSplit(Context* c) {
|
||||
void Value::maybeSplit(Context* c)
|
||||
{
|
||||
if (this->nextWord == this) {
|
||||
this->split(c);
|
||||
}
|
||||
}
|
||||
|
||||
void Value::split(Context* c) {
|
||||
void Value::split(Context* c)
|
||||
{
|
||||
this->grow(c);
|
||||
for (SiteIterator it(c, this); it.hasMore();) {
|
||||
Site* s = it.next();
|
||||
@ -87,11 +95,13 @@ void Value::split(Context* c) {
|
||||
}
|
||||
}
|
||||
|
||||
void Value::removeSite(Context* c, Site* s) {
|
||||
void Value::removeSite(Context* c, Site* s)
|
||||
{
|
||||
for (SiteIterator it(c, this); it.hasMore();) {
|
||||
if (s == it.next()) {
|
||||
if (DebugSites) {
|
||||
char buffer[256]; s->toString(c, buffer, 256);
|
||||
char buffer[256];
|
||||
s->toString(c, buffer, 256);
|
||||
fprintf(stderr, "remove site %s from %p\n", buffer, this);
|
||||
}
|
||||
it.remove(c);
|
||||
@ -101,15 +111,17 @@ void Value::removeSite(Context* c, Site* s) {
|
||||
if (DebugSites) {
|
||||
fprintf(stderr, "%p has more: %d\n", this, this->hasSite(c));
|
||||
}
|
||||
assert(c, not this->findSite(s));
|
||||
assertT(c, not this->findSite(s));
|
||||
}
|
||||
|
||||
bool Value::hasSite(Context* c) {
|
||||
bool Value::hasSite(Context* c)
|
||||
{
|
||||
SiteIterator it(c, this);
|
||||
return it.hasMore();
|
||||
}
|
||||
|
||||
bool Value::uniqueSite(Context* c, Site* s) {
|
||||
bool Value::uniqueSite(Context* c, Site* s)
|
||||
{
|
||||
SiteIterator it(c, this);
|
||||
Site* p UNUSED = it.next();
|
||||
if (it.hasMore()) {
|
||||
@ -128,12 +140,13 @@ bool Value::uniqueSite(Context* c, Site* s) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
assert(c, p == s);
|
||||
assertT(c, p == s);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Value::clearSites(Context* c) {
|
||||
void Value::clearSites(Context* c)
|
||||
{
|
||||
if (DebugSites) {
|
||||
fprintf(stderr, "clear sites for %p\n", this);
|
||||
}
|
||||
@ -143,9 +156,9 @@ void Value::clearSites(Context* c) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool Value::hasBuddy(Context* c, Value* b) {
|
||||
bool Value::hasBuddy(Context* c, Value* b)
|
||||
{
|
||||
Value* a = this;
|
||||
if (a == b) {
|
||||
return true;
|
||||
@ -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,19 +78,23 @@ using namespace isa;
|
||||
|
||||
// END OPERATION COMPILERS
|
||||
|
||||
unsigned
|
||||
argumentFootprint(unsigned footprint)
|
||||
unsigned argumentFootprint(unsigned footprint)
|
||||
{
|
||||
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
|
||||
}
|
||||
|
||||
void
|
||||
nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED,
|
||||
unsigned footprint, void* link, bool,
|
||||
int targetParameterFootprint UNUSED, void** ip, void** stack)
|
||||
void nextFrame(ArchitectureContext* con,
|
||||
uint32_t* start,
|
||||
unsigned size UNUSED,
|
||||
unsigned footprint,
|
||||
void* link,
|
||||
bool,
|
||||
int targetParameterFootprint UNUSED,
|
||||
void** ip,
|
||||
void** stack)
|
||||
{
|
||||
assert(con, *ip >= start);
|
||||
assert(con, *ip <= start + (size / TargetBytesPerWord));
|
||||
assertT(con, *ip >= start);
|
||||
assertT(con, *ip <= start + (size / TargetBytesPerWord));
|
||||
|
||||
uint32_t* instruction = static_cast<uint32_t*>(*ip);
|
||||
|
||||
@ -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) {
|
||||
assert(&con, index < argumentRegisterCount());
|
||||
virtual int argumentRegister(unsigned index)
|
||||
{
|
||||
assertT(&con, index < argumentRegisterCount());
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
virtual bool hasLinkRegister() {
|
||||
virtual bool hasLinkRegister()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual unsigned stackAlignmentInWords() {
|
||||
virtual unsigned stackAlignmentInWords()
|
||||
{
|
||||
return StackAlignmentInWords;
|
||||
}
|
||||
|
||||
virtual bool matchCall(void* returnAddress, void* target) {
|
||||
virtual bool matchCall(void* returnAddress, void* target)
|
||||
{
|
||||
uint32_t* instruction = static_cast<uint32_t*>(returnAddress) - 1;
|
||||
|
||||
return *instruction == static_cast<uint32_t>
|
||||
(bl(static_cast<uint8_t*>(target)
|
||||
- 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;
|
||||
@ -404,10 +465,11 @@ class MyArchitecture: public Architecture {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void planDestination
|
||||
(lir::BinaryOperation op,
|
||||
unsigned, const OperandMask& aMask,
|
||||
unsigned, OperandMask& bMask)
|
||||
virtual void planDestination(lir::BinaryOperation op,
|
||||
unsigned,
|
||||
const OperandMask& aMask,
|
||||
unsigned,
|
||||
OperandMask& bMask)
|
||||
{
|
||||
bMask.typeMask = (1 << lir::RegisterOperand) | (1 << lir::MemoryOperand);
|
||||
bMask.registerMask = GPR_MASK64;
|
||||
@ -443,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:
|
||||
@ -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) {
|
||||
assert(&con, con.client == 0);
|
||||
virtual void setClient(Client* client)
|
||||
{
|
||||
assertT(&con, con.client == 0);
|
||||
con.client = client;
|
||||
}
|
||||
|
||||
virtual Architecture* arch() {
|
||||
virtual Architecture* arch()
|
||||
{
|
||||
return arch_;
|
||||
}
|
||||
|
||||
@ -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,13 +689,16 @@ class MyAssembler: public Assembler {
|
||||
};
|
||||
RUNTIME_ARRAY(Argument, arguments, argumentCount);
|
||||
|
||||
va_list a; va_start(a, argumentCount);
|
||||
va_list a;
|
||||
va_start(a, argumentCount);
|
||||
unsigned footprint = 0;
|
||||
for (unsigned i = 0; i < argumentCount; ++i) {
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned);
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type = static_cast<lir::OperandType>(va_arg(a, int));
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type
|
||||
= static_cast<lir::OperandType>(va_arg(a, int));
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*);
|
||||
footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord);
|
||||
footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
TargetBytesPerWord);
|
||||
}
|
||||
va_end(a);
|
||||
|
||||
@ -630,37 +710,42 @@ class MyAssembler: public Assembler {
|
||||
lir::Register dst(arch_->argumentRegister(i));
|
||||
|
||||
apply(lir::Move,
|
||||
OperandInfo(
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
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
|
||||
// to allocate/deallocate, and nextFrame will need to be taught
|
||||
// how to handle them:
|
||||
assert(&con, footprint < 256);
|
||||
assertT(&con, footprint < 256);
|
||||
|
||||
lir::Register stack(StackRegister);
|
||||
ResolvedPromise footprintPromise(footprint * TargetBytesPerWord);
|
||||
@ -668,26 +753,34 @@ class MyAssembler: public Assembler {
|
||||
subC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
|
||||
|
||||
lir::Register returnAddress(LinkRegister);
|
||||
lir::Memory returnAddressDst
|
||||
(StackRegister, (footprint - 1) * TargetBytesPerWord);
|
||||
moveRM(&con, TargetBytesPerWord, &returnAddress, TargetBytesPerWord,
|
||||
lir::Memory returnAddressDst(StackRegister,
|
||||
(footprint - 1) * TargetBytesPerWord);
|
||||
moveRM(&con,
|
||||
TargetBytesPerWord,
|
||||
&returnAddress,
|
||||
TargetBytesPerWord,
|
||||
&returnAddressDst);
|
||||
}
|
||||
|
||||
virtual void adjustFrame(unsigned difference) {
|
||||
virtual void adjustFrame(unsigned difference)
|
||||
{
|
||||
lir::Register stack(StackRegister);
|
||||
ResolvedPromise differencePromise(difference * TargetBytesPerWord);
|
||||
lir::Constant differenceConstant(&differencePromise);
|
||||
subC(&con, TargetBytesPerWord, &differenceConstant, &stack, &stack);
|
||||
}
|
||||
|
||||
virtual void popFrame(unsigned footprint) {
|
||||
virtual void popFrame(unsigned footprint)
|
||||
{
|
||||
footprint += FrameHeaderSize;
|
||||
|
||||
lir::Register returnAddress(LinkRegister);
|
||||
lir::Memory returnAddressSrc
|
||||
(StackRegister, (footprint - 1) * TargetBytesPerWord);
|
||||
moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord,
|
||||
lir::Memory returnAddressSrc(StackRegister,
|
||||
(footprint - 1) * TargetBytesPerWord);
|
||||
moveMR(&con,
|
||||
TargetBytesPerWord,
|
||||
&returnAddressSrc,
|
||||
TargetBytesPerWord,
|
||||
&returnAddress);
|
||||
|
||||
lir::Register stack(StackRegister);
|
||||
@ -701,26 +794,29 @@ class MyAssembler: public Assembler {
|
||||
int returnAddressSurrogate,
|
||||
int framePointerSurrogate UNUSED)
|
||||
{
|
||||
assert(&con, framePointerSurrogate == lir::NoRegister);
|
||||
assertT(&con, framePointerSurrogate == lir::NoRegister);
|
||||
|
||||
if (TailCalls) {
|
||||
if (offset) {
|
||||
footprint += FrameHeaderSize;
|
||||
|
||||
lir::Register link(LinkRegister);
|
||||
lir::Memory returnAddressSrc
|
||||
(StackRegister, (footprint - 1) * TargetBytesPerWord);
|
||||
moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord,
|
||||
lir::Memory returnAddressSrc(StackRegister,
|
||||
(footprint - 1) * TargetBytesPerWord);
|
||||
moveMR(&con,
|
||||
TargetBytesPerWord,
|
||||
&returnAddressSrc,
|
||||
TargetBytesPerWord,
|
||||
&link);
|
||||
|
||||
lir::Register stack(StackRegister);
|
||||
ResolvedPromise footprintPromise
|
||||
((footprint - offset) * TargetBytesPerWord);
|
||||
ResolvedPromise footprintPromise((footprint - offset)
|
||||
* TargetBytesPerWord);
|
||||
lir::Constant footprintConstant(&footprintPromise);
|
||||
addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack);
|
||||
|
||||
if (returnAddressSurrogate != lir::NoRegister) {
|
||||
assert(&con, offset > 0);
|
||||
assertT(&con, offset > 0);
|
||||
|
||||
lir::Register ras(returnAddressSurrogate);
|
||||
lir::Memory dst(StackRegister, (offset - 1) * TargetBytesPerWord);
|
||||
@ -739,8 +835,8 @@ class MyAssembler: public Assembler {
|
||||
{
|
||||
popFrame(frameFootprint);
|
||||
|
||||
assert(&con, argumentFootprint >= StackAlignmentInWords);
|
||||
assert(&con, (argumentFootprint % StackAlignmentInWords) == 0);
|
||||
assertT(&con, argumentFootprint >= StackAlignmentInWords);
|
||||
assertT(&con, (argumentFootprint % StackAlignmentInWords) == 0);
|
||||
|
||||
unsigned offset;
|
||||
if (TailCalls and argumentFootprint > StackAlignmentInWords) {
|
||||
@ -769,46 +865,52 @@ class MyAssembler: public Assembler {
|
||||
return_(&con);
|
||||
}
|
||||
|
||||
virtual void apply(lir::Operation op) {
|
||||
virtual void apply(lir::Operation op)
|
||||
{
|
||||
arch_->con.operations[op](&con);
|
||||
}
|
||||
|
||||
virtual void apply(lir::UnaryOperation op, OperandInfo a)
|
||||
{
|
||||
arch_->con.unaryOperations[Multimethod::index(op, a.type)]
|
||||
(&con, a.size, a.operand);
|
||||
arch_->con.unaryOperations[Multimethod::index(op, a.type)](
|
||||
&con, a.size, a.operand);
|
||||
}
|
||||
|
||||
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b)
|
||||
{
|
||||
arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)]
|
||||
(&con, a.size, a.operand, b.size, b.operand);
|
||||
arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)](
|
||||
&con, a.size, a.operand, b.size, b.operand);
|
||||
}
|
||||
|
||||
virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c)
|
||||
virtual void apply(lir::TernaryOperation op,
|
||||
OperandInfo a,
|
||||
OperandInfo b,
|
||||
OperandInfo c)
|
||||
{
|
||||
if (isBranch(op)) {
|
||||
assert(&con, a.size == b.size);
|
||||
assert(&con, c.size == TargetBytesPerWord);
|
||||
assert(&con, c.type == lir::ConstantOperand);
|
||||
assertT(&con, a.size == b.size);
|
||||
assertT(&con, c.size == TargetBytesPerWord);
|
||||
assertT(&con, c.type == lir::ConstantOperand);
|
||||
|
||||
arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)]
|
||||
(&con, op, a.size, a.operand, b.operand, c.operand);
|
||||
arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)](
|
||||
&con, op, a.size, a.operand, b.operand, c.operand);
|
||||
} else {
|
||||
assert(&con, b.size == c.size);
|
||||
assert(&con, b.type == lir::RegisterOperand);
|
||||
assert(&con, c.type == lir::RegisterOperand);
|
||||
assertT(&con, b.size == c.size);
|
||||
assertT(&con, b.type == lir::RegisterOperand);
|
||||
assertT(&con, c.type == lir::RegisterOperand);
|
||||
|
||||
arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)]
|
||||
(&con, b.size, a.operand, b.operand, c.operand);
|
||||
arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)](
|
||||
&con, b.size, a.operand, b.operand, c.operand);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setDestination(uint8_t* dst) {
|
||||
virtual void setDestination(uint8_t* dst)
|
||||
{
|
||||
con.result = dst;
|
||||
}
|
||||
|
||||
virtual void write() {
|
||||
virtual void write()
|
||||
{
|
||||
uint8_t* dst = con.result;
|
||||
unsigned dstOffset = 0;
|
||||
for (MyBlock* b = con.firstBlock; b; b = b->next) {
|
||||
@ -828,8 +930,11 @@ class MyAssembler: public Assembler {
|
||||
unsigned poolSize = 0;
|
||||
for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) {
|
||||
if (DebugPool) {
|
||||
fprintf(stderr, "visit pool offset %p %d in block %p\n",
|
||||
o, o->offset, b);
|
||||
fprintf(stderr,
|
||||
"visit pool offset %p %d in block %p\n",
|
||||
o,
|
||||
o->offset,
|
||||
b);
|
||||
}
|
||||
|
||||
unsigned entry = dstOffset + poolSize;
|
||||
@ -840,8 +945,8 @@ class MyAssembler: public Assembler {
|
||||
|
||||
o->entry->address = dst + entry;
|
||||
|
||||
unsigned instruction = o->block->start
|
||||
+ padding(o->block, o->offset) + o->offset;
|
||||
unsigned instruction = o->block->start + padding(o->block, o->offset)
|
||||
+ o->offset;
|
||||
|
||||
int32_t v = (entry - 8) - instruction;
|
||||
expect(&con, v == (v & PoolOffsetMask));
|
||||
@ -854,8 +959,8 @@ class MyAssembler: public Assembler {
|
||||
|
||||
bool jump = needJump(b);
|
||||
if (jump) {
|
||||
write4
|
||||
(dst + dstOffset, isa::b((poolSize + TargetBytesPerWord - 8) >> 2));
|
||||
write4(dst + dstOffset,
|
||||
isa::b((poolSize + TargetBytesPerWord - 8) >> 2));
|
||||
}
|
||||
|
||||
dstOffset += poolSize + (jump ? TargetBytesPerWord : 0);
|
||||
@ -879,20 +984,27 @@ class MyAssembler: public Assembler {
|
||||
*static_cast<target_uintptr_t*>(e->address) = e->constant->value();
|
||||
} else {
|
||||
new (e->constant->listen(sizeof(ConstantPoolListener)))
|
||||
ConstantPoolListener(con.s, static_cast<target_uintptr_t*>(e->address),
|
||||
e->callOffset
|
||||
? dst + e->callOffset->value() + 8
|
||||
: 0);
|
||||
ConstantPoolListener(
|
||||
con.s,
|
||||
static_cast<target_uintptr_t*>(e->address),
|
||||
e->callOffset ? dst + e->callOffset->value() + 8 : 0);
|
||||
}
|
||||
if (false) {
|
||||
fprintf(stderr,
|
||||
"constant %p at %p\n",
|
||||
reinterpret_cast<void*>(e->constant->value()),
|
||||
e->address);
|
||||
}
|
||||
// fprintf(stderr, "constant %p at %p\n", reinterpret_cast<void*>(e->constant->value()), e->address);
|
||||
}
|
||||
}
|
||||
|
||||
virtual Promise* offset(bool forTrace) {
|
||||
virtual Promise* offset(bool forTrace)
|
||||
{
|
||||
return arm::offsetPromise(&con, forTrace);
|
||||
}
|
||||
|
||||
virtual Block* endBlock(bool startNew) {
|
||||
virtual Block* endBlock(bool startNew)
|
||||
{
|
||||
MyBlock* b = con.lastBlock;
|
||||
b->size = con.code.length() - b->offset;
|
||||
if (startNew) {
|
||||
@ -903,26 +1015,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 +1056,18 @@ class MyAssembler: public Assembler {
|
||||
b->lastPoolOffsetTail = b->poolOffsetTail;
|
||||
}
|
||||
|
||||
virtual unsigned length() {
|
||||
virtual unsigned length()
|
||||
{
|
||||
return con.code.length();
|
||||
}
|
||||
|
||||
virtual unsigned footerSize() {
|
||||
virtual unsigned footerSize()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
virtual void dispose()
|
||||
{
|
||||
con.code.dispose();
|
||||
}
|
||||
|
||||
@ -953,17 +1075,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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user