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

This commit is contained in:
Joel Dice 2009-02-15 12:34:01 -07:00
commit bec13838c1
28 changed files with 8600 additions and 3835 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.gdb_history
build
*~

View File

@ -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= \

27
src/arch.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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 <input file> <segment name> <section name> "
"<start symbol name> <end symbol name>\n",
"usage: %s <architecture> <input file> <segment name> "
"<section name> <start symbol name> <end symbol name>\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]);

View File

@ -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<char*>
(&byteArrayBody
(t, vm::methodName(t, method), 0)), methodName) == 0)
and (methodSpec == 0
or strcmp
(reinterpret_cast<char*>
(&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 <classpath>\n", av[0]);
if (ac < 2 or ac > 5) {
fprintf(stderr, "usage: %s <classpath> "
"[<class name> [<method name> [<method spec>]]]\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;
}

View File

@ -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)

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -22,21 +22,26 @@ class Compiler {
class Client {
public:
virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0;
virtual intptr_t getThunk(BinaryOperation op, unsigned size) = 0;
virtual intptr_t getThunk(TernaryOperation op, unsigned size) = 0;
};
static const unsigned Aligned = 1 << 0;
static const unsigned NoReturn = 1 << 1;
class Operand { };
class StackElement { };
class State { };
class Subroutine { };
virtual void pushState() = 0;
virtual void popState() = 0;
virtual void saveStack() = 0;
virtual void resetStack() = 0;
virtual State* saveState() = 0;
virtual void restoreState(State* state) = 0;
virtual Subroutine* startSubroutine() = 0;
virtual void endSubroutine(Subroutine* subroutine) = 0;
virtual void restoreFromSubroutine(Subroutine* subroutine) = 0;
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
unsigned localFootprint) = 0;
unsigned localFootprint, unsigned alignedFrameSize) = 0;
virtual void visitLogicalIp(unsigned logicalIp) = 0;
virtual void startLogicalIp(unsigned logicalIp) = 0;
@ -55,18 +60,18 @@ class Compiler {
unsigned scale = 1) = 0;
virtual Operand* stack() = 0;
virtual Operand* base() = 0;
virtual Operand* thread() = 0;
virtual Operand* label() = 0;
virtual void mark(Operand* label) = 0;
virtual void push(unsigned size) = 0;
virtual void push(unsigned size, Operand* value) = 0;
virtual Operand* pop(unsigned size) = 0;
virtual void pushed(unsigned count) = 0;
virtual void popped(unsigned count, bool isEvent) = 0;
virtual Operand* peek(unsigned size, unsigned index) = 0;
virtual void push(unsigned footprint) = 0;
virtual void push(unsigned footprint, Operand* value) = 0;
virtual void save(unsigned footprint, Operand* value) = 0;
virtual Operand* pop(unsigned footprint) = 0;
virtual void pushed() = 0;
virtual void popped(unsigned footprint) = 0;
virtual StackElement* top() = 0;
virtual unsigned footprint(StackElement*) = 0;
virtual unsigned index(StackElement*) = 0;
virtual Operand* peek(unsigned footprint, unsigned index) = 0;
virtual Operand* call(Operand* address,
unsigned flags,
@ -75,18 +80,27 @@ class Compiler {
unsigned argumentCount,
...) = 0;
virtual Operand* stackCall(Operand* address,
unsigned flags,
TraceHandler* traceHandler,
unsigned resultSize,
unsigned argumentFootprint) = 0;
virtual void return_(unsigned size, Operand* value) = 0;
virtual void storeLocal(unsigned size, Operand* src, unsigned index) = 0;
virtual Operand* loadLocal(unsigned size, unsigned index) = 0;
virtual void initLocal(unsigned size, unsigned index) = 0;
virtual void initLocalsFromLogicalIp(unsigned logicalIp) = 0;
virtual void storeLocal(unsigned footprint, Operand* src,
unsigned index) = 0;
virtual Operand* loadLocal(unsigned footprint, unsigned index) = 0;
virtual void saveLocals() = 0;
virtual void checkBounds(Operand* object, unsigned lengthOffset,
Operand* index, intptr_t handler) = 0;
virtual void store(unsigned size, Operand* src, Operand* dst) = 0;
virtual Operand* load(unsigned size, Operand* src) = 0;
virtual Operand* loadz(unsigned size, Operand* src) = 0;
virtual Operand* load4To8(Operand* src) = 0;
virtual Operand* load(unsigned srcSize, unsigned dstSize, Operand* src) = 0;
virtual Operand* loadz(unsigned size, unsigned dstSize, Operand* src) = 0;
virtual Operand* lcmp(Operand* a, Operand* b) = 0;
virtual void cmp(unsigned size, Operand* a, Operand* b) = 0;
virtual void jl(Operand* address) = 0;

View File

@ -16,14 +16,6 @@ using namespace vm;
namespace {
void*
allocate(System* s, unsigned size)
{
void* p = s->tryAllocate(size);
if (p == 0) s->abort();
return p;
}
const char*
append(System* s, const char* a, const char* b,
const char* c)

View File

@ -2211,7 +2211,7 @@ isAssignableFrom(Thread* t, object a, object b)
return false;
}
bool FORCE_ALIGN
bool
instanceOf(Thread* t, object class_, object o)
{
if (o == 0) {

View File

@ -145,6 +145,10 @@ struct JavaVMVTable {
void* reserved1;
void* reserved2;
#if (! TARGET_RT_MAC_CFM) && defined(__ppc__)
void* cfm_vectors[4];
#endif
jint
(JNICALL *DestroyJavaVM)
(JavaVM*);
@ -164,6 +168,10 @@ struct JavaVMVTable {
jint
(JNICALL *AttachCurrentThreadAsDaemon)
(JavaVM*, JNIEnv**, void*);
#if TARGET_RT_MAC_CFM && defined(__ppc__)
void* real_functions[5];
#endif
};
struct JNIEnvVTable {
@ -172,6 +180,10 @@ struct JNIEnvVTable {
void* reserved2;
void* reserved3;
#if (! TARGET_RT_MAC_CFM) && defined(__ppc__)
void* cfm_vectors[225];
#endif
jint
(JNICALL *GetVersion)
(JNIEnv*);
@ -1087,6 +1099,10 @@ struct JNIEnvVTable {
jlong
(JNICALL *GetDirectBufferCapacity)
(JNIEnv*, jobject);
#if TARGET_RT_MAC_CFM && defined(__ppc__)
void* real_functions[228];
#endif
};
inline int
@ -1526,7 +1542,7 @@ mark(Thread* t, object o, unsigned offset)
}
}
inline void FORCE_ALIGN
inline void
set(Thread* t, object target, unsigned offset, object value)
{
cast<object>(target, offset) = value;
@ -1736,7 +1752,7 @@ makeExceptionInInitializerError(Thread* t, object cause)
return makeExceptionInInitializerError(t, 0, trace, cause);
}
inline object FORCE_ALIGN
inline object
makeNew(Thread* t, object class_)
{
assert(t, t->state == Thread::ActiveState);
@ -1751,7 +1767,7 @@ makeNew(Thread* t, object class_)
return instance;
}
inline object FORCE_ALIGN
inline object
makeNewWeakReference(Thread* t, object class_)
{
assert(t, t->state == Thread::ActiveState);

View File

@ -9,9 +9,10 @@
details. */
#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
#undef assert
# include "CoreFoundation/CoreFoundation.h"
# undef assert
#endif
#include "sys/mman.h"
#include "sys/types.h"
#include "sys/stat.h"
@ -27,7 +28,7 @@
#include "stdint.h"
#include "dirent.h"
#include "x86.h"
#include "arch.h"
#include "system.h"
#define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_) (x)
@ -67,34 +68,6 @@ MySystem* system;
const int signals[] = { VisitSignal, SegFaultSignal, InterruptSignal };
#ifdef __x86_64__
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
# define BASE_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP])
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
#elif defined __i386__
# ifdef __APPLE__
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__eip)
# define BASE_REGISTER(context) (context->uc_mcontext->__ss.__ebp)
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__esp)
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__ebx)
# else
# define IP_REGISTER(context) (context->uc_mcontext->ss.eip)
# define BASE_REGISTER(context) (context->uc_mcontext->ss.ebp)
# define STACK_REGISTER(context) (context->uc_mcontext->ss.esp)
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.ebx)
# endif
# else
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
# define BASE_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX])
# endif
#else
# error unsupported architecture
#endif
void
handleSignal(int signal, siginfo_t* info, void* context);
@ -105,14 +78,6 @@ run(void* r)
return 0;
}
void*
allocate(System* s, unsigned size)
{
void* p = s->tryAllocate(size);
if (p == 0) abort();
return p;
}
void
pathOfExecutable(System* s, const char** retBuf, unsigned* size)
{

158
src/powerpc.S Normal file
View File

@ -0,0 +1,158 @@
/* 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. */
#include "types.h"
.text
#define BYTES_PER_WORD 4
#define LOCAL(x) L##x
#ifdef __APPLE__
.globl _vmNativeCall
_vmNativeCall:
#else
.globl vmNativeCall
vmNativeCall:
#endif
// save return address
mflr r0
stw r0,8(r1)
// r3 aka r13: function
// r4 : stackTotal
// r5 : memoryTable
// r6 : memoryCount
// r7 : gprTable
// r8 : fprTable
// r9 aka r14: returnType
// r15 : stack frame size
// r16 : temporary
// r17 : temporary
// save registers used for local variables
stw r13,24(r1)
stw r14,28(r1)
stw r15,32(r1)
stw r16,36(r1)
stw r17,40(r1)
// allocate stack space
stwux r1,r1,r4
// save our argument registers so we can clobber them
mr r13,r3
mr r14,r9
li r16,0
b LOCAL(test)
LOCAL(loop):
lwzx r17,r16,r5
stwx r17,r16,r1
addi r16,r16,BYTES_PER_WORD
LOCAL(test):
cmplw r16,r6
blt LOCAL(loop)
// do we need to load the floating point registers?
cmpwi r8,0
beq LOCAL(gpr)
// yes, we do
lfd f1,0(r8)
lfd f2,8(r8)
lfd f3,16(r8)
lfd f4,24(r8)
lfd f5,32(r8)
lfd f6,40(r8)
lfd f7,48(r8)
lfd f8,56(r8)
lfd f9,64(r8)
lfd f10,72(r8)
lfd f11,80(r8)
lfd f12,88(r8)
lfd f13,96(r8)
LOCAL(gpr):
// do we need to load the general-purpose registers?
cmpwi r7,0
beq LOCAL(call)
// yes, we do
mr r16,r7
lwz r3,0(r16)
lwz r4,4(r16)
lwz r5,8(r16)
lwz r6,12(r16)
lwz r7,16(r16)
lwz r8,20(r16)
lwz r9,24(r16)
lwz r10,28(r16)
LOCAL(call):
// load and call function address
mtctr r13
bctrl
// handle return value based on expected type
cmpwi r14,VOID_TYPE
bne LOCAL(float)
b LOCAL(exit)
LOCAL(float):
cmpwi r14,FLOAT_TYPE
beq LOCAL(copy)
cmpwi r14,DOUBLE_TYPE
beq LOCAL(copy)
cmpwi r14,INT64_TYPE
beq LOCAL(exit)
mr r4,r3
b LOCAL(exit)
LOCAL(copy):
// move floating point return value to GPRs via memory
stfd f1,8(r1)
lwz r3,8(r1)
lwz r4,12(r1)
b LOCAL(exit)
LOCAL(exit):
// restore stack pointer
lwz r1,0(r1)
// restore registers used for local variables
lwz r13,24(r1)
lwz r14,28(r1)
lwz r15,32(r1)
lwz r16,36(r1)
lwz r17,40(r1)
// load return address
lwz r0,8(r1)
mtlr r0
// return
blr
#ifdef __APPLE__
.globl _vmJump
_vmJump:
#else
.globl vmJump
vmJump:
#endif
mtlr r3
mr r13,r4
mr r1,r5
mr r14,r6
blr

1920
src/powerpc.cpp Normal file

File diff suppressed because it is too large Load Diff

124
src/powerpc.h Normal file
View File

@ -0,0 +1,124 @@
/* 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 POWERPC_H
#define POWERPC_H
#include "types.h"
#include "common.h"
#ifdef __APPLE__
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__srr0)
# define BASE_REGISTER(context) (context->uc_mcontext->__ss.__r13)
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__r1)
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__r14)
# else
# define IP_REGISTER(context) (context->uc_mcontext->ss.srr0)
# define BASE_REGISTER(context) (context->uc_mcontext->ss.r13)
# define STACK_REGISTER(context) (context->uc_mcontext->ss.r1)
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.r14)
# endif
#else
# define IP_REGISTER(context) (context->uc_mcontext.gregs[32])
# define BASE_REGISTER(context) (context->uc_mcontext.gregs[13])
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[1])
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[14])
#endif
extern "C" uint64_t
vmNativeCall(void* function, unsigned stackTotal, void* memoryTable,
unsigned memoryCount, void* gprTable, void* fprTable,
unsigned returnType);
namespace vm {
inline uint64_t
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
unsigned argumentCount, unsigned argumentsSize,
unsigned returnType)
{
const unsigned LinkageArea = 24;
const unsigned GprCount = 8;
uintptr_t gprTable[GprCount];
unsigned gprIndex = 0;
const unsigned FprCount = 13;
uint64_t fprTable[FprCount];
unsigned fprIndex = 0;
uintptr_t stack[argumentsSize / BytesPerWord];
unsigned stackSkip = 0;
unsigned stackIndex = 0;
unsigned ai = 0;
for (unsigned ati = 0; ati < argumentCount; ++ ati) {
switch (argumentTypes[ati]) {
case FLOAT_TYPE: {
if (fprIndex < FprCount) {
fprTable[fprIndex++] = arguments[ai];
++ gprIndex;
++ stackSkip;
} else {
stack[stackIndex++] = arguments[ai];
}
++ ai;
} break;
case DOUBLE_TYPE: {
if (fprIndex < FprCount) {
memcpy(fprTable + fprIndex, arguments + ai, 8);
++ fprIndex;
gprIndex += BytesPerWord / 4;
stackSkip += BytesPerWord / 4;
} else {
memcpy(stack + stackIndex, arguments + ai, 8);
stackIndex += BytesPerWord / 4;
}
ai += BytesPerWord / 4;
} break;
case INT64_TYPE: {
if (gprIndex + BytesPerWord / 4 <= GprCount) {
memcpy(gprTable + gprIndex, arguments + ai, 8);
gprIndex += BytesPerWord / 4;
stackSkip += BytesPerWord / 4;
} else {
memcpy(stack + stackIndex, arguments + ai, 8);
stackIndex += BytesPerWord / 4;
}
ai += BytesPerWord / 4;
} break;
default: {
if (gprIndex < GprCount) {
gprTable[gprIndex++] = arguments[ai];
++ stackSkip;
} else {
stack[stackIndex++] = arguments[ai];
}
++ ai;
} break;
}
}
return vmNativeCall
(function,
- ((((1 + stackSkip + stackIndex) * BytesPerWord) + LinkageArea + 15)
& -16),
stack, stackIndex * BytesPerWord,
(gprIndex ? gprTable : 0),
(fprIndex ? fprTable : 0), returnType);
}
} // namespace vm
#endif//POWERPC_H

View File

@ -143,6 +143,14 @@ class System {
virtual void dispose() = 0;
};
inline void*
allocate(System* s, unsigned size)
{
void* p = s->tryAllocate(size);
if (p == 0) s->abort();
return p;
}
#define ACQUIRE_MONITOR(t, m) \
System::MonitorResource MAKE_NAME(monitorResource_) (t, m)

View File

@ -10,6 +10,8 @@
#include "types.h"
#define LOCAL(x) .L##x
.text
#ifdef __x86_64__
@ -42,9 +44,9 @@ vmNativeCall:
// copy memory arguments into place
movq $0,%rcx
jmp test
jmp LOCAL(test)
loop:
LOCAL(loop):
movq %rcx,%rax
movq %rcx,%rdx
addq %rsp,%rdx
@ -53,13 +55,13 @@ loop:
movq %rax,(%rdx)
addq $8,%rcx
test:
LOCAL(test):
cmpq -32(%rbp),%rcx
jb loop
jb LOCAL(loop)
// do we need to load the general-purpose registers?
cmpq $0,-24(%rbp)
je sse
je LOCAL(sse)
// yes, we do
movq -24(%rbp),%rax
@ -70,10 +72,10 @@ test:
movq 32(%rax),%r8
movq 40(%rax),%r9
sse:
LOCAL(sse):
// do we need to load the SSE registers?
cmpq $0,-16(%rbp)
je call
je LOCAL(call)
// yes, we do
movq -16(%rbp),%rax
@ -86,27 +88,27 @@ sse:
movq 48(%rax),%xmm6
movq 64(%rax),%xmm7
call:
LOCAL(call):
call *-48(%rbp)
// handle return value based on expected type
movq -8(%rbp),%rcx
void:
LOCAL(void):
cmpq $VOID_TYPE,%rcx
jne float
jmp exit
jne LOCAL(float)
jmp LOCAL(exit)
float:
LOCAL(float):
cmpq $FLOAT_TYPE,%rcx
je copy
je LOCAL(copy)
cmpq $DOUBLE_TYPE,%rcx
jne exit
jne LOCAL(exit)
copy:
LOCAL(copy):
movq %xmm0,%rax
exit:
LOCAL(exit):
movq %rbp,%rsp
popq %rbp
ret
@ -147,9 +149,9 @@ vmNativeCall:
// copy arguments into place
movl $0,%ecx
jmp test
jmp LOCAL(test)
loop:
LOCAL(loop):
movl %ecx,%eax
movl %ecx,%edx
addl %esp,%edx
@ -158,9 +160,9 @@ loop:
movl %eax,(%edx)
addl $4,%ecx
test:
LOCAL(test):
cmpl 16(%ebp),%ecx
jb loop
jb LOCAL(loop)
// call function
call *8(%ebp)
@ -168,31 +170,31 @@ test:
// handle return value based on expected type
movl 20(%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 float
jmp exit
jne LOCAL(float)
jmp LOCAL(exit)
float:
LOCAL(float):
cmpl $FLOAT_TYPE,%ecx
jne double
jne LOCAL(double)
fstps 8(%ebp)
movl 8(%ebp),%eax
jmp exit
jmp LOCAL(exit)
double:
LOCAL(double):
cmpl $DOUBLE_TYPE,%ecx
jne exit
jne LOCAL(exit)
fstpl 8(%ebp)
movl 8(%ebp),%eax
movl 12(%ebp),%edx
exit:
LOCAL(exit):
movl %ebp,%esp
popl %ebp
ret

File diff suppressed because it is too large Load Diff

View File

@ -12,14 +12,29 @@
#define X86_H
#include "types.h"
#include "stdint.h"
#include "common.h"
extern "C" void NO_RETURN
vmJump(void* address, void* base, void* stack, void* thread);
#ifdef __i386__
# ifdef __APPLE__
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__eip)
# define BASE_REGISTER(context) (context->uc_mcontext->__ss.__ebp)
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__esp)
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__ebx)
# else
# define IP_REGISTER(context) (context->uc_mcontext->ss.eip)
# define BASE_REGISTER(context) (context->uc_mcontext->ss.ebp)
# define STACK_REGISTER(context) (context->uc_mcontext->ss.esp)
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.ebx)
# endif
# else
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
# define BASE_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX])
# endif
extern "C" uint64_t
vmNativeCall(void* function, void* stack, unsigned stackSize,
unsigned returnType);
@ -37,6 +52,11 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
#elif defined __x86_64__
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
# define BASE_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP])
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
extern "C" uint64_t
vmNativeCall(void* function, void* stack, unsigned stackSize,
void* gprTable, void* sseTable, unsigned returnType);
@ -79,7 +99,7 @@ dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
}
}
return vmNativeCall(function, stack, stackIndex * 8,
return vmNativeCall(function, stack, stackIndex * BytesPerWord,
(gprIndex ? gprTable : 0),
(sseIndex ? sseTable : 0), returnType);
}
@ -87,7 +107,7 @@ dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
} // namespace vm
#else
# error unsupported platform
# error unsupported architecture
#endif

58
test/Arrays.java Normal file
View File

@ -0,0 +1,58 @@
public class Arrays {
private static void expect(boolean v) {
if (! v) throw new RuntimeException();
}
public static void main(String[] args) {
{ int[] array = new int[0];
Exception exception = null;
try {
int x = array[0];
} catch (ArrayIndexOutOfBoundsException e) {
exception = e;
}
expect(exception != null);
}
{ int[] array = new int[3];
int i = 0;
array[i++] = 1;
array[i++] = 2;
array[i++] = 3;
expect(array[--i] == 3);
expect(array[--i] == 2);
expect(array[--i] == 1);
}
{ Object[][] array = new Object[1][1];
expect(array.length == 1);
expect(array[0].length == 1);
}
{ Object[][] array = new Object[2][3];
expect(array.length == 2);
expect(array[0].length == 3);
}
{ int j = 0;
byte[] decodeTable = new byte[256];
for (int i = 'A'; i <= 'Z'; ++i) decodeTable[i] = (byte) j++;
for (int i = 'a'; i <= 'z'; ++i) decodeTable[i] = (byte) j++;
for (int i = '0'; i <= '9'; ++i) decodeTable[i] = (byte) j++;
decodeTable['+'] = (byte) j++;
decodeTable['/'] = (byte) j++;
decodeTable['='] = 0;
expect(decodeTable['a'] != 0);
}
{ boolean p = true;
int[] array = new int[] { 1, 2 };
expect(array[0] == array[p ? 0 : 1]);
p = false;
expect(array[1] == array[p ? 0 : 1]);
}
}
}

85
test/Integers.java Normal file
View File

@ -0,0 +1,85 @@
public class Integers {
private static void expect(boolean v) {
if (! v) throw new RuntimeException();
}
private static int gcd(int m, int n) {
int temp;
m = Math.abs(m);
n = Math.abs(n);
if (m < n) {
temp = m;
m = n;
n = temp;
}
while (n != 0) {
temp = m;
m = n;
n = temp % n;
}
return m;
}
public static void main(String[] args) {
expect(gcd(12, 4) == 4);
{ int a = 2;
int b = 2;
int c = a + b;
}
{ int a = 2;
int c = a + a;
}
{ int a = -5;
int b = 2;
expect(a >> b == -5 >> 2);
expect(a >>> b == -5 >>> 2);
expect(a << b == -5 << 2);
expect(a + b == -5 + 2);
expect(a - b == -5 - 2);
expect(a * b == -5 * 2);
expect(a / b == -5 / 2);
expect(a % b == -5 % 2);
expect((a & b) == (-5 & 2));
expect((a | b) == (-5 | 2));
expect((a ^ b) == (-5 ^ 2));
expect(-a == 5);
expect(~a == ~-5);
a = 5;
b = 2;
expect(a >> b == 5 >> 2);
expect(a >>> b == 5 >>> 2);
expect(a << b == 5 << 2);
expect(a + b == 5 + 2);
expect(a - b == 5 - 2);
expect(a * b == 5 * 2);
expect(a / b == 5 / 2);
expect(a % b == 5 % 2);
expect((a & b) == (5 & 2));
expect((a | b) == (5 | 2));
expect((a ^ b) == (5 ^ 2));
expect(-a == -5);
expect(~a == ~5);
}
{ int get_buffer = 2144642881;
int bits_left = 30;
int l = 9;
int code = (((get_buffer >> (bits_left -= (l)))) & ((1<<(l))-1));
expect(code == 510);
}
{ int width = 8;
int height = 8;
int depth = 24;
int scanlinePad = 4;
int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1))
/ scanlinePad * scanlinePad;
expect(bytesPerLine == 24);
}
}
}

193
test/Longs.java Normal file
View File

@ -0,0 +1,193 @@
public class Longs {
private static void expect(boolean v) {
if (! v) throw new RuntimeException();
}
public static void putInt(int val, byte[] dst, int offset) {
System.out.println("put " + val);
dst[offset] = (byte)((val >> 24) & 0xff);
dst[offset+1] = (byte)((val >> 16) & 0xff);
dst[offset+2] = (byte)((val >> 8) & 0xff);
dst[offset+3] = (byte)((val ) & 0xff);
}
public static void putLong(long val, byte[] dst, int offset) {
putInt((int)(val >> 32), dst, offset);
putInt((int)val, dst, offset + 4);
}
private static long roundUp(long a, long b) {
a += b - 1L;
return a - (a % b);
}
public static void main(String[] args) {
{ long foo = 25214903884L;
int radix = 10;
expect(foo > 0);
foo /= radix;
expect(foo > 0);
}
expect(roundUp(156, 2) == 156);
expect(((int) roundUp(156, 2)) == 156);
expect(Long.parseLong("25214903884") == 25214903884L);
expect(Long.parseLong("-9223372036854775808") == -9223372036854775808L);
expect(String.valueOf(25214903884L).equals("25214903884"));
expect(String.valueOf(-9223372036854775808L).equals
("-9223372036854775808"));
{ long a = -5;
long b = 2;
expect(a >> b == -5L >> 2);
expect(a >>> b == -5L >>> 2);
expect(a << b == -5L << 2);
expect(a + b == -5L + 2L);
expect(a - b == -5L - 2L);
expect(a * b == -5L * 2L);
expect(a / b == -5L / 2L);
expect(a % b == -5L % 2L);
expect((a & b) == (-5L & 2L));
expect((a | b) == (-5L | 2L));
expect((a ^ b) == (-5L ^ 2L));
expect(-a == 5L);
expect(~a == ~-5L);
a = 5;
b = 2;
expect(a >> b == 5L >> 2);
expect(a >>> b == 5L >>> 2);
expect(a << b == 5L << 2);
expect(a + b == 5L + 2L);
expect(a - b == 5L - 2L);
expect(a * b == 5L * 2L);
expect(a / b == 5L / 2L);
expect(a % b == 5L % 2L);
expect((a & b) == (5L & 2L));
expect((a | b) == (5L | 2L));
expect((a ^ b) == (5L ^ 2L));
expect(-a == -5L);
expect(~a == ~5L);
}
{ long a = -25214903884L;
long b = 2;
expect(a >> b == -25214903884L >> 2);
expect(a >>> b == -25214903884L >>> 2);
expect(a << b == -25214903884L << 2);
expect(a + b == -25214903884L + 2L);
expect(a - b == -25214903884L - 2L);
expect(a * b == -25214903884L * 2L);
expect(a / b == -25214903884L / 2L);
expect(a % b == -25214903884L % 2L);
expect((a & b) == (-25214903884L & 2L));
expect((a | b) == (-25214903884L | 2L));
expect((a ^ b) == (-25214903884L ^ 2L));
expect(-a == 25214903884L);
expect(~a == ~-25214903884L);
a = 25214903884L;
b = 2;
expect(a >> b == 25214903884L >> 2);
expect(a >>> b == 25214903884L >>> 2);
expect(a << b == 25214903884L << 2);
expect(a + b == 25214903884L + 2L);
expect(a - b == 25214903884L - 2L);
expect(a * b == 25214903884L * 2L);
expect(a / b == 25214903884L / 2L);
expect(a % b == 25214903884L % 2L);
expect((a & b) == (25214903884L & 2L));
expect((a | b) == (25214903884L | 2L));
expect((a ^ b) == (25214903884L ^ 2L));
expect(-a == -25214903884L);
expect(~a == ~25214903884L);
}
{ long b = 2;
expect((-25214903884L) >> b == -25214903884L >> 2);
expect((-25214903884L) >>> b == -25214903884L >>> 2);
expect((-25214903884L) << b == -25214903884L << 2);
expect((-25214903884L) + b == -25214903884L + 2L);
expect((-25214903884L) - b == -25214903884L - 2L);
expect((-25214903884L) * b == -25214903884L * 2L);
expect((-25214903884L) / b == -25214903884L / 2L);
expect((-25214903884L) % b == -25214903884L % 2L);
expect(((-25214903884L) & b) == (-25214903884L & 2L));
expect(((-25214903884L) | b) == (-25214903884L | 2L));
expect(((-25214903884L) ^ b) == (-25214903884L ^ 2L));
b = 2;
expect(25214903884L >> b == 25214903884L >> 2);
expect(25214903884L >>> b == 25214903884L >>> 2);
expect(25214903884L << b == 25214903884L << 2);
expect(25214903884L + b == 25214903884L + 2L);
expect(25214903884L - b == 25214903884L - 2L);
expect(25214903884L * b == 25214903884L * 2L);
expect(25214903884L / b == 25214903884L / 2L);
expect(25214903884L % b == 25214903884L % 2L);
expect((25214903884L & b) == (25214903884L & 2L));
expect((25214903884L | b) == (25214903884L | 2L));
expect((25214903884L ^ b) == (25214903884L ^ 2L));
}
{ long a = 2L;
expect(a + (-25214903884L) == 2L + (-25214903884L));
expect(a - (-25214903884L) == 2L - (-25214903884L));
expect(a * (-25214903884L) == 2L * (-25214903884L));
expect(a / (-25214903884L) == 2L / (-25214903884L));
expect(a % (-25214903884L) == 2L % (-25214903884L));
expect((a & (-25214903884L)) == (2L & (-25214903884L)));
expect((a | (-25214903884L)) == (2L | (-25214903884L)));
expect((a ^ (-25214903884L)) == (2L ^ (-25214903884L)));
a = 2L;
expect(a + 25214903884L == 2L + 25214903884L);
expect(a - 25214903884L == 2L - 25214903884L);
expect(a * 25214903884L == 2L * 25214903884L);
expect(a / 25214903884L == 2L / 25214903884L);
expect(a % 25214903884L == 2L % 25214903884L);
expect((a & 25214903884L) == (2L & 25214903884L));
expect((a | 25214903884L) == (2L | 25214903884L));
expect((a ^ 25214903884L) == (2L ^ 25214903884L));
}
{ long x = 231;
expect((x >> 32) == 0);
expect((x >>> 32) == 0);
expect((x << 32) == 992137445376L);
int shift = 32;
expect((x >> shift) == 0);
expect((x >>> shift) == 0);
expect((x << shift) == 992137445376L);
long y = -231;
expect((y >> 32) == 0xffffffffffffffffL);
expect((y >>> 32) == 0xffffffffL);
}
expect(Long.valueOf(231L) == 231L);
{ byte[] array = new byte[8];
putLong(231, array, 0);
expect((array[0] & 0xff) == 0);
expect((array[1] & 0xff) == 0);
expect((array[2] & 0xff) == 0);
expect((array[3] & 0xff) == 0);
expect((array[4] & 0xff) == 0);
expect((array[5] & 0xff) == 0);
expect((array[6] & 0xff) == 0);
expect((array[7] & 0xff) == 231);
}
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8);
buffer.putLong(231);
buffer.flip();
expect(buffer.getLong() == 231);
}
}

View File

@ -51,19 +51,6 @@ public class Misc {
}
}
public static void putInt(int val, byte[] dst, int offset) {
System.out.println("put " + val);
dst[offset] = (byte)((val >> 24) & 0xff);
dst[offset+1] = (byte)((val >> 16) & 0xff);
dst[offset+2] = (byte)((val >> 8) & 0xff);
dst[offset+3] = (byte)((val ) & 0xff);
}
public static void putLong(long val, byte[] dst, int offset) {
putInt((int)(val >> 32), dst, offset);
putInt((int)val, dst, offset + 4);
}
public String toString() {
return super.toString();
}
@ -91,252 +78,35 @@ public class Misc {
return a + b + c;
}
private static long roundUp(long a, long b) {
a += b - 1L;
return a - (a % b);
private static Object gimmeNull() {
return null;
}
private static Object queryDefault(Object default_) {
Object o = gimmeNull();
return (o == null ? default_ : o);
}
public static void main(String[] args) {
{ long foo = 25214903884L;
int radix = 10;
expect(foo > 0);
foo /= radix;
expect(foo > 0);
}
expect(new String(new byte[] { 99, 111, 109, 46, 101, 99, 111, 118, 97,
116, 101, 46, 110, 97, 116, 46, 98, 117,
115, 46, 83, 121, 109, 98, 111, 108 })
.equals("com.ecovate.nat.bus.Symbol"));
expect(Long.parseLong("25214903884") == 25214903884L);
expect(Long.parseLong("-9223372036854775808") == -9223372036854775808L);
expect(String.valueOf(25214903884L).equals("25214903884"));
expect(String.valueOf(-9223372036854775808L).equals
("-9223372036854775808"));
{ boolean p = true;
int[] array = new int[] { 1, 2 };
expect(array[0] == array[p ? 0 : 1]);
p = false;
expect(array[1] == array[p ? 0 : 1]);
}
expect(roundUp(156, 2) == 156);
expect(queryDefault(new Object()) != null);
{ Foo foo = new Foo();
int x = foo.a + foo.b + foo.c;
bar(foo.a, foo.b, foo.c);
}
{ int get_buffer = 2144642881;
int bits_left = 30;
int l = 9;
int code = (((get_buffer >> (bits_left -= (l)))) & ((1<<(l))-1));
expect(code == 510);
}
{ int width = 8;
int height = 8;
int depth = 24;
int scanlinePad = 4;
int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1))
/ scanlinePad * scanlinePad;
expect(bytesPerLine == 24);
}
{ int a = -5;
int b = 2;
expect(a >> b == -5 >> 2);
expect(a >>> b == -5 >>> 2);
expect(a << b == -5 << 2);
expect(a + b == -5 + 2);
expect(a - b == -5 - 2);
expect(a * b == -5 * 2);
expect(a / b == -5 / 2);
expect(a % b == -5 % 2);
expect((a & b) == (-5 & 2));
expect((a | b) == (-5 | 2));
expect((a ^ b) == (-5 ^ 2));
expect(-a == 5);
expect(~a == ~-5);
a = 5;
b = 2;
expect(a >> b == 5 >> 2);
expect(a >>> b == 5 >>> 2);
expect(a << b == 5 << 2);
expect(a + b == 5 + 2);
expect(a - b == 5 - 2);
expect(a * b == 5 * 2);
expect(a / b == 5 / 2);
expect(a % b == 5 % 2);
expect((a & b) == (5 & 2));
expect((a | b) == (5 | 2));
expect((a ^ b) == (5 ^ 2));
expect(-a == -5);
expect(~a == ~5);
}
{ long a = -5;
long b = 2;
expect(a >> b == -5L >> 2);
expect(a >>> b == -5L >>> 2);
expect(a << b == -5L << 2);
expect(a + b == -5L + 2L);
expect(a - b == -5L - 2L);
expect(a * b == -5L * 2L);
expect(a / b == -5L / 2L);
expect(a % b == -5L % 2L);
expect((a & b) == (-5L & 2L));
expect((a | b) == (-5L | 2L));
expect((a ^ b) == (-5L ^ 2L));
expect(-a == 5L);
expect(~a == ~-5L);
a = 5;
b = 2;
expect(a >> b == 5L >> 2);
expect(a >>> b == 5L >>> 2);
expect(a << b == 5L << 2);
expect(a + b == 5L + 2L);
expect(a - b == 5L - 2L);
expect(a * b == 5L * 2L);
expect(a / b == 5L / 2L);
expect(a % b == 5L % 2L);
expect((a & b) == (5L & 2L));
expect((a | b) == (5L | 2L));
expect((a ^ b) == (5L ^ 2L));
expect(-a == -5L);
expect(~a == ~5L);
}
{ long a = -25214903884L;
long b = 2;
expect(a >> b == -25214903884L >> 2);
expect(a >>> b == -25214903884L >>> 2);
expect(a << b == -25214903884L << 2);
expect(a + b == -25214903884L + 2L);
expect(a - b == -25214903884L - 2L);
expect(a * b == -25214903884L * 2L);
expect(a / b == -25214903884L / 2L);
expect(a % b == -25214903884L % 2L);
expect((a & b) == (-25214903884L & 2L));
expect((a | b) == (-25214903884L | 2L));
expect((a ^ b) == (-25214903884L ^ 2L));
expect(-a == 25214903884L);
expect(~a == ~-25214903884L);
a = 25214903884L;
b = 2;
expect(a >> b == 25214903884L >> 2);
expect(a >>> b == 25214903884L >>> 2);
expect(a << b == 25214903884L << 2);
expect(a + b == 25214903884L + 2L);
expect(a - b == 25214903884L - 2L);
expect(a * b == 25214903884L * 2L);
expect(a / b == 25214903884L / 2L);
expect(a % b == 25214903884L % 2L);
expect((a & b) == (25214903884L & 2L));
expect((a | b) == (25214903884L | 2L));
expect((a ^ b) == (25214903884L ^ 2L));
expect(-a == -25214903884L);
expect(~a == ~25214903884L);
}
{ long b = 2;
expect((-25214903884L) >> b == -25214903884L >> 2);
expect((-25214903884L) >>> b == -25214903884L >>> 2);
expect((-25214903884L) << b == -25214903884L << 2);
expect((-25214903884L) + b == -25214903884L + 2L);
expect((-25214903884L) - b == -25214903884L - 2L);
expect((-25214903884L) * b == -25214903884L * 2L);
expect((-25214903884L) / b == -25214903884L / 2L);
expect((-25214903884L) % b == -25214903884L % 2L);
expect(((-25214903884L) & b) == (-25214903884L & 2L));
expect(((-25214903884L) | b) == (-25214903884L | 2L));
expect(((-25214903884L) ^ b) == (-25214903884L ^ 2L));
b = 2;
expect(25214903884L >> b == 25214903884L >> 2);
expect(25214903884L >>> b == 25214903884L >>> 2);
expect(25214903884L << b == 25214903884L << 2);
expect(25214903884L + b == 25214903884L + 2L);
expect(25214903884L - b == 25214903884L - 2L);
expect(25214903884L * b == 25214903884L * 2L);
expect(25214903884L / b == 25214903884L / 2L);
expect(25214903884L % b == 25214903884L % 2L);
expect((25214903884L & b) == (25214903884L & 2L));
expect((25214903884L | b) == (25214903884L | 2L));
expect((25214903884L ^ b) == (25214903884L ^ 2L));
}
{ long a = 2L;
expect(a + (-25214903884L) == 2L + (-25214903884L));
expect(a - (-25214903884L) == 2L - (-25214903884L));
expect(a * (-25214903884L) == 2L * (-25214903884L));
expect(a / (-25214903884L) == 2L / (-25214903884L));
expect(a % (-25214903884L) == 2L % (-25214903884L));
expect((a & (-25214903884L)) == (2L & (-25214903884L)));
expect((a | (-25214903884L)) == (2L | (-25214903884L)));
expect((a ^ (-25214903884L)) == (2L ^ (-25214903884L)));
a = 2L;
expect(a + 25214903884L == 2L + 25214903884L);
expect(a - 25214903884L == 2L - 25214903884L);
expect(a * 25214903884L == 2L * 25214903884L);
expect(a / 25214903884L == 2L / 25214903884L);
expect(a % 25214903884L == 2L % 25214903884L);
expect((a & 25214903884L) == (2L & 25214903884L));
expect((a | 25214903884L) == (2L | 25214903884L));
expect((a ^ 25214903884L) == (2L ^ 25214903884L));
}
byte2 = 0;
expect(byte2 == 0);
expect(Long.valueOf(231L) == 231L);
{ long x = 231;
expect((x >> 32) == 0);
expect((x >>> 32) == 0);
expect((x << 32) == 992137445376L);
int shift = 32;
expect((x >> shift) == 0);
expect((x >>> shift) == 0);
expect((x << shift) == 992137445376L);
long y = -231;
expect((y >> 32) == 0xffffffffffffffffL);
expect((y >>> 32) == 0xffffffffL);
}
{ byte[] array = new byte[8];
putLong(231, array, 0);
expect((array[0] & 0xff) == 0);
expect((array[1] & 0xff) == 0);
expect((array[2] & 0xff) == 0);
expect((array[3] & 0xff) == 0);
expect((array[4] & 0xff) == 0);
expect((array[5] & 0xff) == 0);
expect((array[6] & 0xff) == 0);
expect((array[7] & 0xff) == 231);
}
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8);
buffer.putLong(231);
buffer.flip();
expect(buffer.getLong() == 231);
boolean v = Boolean.valueOf("true");
ClassLoader.getSystemClassLoader().toString();
{ int a = 2;
int b = 2;
int c = a + b;
}
{ Misc m = new Misc();
m.toString();
@ -374,33 +144,6 @@ public class Misc {
expect(zip() == 47);
expect(zup() == 47);
{ int[] array = new int[0];
Exception exception = null;
try {
int x = array[0];
} catch (ArrayIndexOutOfBoundsException e) {
exception = e;
}
expect(exception != null);
}
{ int[] array = new int[3];
int i = 0;
array[i++] = 1;
array[i++] = 2;
array[i++] = 3;
expect(array[--i] == 3);
expect(array[--i] == 2);
expect(array[--i] == 1);
}
{ Object[][] array = new Object[1][1];
expect(array.length == 1);
expect(array[0].length == 1);
}
{
Object a = new Object();
Object b = new Object();
@ -421,16 +164,23 @@ public class Misc {
foo.a = (foo.a + 1) % foo.array.length;
}
{ int j = 0;
byte[] decodeTable = new byte[256];
for (int i = 'A'; i <= 'Z'; ++i) decodeTable[i] = (byte) j++;
for (int i = 'a'; i <= 'z'; ++i) decodeTable[i] = (byte) j++;
for (int i = '0'; i <= '9'; ++i) decodeTable[i] = (byte) j++;
decodeTable['+'] = (byte) j++;
decodeTable['/'] = (byte) j++;
decodeTable['='] = 0;
{ boolean foo = false;
boolean iconic = false;
do {
zap();
iconic = foo ? true : false;
} while (foo);
zap();
}
expect(decodeTable['a'] != 0);
{ int x = 0;
if (x == 0) {
x = 1;
do {
int y = x;
x = 1;
} while (x != 1);
}
}
}
}

11
test/Simple.java Normal file
View File

@ -0,0 +1,11 @@
public class Simple {
public static int size(long v, int radix) {
int size = 0;
for (long n = v; n != 0; n /= radix) ++size;
return size;
}
public static void main(String[] args) {
size(42, 10);
}
}

42
test/Subroutine.java Normal file
View File

@ -0,0 +1,42 @@
public class Subroutine {
private static void expect(boolean v) {
if (! v) throw new RuntimeException();
}
// This test is intended to cover the jsr and ret instructions.
// However, recent Sun javac versions avoid generating these
// instructions by default, so we must compile this class using
// -source 1.2 -target 1.1 -XDjsrlimit=0.
//
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4381996
//
private static void test(boolean throw_, boolean predicate) {
int x = 42;
int y = 99;
int a = 0;
try {
try {
int z = x + y;
if (throw_) throw new DummyException();
if (predicate) {
return;
}
Integer.valueOf(z).toString();
} finally {
a = x + y;
System.gc();
}
expect(a == x + y);
} catch (DummyException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
test(false, false);
test(false, true);
test(true, false);
}
private static class DummyException extends RuntimeException { }
}