mirror of
https://github.com/corda/corda.git
synced 2025-01-21 03:55:00 +00:00
Merge branch 'powerpc' of oss.readytalk.com:/var/local/git/avian
This commit is contained in:
commit
bec13838c1
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
.gdb_history
|
||||
build
|
||||
*~
|
24
makefile
24
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= \
|
||||
|
27
src/arch.h
Normal file
27
src/arch.h
Normal 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
|
167
src/assembler.h
167
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
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
956
src/compile.cpp
956
src/compile.cpp
File diff suppressed because it is too large
Load Diff
5564
src/compiler.cpp
5564
src/compiler.cpp
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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
158
src/powerpc.S
Normal 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
1920
src/powerpc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
124
src/powerpc.h
Normal file
124
src/powerpc.h
Normal 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
|
@ -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)
|
||||
|
||||
|
66
src/x86.S
66
src/x86.S
@ -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
|
||||
|
2432
src/x86.cpp
2432
src/x86.cpp
File diff suppressed because it is too large
Load Diff
32
src/x86.h
32
src/x86.h
@ -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
58
test/Arrays.java
Normal 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
85
test/Integers.java
Normal 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
193
test/Longs.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
306
test/Misc.java
306
test/Misc.java
@ -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
11
test/Simple.java
Normal 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
42
test/Subroutine.java
Normal 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 { }
|
||||
}
|
Loading…
Reference in New Issue
Block a user