diff --git a/.gitignore b/.gitignore
index bf4aaa6e69..aff794f5e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.gdb_history
build
+*~
\ No newline at end of file
diff --git a/makefile b/makefile
index 227d5cd4e4..a2ad32ecc6 100644
--- a/makefile
+++ b/makefile
@@ -4,6 +4,9 @@ name = avian
version = 0.1.1
build-arch = $(shell uname -m | sed 's/^i.86$$/i386/')
+ifeq ($(build-arch),Power)
+ build-arch = powerpc
+endif
build-platform = \
$(shell uname -s | tr [:upper:] [:lower:] \
@@ -90,6 +93,12 @@ ifeq ($(arch),i386)
object-format = elf32-i386
pointer-size = 4
endif
+ifeq ($(arch),powerpc)
+ asm = powerpc
+ object-arch = powerpc
+ object-format = elf32-powerpc
+ pointer-size = 4
+endif
ifeq ($(platform),darwin)
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src)
@@ -189,6 +198,7 @@ vm-depends = \
$(src)/zone.h \
$(src)/assembler.h \
$(src)/compiler.h \
+ $(src)/$(asm).h \
$(src)/heapwalk.h \
$(src)/bootimage.h
@@ -230,11 +240,13 @@ ifeq ($(heapdump),true)
cflags += -DAVIAN_HEAPDUMP
endif
+bootimage-mode = $(mode)
+
bootimage-generator-sources = $(src)/bootimage.cpp
bootimage-generator-objects = \
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(native-build))
bootimage-generator = \
- $(build)/$(build-platform)-$(build-arch)-compile-fast/bootimage-generator
+ $(build)/$(build-platform)-$(build-arch)-compile-$(bootimage-mode)/bootimage-generator
bootimage-bin = $(native-build)/bootimage.bin
bootimage-object = $(native-build)/bootimage-bin.o
@@ -355,6 +367,8 @@ $(test-dep): $(test-sources)
@mkdir -p $(dir $(@))
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
$(shell $(MAKE) -s --no-print-directory $(test-classes))
+ $(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(dir $(@)) \
+ test/Subroutine.java
@touch $(@)
define compile-object
@@ -404,7 +418,7 @@ $(binaryToMacho): $(src)/binaryToMacho.cpp
$(classpath-object): $(build)/classpath.jar $(binaryToMacho)
@echo "creating $(@)"
ifeq ($(platform),darwin)
- $(binaryToMacho) $(build)/classpath.jar __TEXT __text \
+ $(binaryToMacho) $(asm) $(build)/classpath.jar __TEXT __text \
__binary_classpath_jar_start __binary_classpath_jar_end > $(@)
else
(wd=$$(pwd); \
@@ -458,9 +472,11 @@ else
endif
$(strip) $(strip-all) $(@)
-$(bootimage-generator):
+$(bootimage-generator): make-bootimage-generator
+
+make-bootimage-generator:
(unset MAKEFLAGS && \
- make mode=fast process=compile \
+ make mode=$(bootimage-mode) process=compile \
arch=$(build-arch) \
platform=$(build-platform) \
bootimage-generator= \
diff --git a/src/arch.h b/src/arch.h
new file mode 100644
index 0000000000..ae613297b6
--- /dev/null
+++ b/src/arch.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2008, 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 ARCH_H
+#define ARCH_H
+
+#include "common.h"
+
+extern "C" void NO_RETURN
+vmJump(void* address, void* base, void* stack, void* thread);
+
+#if (defined __i386__) || (defined __x86_64__)
+# include "x86.h"
+#elif defined __POWERPC__
+# include "powerpc.h"
+#else
+# error unsupported architecture
+#endif
+
+#endif//ARCH_H
diff --git a/src/assembler.h b/src/assembler.h
index 0677178e68..549e7cad2b 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -23,8 +23,6 @@ enum Operation {
const unsigned OperationCount = Return + 1;
enum UnaryOperation {
- Push,
- Pop,
Call,
LongCall,
AlignedCall,
@@ -35,20 +33,22 @@ enum UnaryOperation {
JumpIfLessOrEqual,
JumpIfGreaterOrEqual,
JumpIfEqual,
- JumpIfNotEqual,
+ JumpIfNotEqual
+};
+
+const unsigned UnaryOperationCount = JumpIfNotEqual + 1;
+
+enum BinaryOperation {
+ Move,
+ MoveZ,
+ Compare,
Negate
};
-const unsigned UnaryOperationCount = Negate + 1;
+const unsigned BinaryOperationCount = Negate + 1;
-enum BinaryOperation {
- LoadAddress,
- Move,
- MoveZ,
- Move4To8,
- Swap,
+enum TernaryOperation {
LongCompare,
- Compare,
Add,
Subtract,
Multiply,
@@ -62,7 +62,7 @@ enum BinaryOperation {
Xor
};
-const unsigned BinaryOperationCount = Xor + 1;
+const unsigned TernaryOperationCount = Xor + 1;
enum OperandType {
ConstantOperand,
@@ -74,7 +74,6 @@ enum OperandType {
const unsigned OperandTypeCount = MemoryOperand + 1;
const int NoRegister = -1;
-const int AnyRegister = -2;
class Promise {
public:
@@ -105,6 +104,43 @@ class ResolvedPromise: public Promise {
int64_t value_;
};
+class ShiftMaskPromise: public Promise {
+ public:
+ ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
+ base(base), shift(shift), mask(mask)
+ { }
+
+ virtual int64_t value() {
+ return (base->value() >> shift) & mask;
+ }
+
+ virtual bool resolved() {
+ return base->resolved();
+ }
+
+ Promise* base;
+ unsigned shift;
+ int64_t mask;
+};
+
+class CombinedPromise: public Promise {
+ public:
+ CombinedPromise(Promise* low, Promise* high):
+ low(low), high(high)
+ { }
+
+ virtual int64_t value() {
+ return low->value() | (high->value() << 32);
+ }
+
+ virtual bool resolved() {
+ return low->resolved() and high->resolved();
+ }
+
+ Promise* low;
+ Promise* high;
+};
+
class ListenPromise: public Promise {
public:
ListenPromise(System* s, Allocator* allocator):
@@ -160,7 +196,8 @@ class DelayedPromise: public ListenPromise {
class TraceHandler {
public:
- virtual void handleTrace(Promise* address) = 0;
+ virtual void handleTrace(Promise* address, unsigned padIndex,
+ unsigned padding) = 0;
};
class Assembler {
@@ -211,46 +248,100 @@ class Assembler {
virtual void restore(int r) = 0;
};
+ class Block {
+ public:
+ virtual unsigned resolve(unsigned start, Block* next) = 0;
+ };
+
+ class Architecture {
+ public:
+ virtual unsigned registerCount() = 0;
+
+ virtual int stack() = 0;
+ virtual int thread() = 0;
+ virtual int returnLow() = 0;
+ virtual int returnHigh() = 0;
+
+ virtual bool condensedAddressing() = 0;
+
+ virtual bool reserved(int register_) = 0;
+
+ virtual unsigned argumentRegisterCount() = 0;
+ virtual int argumentRegister(unsigned index) = 0;
+
+ virtual void updateCall(UnaryOperation op, bool assertAlignment,
+ void* returnAddress, void* newTarget) = 0;
+
+ virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
+
+ virtual void* frameIp(void* stack) = 0;
+ virtual unsigned frameHeaderSize() = 0;
+ virtual unsigned frameReturnAddressSize() = 0;
+ virtual unsigned frameFooterSize() = 0;
+ virtual void nextFrame(void** stack, void** base) = 0;
+
+ virtual void plan
+ (UnaryOperation op,
+ unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
+ bool* thunk) = 0;
+
+ virtual void plan
+ (BinaryOperation op,
+ unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
+ unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask,
+ bool* thunk) = 0;
+
+ virtual void plan
+ (TernaryOperation op,
+ unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
+ unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask,
+ unsigned cSize, uint8_t* cTypeMask, uint64_t* cRegisterMask,
+ bool* thunk) = 0;
+
+ virtual void acquire() = 0;
+ virtual void release() = 0;
+ };
+
virtual void setClient(Client* client) = 0;
- virtual unsigned registerCount() = 0;
+ virtual Architecture* arch() = 0;
- virtual int base() = 0;
- virtual int stack() = 0;
- virtual int thread() = 0;
- virtual int returnLow() = 0;
- virtual int returnHigh() = 0;
-
- virtual unsigned argumentRegisterCount() = 0;
- virtual int argumentRegister(unsigned index) = 0;
-
- virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask,
- uint64_t* registerMask, bool* thunk) = 0;
-
- virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask,
- uint64_t* aRegisterMask, uint8_t* bTypeMask,
- uint64_t* bRegisterMask, bool* thunk) = 0;
+ virtual void saveFrame(unsigned stackOffset, unsigned baseOffset) = 0;
+ virtual void pushFrame(unsigned argumentCount, ...) = 0;
+ virtual void allocateFrame(unsigned footprint) = 0;
+ virtual void popFrame() = 0;
virtual void apply(Operation op) = 0;
- virtual void apply(UnaryOperation op, unsigned size, OperandType type,
- Operand* operand) = 0;
+ virtual void apply(UnaryOperation op,
+ unsigned aSize, OperandType aType, Operand* aOperand) = 0;
- virtual void apply(BinaryOperation op, unsigned size, OperandType aType,
- Operand* a, OperandType bType, Operand* b) = 0;
+ virtual void apply(BinaryOperation op,
+ unsigned aSize, OperandType aType, Operand* aOperand,
+ unsigned bSize, OperandType bType, Operand* bOperand) = 0;
+
+ virtual void apply(TernaryOperation op,
+ unsigned aSize, OperandType aType, Operand* aOperand,
+ unsigned bSize, OperandType bType, Operand* bOperand,
+ unsigned cSize, OperandType cType, Operand* cOperand) = 0;
virtual void writeTo(uint8_t* dst) = 0;
- virtual unsigned length() = 0;
+ virtual Promise* offset() = 0;
- virtual void updateCall(UnaryOperation op, bool assertAlignment,
- void* returnAddress, void* newTarget) = 0;
+ virtual Block* endBlock(bool startNew) = 0;
+
+ virtual unsigned length() = 0;
virtual void dispose() = 0;
};
+Assembler::Architecture*
+makeArchitecture(System* system);
+
Assembler*
-makeAssembler(System* system, Allocator* allocator, Zone* zone);
+makeAssembler(System* system, Allocator* allocator, Zone* zone,
+ Assembler::Architecture* architecture);
} // namespace vm
diff --git a/src/binaryToMacho.cpp b/src/binaryToMacho.cpp
index 88259b81cb..c5f55d118a 100644
--- a/src/binaryToMacho.cpp
+++ b/src/binaryToMacho.cpp
@@ -20,6 +20,8 @@
#include "mach-o/loader.h"
#include "mach-o/nlist.h"
+
+
namespace {
inline unsigned
@@ -29,18 +31,29 @@ pad(unsigned n)
}
void
-writeObject(FILE* out, const uint8_t* data, unsigned size,
+writeObject(const char* architecture,
+ FILE* out, const uint8_t* data, unsigned size,
const char* segmentName, const char* sectionName,
const char* startName, const char* endName)
{
unsigned startNameLength = strlen(startName) + 1;
unsigned endNameLength = strlen(endName) + 1;
+ cpu_type_t cpuType;
+ cpu_subtype_t cpuSubtype;
+ if (strcmp(architecture, "x86") == 0) {
+ cpuType = CPU_TYPE_I386;
+ cpuSubtype = CPU_SUBTYPE_I386_ALL;
+ } else if (strcmp(architecture, "powerpc") == 0) {
+ cpuType = CPU_TYPE_POWERPC;
+ cpuSubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+
mach_header header = {
MH_MAGIC, // magic
- CPU_TYPE_I386, // cputype
- CPU_SUBTYPE_I386_ALL, // cpusubtype
- MH_OBJECT, // filetype
+ cpuType,
+ cpuSubtype,
+ MH_OBJECT, // filetype,
2, // ncmds
sizeof(segment_command)
+ sizeof(section)
@@ -142,17 +155,17 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
int
main(int argc, const char** argv)
{
- if (argc != 6) {
+ if (argc != 7) {
fprintf(stderr,
- "usage: %s "
- " \n",
+ "usage: %s "
+ " \n",
argv[0]);
return -1;
}
uint8_t* data = 0;
unsigned size;
- int fd = open(argv[1], O_RDONLY);
+ int fd = open(argv[2], O_RDONLY);
if (fd != -1) {
struct stat s;
int r = fstat(fd, &s);
@@ -165,8 +178,11 @@ main(int argc, const char** argv)
}
if (data) {
- writeObject(stdout, data, size, argv[2], argv[3], argv[4], argv[5]);
+ writeObject
+ (argv[1], stdout, data, size, argv[3], argv[4], argv[5], argv[6]);
+
munmap(data, size);
+
return 0;
} else {
perror(argv[0]);
diff --git a/src/bootimage.cpp b/src/bootimage.cpp
index 9291acdfd0..2ff9c6c1bf 100644
--- a/src/bootimage.cpp
+++ b/src/bootimage.cpp
@@ -33,7 +33,8 @@ endsWith(const char* suffix, const char* s, unsigned length)
object
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
- unsigned capacity, uintptr_t* codeMap)
+ unsigned capacity, uintptr_t* codeMap, const char* className,
+ const char* methodName, const char* methodSpec)
{
unsigned size = 0;
t->m->processor->compileThunks(t, image, code, &size, capacity);
@@ -50,7 +51,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
unsigned nameSize = 0;
const char* name = it.next(&nameSize);
- if (endsWith(".class", name, nameSize)) {
+ if (endsWith(".class", name, nameSize)
+ and (className == 0 or strncmp(name, className, nameSize - 6) == 0))
+ {
//fprintf(stderr, "%.*s\n", nameSize - 6, name);
object c = resolveClass
(t, makeByteArray(t, "%.*s", nameSize - 6, name));
@@ -59,7 +62,19 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
if (classMethodTable(t, c)) {
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
object method = arrayBody(t, classMethodTable(t, c), i);
- if (methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE)) {
+ if ((methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE))
+ and ((methodName == 0
+ or strcmp
+ (reinterpret_cast
+ (&byteArrayBody
+ (t, vm::methodName(t, method), 0)), methodName) == 0)
+ and (methodSpec == 0
+ or strcmp
+ (reinterpret_cast
+ (&byteArrayBody
+ (t, vm::methodSpec(t, method), 0)), methodSpec)
+ == 0)))
+ {
t->m->processor->compileMethod
(t, zone, code, &size, capacity, &constants, &calls, &addresses,
method);
@@ -255,7 +270,8 @@ offset(object a, uintptr_t* b)
}
void
-writeBootImage(Thread* t, FILE* out)
+writeBootImage(Thread* t, FILE* out, const char* className,
+ const char* methodName, const char* methodSpec)
{
Zone zone(t->m->system, t->m->heap, 64 * 1024);
BootImage image;
@@ -267,7 +283,8 @@ writeBootImage(Thread* t, FILE* out)
memset(codeMap, 0, codeMapSize(CodeCapacity));
object constants = makeCodeImage
- (t, &zone, &image, code, CodeCapacity, codeMap);
+ (t, &zone, &image, code, CodeCapacity, codeMap, className, methodName,
+ methodSpec);
PROTECT(t, constants);
const unsigned HeapCapacity = 32 * 1024 * 1024;
@@ -348,8 +365,9 @@ writeBootImage(Thread* t, FILE* out)
int
main(int ac, const char** av)
{
- if (ac != 2) {
- fprintf(stderr, "usage: %s \n", av[0]);
+ if (ac < 2 or ac > 5) {
+ fprintf(stderr, "usage: %s "
+ "[ [ []]]\n", av[0]);
return -1;
}
@@ -363,7 +381,9 @@ main(int ac, const char** av)
enter(t, Thread::ActiveState);
enter(t, Thread::IdleState);
- writeBootImage(t, stdout);
+ writeBootImage
+ (t, stdout, (ac > 2 ? av[2] : 0), (ac > 3 ? av[3] : 0),
+ (ac > 4 ? av[4] : 0));
return 0;
}
diff --git a/src/common.h b/src/common.h
index e2783c7ef9..0b5fc040a3 100644
--- a/src/common.h
+++ b/src/common.h
@@ -29,7 +29,7 @@
# define PATH_SEPARATOR ':'
#endif
-#ifdef __i386__
+#if (defined __i386__) || (defined __POWERPC__)
# define LD "d"
# define LLD "lld"
#ifdef __APPLE__
@@ -62,12 +62,6 @@
# define SO_SUFFIX ".so"
#endif
-#ifdef __APPLE__
-# define FORCE_ALIGN __attribute__((force_align_arg_pointer))
-#else
-# define FORCE_ALIGN
-#endif
-
#define NO_RETURN __attribute__((noreturn))
#define LIKELY(v) __builtin_expect((v) != 0, true)
diff --git a/src/compile.S b/src/compile.S
index 90416024ee..80c1350384 100644
--- a/src/compile.S
+++ b/src/compile.S
@@ -10,6 +10,8 @@
#include "types.h"
+#define LOCAL(x) .L##x
+
.text
#ifdef __x86_64__
@@ -37,15 +39,15 @@ vmInvoke:
// copy arguments into place
pushq %rcx
movq $0,%r9
- jmp test
+ jmp LOCAL(test)
-loop:
+LOCAL(loop):
push (%rdx,%r9,8)
inc %r9
-test:
+LOCAL(test):
cmpq %rcx,%r9
- jb loop
+ jb LOCAL(loop)
// call function
call *%rsi
@@ -97,15 +99,15 @@ vmInvoke:
// copy arguments into place
movl $0,%ecx
mov 16(%ebp),%edx
- jmp test
+ jmp LOCAL(test)
-loop:
+LOCAL(loop):
push (%edx,%ecx,4)
inc %ecx
-test:
+LOCAL(test):
cmpl 20(%ebp),%ecx
- jb loop
+ jb LOCAL(loop)
// call function
call *12(%ebp)
@@ -118,20 +120,20 @@ test:
// handle return value based on expected type
movl 24(%ebp),%ecx
-void:
+LOCAL(void):
cmpl $VOID_TYPE,%ecx
- jne int64
- jmp exit
+ jne LOCAL(int64)
+ jmp LOCAL(exit)
-int64:
+LOCAL(int64):
cmpl $INT64_TYPE,%ecx
- jne int32
- jmp exit
+ jne LOCAL(int32)
+ jmp LOCAL(exit)
-int32:
+LOCAL(int32):
movl $0,%edx
-exit:
+LOCAL(exit):
popl %edi
popl %esi
popl %ebx
diff --git a/src/compile.cpp b/src/compile.cpp
index 89e1b6d658..85da676149 100644
--- a/src/compile.cpp
+++ b/src/compile.cpp
@@ -14,7 +14,7 @@
#include "process.h"
#include "assembler.h"
#include "compiler.h"
-#include "x86.h"
+#include "arch.h"
using namespace vm;
@@ -27,7 +27,7 @@ vmCall();
namespace {
-const bool DebugCompile = false;
+const bool DebugCompile = true;
const bool DebugNatives = false;
const bool DebugCallTable = false;
const bool DebugMethodTree = false;
@@ -35,6 +35,10 @@ const bool DebugFrameMaps = false;
const bool CheckArrayBounds = true;
+const unsigned MaxNativeCallFootprint = 4;
+
+const unsigned InitialZoneCapacityInBytes = 64 * 1024;
+
class MyThread: public Thread {
public:
class CallTrace {
@@ -65,26 +69,31 @@ class MyThread: public Thread {
CallTrace* next;
};
- MyThread(Machine* m, object javaThread, Thread* parent):
+ MyThread(Machine* m, object javaThread, MyThread* parent):
Thread(m, javaThread, parent),
ip(0),
base(0),
stack(0),
trace(0),
- reference(0)
- { }
+ reference(0),
+ arch(parent ? parent->arch : makeArchitecture(m->system))
+ {
+ arch->acquire();
+ }
void* ip;
void* base;
void* stack;
CallTrace* trace;
Reference* reference;
+ Assembler::Architecture* arch;
};
object
resolveThisPointer(MyThread* t, void* stack, object method)
{
- return reinterpret_cast